|
@@ -1,6 +1,7 @@
|
1
|
1
|
"""
|
2
|
2
|
Provides the graphical front-end for Piket.
|
3
|
3
|
"""
|
|
4
|
+import logging
|
4
|
5
|
import os
|
5
|
6
|
import sys
|
6
|
7
|
|
|
@@ -18,7 +19,7 @@ from PySide2.QtWidgets import (
|
18
|
19
|
QWidget,
|
19
|
20
|
)
|
20
|
21
|
from PySide2.QtGui import QIcon
|
21
|
|
-from PySide2.QtCore import QSize, Qt, QObject, Signal, Slot
|
|
22
|
+from PySide2.QtCore import QObject, QSize, Qt, Signal, Slot
|
22
|
23
|
|
23
|
24
|
# pylint: enable=E0611
|
24
|
25
|
|
|
@@ -29,6 +30,9 @@ except ImportError:
|
29
|
30
|
|
30
|
31
|
from piket_client.sound import PLOP_WAVE
|
31
|
32
|
from piket_client.model import Person, ConsumptionType
|
|
33
|
+import piket_client.logger
|
|
34
|
+
|
|
35
|
+LOG = logging.getLogger(__name__)
|
32
|
36
|
|
33
|
37
|
|
34
|
38
|
def plop() -> None:
|
|
@@ -49,16 +53,21 @@ class NameButton(QPushButton):
|
49
|
53
|
self.clicked.connect(self.process_click)
|
50
|
54
|
|
51
|
55
|
@Slot(str)
|
52
|
|
- def new_active_id(self, new_id: str):
|
|
56
|
+ def new_active_id(self, new_id: str) -> None:
|
|
57
|
+ """ Change the active ConsumptionType id, update the label. """
|
53
|
58
|
self.active_id = new_id
|
54
|
59
|
self.setText(self.current_label)
|
55
|
60
|
|
56
|
|
- @property
|
57
|
|
- def active_consumption_type_id(self) -> str:
|
58
|
|
- return self.parent().active_consumption_type_id
|
|
61
|
+ @Slot()
|
|
62
|
+ def rebuild(self) -> None:
|
|
63
|
+ """ Refresh the Person object and the label. """
|
|
64
|
+ self.person = self.person.reload()
|
|
65
|
+ self.setText(self.current_label)
|
59
|
66
|
|
60
|
67
|
@property
|
61
|
68
|
def current_count(self) -> int:
|
|
69
|
+ """ Return the count of the currently active ConsumptionType for this
|
|
70
|
+ Person. """
|
62
|
71
|
return self.person.consumptions.get(self.active_id, 0)
|
63
|
72
|
|
64
|
73
|
@property
|
|
@@ -81,29 +90,44 @@ class NameButtons(QWidget):
|
81
|
90
|
|
82
|
91
|
new_id_set = Signal(str)
|
83
|
92
|
|
84
|
|
- def __init__(self, consumption_type_id) -> None:
|
|
93
|
+ def __init__(self, consumption_type_id: str) -> None:
|
85
|
94
|
super().__init__()
|
86
|
95
|
|
87
|
96
|
self.layout = None
|
|
97
|
+ self.layout = QGridLayout()
|
|
98
|
+ self.setLayout(self.layout)
|
88
|
99
|
self.active_consumption_type_id = consumption_type_id
|
89
|
100
|
self.init_ui()
|
90
|
101
|
|
91
|
102
|
@Slot(str)
|
92
|
103
|
def consumption_type_changed(self, new_id: str):
|
|
104
|
+ """ Process a change of the consumption type and propagate to the
|
|
105
|
+ contained buttons. """
|
93
|
106
|
self.active_consumption_type_id = new_id
|
94
|
107
|
self.new_id_set.emit(new_id)
|
95
|
108
|
|
96
|
109
|
def init_ui(self) -> None:
|
97
|
110
|
""" Initialize UI: build GridLayout, retrieve People and build a button
|
98
|
111
|
for each. """
|
99
|
|
- self.layout = QGridLayout()
|
100
|
112
|
|
101
|
|
- for index, person in enumerate(Person.get_all()):
|
|
113
|
+ ps = Person.get_all()
|
|
114
|
+ num_columns = round(len(ps) / 10) + 1
|
|
115
|
+
|
|
116
|
+ if self.layout:
|
|
117
|
+ LOG.debug("Removing %s widgets for rebuild", self.layout.count())
|
|
118
|
+ for index in range(self.layout.count()):
|
|
119
|
+ item = self.layout.itemAt(0)
|
|
120
|
+ LOG.debug("Removing item %s: %s", index, item)
|
|
121
|
+ if item:
|
|
122
|
+ w = item.widget()
|
|
123
|
+ LOG.debug("Person %s", w.person)
|
|
124
|
+ self.layout.removeItem(item)
|
|
125
|
+ w.deleteLater()
|
|
126
|
+
|
|
127
|
+ for index, person in enumerate(ps):
|
102
|
128
|
button = NameButton(person, self.active_consumption_type_id, self)
|
103
|
129
|
self.new_id_set.connect(button.new_active_id)
|
104
|
|
- self.layout.addWidget(button, index // 2, index % 2)
|
105
|
|
-
|
106
|
|
- self.setLayout(self.layout)
|
|
130
|
+ self.layout.addWidget(button, index // num_columns, index % num_columns)
|
107
|
131
|
|
108
|
132
|
|
109
|
133
|
class PiketMainWindow(QMainWindow):
|
|
@@ -157,7 +181,40 @@ class PiketMainWindow(QMainWindow):
|
157
|
181
|
ag = QActionGroup(self.toolbar)
|
158
|
182
|
ag.setExclusive(True)
|
159
|
183
|
|
160
|
|
- for ct in ConsumptionType.get_all():
|
|
184
|
+ cts = ConsumptionType.get_all()
|
|
185
|
+ if not cts:
|
|
186
|
+ self.show_keyboard()
|
|
187
|
+ name, ok = QInputDialog.getItem(
|
|
188
|
+ self,
|
|
189
|
+ "Consumptietype toevoegen",
|
|
190
|
+ (
|
|
191
|
+ "Dit lijkt de eerste keer te zijn dat Piket start. Wat wil je "
|
|
192
|
+ "tellen? Je kunt later meer typen toevoegen."
|
|
193
|
+ ),
|
|
194
|
+ ["Bier", "Wijn", "Cola"],
|
|
195
|
+ current=0,
|
|
196
|
+ editable=True,
|
|
197
|
+ )
|
|
198
|
+ self.hide_keyboard()
|
|
199
|
+
|
|
200
|
+ if ok and name:
|
|
201
|
+ c_type = ConsumptionType(name=name)
|
|
202
|
+ c_type = c_type.create()
|
|
203
|
+
|
|
204
|
+ cts.append(c_type)
|
|
205
|
+
|
|
206
|
+ else:
|
|
207
|
+ QMessageBox.critical(
|
|
208
|
+ self,
|
|
209
|
+ "Kan niet doorgaan",
|
|
210
|
+ (
|
|
211
|
+ "Je drukte op 'Annuleren' of voerde geen naam in, dus ik"
|
|
212
|
+ "sluit af."
|
|
213
|
+ ),
|
|
214
|
+ )
|
|
215
|
+ sys.exit()
|
|
216
|
+
|
|
217
|
+ for ct in cts:
|
161
|
218
|
action = QAction(self.load_icon(ct.icon or "beer_bottle.svg"), ct.name, ag)
|
162
|
219
|
action.setCheckable(True)
|
163
|
220
|
action.setData(str(ct.consumption_type_id))
|
|
@@ -202,10 +259,9 @@ class PiketMainWindow(QMainWindow):
|
202
|
259
|
self.hide_keyboard()
|
203
|
260
|
if ok and name:
|
204
|
261
|
person = Person(name=name)
|
205
|
|
- person = person.save()
|
|
262
|
+ person = person.create()
|
206
|
263
|
|
207
|
|
- self.main_widget = NameButtons()
|
208
|
|
- self.setCentralWidget(self.main_widget)
|
|
264
|
+ self.main_widget.init_ui()
|
209
|
265
|
|
210
|
266
|
@staticmethod
|
211
|
267
|
def create_spacer() -> QWidget:
|