|
@@ -2,11 +2,12 @@
|
2
|
2
|
Provides the graphical front-end for Piket.
|
3
|
3
|
"""
|
4
|
4
|
import collections
|
|
5
|
+import itertools
|
5
|
6
|
import logging
|
6
|
7
|
import math
|
7
|
8
|
import os
|
8
|
9
|
import sys
|
9
|
|
-from typing import Deque
|
|
10
|
+from typing import Deque, Iterator
|
10
|
11
|
|
11
|
12
|
import qdarkstyle
|
12
|
13
|
|
|
@@ -26,7 +27,8 @@ from PySide2.QtWidgets import (
|
26
|
27
|
QWidget,
|
27
|
28
|
)
|
28
|
29
|
from PySide2.QtGui import QIcon
|
29
|
|
-from PySide2.QtCore import QObject, QSize, Qt, Signal, Slot
|
|
30
|
+from PySide2.QtCore import QObject, QSize, Qt, Signal, Slot, QUrl
|
|
31
|
+from PySide2.QtMultimedia import QSoundEffect
|
30
|
32
|
|
31
|
33
|
# pylint: enable=E0611
|
32
|
34
|
|
|
@@ -35,7 +37,7 @@ try:
|
35
|
37
|
except ImportError:
|
36
|
38
|
dbus = None
|
37
|
39
|
|
38
|
|
-from piket_client.sound import PLOP_WAVE, UNDO_WAVE
|
|
40
|
+from piket_client.sound import PLOP_PATH, UNDO_PATH
|
39
|
41
|
from piket_client.model import (
|
40
|
42
|
Person,
|
41
|
43
|
ConsumptionType,
|
|
@@ -49,11 +51,6 @@ import piket_client.logger
|
49
|
51
|
LOG = logging.getLogger(__name__)
|
50
|
52
|
|
51
|
53
|
|
52
|
|
-def plop() -> None:
|
53
|
|
- """ Asynchronously play the plop sound. """
|
54
|
|
- PLOP_WAVE.play()
|
55
|
|
-
|
56
|
|
-
|
57
|
54
|
class NameButton(QPushButton):
|
58
|
55
|
""" Wraps a QPushButton to provide a counter. """
|
59
|
56
|
|
|
@@ -99,7 +96,7 @@ class NameButton(QPushButton):
|
99
|
96
|
LOG.debug("Button clicked.")
|
100
|
97
|
result = self.person.add_consumption(self.active_id)
|
101
|
98
|
if result:
|
102
|
|
- plop()
|
|
99
|
+ self.window().play_plop()
|
103
|
100
|
self.setText(self.current_label)
|
104
|
101
|
self.consumption_created.emit(result)
|
105
|
102
|
else:
|
|
@@ -177,6 +174,9 @@ class PiketMainWindow(QMainWindow):
|
177
|
174
|
|
178
|
175
|
consumption_type_changed = Signal(str)
|
179
|
176
|
|
|
177
|
+ plop_loop: Iterator[QSoundEffect]
|
|
178
|
+ undo_loop: Iterator[QSoundEffect]
|
|
179
|
+
|
180
|
180
|
def __init__(self) -> None:
|
181
|
181
|
LOG.debug("Initializing PiketMainWindow.")
|
182
|
182
|
super().__init__()
|
|
@@ -292,6 +292,17 @@ class PiketMainWindow(QMainWindow):
|
292
|
292
|
|
293
|
293
|
self.addToolBar(self.toolbar)
|
294
|
294
|
|
|
295
|
+ # Load sounds
|
|
296
|
+ plops = [QSoundEffect(self) for _ in range(7)]
|
|
297
|
+ for qse in plops:
|
|
298
|
+ qse.setSource(QUrl.fromLocalFile(str(PLOP_PATH)))
|
|
299
|
+ self.plop_loop = itertools.cycle(plops)
|
|
300
|
+
|
|
301
|
+ undos = [QSoundEffect(self) for _ in range(5)]
|
|
302
|
+ for qse in undos:
|
|
303
|
+ qse.setSource(QUrl.fromLocalFile(str(UNDO_PATH)))
|
|
304
|
+ self.undo_loop = itertools.cycle(undos)
|
|
305
|
+
|
295
|
306
|
# Initialize main widget
|
296
|
307
|
self.main_widget = NameButtons(self.ct_ag.actions()[0].data(), self)
|
297
|
308
|
self.consumption_type_changed.connect(self.main_widget.consumption_type_changed)
|
|
@@ -337,7 +348,7 @@ class PiketMainWindow(QMainWindow):
|
337
|
348
|
person.set_active(True)
|
338
|
349
|
|
339
|
350
|
else:
|
340
|
|
- person = Person(full_name=name, display_name=None, )
|
|
351
|
+ person = Person(full_name=name, display_name=None,)
|
341
|
352
|
person.create()
|
342
|
353
|
|
343
|
354
|
assert self.main_widget is not None
|
|
@@ -379,7 +390,7 @@ class PiketMainWindow(QMainWindow):
|
379
|
390
|
|
380
|
391
|
def do_undo(self) -> None:
|
381
|
392
|
""" Undo the last marked consumption. """
|
382
|
|
- UNDO_WAVE.play()
|
|
393
|
+ next(self.undo_loop).play()
|
383
|
394
|
|
384
|
395
|
to_undo = self.undo_queue.pop()
|
385
|
396
|
LOG.warning("Undoing consumption %s", to_undo)
|
|
@@ -423,6 +434,9 @@ class PiketMainWindow(QMainWindow):
|
423
|
434
|
icon = QIcon(os.path.join(self.icons_dir, filename))
|
424
|
435
|
return icon
|
425
|
436
|
|
|
437
|
+ def play_plop(self) -> None:
|
|
438
|
+ next(self.plop_loop).play()
|
|
439
|
+
|
426
|
440
|
|
427
|
441
|
def main() -> None:
|
428
|
442
|
""" Main entry point of GUI client. """
|