github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/client/GUI/onglets/personnes.go (about)

     1  package onglets
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  
     9  	dm "github.com/benoitkugler/goACVE/server/core/datamodel"
    10  	rd "github.com/benoitkugler/goACVE/server/core/rawdata"
    11  
    12  	"github.com/benoitkugler/goACVE/client/GUI/common"
    13  
    14  	"github.com/therecipe/qt/gui"
    15  
    16  	"github.com/therecipe/qt/core"
    17  
    18  	"github.com/benoitkugler/goACVE/client/GUI/lists"
    19  
    20  	"github.com/benoitkugler/goACVE/client/GUI/basic"
    21  	"github.com/benoitkugler/goACVE/client/GUI/fields"
    22  	"github.com/benoitkugler/goACVE/client/controllers"
    23  	"github.com/therecipe/qt/widgets"
    24  )
    25  
    26  func (t *Personnes) Render() {
    27  	t.liste.Model().SetData(t.controller.Liste)
    28  	t.liste.SetSearch(t.controller.Etat.Recherche)
    29  	t.showTemporaire.SetChecked(bool(t.controller.Etat.CritereShowTemporaire))
    30  	t.showOrga.SetData(t.controller.Etat.CritereShowOrganismes)
    31  	t.stats.SetData(t.controller.GetStats())
    32  	if t.controller.Etat.ItemCurrent != nil {
    33  		// on dirait que Qt a besoin d'abord de re-tracer la liste
    34  		// avant de pouvoir sélectionner correctement la personne
    35  		basic.Delay(func() {
    36  			t.liste.SelectRow(t.controller.Etat.ItemCurrent)
    37  		})
    38  	}
    39  }
    40  
    41  func (t *Personnes) ConfirmeSupprimePersonne(pers dm.AccesPersonne) bool {
    42  	return basic.Confirmation(
    43  		fmt.Sprintf("Confirmez-vous la suppression de <b>%s</b> ? <br/>"+
    44  			"Cette opération est irréversible.", pers.RawData().NomPrenom()),
    45  		"Supprimer définitivement", basic.ONDelete)
    46  }
    47  
    48  func (t *Personnes) ConfirmeSupprimeOrganisme(org dm.AccesOrganisme) bool {
    49  	return basic.Confirmation(
    50  		fmt.Sprintf("Confirmez-vous la suppression de l'organisme <b>%s</b> ? <br/>"+
    51  			"Cette opération est irréversible.", org.RawData().Nom),
    52  		"Supprimer définitivement", basic.ONDelete)
    53  }
    54  
    55  type Personnes struct {
    56  	*widgets.QFrame
    57  	controller *controllers.Personnes
    58  	parent     *widgets.QTabWidget
    59  	toolbar    *widgets.QToolBar
    60  
    61  	liste lists.Table
    62  	stats common.Statistics
    63  
    64  	showTemporaire *widgets.QCheckBox
    65  	showOrga       fields.OptionnalBool
    66  }
    67  
    68  func newPersonnes(ct *controllers.Personnes) *Personnes {
    69  	p := Personnes{QFrame: basic.Frame(), controller: ct}
    70  	p.liste.Headers = ct.Header
    71  	p.liste.Title = "Personnes/Organismes"
    72  	p.liste.OnSearch = func(pattern string) {
    73  		ct.Etat.Recherche = pattern
    74  		ct.Reset()
    75  	}
    76  	p.liste.OnSort = func(field rd.Field, reverse bool) {
    77  		ct.Etat.CriteresTri = ct.Etat.CriteresTri.AddCritere(field, reverse)
    78  		ct.Reset()
    79  	}
    80  	p.liste.OnClick = func(acces rd.Item, _ int) {
    81  		ct.Etat.ItemCurrent = acces.Id
    82  		p.UpdateToolbar()
    83  	}
    84  	p.liste.OnDoubleClick = func(acces rd.Item, _ int) {
    85  		switch id := acces.Id.(type) {
    86  		case rd.IdPersonne:
    87  			ac := ct.Base.NewPersonne(id.Int64())
    88  			out, ok := editPersonne(ct.EditRight, ac.RawData())
    89  			if !ok {
    90  				return
    91  			}
    92  			ct.UpdatePersonne(out)
    93  		case rd.IdOrganisme:
    94  			ac := ct.Base.NewOrganisme(id.Int64())
    95  			out, ok := editOrganisme(ct.Base, ct.EditRight, ac.RawData())
    96  			if !ok {
    97  				return
    98  			}
    99  			ct.UpdateOrganisme(out)
   100  		}
   101  	}
   102  	p.liste.OnRightClick = func(acces rd.Item, pos *core.QPoint) {
   103  		menu := widgets.NewQMenu(p.liste)
   104  		switch id := acces.Id.(type) {
   105  		case rd.IdOrganisme:
   106  			raw := ct.Base.NewOrganisme(id.Int64()).RawData()
   107  			if contact := raw.IdContact; contact.IsNotNil() {
   108  				ac := menu.AddAction("Aller au contact...")
   109  				ac.ConnectTriggered(func(_ bool) {
   110  					ct.SelectPersonne(ct.Base.NewPersonne(contact.Int64))
   111  				})
   112  			}
   113  			if contact := raw.IdContactDon; contact.IsNotNil() {
   114  				ac := menu.AddAction("Aller au contact pour les dons...")
   115  				ac.ConnectTriggered(func(_ bool) {
   116  					ct.SelectPersonne(ct.Base.NewPersonne(contact.Int64))
   117  				})
   118  			}
   119  		case rd.IdPersonne:
   120  			parents, enfants := ct.GetParentsEnfants(id)
   121  			ac := menu.AddAction2(basic.Icons.History, "Afficher l'historique...")
   122  			ac.ConnectTriggered(func(_ bool) {
   123  				p.afficherHistorique(id)
   124  			})
   125  			if len(parents) > 0 {
   126  				menu.AddSection("Responsables")
   127  				for _, parent := range parents {
   128  					parent := parent
   129  					ac := menu.AddAction(fmt.Sprintf("%s (%s)", parent.RawData().NomPrenom(), parent.RawData().DateNaissance))
   130  					ac.ConnectTriggered(func(_ bool) {
   131  						ct.SelectPersonne(parent)
   132  					})
   133  				}
   134  			}
   135  			if len(enfants) > 0 {
   136  				menu.AddSection("Participants")
   137  				for _, enfant := range enfants {
   138  					enfant := enfant
   139  					ac := menu.AddAction(fmt.Sprintf("%s (%s)", enfant.RawData().NomPrenom(), enfant.RawData().DateNaissance))
   140  					ac.ConnectTriggered(func(_ bool) {
   141  						ct.SelectPersonne(enfant)
   142  					})
   143  				}
   144  			}
   145  		default:
   146  			return
   147  		}
   148  		p.liste.ShowContextMenu(menu, pos)
   149  	}
   150  
   151  	rightHeader := widgets.NewQHBoxLayout()
   152  
   153  	p.showOrga = fields.NewOptionnalBool(true, "Organismes", "Personnes")
   154  	p.showOrga.ConnectCurrentIndexChanged(func(int) {
   155  		p.controller.Etat.CritereShowOrganismes = p.showOrga.GetData()
   156  		p.controller.Reset()
   157  	})
   158  
   159  	p.showTemporaire = widgets.NewQCheckBox2("Afficher les personnes non référencées", nil)
   160  	p.showTemporaire.ConnectClicked(func(checked bool) {
   161  		p.controller.Etat.CritereShowTemporaire = rd.Bool(checked)
   162  		p.controller.Reset()
   163  	})
   164  	export := basic.Button("Exporter...")
   165  	export.SetObjectName(basic.ONAction)
   166  	export.ConnectClicked(func(_ bool) {
   167  		p.afficherExport()
   168  	})
   169  
   170  	rightHeader.AddWidget(p.showTemporaire, 1, core.Qt__AlignLeft)
   171  	rightHeader.AddWidget(basic.Label("Catégorie :"), 1, 0)
   172  	rightHeader.AddWidget(p.showOrga, 1, 0)
   173  	rightHeader.AddWidget(export, 1, 0)
   174  	p.liste.RightHeader = rightHeader
   175  
   176  	p.liste.Init()
   177  	p.liste.View.SetColumnWidth(0, 300)
   178  	p.liste.View.SetColumnWidth(1, 50)
   179  	p.liste.View.SetColumnWidth(3, 200)
   180  	p.liste.View.SetColumnWidth(4, 200)
   181  	p.liste.View.ConnectKeyPressEvent(func(event *gui.QKeyEvent) {
   182  		if event.Matches(gui.QKeySequence__Copy) {
   183  			item, ok := p.liste.CurrentData()
   184  			if !ok {
   185  				return
   186  			}
   187  			b, err := json.Marshal(ct.Base.Personnes[item.Id.Int64()])
   188  			if err != nil {
   189  				return
   190  			}
   191  			basic.Copy(string(b))
   192  			return
   193  		}
   194  		p.liste.View.KeyPressEventDefault(event)
   195  	})
   196  	p.stats = common.NewStatistics(true)
   197  	lay := widgets.NewQVBoxLayout2(p)
   198  	lay.AddWidget(p.stats, 0, 0)
   199  	lay.AddWidget(p.liste, 3, 0)
   200  	return &p
   201  }
   202  
   203  func (t *Personnes) creerPersonne() {
   204  	p, ok := editPersonne(true, rd.Personne{})
   205  	if !ok {
   206  		return
   207  	}
   208  	t.controller.CreePersonne(p)
   209  }
   210  
   211  func (t *Personnes) creerOrganisme() {
   212  	p, ok := editOrganisme(t.controller.Base, true, rd.Organisme{})
   213  	if !ok {
   214  		return
   215  	}
   216  	t.controller.CreeOrganisme(p)
   217  }
   218  
   219  func (t *Personnes) afficherHistorique(id rd.IdPersonne) {
   220  	data := t.controller.GetHistorique(id.Int64())
   221  	np := t.controller.Base.NewPersonne(id.Int64()).RawData().NomPrenom()
   222  	diag := basic.Dialog("Historique")
   223  	diag.Layout().AddWidget(basic.Label(fmt.Sprintf("Historique de <b>%s</b>", np)))
   224  	var list lists.Table
   225  	list.Headers = []rd.Header{
   226  		{Field: controllers.HistoriqueCamp, Label: "Camp"},
   227  		{Field: controllers.HistoriqueAnnee, Label: "Année"},
   228  		{Field: controllers.HistoriqueRole, Label: "Rôle"},
   229  	}
   230  	list.Placeholder = fmt.Sprintf("Aucune participation n'est enregistrée pour %s", np)
   231  	list.ResizeToContents = true
   232  	list.Init()
   233  	list.Model().SetData(data)
   234  	diag.Layout().AddWidget(list)
   235  	diag.Show()
   236  }
   237  
   238  func (t *Personnes) afficherCriteres() {
   239  	dial := newDialogCriteres(t.controller)
   240  	dial.Show()
   241  }
   242  
   243  func (t *Personnes) afficherExport() {
   244  	d := newExport(t.controller)
   245  	d.update(true)
   246  	d.Exec()
   247  }
   248  
   249  func (t *Personnes) afficherDocuments() {
   250  	d := common.NewDocuments(t.controller.Main(), t.controller.EditRight, false)
   251  	d.SetModal(true)
   252  	d.Show()
   253  	d.RenderDocuments()
   254  }
   255  
   256  func (t *Personnes) supprimer() { t.controller.SupprimeItem() }
   257  
   258  func editPersonne(editable bool, personne rd.Personne) (rd.Personne, bool) {
   259  	f := common.NewFichePersonne(editable)
   260  	f.SetData(personne)
   261  	det := common.NewDetails(&f, editable)
   262  	det.ConnectKeyPressEvent(func(event *gui.QKeyEvent) {
   263  		if event.Matches(gui.QKeySequence__Paste) {
   264  			persJson := basic.Paste()
   265  			var pers rd.Personne
   266  			err := json.Unmarshal([]byte(persJson), &pers)
   267  			if err != nil {
   268  				return
   269  			}
   270  			f.SetCoordonnees(pers)
   271  			return
   272  		}
   273  		det.KeyPressEventDefault(event)
   274  	})
   275  
   276  	basic.Delay(f.RemoveFocus)
   277  	if det.Exec() == 0 {
   278  		return rd.Personne{}, false
   279  	}
   280  	p := f.GetData()
   281  	return p, true
   282  }
   283  
   284  func editOrganisme(b *dm.BaseLocale, editable bool, organisme rd.Organisme) (rd.Organisme, bool) {
   285  	f := common.NewFicheOrganisme(b, editable)
   286  	f.SetData(organisme)
   287  	det := common.NewDetails(&f, editable)
   288  	if det.Exec() == 0 {
   289  		return rd.Organisme{}, false
   290  	}
   291  	p := f.GetData()
   292  	return p, true
   293  }
   294  
   295  // --------------------- Fenêtre de recherche par critère --------------------------
   296  
   297  type dialogCriteres struct {
   298  	*widgets.QDialog
   299  
   300  	ct       *controllers.Personnes
   301  	liste    lists.Table
   302  	labelRes *widgets.QLabel
   303  
   304  	role           fields.Enum
   305  	annee          fields.String
   306  	periode        fields.Enum
   307  	hasDocument    fields.CategorieDocument
   308  	famille        fields.Enum
   309  	ageMin         fields.Int
   310  	ageMax         fields.Int
   311  	departement    fields.Departement
   312  	rangMembreAsso fields.RangMembreAsso
   313  	echoRocher     fields.OptionnalBool
   314  	eonews         fields.OptionnalBool
   315  	pubEte         fields.OptionnalBool
   316  	pubHiver       fields.OptionnalBool
   317  	versionPapier  fields.OptionnalBool
   318  }
   319  
   320  func newDialogCriteres(ct *controllers.Personnes) dialogCriteres {
   321  	d := dialogCriteres{QDialog: basic.Dialog2("Recherche par critères")}
   322  	d.ct = ct
   323  
   324  	roles := append([]fields.Choice{
   325  		{Field: "", Label: "Indifférent"},
   326  		{},
   327  		{Field: controllers.RoleEquipe, Label: "Equipier"},
   328  		{Field: controllers.RoleInscrit, Label: "Inscrit"},
   329  		{Field: controllers.RoleAttente, Label: "En liste d'attente"},
   330  		{}},
   331  		fields.RoleEquipes...)
   332  	d.role = fields.NewEnum(roles, true)
   333  	d.annee = fields.NewString(true)
   334  	periodes := []fields.Choice{
   335  		{Field: "", Label: "Indifférent"},
   336  		{},
   337  		{Field: rd.PERIODES.AUTOMNE.String(), Label: "Automne"},
   338  		{Field: rd.PERIODES.HIVER.String(), Label: "Hiver"},
   339  		{Field: rd.PERIODES.PRINTEMPS.String(), Label: "Printemps"},
   340  		{Field: rd.PERIODES.ETE.String(), Label: "Eté"},
   341  	}
   342  	d.periode = fields.NewEnum(periodes, true)
   343  	d.hasDocument = fields.NewOptionnalCategorieDocument(ct.Base)
   344  
   345  	d.famille = fields.NewEnum([]fields.Choice{
   346  		{Field: "", Label: "Aucune modification"},
   347  		{Field: controllers.LienResposEtParticipants, Label: "Ajouter les responsables"},
   348  		{Field: controllers.LienRespos, Label: "Ne choisir que les responsables"},
   349  	}, true)
   350  
   351  	d.ageMin, d.ageMax = fields.NewInt(true), fields.NewInt(true)
   352  	d.departement = fields.NewDepartement(true)
   353  	d.rangMembreAsso = fields.NewRangMembreAsso(true, true)
   354  	d.echoRocher = fields.NewOptionnalBool(true, "Oui", "Non")
   355  	d.eonews = fields.NewOptionnalBool(true, "Oui", "Non")
   356  	d.pubEte = fields.NewOptionnalBool(true, "Oui", "Non")
   357  	d.pubHiver = fields.NewOptionnalBool(true, "Oui", "Non")
   358  	d.versionPapier = fields.NewOptionnalBool(true, "Oui", "Non")
   359  
   360  	f := widgets.NewQGroupBox2("Critères sur la participation", nil)
   361  	f2 := widgets.NewQGroupBox2("Critères sur la personne", nil)
   362  
   363  	d.role.ConnectCurrentIndexChanged(d.search)
   364  	d.annee.ConnectTextChanged(func(string) { d.search(0) })
   365  	d.periode.ConnectCurrentIndexChanged(d.search)
   366  	d.hasDocument.ConnectCurrentIndexChanged(d.search)
   367  	d.famille.ConnectCurrentIndexChanged(d.search)
   368  	d.ageMin.ConnectValueChanged(d.search)
   369  	d.ageMax.ConnectValueChanged(d.search)
   370  	d.departement.ConnectTextChanged(func(string) { d.search(0) })
   371  	d.rangMembreAsso.ConnectCurrentIndexChanged(d.search)
   372  	d.echoRocher.ConnectCurrentIndexChanged(d.search)
   373  	d.eonews.ConnectCurrentIndexChanged(d.search)
   374  	d.pubEte.ConnectCurrentIndexChanged(d.search)
   375  	d.pubHiver.ConnectCurrentIndexChanged(d.search)
   376  	d.versionPapier.ConnectCurrentIndexChanged(d.search)
   377  
   378  	d.labelRes = basic.Label("")
   379  	d.labelRes.SetAlignment(core.Qt__AlignCenter)
   380  	d.liste = lists.Table{
   381  		Liste: lists.Liste{
   382  			Headers: []rd.Header{
   383  				{Field: dm.PersonneNomPrenom, Label: "Personne"},
   384  				{Field: dm.PersonneMail, Label: "Mail"},
   385  				{Field: dm.PersonneCodePostal, Label: "Code postal"},
   386  			},
   387  			MinWidth: 300,
   388  			OnDelete: func(_ rd.Item, index int) { // sans confirmation
   389  				d.liste.Model().SetData(controllers.RemoveItem(d.liste.Model().GetData(), index))
   390  			},
   391  		},
   392  	}
   393  	d.liste.Init()
   394  	d.liste.HorizontalHeader().SetMinimumSectionSize(60)
   395  	d.liste.HorizontalHeader().ResizeSection(0, 200)
   396  	d.liste.HorizontalHeader().ResizeSection(1, 250)
   397  
   398  	effaceListe := basic.Button("Effacer la liste principale")
   399  	effaceListe.SetObjectName(basic.ONDelete)
   400  	effaceListe.ConnectClicked(func(_ bool) {
   401  		ct.EffaceListe()
   402  	})
   403  	ct.EffaceListe()
   404  
   405  	ajouteOrga := basic.Button("Ajouter les organismes")
   406  	ajouteOrga.SetObjectName(basic.ONAdd)
   407  	ajouteOrga.SetToolTip("Ajouter les organismes à la liste principale.")
   408  	ajouteOrga.ConnectClicked(func(_ bool) {
   409  		ct.AjouteOrganismesToListe()
   410  	})
   411  
   412  	ajouteListe := basic.Button("Ajouter les résultats")
   413  	ajouteListe.SetObjectName(basic.ONAdd)
   414  	ajouteListe.SetToolTip("Ajouter ces résultats à la liste principale.")
   415  	ajouteListe.ConnectClicked(func(_ bool) {
   416  		ct.AjouteToListe(d.liste.Model().GetData())
   417  	})
   418  
   419  	mainLay := widgets.NewQVBoxLayout()
   420  
   421  	lay := widgets.NewQFormLayout(f)
   422  	lay.AddRow3("Rôle", d.role)
   423  	lay.AddRow3("Année", d.annee)
   424  	lay.AddRow3("Période", d.periode)
   425  	lay.AddRow3("Document", d.hasDocument)
   426  	mainLay.AddWidget(f, 2, 0)
   427  
   428  	mainLay.AddSpacing(5)
   429  	mainLay.AddWidget(d.famille, 1, 0)
   430  	mainLay.AddSpacing(5)
   431  
   432  	lay2 := widgets.NewQFormLayout(f2)
   433  	layAge := widgets.NewQHBoxLayout()
   434  	layAge.AddWidget(basic.Label("De"), 1, 0)
   435  	layAge.AddWidget(d.ageMin, 3, 0)
   436  	layAge.AddWidget(basic.Label("à"), 1, 0)
   437  	layAge.AddWidget(d.ageMax, 3, 0)
   438  	lay2.AddRow4("Age", layAge)
   439  	lay2.AddRow3("Département", d.departement)
   440  	lay2.AddRow3("Membre de l'association", d.rangMembreAsso)
   441  	lay2.AddRow3("Echo du Rocher", d.echoRocher)
   442  	lay2.AddRow3("éOnews", d.eonews)
   443  	lay2.AddRow3("Pub. Eté", d.pubEte)
   444  	lay2.AddRow3("Pub. Hiver", d.pubHiver)
   445  	lay2.AddRow3("Version Papier", d.versionPapier)
   446  	mainLay.AddWidget(f2, 2, 0)
   447  	mainLay.AddSpacing(10)
   448  	mainLay.AddWidget(d.labelRes, 1, 0)
   449  
   450  	dialogLay := widgets.NewQGridLayout(d)
   451  	dialogLay.AddLayout2(mainLay, 0, 0, 2, 1, 0)
   452  	dialogLay.AddWidget3(d.liste, 0, 1, 1, 4, 0)
   453  	dialogLay.AddWidget2(effaceListe, 1, 1, 0)
   454  	dialogLay.AddWidget2(ajouteOrga, 1, 3, 0)
   455  	dialogLay.AddWidget2(ajouteListe, 1, 4, 0)
   456  	d.Resize(d.SizeHint())
   457  	return d
   458  }
   459  
   460  // si invalide, renvoi nil
   461  func parseAnnees(s string) map[int]bool {
   462  	s = strings.TrimSpace(strings.ReplaceAll(s, " ", ""))
   463  	if i, err := strconv.Atoi(s); err == nil {
   464  		return map[int]bool{i: true}
   465  	}
   466  	out := map[int]bool{}
   467  	parts := strings.Split(s, "-")
   468  	if len(parts) == 2 {
   469  		debut, err1 := strconv.Atoi(parts[0])
   470  		fin, err2 := strconv.Atoi(parts[1])
   471  		if err1 == nil && err2 == nil {
   472  			for an := debut; an <= fin; an += 1 {
   473  				out[an] = true
   474  			}
   475  			return out
   476  		}
   477  	}
   478  	parts = strings.Split(s, ";")
   479  	for _, p := range parts {
   480  		an, err := strconv.Atoi(p)
   481  		if err != nil {
   482  			return nil
   483  		}
   484  		out[an] = true
   485  	}
   486  	return out
   487  }
   488  
   489  func (d dialogCriteres) getCriteres() controllers.CritereRecherche {
   490  	cpa := controllers.CriteresRechercheParticipant{
   491  		Role:             d.role.GetData(),
   492  		Annee:            parseAnnees(string(d.annee.GetData())),
   493  		Periode:          d.periode.GetData(),
   494  		LiensResponsable: d.famille.GetData(),
   495  	}
   496  	var age *[2]int
   497  	aMin, aMax := d.ageMin.GetData(), d.ageMax.GetData()
   498  	if aMin > 0 && aMax > 0 && aMin <= aMax {
   499  		t := [2]int{int(aMin), int(aMax)}
   500  		age = &t
   501  	}
   502  	cpe := controllers.CriteresRecherchePersonne{
   503  		Age:           age,
   504  		Departement:   d.departement.GetData(),
   505  		EchoRocher:    d.echoRocher.GetData(),
   506  		Eonews:        d.eonews.GetData(),
   507  		MembreAsso:    d.rangMembreAsso.GetData(),
   508  		PubEte:        d.pubEte.GetData(),
   509  		PubHiver:      d.pubHiver.GetData(),
   510  		VersionPapier: d.versionPapier.GetData(),
   511  		HasDocument:   d.hasDocument.GetData(),
   512  	}
   513  	return controllers.CritereRecherche{Personne: cpe, Participant: cpa}
   514  }
   515  
   516  func (d *dialogCriteres) search(_ int) {
   517  	res := d.ct.RecherchePersonnesByCriteres(d.getCriteres())
   518  	d.liste.Model().SetData(res)
   519  	d.labelRes.SetText(fmt.Sprintf("<b>%d</b> résultat(s) (sur %d personnes)",
   520  		len(res), len(d.ct.Base.Personnes)))
   521  }
   522  
   523  // ------------------------------- Export -------------------------------
   524  
   525  type export struct {
   526  	*widgets.QDialog
   527  
   528  	mode        *widgets.QComboBox
   529  	description *widgets.QLabel
   530  	option      *widgets.QComboBox
   531  	labelOption *widgets.QLabel
   532  	preview     *widgets.QLabel
   533  
   534  	controller *controllers.Personnes
   535  }
   536  
   537  func newExport(ct *controllers.Personnes) export {
   538  	d := export{QDialog: basic.Dialog2("Exporter"), controller: ct}
   539  	lay := widgets.NewQFormLayout(d)
   540  
   541  	d.mode = widgets.NewQComboBox(nil)
   542  	d.mode.AddItem("Liste excel", core.NewQVariant5(int(controllers.ExportDEFAULT)))
   543  	d.mode.AddItem("Publipostage", core.NewQVariant5(int(controllers.ExportPUBLIPOSTAGE)))
   544  	d.mode.AddItem("Mailchimp", core.NewQVariant5(int(controllers.ExportMAILCHIMP)))
   545  	d.mode.AddItem("Mails", core.NewQVariant5(int(controllers.ExportMAILS)))
   546  	d.mode.AddItem("Tels. portables", core.NewQVariant5(int(controllers.ExportPORTABLES)))
   547  	d.mode.AddItem("Cotisations", core.NewQVariant5(int(controllers.ExportCOTISATIONS)))
   548  
   549  	d.description = basic.Label("")
   550  
   551  	d.option = widgets.NewQComboBox(nil)
   552  	d.option.SetEnabled(false)
   553  
   554  	d.labelOption = basic.Label("")
   555  
   556  	d.preview = basic.Label("")
   557  
   558  	d.mode.ConnectCurrentIndexChanged(func(_ int) {
   559  		d.update(true)
   560  	})
   561  	d.option.ConnectCurrentIndexChanged(func(_ int) {
   562  		d.update(false)
   563  	})
   564  
   565  	valid := basic.Button("Exporter")
   566  	valid.ConnectClicked(func(_ bool) {
   567  		d.export()
   568  	})
   569  
   570  	lay.AddRow3("Mode d'export", d.mode)
   571  	lay.AddRow5(d.description)
   572  	lay.AddRow(d.labelOption, d.option)
   573  	lay.AddRow5(d.preview)
   574  	lay.AddRow5(valid)
   575  	return d
   576  }
   577  
   578  func (e export) setupOption(mode controllers.ModeExport) {
   579  	e.option.Clear()
   580  	switch mode {
   581  	case controllers.ExportPUBLIPOSTAGE:
   582  		e.option.AddItem("Aucun", core.NewQVariant5(0))
   583  		e.option.AddItem("Pub. été", core.NewQVariant5(int(dm.PubEte)))
   584  		e.option.AddItem("Pub. hiver", core.NewQVariant5(int(dm.PubHiver)))
   585  		e.option.AddItem("Echo du rocher", core.NewQVariant5(int(dm.EchoRocher)))
   586  		e.option.SetEnabled(true)
   587  		e.labelOption.SetText("Type d'envoi (choix des exemplaires)")
   588  	case controllers.ExportCOTISATIONS:
   589  		e.option.AddItem("Alphabétique", core.NewQVariant5(int(dm.MembresTriAlphabetique)))
   590  		e.option.AddItem("Par cotisations", core.NewQVariant5(int(dm.MembresTriCotisation)))
   591  		e.option.SetEnabled(true)
   592  		e.labelOption.SetText("Tri des membres")
   593  	default:
   594  		e.option.SetEnabled(false)
   595  		e.labelOption.SetText("")
   596  	}
   597  }
   598  
   599  func (e export) modeOption() (controllers.ModeExport, dm.OptionExport) {
   600  	mode := controllers.ModeExport(e.mode.CurrentData(int(core.Qt__UserRole)).ToInt(nil))
   601  	option := dm.OptionExport(e.option.CurrentData(int(core.Qt__UserRole)).ToInt(nil))
   602  	return mode, option
   603  }
   604  
   605  func (e export) update(setupOption bool) {
   606  	mode, _ := e.modeOption()
   607  	e.description.SetText(mode.Description())
   608  	if setupOption {
   609  		e.setupOption(mode)
   610  	}
   611  	_, option := e.modeOption() // setupOption ré-initialise les options
   612  	res, invalides := e.controller.ValideExport(mode, option)
   613  	e.preview.SetText(fmt.Sprintf("<b>%d</b> éléments (<i>%d invalides</i>)", len(res), invalides))
   614  }
   615  
   616  func (e export) export() {
   617  	mode, option := e.modeOption()
   618  	path := e.controller.ExportAndSave(mode, option)
   619  	basic.ShowFile(path)
   620  	e.Accept()
   621  }