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

     1  package fields
     2  
     3  import (
     4  	"strconv"
     5  	"time"
     6  
     7  	"github.com/therecipe/qt/core"
     8  
     9  	rd "github.com/benoitkugler/goACVE/server/core/rawdata"
    10  
    11  	"github.com/benoitkugler/goACVE/client/GUI/basic"
    12  	"github.com/therecipe/qt/widgets"
    13  )
    14  
    15  type Euros struct {
    16  	*widgets.QDoubleSpinBox
    17  }
    18  
    19  func NewEuros(editable bool) Euros {
    20  	w := Euros{widgets.NewQDoubleSpinBox(nil)}
    21  	w.SetSuffix("€")
    22  	w.SetEnabled(editable)
    23  	w.SetMaximum(1000000)
    24  	w.SetMinimumWidth(40)
    25  	w.SetMaximumWidth(90)
    26  	return w
    27  }
    28  
    29  func (f Euros) GetData() rd.Euros {
    30  	return rd.Euros(f.Value())
    31  }
    32  
    33  func (f Euros) SetData(data rd.Euros) {
    34  	f.SetValue(float64(data))
    35  }
    36  
    37  type Pourcent struct {
    38  	*widgets.QSpinBox
    39  }
    40  
    41  func NewPourcent(editable bool) Pourcent {
    42  	w := Pourcent{widgets.NewQSpinBox(nil)}
    43  	w.SetMaximum(100)
    44  	w.SetMinimum(0)
    45  	w.SetSuffix("%")
    46  	w.SetEnabled(editable)
    47  	w.SetFixedWidth(80)
    48  	return w
    49  }
    50  
    51  func (f Pourcent) GetData() rd.Pourcent {
    52  	return rd.Pourcent(f.Value())
    53  }
    54  
    55  func (f Pourcent) SetData(data rd.Pourcent) {
    56  	f.SetValue(int(data))
    57  }
    58  
    59  type Int struct {
    60  	*widgets.QSpinBox
    61  }
    62  
    63  func NewInt(editable bool) Int {
    64  	w := Int{widgets.NewQSpinBox(nil)}
    65  	w.SetEnabled(editable)
    66  	w.SetMaximum(1000000)
    67  	w.SetMinimum(0)
    68  	return w
    69  }
    70  
    71  func (f Int) GetData() rd.Int {
    72  	return rd.Int(f.Value())
    73  }
    74  
    75  func (f Int) SetData(data rd.Int) {
    76  	f.SetValue(int(data))
    77  }
    78  
    79  type Bool struct {
    80  	*widgets.QCheckBox
    81  }
    82  
    83  func NewBool(editable bool) Bool {
    84  	w := Bool{widgets.NewQCheckBox(nil)}
    85  	w.SetEnabled(editable)
    86  	return w
    87  }
    88  
    89  func (f Bool) GetData() rd.Bool {
    90  	return rd.Bool(f.IsChecked())
    91  }
    92  
    93  func (f Bool) SetData(data rd.Bool) {
    94  	f.SetChecked(bool(data))
    95  }
    96  
    97  type Date struct {
    98  	*widgets.QFrame
    99  
   100  	jour, mois, annee *widgets.QSpinBox
   101  
   102  	// s'ajoute à une année à deux chiffres. ex : 25 -> 1925 (ou 2025)
   103  	centuryHint int
   104  }
   105  
   106  func NewDate(editable bool, centuryHint int) Date {
   107  	w := Date{
   108  		QFrame:      basic.Frame(),
   109  		jour:        widgets.NewQSpinBox(nil),
   110  		mois:        widgets.NewQSpinBox(nil),
   111  		annee:       widgets.NewQSpinBox(nil),
   112  		centuryHint: centuryHint,
   113  	}
   114  	layout := widgets.NewQHBoxLayout2(w)
   115  	layout.SetSpacing(0)
   116  	layout.SetContentsMargins(0, 0, 0, 0)
   117  	layout.AddWidget(w.jour, 1, 0)
   118  	layout.AddWidget(w.mois, 1, 0)
   119  	layout.AddWidget(w.annee, 2, 0)
   120  
   121  	w.jour.SetMinimumWidth(10)
   122  	w.mois.SetMinimumWidth(10)
   123  	w.annee.SetMinimumWidth(20)
   124  
   125  	w.jour.SetMinimum(1)
   126  	w.mois.SetMinimum(1)
   127  	w.annee.SetMinimum(1)
   128  
   129  	w.jour.SetMaximum(31)
   130  	w.mois.SetMaximum(12)
   131  	w.annee.SetMaximum(2500)
   132  
   133  	w.jour.SetToolTip("Jour")
   134  	w.jour.SetToolTip("Mois")
   135  	w.jour.SetToolTip("Année")
   136  
   137  	w.jour.ConnectEditingFinished(w.validate)
   138  	w.mois.ConnectEditingFinished(w.validate)
   139  	w.annee.ConnectEditingFinished(w.validate)
   140  	w.annee.ConnectValueChanged(w.onChange)
   141  	w.SetEditable(editable)
   142  	return w
   143  }
   144  
   145  func (f Date) SetEditable(b bool) {
   146  	f.jour.SetReadOnly(!b)
   147  	f.mois.SetReadOnly(!b)
   148  	f.annee.SetReadOnly(!b)
   149  }
   150  
   151  func (f Date) ConnectDataChanged(fu func()) {
   152  	f.jour.ConnectValueChanged(func(_ int) { fu() })
   153  	f.mois.ConnectValueChanged(func(_ int) { fu() })
   154  	f.annee.ConnectValueChanged(func(_ int) { fu() })
   155  }
   156  
   157  func (f Date) validate() {
   158  	if f.annee.Value() < 100 {
   159  		f.annee.SetValue(f.annee.Value() + f.centuryHint)
   160  	}
   161  	f.SetData(f.GetData())
   162  }
   163  
   164  func (f Date) onChange(year int) {
   165  	style := "color : black"
   166  	if year < 1000 {
   167  		style = "color : red;"
   168  	}
   169  	f.annee.SetStyleSheet(style)
   170  }
   171  
   172  func (f Date) GetData() rd.Date {
   173  	year, month, day := f.annee.Value(), f.mois.Value(), f.jour.Value()
   174  	return rd.Date(time.Date(year, time.Month(month), day,
   175  		0, 0, 0, 0, time.UTC))
   176  }
   177  
   178  func (f Date) SetData(data rd.Date) {
   179  	date := time.Time(data)
   180  	f.jour.SetValue(date.Day())
   181  	f.mois.SetValue(int(date.Month()))
   182  	f.annee.SetValue(date.Year())
   183  }
   184  
   185  // Plage représente deux dates
   186  type Plage struct {
   187  	*widgets.QFrame
   188  
   189  	from Date
   190  	to   Date
   191  }
   192  
   193  func newPlageLayout(from, to Date, parent widgets.QWidget_ITF) *widgets.QHBoxLayout {
   194  	lay := widgets.NewQHBoxLayout2(parent)
   195  	lay.SetContentsMargins(0, 0, 0, 0)
   196  	lay.AddWidget(basic.Label("du"), 0, 0)
   197  	lay.AddWidget(from, 2, 0)
   198  	lay.AddWidget(basic.Label("au"), 0, 0)
   199  	lay.AddWidget(to, 2, 0)
   200  	return lay
   201  }
   202  
   203  func NewPlage(editable bool) Plage {
   204  	m := Plage{QFrame: basic.Frame()}
   205  	m.from = NewDate(editable, 1900)
   206  	m.to = NewDate(editable, 1900)
   207  	newPlageLayout(m.from, m.to, m)
   208  	return m
   209  }
   210  
   211  func (f Plage) Valid() bool {
   212  	return f.from.GetData().Time().Before(f.to.GetData().Time())
   213  }
   214  
   215  func (f Plage) GetData() rd.Plage {
   216  	return rd.Plage{
   217  		From: f.from.GetData(),
   218  		To:   f.to.GetData(),
   219  	}
   220  }
   221  
   222  func (f Plage) SetData(data rd.Plage) {
   223  	f.from.SetData(data.From)
   224  	f.to.SetData(data.To)
   225  }
   226  
   227  // SetMonthMode paramètre le widget pour la saisie d'une
   228  // plage de mois.
   229  func (f Plage) SetMonthMode() {
   230  	f.from.jour.SetMaximum(28)
   231  	f.to.jour.SetReadOnly(true)
   232  	f.from.ConnectDataChanged(func() {
   233  		f.to.SetData(f.from.GetData())
   234  	})
   235  }
   236  
   237  // OptionnalPlage représente une plage optionnelle
   238  // avec une valeur par défaut si le champ est vide
   239  type OptionnalPlage struct {
   240  	Plage
   241  
   242  	defaut rd.Plage
   243  	active *widgets.QCheckBox
   244  }
   245  
   246  func NewOptionnalPlage(editable bool, defaut rd.Plage) OptionnalPlage {
   247  	op := OptionnalPlage{Plage: Plage{QFrame: basic.Frame()}, defaut: defaut}
   248  	op.from = NewDate(editable, 1900)
   249  	op.to = NewDate(editable, 1900)
   250  	op.active = widgets.NewQCheckBox2("Actif", nil)
   251  	op.active.ConnectClicked(func(checked bool) {
   252  		op.to.SetEnabled(checked)
   253  		op.from.SetEnabled(checked)
   254  	})
   255  
   256  	lay := widgets.NewQVBoxLayout2(op)
   257  	lay.AddWidget(op.active, 1, core.Qt__AlignCenter)
   258  	lay.AddLayout(newPlageLayout(op.from, op.to, nil), 1)
   259  	return op
   260  }
   261  
   262  func (f OptionnalPlage) GetData() rd.Plage {
   263  	if f.active.IsChecked() {
   264  		return f.Plage.GetData()
   265  	}
   266  	return rd.Plage{}
   267  }
   268  
   269  func (f *OptionnalPlage) SetData(data rd.Plage) {
   270  	shouldCheked := data != rd.Plage{}
   271  	if shouldCheked {
   272  		f.Plage.SetData(data)
   273  	} else {
   274  		f.Plage.SetData(f.defaut)
   275  	}
   276  	f.active.SetChecked(shouldCheked)
   277  	f.to.SetEnabled(shouldCheked)
   278  	f.from.SetEnabled(shouldCheked)
   279  }
   280  
   281  type OptionnalBool Enum
   282  
   283  func NewOptionnalBool(editable bool, labelOui, labelNon string) OptionnalBool {
   284  	enum := NewEnum([]Choice{
   285  		{Label: "Indifférent", Field: strconv.Itoa(0)},
   286  		{Label: labelOui, Field: strconv.Itoa(int(rd.OBOui))},
   287  		{Label: labelNon, Field: strconv.Itoa(int(rd.OBNon))},
   288  	}, editable)
   289  	return OptionnalBool(enum)
   290  }
   291  
   292  func (f OptionnalBool) GetData() rd.OptionnalBool {
   293  	i, _ := strconv.Atoi(Enum(f).GetData())
   294  	return rd.OptionnalBool(int8(i))
   295  }
   296  
   297  func (f OptionnalBool) SetData(data rd.OptionnalBool) {
   298  	Enum(f).SetData(strconv.Itoa(int(data)))
   299  }
   300  
   301  type Completion Enum
   302  
   303  type LabelCompletion struct {
   304  	Label      string
   305  	Completion rd.Completion
   306  }
   307  
   308  func NewCompletion(editable bool) Completion {
   309  	comp := Completion(NewEnum(nil, editable))
   310  	comp.Setup([]LabelCompletion{
   311  		{Label: "Indifférent", Completion: 0},
   312  		{Label: "Non commencé", Completion: rd.NonCommencee},
   313  		{Label: "En cours", Completion: rd.EnCours},
   314  		{Label: "Complété", Completion: rd.Complete},
   315  	})
   316  	return comp
   317  }
   318  
   319  func (f Completion) Setup(labels []LabelCompletion) {
   320  	c := make([]Choice, len(labels))
   321  	for i, v := range labels {
   322  		c[i] = Choice{Label: v.Label, Field: strconv.Itoa(int(v.Completion))}
   323  	}
   324  	Enum(f).setChoice(c)
   325  }
   326  
   327  func (f Completion) GetData() rd.Completion {
   328  	i, _ := strconv.Atoi(Enum(f).GetData())
   329  	return rd.Completion(i)
   330  }
   331  
   332  func (f Completion) SetData(data rd.Completion) {
   333  	Enum(f).SetData(strconv.Itoa(int(data)))
   334  }