github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/client/GUI/fields/lists.go (about) 1 package fields 2 3 import ( 4 "github.com/benoitkugler/goACVE/client/GUI/basic" 5 "github.com/benoitkugler/goACVE/client/GUI/lists" 6 rd "github.com/benoitkugler/goACVE/server/core/rawdata" 7 "github.com/therecipe/qt/widgets" 8 ) 9 10 // stringList permet la modification d'une liste de string 11 type stringList struct { 12 lists.Table 13 14 title string 15 formatter func(string) string 16 } 17 18 func newStringList(editable bool, placeholder string) *stringList { 19 w := stringList{ 20 Table: lists.Table{ 21 Liste: lists.Liste{ 22 Headers: []rd.Header{{}}, 23 Placeholder: placeholder, 24 }, 25 HideHeaders: true, 26 ResizeToContents: true, 27 }, 28 } 29 30 if editable { 31 w.OnDoubleClick = func(acces rd.Item, index int) { 32 tel := w.editString(acces.Fields.Data(0).String()) 33 if tel == "" { // annule 34 return 35 } 36 data := w.GetData() 37 data[index] = tel 38 w.SetData(data) 39 } 40 w.OnAdd = func() { 41 tel := w.editString("") 42 if tel == "" { // annule 43 return 44 } 45 w.SetData(append(w.GetData(), tel)) 46 } 47 w.OnDelete = func(_ rd.Item, index int) { 48 data := w.GetData() 49 w.SetData(append(data[:index], data[index+1:]...)) 50 } 51 } 52 w.Init() 53 return &w 54 } 55 56 // empty string to cancel 57 func (f stringList) editString(tel string) string { 58 dialog := basic.Dialog2(f.title) 59 layout := widgets.NewQFormLayout(dialog) 60 edit := NewString(true) 61 msg := "Ajouter" 62 if tel != "" { 63 msg = "Modifier" 64 } 65 edit.SetData(rd.String(tel)) 66 valid := basic.Button(msg) 67 68 var out string 69 valid.ConnectClicked(func(_ bool) { 70 out = edit.GetData().String() 71 dialog.Accept() 72 }) 73 74 layout.AddRow3(f.title+" :", edit) 75 layout.AddRow5(valid) 76 77 dialog.Exec() 78 if f.formatter != nil { 79 out = f.formatter(out) 80 } 81 return out 82 } 83 84 func (f stringList) GetData() []string { 85 data := f.Model().GetData() 86 out := make([]string, len(data)) 87 for index, d := range data { 88 out[index] = d.Fields.Data(0).String() 89 } 90 return out 91 } 92 93 func (f stringList) SetData(data []string) { 94 modelData := make([]rd.Item, len(data)) 95 for index, d := range data { 96 if f.formatter != nil { 97 d = f.formatter(d) 98 } 99 modelData[index] = rd.Item{Fields: rd.F{0: rd.String(d)}} 100 } 101 f.Model().SetData(modelData) 102 } 103 104 // Tels permet la modification d'une liste de numéros de téléphones 105 type Tels struct { 106 *stringList 107 } 108 109 func NewTels(editable bool) Tels { 110 w := newStringList(editable, "Aucun numéro.") 111 w.title = "Numéro de téléphone" 112 w.formatter = rd.FormatTel 113 114 return Tels{w} 115 } 116 117 func (f Tels) GetData() rd.Tels { 118 return f.stringList.GetData() 119 } 120 121 func (f Tels) SetData(data rd.Tels) { 122 f.stringList.SetData(data) 123 } 124 125 // Mails permet la modification d'une liste d'adresses mails 126 type Mails struct { 127 *stringList 128 } 129 130 func NewMails(editable bool) Mails { 131 w := newStringList(editable, "Aucun mail.") 132 w.title = "Mail" 133 w.formatter = nil 134 135 return Mails{w} 136 } 137 138 type optionStatut struct { 139 *widgets.QFrame 140 141 table lists.Table 142 143 // données sous-jacentes à synchroniser 144 data []rd.PrixParStatut 145 } 146 147 func newOptionStatut(editable bool) *optionStatut { 148 w := &optionStatut{QFrame: basic.Frame()} 149 outerLayout := widgets.NewQVBoxLayout2(w) 150 151 w.table = lists.Table{ 152 Liste: lists.Liste{ 153 Headers: []rd.Header{ 154 {Field: rd.PPSStatut, Label: "Statut"}, 155 {Field: rd.PPSPrix, Label: "Prix"}, 156 {Field: rd.PPSDescription, Label: "Description"}, 157 }, 158 Placeholder: "Aucun statut spécial n'est enregistré.", 159 }, 160 ResizeToContents: true, 161 } 162 163 if editable { 164 w.table.OnDoubleClick = func(_ rd.Item, index int) { 165 ptr := editStatut(w.data[index]) 166 if ptr == nil { 167 return 168 } 169 data := w.GetData() 170 data[index] = *ptr 171 w.SetData(data) 172 } 173 w.table.OnAdd = func() { 174 ptr := editStatut(rd.PrixParStatut{}) 175 if ptr == nil { 176 return 177 } 178 ptr.Id = nextId(w.GetData()) 179 w.SetData(append(w.GetData(), *ptr)) 180 } 181 w.table.OnDelete = func(_ rd.Item, index int) { 182 data := w.GetData() 183 w.SetData(append(data[:index], data[index+1:]...)) 184 } 185 } 186 187 w.table.Init() 188 outerLayout.AddWidget(basic.Label(`<i>Le prix dépend du statut du participant. 189 Le statut est attribué parmi la liste ci-dessous.</i><br>`), 0, 0) 190 outerLayout.AddWidget(w.table, 1, 0) 191 w.SetEnabled(editable) 192 return w 193 } 194 195 // s'assure de renvoyer un id valide, c'est à dire >= 1 196 func nextId(currents []rd.PrixParStatut) int64 { 197 var max int64 198 for _, statut := range currents { 199 if max < statut.Id { 200 max = statut.Id 201 } 202 } 203 return max + 1 204 } 205 206 func editStatut(item rd.PrixParStatut) *rd.PrixParStatut { 207 title := "Ajouter un statut spécial" 208 if item.Statut != "" { 209 title = "Modifier le statut" 210 } 211 d := basic.Dialog2(title) 212 lay := widgets.NewQFormLayout(d) 213 statut := NewString2(true, 20, nil) 214 statut.SetToolTip("Statut affiché sur la facture.") 215 desc := NewString(true) 216 desc.SetToolTip("Description affichée sur le formulaire d'inscription.") 217 prix := NewEuros(true) 218 219 valid := basic.Button("Valider") 220 valid.ConnectClicked(func(checked bool) { 221 d.Accept() 222 }) 223 statut.SetData(item.Statut) 224 desc.SetData(item.Description) 225 prix.SetData(item.Prix) 226 lay.AddRow3("Statut", statut) 227 lay.AddRow3("Description", desc) 228 lay.AddRow3("Prix", prix) 229 lay.AddRow5(valid) 230 231 if d.Exec() == 0 { 232 return nil 233 } 234 item.Description = desc.GetData() 235 item.Statut = statut.GetData() 236 item.Prix = prix.GetData() 237 return &item 238 } 239 240 func (f optionStatut) GetData() []rd.PrixParStatut { 241 return f.data 242 } 243 244 func (f *optionStatut) SetData(data []rd.PrixParStatut) { 245 f.data = data 246 items := make([]rd.Item, len(data)) 247 for index, prix := range data { 248 items[index] = prix.AsItem() 249 } 250 f.table.Model().SetData(items) 251 } 252 253 // ------------------ Destinataires --------------------- 254 255 type Destinataires struct { 256 lists.Table 257 258 // données sous-jacentes à synchroniser 259 data rd.DestinatairesOptionnels 260 261 OnClick func(destinataire rd.Destinataire) 262 } 263 264 func NewDestinataires(editable bool) *Destinataires { 265 w := Destinataires{} 266 w.Table = lists.Table{ 267 Liste: lists.Liste{ 268 MinHeight: 300, 269 Headers: []rd.Header{ 270 {Field: rd.DNomPrenom, Label: "Destinataire"}, 271 }, 272 Placeholder: "Aucun destinataire supplémentaire n'est enregistré.", 273 }, 274 ResizeToContents: true, 275 } 276 277 if editable { 278 w.OnDoubleClick = func(_ rd.Item, index int) { 279 dest, ok := editDestinataire(w.data[index], editable) 280 if !ok { 281 return 282 } 283 data := w.GetData() 284 data[index] = dest 285 w.SetData(data) 286 } 287 w.OnAdd = func() { 288 dest, ok := editDestinataire(rd.Destinataire{}, editable) 289 if !ok { 290 return 291 } 292 w.SetData(append(w.GetData(), dest)) 293 } 294 w.OnDelete = func(_ rd.Item, index int) { 295 data := w.GetData() 296 w.SetData(append(data[:index], data[index+1:]...)) 297 } 298 } 299 300 w.Table.OnClick = func(_ rd.Item, index int) { 301 if w.OnClick != nil { 302 w.OnClick(w.GetData()[index]) 303 } 304 } 305 w.Table.Init() 306 return &w 307 } 308 309 func (f Destinataires) GetData() rd.DestinatairesOptionnels { 310 return f.data 311 } 312 313 func (f *Destinataires) SetData(data rd.DestinatairesOptionnels) { 314 f.data = data 315 items := make([]rd.Item, len(data)) 316 for index, prix := range data { 317 items[index] = prix.AsItem() 318 } 319 f.Model().SetData(items) 320 } 321 322 func editDestinataire(destinataire rd.Destinataire, editable bool) (rd.Destinataire, bool) { 323 d := basic.Dialog2("Destinataire") 324 325 nomPrenom := NewString(editable) 326 sexe := NewSexe(editable) 327 adresse := NewMultiLineString(editable, "Adresse...") 328 codePostal := NewString(editable) 329 ville := NewString(editable) 330 331 nomPrenom.SetData(destinataire.NomPrenom) 332 sexe.SetData(destinataire.Sexe) 333 adresse.SetData(destinataire.Adresse) 334 codePostal.SetData(destinataire.CodePostal) 335 ville.SetData(destinataire.Ville) 336 337 lay := widgets.NewQFormLayout(d) 338 lay.AddRow3("Destinataire", nomPrenom) 339 lay.AddRow3("Sexe", sexe) 340 lay.AddRow3("Adresse", adresse) 341 lay.AddRow3("Code postal", codePostal) 342 lay.AddRow3("Ville", ville) 343 344 if editable { 345 valid := basic.Button("Valider") 346 valid.ConnectClicked(func(_ bool) { 347 d.Accept() 348 }) 349 350 lay.AddRow5(valid) 351 } 352 353 ok := d.Exec() > 0 354 out := rd.Destinataire{ 355 NomPrenom: nomPrenom.GetData(), 356 Sexe: sexe.GetData(), 357 Adresse: adresse.GetData(), 358 CodePostal: codePostal.GetData(), 359 Ville: ville.GetData(), 360 } 361 return out, ok 362 }