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

     1  package fields
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  
     7  	rd "github.com/benoitkugler/goACVE/server/core/rawdata"
     8  
     9  	"github.com/therecipe/qt/core"
    10  
    11  	"github.com/benoitkugler/goACVE/client/GUI/basic"
    12  
    13  	"github.com/therecipe/qt/widgets"
    14  )
    15  
    16  type materielSkiCamp struct {
    17  	*widgets.QGroupBox
    18  
    19  	prixAcve   Euros
    20  	prixLoueur Euros
    21  }
    22  
    23  func newMaterielSkiCamp(editable bool) materielSkiCamp {
    24  	w := materielSkiCamp{QGroupBox: widgets.NewQGroupBox2("Matériel de ski",
    25  		nil)}
    26  	w.SetCheckable(true)
    27  	w.prixAcve = NewEuros(editable)
    28  	w.prixLoueur = NewEuros(editable)
    29  	lay := widgets.NewQHBoxLayout2(w)
    30  	lay.AddWidget(basic.Label("prix ACVE"), 2, 0)
    31  	lay.AddWidget(w.prixAcve, 1, 0)
    32  	lay.AddWidget(basic.Label("prix Loueur"), 2, 0)
    33  	lay.AddWidget(w.prixLoueur, 1, 0)
    34  	w.SetEnabled(editable)
    35  	return w
    36  }
    37  
    38  func (f materielSkiCamp) GetData() rd.MaterielSkiCamp {
    39  	return rd.MaterielSkiCamp{
    40  		Actif:      f.IsChecked(),
    41  		PrixAcve:   f.prixAcve.GetData(),
    42  		PrixLoueur: f.prixLoueur.GetData(),
    43  	}
    44  }
    45  
    46  func (f materielSkiCamp) SetData(data rd.MaterielSkiCamp) {
    47  	f.SetChecked(data.Actif)
    48  	f.prixAcve.SetData(data.PrixAcve)
    49  	f.prixLoueur.SetData(data.PrixLoueur)
    50  }
    51  
    52  type trajetBus struct {
    53  	rendezVous String
    54  	prix       Euros
    55  }
    56  
    57  func newTrajetBus(editable bool) trajetBus {
    58  	w := trajetBus{}
    59  	w.rendezVous = NewString(editable)
    60  	w.prix = NewEuros(editable)
    61  	return w
    62  }
    63  
    64  func (f trajetBus) GetData() rd.TrajetBus {
    65  	return rd.TrajetBus{
    66  		RendezVous: f.rendezVous.GetData(),
    67  		Prix:       f.prix.GetData(),
    68  	}
    69  }
    70  
    71  func (f trajetBus) SetData(data rd.TrajetBus) {
    72  	f.rendezVous.SetData(data.RendezVous)
    73  	f.prix.SetData(data.Prix)
    74  }
    75  
    76  type busCamp struct {
    77  	*widgets.QGroupBox
    78  
    79  	commentaire MultiLineString
    80  	aller       trajetBus
    81  	retour      trajetBus
    82  }
    83  
    84  func newBusCamp(editable bool) busCamp {
    85  	w := busCamp{QGroupBox: widgets.NewQGroupBox2("Navette",
    86  		nil)}
    87  	w.SetCheckable(true)
    88  	w.commentaire = NewMultiLineString(editable, "Description...")
    89  	w.aller = newTrajetBus(editable)
    90  	w.retour = newTrajetBus(editable)
    91  	lay := widgets.NewQGridLayout(w)
    92  
    93  	lay.AddWidget3(basic.Label("Description :"), 0, 0, 1, 5, 0)
    94  	lay.AddWidget3(w.commentaire, 0, 0, 1, 5, 0)
    95  	lay.AddWidget2(basic.Label("<i>Aller</i>"), 1, 0, 0)
    96  	lay.AddWidget2(basic.Label("rendez-vous"), 1, 1, 0)
    97  	lay.AddWidget2(w.aller.rendezVous, 1, 2, 0)
    98  	lay.AddWidget2(basic.Label("prix"), 1, 3, 0)
    99  	lay.AddWidget2(w.aller.prix, 1, 4, 0)
   100  	lay.AddWidget2(basic.Label("<i>Retour</i>"), 2, 0, 0)
   101  	lay.AddWidget2(basic.Label("rendez-vous"), 2, 1, 0)
   102  	lay.AddWidget2(w.retour.rendezVous, 2, 2, 0)
   103  	lay.AddWidget2(basic.Label("prix"), 2, 3, 0)
   104  	lay.AddWidget2(w.retour.prix, 2, 4, 0)
   105  
   106  	w.SetEnabled(editable)
   107  	return w
   108  }
   109  
   110  func (f busCamp) GetData() rd.BusCamp {
   111  	return rd.BusCamp{
   112  		Actif:       f.IsChecked(),
   113  		Commentaire: f.commentaire.GetData(),
   114  		Aller:       f.aller.GetData(),
   115  		Retour:      f.retour.GetData(),
   116  	}
   117  }
   118  
   119  func (f busCamp) SetData(data rd.BusCamp) {
   120  	f.SetChecked(data.Actif)
   121  	f.commentaire.SetData(data.Commentaire)
   122  	f.aller.SetData(data.Aller)
   123  	f.retour.SetData(data.Retour)
   124  }
   125  
   126  // OptionsCamp accède aux options d'un camp.
   127  // Voir aussi OptionsParticipant
   128  type OptionsCamp struct {
   129  	*widgets.QGroupBox
   130  
   131  	bus         busCamp
   132  	materielSki materielSkiCamp
   133  }
   134  
   135  func NewOptionsCamp(editable bool) OptionsCamp {
   136  	w := OptionsCamp{QGroupBox: widgets.NewQGroupBox2("Options", nil)}
   137  	w.bus = newBusCamp(editable)
   138  	w.materielSki = newMaterielSkiCamp(editable)
   139  	lay := widgets.NewQFormLayout(w)
   140  	lay.AddRow5(w.bus)
   141  	lay.AddRow5(w.materielSki)
   142  	w.SetEditable(editable)
   143  	return w
   144  }
   145  
   146  func (f OptionsCamp) SetEditable(b bool) {
   147  	f.bus.SetEnabled(b)
   148  	f.materielSki.SetEnabled(b)
   149  }
   150  
   151  func (f OptionsCamp) GetData() rd.OptionsCamp {
   152  	return rd.OptionsCamp{
   153  		Bus:         f.bus.GetData(),
   154  		MaterielSki: f.materielSki.GetData(),
   155  	}
   156  }
   157  
   158  func (f OptionsCamp) SetData(data rd.OptionsCamp) {
   159  	f.bus.SetData(data.Bus)
   160  	f.materielSki.SetData(data.MaterielSki)
   161  }
   162  
   163  type materielSki struct {
   164  	*widgets.QGroupBox
   165  
   166  	need     materielSkiNeed
   167  	pointure Int
   168  	taille   Int
   169  	poids    Int
   170  	mode     materielSkiMode
   171  	casque   Bool
   172  }
   173  
   174  func newMaterielSki(editable bool) materielSki {
   175  	w := materielSki{QGroupBox: widgets.NewQGroupBox2("Matériel de ski", nil)}
   176  	w.need = newMaterielSkiNeed(editable)
   177  	w.pointure = NewInt(editable)
   178  	w.pointure.SetMaximum(99)
   179  	w.taille = NewInt(editable)
   180  	w.taille.SetSuffix("cm")
   181  	w.taille.SetMaximum(300)
   182  	w.poids = NewInt(editable)
   183  	w.poids.SetSuffix("kg")
   184  	w.poids.SetMaximum(400)
   185  	w.mode = newMaterielSkiMode(editable)
   186  	w.casque = NewBool(editable)
   187  
   188  	layout1 := widgets.NewQFormLayout(nil)
   189  	layout1.AddRow3("Besoin", w.need)
   190  	layout1.AddRow3("Catégorie", w.mode)
   191  	layout1.AddRow3("Avec un casque", w.casque)
   192  	layout2 := widgets.NewQFormLayout(nil)
   193  	layout2.AddRow3("Poids", w.poids)
   194  	layout2.AddRow3("Taille", w.taille)
   195  	layout2.AddRow3("Pointure", w.pointure)
   196  	layout := widgets.NewQHBoxLayout2(w)
   197  	layout.AddLayout(layout1, 1)
   198  	layout.AddLayout(layout2, 1)
   199  
   200  	w.need.ConnectCurrentIndexChanged(func(_ int) {
   201  		w.SetData(w.GetData())
   202  	})
   203  	w.SetEnabled(editable)
   204  	return w
   205  }
   206  
   207  func (f materielSki) activeFields(actif bool) {
   208  	f.pointure.SetEnabled(actif)
   209  	f.taille.SetEnabled(actif)
   210  	f.poids.SetEnabled(actif)
   211  	f.mode.SetEnabled(actif)
   212  	f.casque.SetEnabled(actif)
   213  }
   214  
   215  func (f materielSki) GetData() rd.MaterielSki {
   216  	return rd.MaterielSki{
   217  		Need:     f.need.GetData(),
   218  		Pointure: int(f.pointure.GetData()),
   219  		Taille:   int(f.taille.GetData()),
   220  		Poids:    int(f.poids.GetData()),
   221  		Mode:     f.mode.GetData(),
   222  		Casque:   bool(f.casque.GetData()),
   223  	}
   224  }
   225  
   226  func (f materielSki) SetData(data rd.MaterielSki) {
   227  	f.need.SetData(data.Need)
   228  	f.pointure.SetData(rd.Int(data.Pointure))
   229  	f.taille.SetData(rd.Int(data.Taille))
   230  	f.poids.SetData(rd.Int(data.Poids))
   231  	f.mode.SetData(data.Mode)
   232  	f.casque.SetData(rd.Bool(data.Casque))
   233  	f.activeFields(data.Need != "")
   234  }
   235  
   236  // OptionsParticipant accède aux options d'un participant.
   237  // Répond à OptionsCamp
   238  type OptionsParticipant struct {
   239  	*widgets.QFrame
   240  
   241  	bus         Bus
   242  	materielSki materielSki
   243  }
   244  
   245  func NewOptionsParticipant(editable bool) OptionsParticipant {
   246  	w := OptionsParticipant{QFrame: basic.Frame()}
   247  	w.bus = NewBus(editable)
   248  	w.materielSki = newMaterielSki(editable)
   249  	lay := widgets.NewQFormLayout(w)
   250  	lay.AddRow3("Trajet en bus", w.bus)
   251  	lay.AddRow5(w.materielSki)
   252  	w.SetEnabled(editable)
   253  	return w
   254  }
   255  
   256  func (f OptionsParticipant) GetData() rd.OptionsParticipant {
   257  	return rd.OptionsParticipant{
   258  		Bus:         f.bus.GetData(),
   259  		MaterielSki: f.materielSki.GetData(),
   260  	}
   261  }
   262  
   263  func (f OptionsParticipant) SetData(data rd.OptionsParticipant) {
   264  	f.bus.SetData(data.Bus)
   265  	f.materielSki.SetData(data.MaterielSki)
   266  }
   267  
   268  type optionSemaineCamp struct {
   269  	*widgets.QFrame
   270  
   271  	plage1 Plage
   272  	prix1  Euros
   273  	plage2 Plage
   274  	prix2  Euros
   275  }
   276  
   277  func newOptionSemaineCamp(editable bool) optionSemaineCamp {
   278  	w := optionSemaineCamp{QFrame: basic.Frame()}
   279  
   280  	w.plage1 = NewPlage(editable)
   281  	w.plage2 = NewPlage(editable)
   282  	w.prix1 = NewEuros(editable)
   283  	w.prix2 = NewEuros(editable)
   284  
   285  	layout := widgets.NewQFormLayout(w)
   286  	layout.AddRow5(basic.Label("<i>Le camp est accessible sur une des deux semaines suivantes.<i><br>"))
   287  	layout.AddRow3("Semaine 1", w.plage1)
   288  	layout.AddRow3("Prix de la semaine 1", w.prix1)
   289  	layout.AddRow3("Semaine 2", w.plage2)
   290  	layout.AddRow3("Prix de la semaine 2", w.prix2)
   291  
   292  	w.SetEnabled(editable)
   293  	return w
   294  }
   295  
   296  func (f optionSemaineCamp) GetData() rd.OptionSemaineCamp {
   297  	return rd.OptionSemaineCamp{
   298  		Plage1: f.plage1.GetData(),
   299  		Plage2: f.plage2.GetData(),
   300  		Prix1:  f.prix1.GetData(),
   301  		Prix2:  f.prix2.GetData(),
   302  	}
   303  }
   304  
   305  func (f optionSemaineCamp) SetData(data rd.OptionSemaineCamp) {
   306  	f.plage1.SetData(data.Plage1)
   307  	f.plage2.SetData(data.Plage2)
   308  	f.prix1.SetData(data.Prix1)
   309  	f.prix2.SetData(data.Prix2)
   310  }
   311  
   312  type optionQuotientFamilial struct {
   313  	*widgets.QFrame
   314  
   315  	prix [4]Euros
   316  }
   317  
   318  func newOptionQuotientFamilial(editable bool) optionQuotientFamilial {
   319  	w := optionQuotientFamilial{QFrame: basic.Frame()}
   320  	outerLayout := widgets.NewQVBoxLayout2(w)
   321  	lay := widgets.NewQGridLayout2()
   322  	lay.SetSpacing(15)
   323  	for index, borneInf := range rd.QuotientFamilial {
   324  		w.prix[index] = NewEuros(editable)
   325  		var label string
   326  		if index == 3 {
   327  			label = fmt.Sprintf("plus de %d", borneInf+1)
   328  			w.prix[index].SetEnabled(false) // cohérence avec le prix de base
   329  		} else {
   330  			label = fmt.Sprintf("entre %d et %d", borneInf+1, rd.QuotientFamilial[index+1])
   331  		}
   332  		lay.AddWidget2(basic.Label(label), 1, index, 0)
   333  		lay.AddWidget2(w.prix[index], 2, index, 0)
   334  	}
   335  	outerLayout.AddWidget(basic.Label(`<i>Le prix du camp dépend du quotient familial du participant (ou de son responsable).</i><br>`),
   336  		0, 0)
   337  	outerLayout.AddLayout(lay, 0)
   338  	outerLayout.AddStretch(2)
   339  	w.SetEnabled(editable)
   340  	return w
   341  }
   342  
   343  func (f optionQuotientFamilial) GetData() [4]rd.Euros {
   344  	var out [4]rd.Euros
   345  	for index, w := range f.prix {
   346  		out[index] = w.GetData()
   347  	}
   348  	return out
   349  }
   350  
   351  func (f optionQuotientFamilial) SetData(data [4]rd.Euros, prixBase rd.Euros) {
   352  	for index, val := range data {
   353  		if index < 3 {
   354  			f.prix[index].SetData(val)
   355  		}
   356  	}
   357  	f.prix[3].SetData(prixBase)
   358  }
   359  
   360  type optionJoursCamp struct {
   361  	*widgets.QFrame
   362  
   363  	prix []Euros
   364  
   365  	scrollArea *widgets.QScrollArea
   366  }
   367  
   368  func newOptionJours(editable bool) optionJoursCamp {
   369  	w := optionJoursCamp{QFrame: basic.Frame()}
   370  	outerLayout := widgets.NewQVBoxLayout2(w)
   371  
   372  	outerLayout.AddWidget(basic.Label(`<i>Le prix est variable en fonction du nombre de jours de participation au camp.</i><br>`), 0, 0)
   373  	s := widgets.NewQScrollArea(nil)
   374  	s.SetMinimumWidth(800)
   375  	s.SetMinimumHeight(150)
   376  	s.SetSizeAdjustPolicy(widgets.QAbstractScrollArea__AdjustToContents)
   377  	//s.SetWidgetResizable(true)
   378  	outerLayout.AddWidget(s, 0, 0)
   379  	outerLayout.AddStretch(1)
   380  	w.scrollArea = s
   381  	w.SetEnabled(editable)
   382  	return w
   383  }
   384  
   385  func (f *optionJoursCamp) setupWidgets(prixBase rd.Euros, nbJoursMax int) {
   386  	widgetPrix := basic.Frame()
   387  	lay := widgets.NewQGridLayout(widgetPrix)
   388  	lay.SetSpacing(15)
   389  	f.prix = make([]Euros, nbJoursMax)
   390  	for index := 0; index < nbJoursMax; index++ {
   391  		f.prix[index] = NewEuros(true) // le parent se charge du caractère actif/inactif
   392  		label := fmt.Sprintf("%d jour(s)", index+1)
   393  		if index == nbJoursMax-1 {
   394  			f.prix[index].SetEnabled(false) // cohérence avec le prix de base
   395  			f.prix[index].SetData(prixBase)
   396  		}
   397  		lay.AddWidget2(basic.Label(label), 0, index, 0)
   398  		lay.AddWidget2(f.prix[index], 1, index, 0)
   399  	}
   400  	f.scrollArea.SetWidget(widgetPrix)
   401  }
   402  
   403  func (f optionJoursCamp) GetData() []rd.Euros {
   404  	out := make([]rd.Euros, len(f.prix))
   405  	for index, w := range f.prix {
   406  		out[index] = w.GetData()
   407  	}
   408  	return out
   409  }
   410  
   411  func (f *optionJoursCamp) SetData(data []rd.Euros, prixBase rd.Euros, nbJoursMax int) {
   412  	f.setupWidgets(prixBase, nbJoursMax)
   413  	if len(data) != len(f.prix) { // le nombre de jours ne colle pas, on ignore
   414  		return
   415  	}
   416  	for index, widget := range f.prix {
   417  		if index < len(f.prix)-1 {
   418  			widget.SetData(data[index])
   419  		}
   420  	}
   421  }
   422  
   423  type OptionsPrixCamp struct {
   424  	*widgets.QPushButton
   425  
   426  	actif            Enum
   427  	statut           *optionStatut
   428  	jours            optionJoursCamp
   429  	quotientFamilial optionQuotientFamilial
   430  	semaine          optionSemaineCamp
   431  
   432  	// requis pour pouvoir ajuster les options
   433  	GetPrixBaseNbJoursMax func() (prixBase rd.Euros, nbJoursMax int)
   434  }
   435  
   436  func NewOptionsPrixCamp(editable bool) *OptionsPrixCamp {
   437  	w := OptionsPrixCamp{QPushButton: basic.Button("Options sur le prix")}
   438  	w.ConnectClicked(w.onClick)
   439  	w.statut = newOptionStatut(editable)
   440  	w.jours = newOptionJours(editable)
   441  	w.quotientFamilial = newOptionQuotientFamilial(editable)
   442  	w.semaine = newOptionSemaineCamp(editable)
   443  
   444  	w.actif = NewEnum([]Choice{
   445  		{Field: "", Label: "Aucun"},
   446  		{Field: rd.OptionsPrix.STATUT, Label: "Prix par statut"},
   447  		{Field: rd.OptionsPrix.JOUR, Label: "Prix à la journée"},
   448  		{Field: rd.OptionsPrix.QUOTIENT_FAMILIAL, Label: "Prix au quotient familial"},
   449  		{Field: rd.OptionsPrix.SEMAINE, Label: "Prix à la semaine"},
   450  	}, editable)
   451  	return &w
   452  }
   453  
   454  func (f OptionsPrixCamp) SetEditable(b bool) {
   455  	f.actif.SetEnabled(false)
   456  	f.statut.SetEnabled(b)
   457  	f.jours.SetEnabled(b)
   458  	f.quotientFamilial.SetEnabled(b)
   459  	f.semaine.SetEnabled(b)
   460  }
   461  
   462  func (f OptionsPrixCamp) setLabel() {
   463  	l := f.GetData().String()
   464  	msg := "Options sur le prix"
   465  	style := ""
   466  	if l != "" {
   467  		msg += fmt.Sprintf(" (%s)", l)
   468  		style = "bold"
   469  	}
   470  	f.SetStyleSheet("font-weight: " + style)
   471  	f.SetText(msg)
   472  }
   473  
   474  func (f *OptionsPrixCamp) onClick(_ bool) {
   475  	d := basic.Dialog2("Options sur le prix du camp")
   476  	outerLayout := widgets.NewQFormLayout(d)
   477  	stacks := widgets.NewQStackedWidget(nil)
   478  	stacks.AddWidget(basic.Label("<i>Aucune modification sur le prix de base</i>"))
   479  	stacks.AddWidget(f.statut)
   480  	stacks.AddWidget(f.jours)
   481  	stacks.AddWidget(f.quotientFamilial)
   482  	stacks.AddWidget(f.semaine)
   483  	currentIndex := map[string]int{
   484  		rd.OptionsPrix.STATUT: 1, rd.OptionsPrix.JOUR: 2,
   485  		rd.OptionsPrix.QUOTIENT_FAMILIAL: 3, rd.OptionsPrix.SEMAINE: 4,
   486  	}[f.actif.GetData()]
   487  	stacks.SetCurrentIndex(currentIndex)
   488  	f.actif.ConnectCurrentIndexChanged(stacks.SetCurrentIndex)
   489  	valid := basic.Button("Valider")
   490  	valid.ConnectClicked(func(_ bool) {
   491  		d.Accept()
   492  	})
   493  
   494  	outerLayout.AddRow3("Option sur le prix :", f.actif)
   495  	outerLayout.AddRow5(stacks)
   496  	outerLayout.AddRow5(valid)
   497  
   498  	prixBase, nbJoursMax := f.GetPrixBaseNbJoursMax()
   499  
   500  	f.SetData(f.GetData(), prixBase, nbJoursMax) // on ajuste si le reste a changé
   501  	initialOptions := f.GetData()
   502  	if d.Exec() == 0 { // on restaure les anciennes valeurs
   503  		f.SetData(initialOptions, prixBase, nbJoursMax)
   504  	}
   505  	f.setLabel()
   506  }
   507  
   508  func (f OptionsPrixCamp) GetData() rd.OptionPrixCamp {
   509  	return rd.OptionPrixCamp{
   510  		Active:           f.actif.GetData(),
   511  		Statut:           f.statut.GetData(),
   512  		Jour:             f.jours.GetData(),
   513  		QuotientFamilial: f.quotientFamilial.GetData(),
   514  		Semaine:          f.semaine.GetData(),
   515  	}
   516  }
   517  
   518  func (f *OptionsPrixCamp) SetData(data rd.OptionPrixCamp, prixBase rd.Euros, nbJoursMax int) {
   519  	f.actif.SetData(data.Active)
   520  	f.statut.SetData(data.Statut)
   521  	f.jours.SetData(data.Jour, prixBase, nbJoursMax)
   522  	f.quotientFamilial.SetData(data.QuotientFamilial, prixBase)
   523  	f.semaine.SetData(data.Semaine)
   524  	f.setLabel()
   525  }
   526  
   527  type optionJoursParticipant struct {
   528  	*widgets.QScrollArea
   529  
   530  	choix []*widgets.QCheckBox
   531  }
   532  
   533  func newOptionJoursParticipant(editable bool, dates rd.Plage) optionJoursParticipant {
   534  	w := optionJoursParticipant{QScrollArea: widgets.NewQScrollArea(nil)}
   535  
   536  	w.SetMinimumWidth(800)
   537  	w.SetMinimumHeight(150)
   538  	w.SetSizeAdjustPolicy(widgets.QAbstractScrollArea__AdjustToContents)
   539  	//s.SetWidgetResizable(true)
   540  	w.SetWidget(w.setupWidgets(dates))
   541  	w.SetEnabled(editable)
   542  	return w
   543  }
   544  
   545  func (f *optionJoursParticipant) setupWidgets(dates rd.Plage) *widgets.QFrame {
   546  	widgetJours := basic.Frame()
   547  	lay := widgets.NewQGridLayout(widgetJours)
   548  	lay.SetContentsMargins(3, 0, 3, 0)
   549  	lay.SetSpacing(15)
   550  	f.choix = make([]*widgets.QCheckBox, dates.NbJours())
   551  	for index := range f.choix {
   552  		f.choix[index] = widgets.NewQCheckBox(f) // le parent se charge du caractère actif/inactif
   553  		label := fmt.Sprintf("Jour %d", index+1)
   554  		lay.AddWidget2(basic.Label(label), 0, index, 0)
   555  		lay.AddWidget2(f.choix[index], 1, index, 0)
   556  	}
   557  	return widgetJours
   558  }
   559  
   560  func (f optionJoursParticipant) GetData() rd.Jours {
   561  	var out rd.Jours
   562  	for index, w := range f.choix {
   563  		if w.IsChecked() {
   564  			out = append(out, index)
   565  		}
   566  	}
   567  	if len(out.Set()) == len(f.choix) {
   568  		// tous cochés = zero value
   569  		out = nil
   570  	}
   571  	return out
   572  }
   573  
   574  func (f *optionJoursParticipant) SetData(data rd.Jours) {
   575  	crible := data.Set()
   576  	isZero := len(data) == 0 // isZero = tous cochés
   577  	for index, cb := range f.choix {
   578  		cb.SetChecked(isZero || crible[index])
   579  	}
   580  }
   581  
   582  type OptionPrixParticipant struct {
   583  	*widgets.QFrame
   584  
   585  	semaine          Semaine
   586  	quotientFamilial Int
   587  	jour             optionJoursParticipant
   588  	statut           ChoixStatut
   589  
   590  	layout *widgets.QFormLayout
   591  
   592  	Categorie string
   593  }
   594  
   595  func NewOptionPrixParticipant(editable bool, categorie string, status []rd.PrixParStatut, datesCamp rd.Plage) OptionPrixParticipant {
   596  	w := OptionPrixParticipant{QFrame: basic.Frame()}
   597  	w.semaine = NewSemaine(editable)
   598  	w.quotientFamilial = NewInt(editable)
   599  	w.jour = newOptionJoursParticipant(editable, datesCamp)
   600  	w.statut = NewChoixStatut(editable)
   601  	w.layout = widgets.NewQFormLayout(w)
   602  
   603  	w.setChoix(categorie, status)
   604  
   605  	w.SetEnabled(editable)
   606  	return w
   607  }
   608  
   609  func (f *OptionPrixParticipant) setChoix(categorie string, statuts []rd.PrixParStatut) {
   610  	f.statut.SetChoix(statuts)
   611  	for f.layout.Count() > 0 {
   612  		f.layout.RemoveRow(f.layout.Count() - 1)
   613  	}
   614  	switch categorie {
   615  	case rd.OptionsPrix.SEMAINE:
   616  		f.layout.AddRow5(basic.Label("<i>Le camp propose un prix à la semaine.</i><br>"))
   617  		f.layout.AddRow3("Semaine", f.semaine)
   618  	case rd.OptionsPrix.STATUT:
   619  		f.layout.AddRow5(basic.Label("<i>Le prix peut varier en fonction du statut du participant.</i><br>"))
   620  		f.layout.AddRow3("Statut", f.statut)
   621  	case rd.OptionsPrix.QUOTIENT_FAMILIAL:
   622  		f.layout.AddRow5(basic.Label("<i>Le prix du camp varie en fonction du quotient familial du participant ou de son responsable.</i><br>"))
   623  		f.layout.AddRow3("Quotient familial", f.quotientFamilial)
   624  	case rd.OptionsPrix.JOUR:
   625  		f.layout.AddRow5(basic.Label("<i>Le prix varie en fonction du nombre de jours de présence.</i><br>"))
   626  		f.layout.AddRow3("Présence sur les jours", f.jour)
   627  	default:
   628  		f.layout.AddRow5(basic.Label("<i>Le camp ne propose aucune option sur le prix.</i><br>"))
   629  	}
   630  }
   631  
   632  func (f OptionPrixParticipant) GetData() rd.OptionPrixParticipant {
   633  	return rd.OptionPrixParticipant{
   634  		Semaine:          f.semaine.GetData(),
   635  		QuotientFamilial: f.quotientFamilial.GetData(),
   636  		Jour:             f.jour.GetData(),
   637  		Statut:           f.statut.GetData(),
   638  	}
   639  }
   640  
   641  func (f OptionPrixParticipant) SetData(data rd.OptionPrixParticipant) {
   642  	f.semaine.SetData(data.Semaine)
   643  	f.quotientFamilial.SetData(data.QuotientFamilial)
   644  	f.jour.SetData(data.Jour)
   645  	f.statut.SetData(data.Statut)
   646  }
   647  
   648  type remises struct {
   649  	*widgets.QGroupBox
   650  
   651  	Enfants   Pourcent
   652  	Equipiers Pourcent
   653  	Speciale  Euros
   654  }
   655  
   656  func newRemises(editable bool) remises {
   657  	s := remises{QGroupBox: widgets.NewQGroupBox2("Remises", nil)}
   658  	layR := widgets.NewQFormLayout(s)
   659  	s.Enfants = NewPourcent(editable)
   660  	s.Equipiers = NewPourcent(editable)
   661  	s.Speciale = NewEuros(editable)
   662  
   663  	layR.AddRow3("Nombre d'enfants", s.Enfants)
   664  	layR.AddRow3("Equipiers", s.Equipiers)
   665  	layR.AddRow3("Spéciale", s.Speciale)
   666  
   667  	return s
   668  }
   669  
   670  func (f remises) GetData() rd.Remises {
   671  	return rd.Remises{
   672  		ReducEnfants:   f.Enfants.GetData(),
   673  		ReducEquipiers: f.Equipiers.GetData(),
   674  		ReducSpeciale:  f.Speciale.GetData(),
   675  	}
   676  }
   677  
   678  func (f remises) SetData(data rd.Remises) {
   679  	f.Enfants.SetData(data.ReducEnfants)
   680  	f.Equipiers.SetData(data.ReducEquipiers)
   681  	f.Speciale.SetData(data.ReducSpeciale)
   682  }
   683  
   684  // OptionsFinanceParticipant regroupe les remises
   685  // et l'option sur le prix.
   686  type OptionsFinanceParticipant struct {
   687  	*widgets.QPushButton
   688  
   689  	remises               remises
   690  	OptionPrixParticipant OptionPrixParticipant
   691  
   692  	DataChanged func()
   693  }
   694  
   695  func NewOptionsFinanceParticipant(editable bool, categorie string, status []rd.PrixParStatut, defaultPlage rd.Plage) *OptionsFinanceParticipant {
   696  	f := OptionsFinanceParticipant{QPushButton: basic.Button("Options")}
   697  	f.ConnectClicked(f.onClick)
   698  
   699  	f.remises = newRemises(editable)
   700  	f.OptionPrixParticipant = NewOptionPrixParticipant(editable, categorie, status, defaultPlage)
   701  
   702  	return &f
   703  }
   704  
   705  func (f *OptionsFinanceParticipant) onClick(_ bool) {
   706  	d := basic.Dialog2("Options financières")
   707  
   708  	valid := basic.Button("Valider")
   709  	valid.ConnectClicked(func(_ bool) {
   710  		d.Accept()
   711  		if f.DataChanged != nil {
   712  			f.DataChanged()
   713  		}
   714  	})
   715  	valid.SetEnabled(f.OptionPrixParticipant.IsEnabled())
   716  
   717  	lay := widgets.NewQGridLayout(d)
   718  	lay.AddWidget2(f.remises, 0, 0, 0)
   719  	lay.AddWidget2(f.OptionPrixParticipant, 0, 1, 0)
   720  	lay.AddWidget3(valid, 1, 0, 1, 2, 0)
   721  
   722  	initialRemises, initialOption := f.GetData()
   723  	if d.Exec() == 0 { // on restaure les anciennes valeurs
   724  		f.SetData(initialRemises, initialOption)
   725  	}
   726  	f.setLabel()
   727  }
   728  
   729  func (f OptionsFinanceParticipant) setLabel() {
   730  	msg := "Options"
   731  	rem, optionPrix := f.GetData()
   732  	isRemiseActive := rem.IsActive()
   733  	isOptionActive := optionPrix.IsNonNil(f.OptionPrixParticipant.Categorie)
   734  
   735  	if isRemiseActive {
   736  		msg += " (remises actives)"
   737  	}
   738  	if isOptionActive {
   739  		msg += " (option active)"
   740  	}
   741  
   742  	style := ""
   743  	if isRemiseActive || isOptionActive {
   744  		style = "bold"
   745  	}
   746  	f.SetStyleSheet("font-weight: " + style)
   747  	f.SetText(msg)
   748  }
   749  
   750  func (f OptionsFinanceParticipant) GetData() (rd.Remises, rd.OptionPrixParticipant) {
   751  	return f.remises.GetData(), f.OptionPrixParticipant.GetData()
   752  }
   753  
   754  func (f OptionsFinanceParticipant) SetData(rem rd.Remises, opt rd.OptionPrixParticipant) {
   755  	f.remises.SetData(rem)
   756  	f.OptionPrixParticipant.SetData(opt)
   757  	f.setLabel()
   758  }
   759  
   760  type Exemplaires struct {
   761  	*widgets.QFrame
   762  
   763  	pubEte     Int
   764  	pubHiver   Int
   765  	echoRocher Int
   766  }
   767  
   768  func NewExemplaires(editable bool) Exemplaires {
   769  	f := Exemplaires{QFrame: basic.Frame()}
   770  
   771  	f.pubEte = NewInt(editable)
   772  	f.pubHiver = NewInt(editable)
   773  	f.echoRocher = NewInt(editable)
   774  
   775  	lay := widgets.NewQFormLayout(f)
   776  	lay.AddRow3("Publicité pour séjours d'été", f.pubEte)
   777  	lay.AddRow3("Publicité pour séjours d'hiver", f.pubHiver)
   778  	lay.AddRow3("Echo du Rocher", f.echoRocher)
   779  	return f
   780  }
   781  
   782  func (f Exemplaires) GetData() rd.Exemplaires {
   783  	return rd.Exemplaires{
   784  		PubEte:     int(f.pubEte.GetData()),
   785  		PubHiver:   int(f.pubHiver.GetData()),
   786  		EchoRocher: int(f.echoRocher.GetData()),
   787  	}
   788  }
   789  
   790  func (f Exemplaires) SetData(data rd.Exemplaires) {
   791  	f.pubEte.SetData(rd.Int(data.PubEte))
   792  	f.pubHiver.SetData(rd.Int(data.PubHiver))
   793  	f.echoRocher.SetData(rd.Int(data.EchoRocher))
   794  }
   795  
   796  type Cotisation struct {
   797  	*widgets.QPushButton
   798  
   799  	cbs map[int]*widgets.QCheckBox
   800  }
   801  
   802  func NewCotisation(editable bool) Cotisation {
   803  	w := Cotisation{QPushButton: basic.Button("Cotisations annuelles")}
   804  	w.cbs = map[int]*widgets.QCheckBox{}
   805  	for _, an := range rd.AnneesCotisations {
   806  		cb := widgets.NewQCheckBox2(strconv.Itoa(an), nil)
   807  		w.cbs[an] = cb
   808  	}
   809  	w.ConnectClicked(func(_ bool) {
   810  		w.edit()
   811  	})
   812  	w.SetEnabled(editable)
   813  	return w
   814  }
   815  
   816  func (f *Cotisation) edit() {
   817  	current := f.GetData()
   818  	dial := basic.Dialog2("Cotisations")
   819  	layout := widgets.NewQVBoxLayout2(dial)
   820  	row := widgets.NewQHBoxLayout()
   821  	for _, an := range rd.AnneesCotisations {
   822  		row.AddWidget(f.cbs[an], 1, core.Qt__AlignCenter)
   823  	}
   824  	valid := basic.Button("Valider")
   825  	valid.SetObjectName(basic.ONAction)
   826  	valid.ConnectClicked(func(_ bool) {
   827  		dial.Accept()
   828  	})
   829  	layout.AddWidget(basic.Label("<i>Années de cotisations payées :</i>"), 1, 0)
   830  	layout.AddLayout(row, 2)
   831  	layout.AddWidget(valid, 1, 0)
   832  	if dial.Exec() == 0 { // on restaure les valeurs précédentes
   833  		f.SetData(current)
   834  	}
   835  }
   836  
   837  func (f Cotisation) GetData() rd.Cotisation {
   838  	var out rd.Cotisation
   839  	for an, cb := range f.cbs {
   840  		if cb.IsChecked() {
   841  			out = append(out, int64(an))
   842  		}
   843  	}
   844  	return out
   845  }
   846  
   847  func (f *Cotisation) SetData(data rd.Cotisation) {
   848  	m := data.Map()
   849  	for an, cb := range f.cbs {
   850  		cb.SetChecked(m[an])
   851  	}
   852  }