pytodo-qt 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pytodo-qt might be problematic. Click here for more details.
- pytodo_qt-0.2.0.dist-info/COPYING +674 -0
- pytodo_qt-0.2.0.dist-info/METADATA +62 -0
- pytodo_qt-0.2.0.dist-info/RECORD +26 -0
- pytodo_qt-0.2.0.dist-info/WHEEL +5 -0
- pytodo_qt-0.2.0.dist-info/entry_points.txt +2 -0
- pytodo_qt-0.2.0.dist-info/top_level.txt +1 -0
- todo/__init__.py +0 -0
- todo/__main__.py +120 -0
- todo/core/Logger.py +47 -0
- todo/core/TodoDataBase.py +234 -0
- todo/core/__init__.py +35 -0
- todo/core/json_helpers.py +89 -0
- todo/core/settings.py +30 -0
- todo/crypto/AESCipher.py +57 -0
- todo/crypto/__init__.py +0 -0
- todo/gui/AddTodoDialog.py +87 -0
- todo/gui/MainWindow.py +925 -0
- todo/gui/SyncDialog.py +103 -0
- todo/gui/__init__.py +0 -0
- todo/gui/icons/minus.png +0 -0
- todo/gui/icons/plus.png +0 -0
- todo/gui/icons/todo.png +0 -0
- todo/net/__init__.py +20 -0
- todo/net/sync_operations.py +18 -0
- todo/net/tcp_client_lib.py +123 -0
- todo/net/tcp_server_lib.py +139 -0
todo/gui/MainWindow.py
ADDED
|
@@ -0,0 +1,925 @@
|
|
|
1
|
+
"""MainWindow.py
|
|
2
|
+
|
|
3
|
+
This module implements the GUI for To-Do.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport
|
|
10
|
+
|
|
11
|
+
from todo.core import error_on_none_db, settings, json_helpers
|
|
12
|
+
from todo.core.Logger import Logger
|
|
13
|
+
from todo.gui.AddTodoDialog import AddTodoDialog
|
|
14
|
+
from todo.gui.SyncDialog import SyncDialog
|
|
15
|
+
from todo.net.sync_operations import sync_operations
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
logger = Logger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class CreateMainWindow(QtWidgets.QMainWindow):
|
|
22
|
+
"""This class implements the bulk of the gui functionality in To-Do.
|
|
23
|
+
|
|
24
|
+
It creates the main window, and helps to facilitate management of the
|
|
25
|
+
list database for the user.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, *args):
|
|
29
|
+
"""Create the window, make a table, fill table with to-do data."""
|
|
30
|
+
logger.log.info("Creating the main window")
|
|
31
|
+
|
|
32
|
+
# create the window, set title and tooltip, resize and center window
|
|
33
|
+
QtWidgets.QMainWindow.__init__(self)
|
|
34
|
+
self.setWindowIcon(QtGui.QIcon("gui/icons/todo.png"))
|
|
35
|
+
self.setWindowTitle("To-Do")
|
|
36
|
+
self.setToolTip("Python3 + Qt5 = Happy <u>To-Do</u> Programmer!")
|
|
37
|
+
QtWidgets.QToolTip.setFont(QtGui.QFont("Helvetica", 10))
|
|
38
|
+
self.resize(800, 500)
|
|
39
|
+
self.center()
|
|
40
|
+
|
|
41
|
+
# create our special font
|
|
42
|
+
self.complete_font = QtGui.QFont("Helvetica", 10, QtGui.QFont.Bold)
|
|
43
|
+
self.complete_font.setStrikeOut(True)
|
|
44
|
+
|
|
45
|
+
# create our normal font
|
|
46
|
+
self.normal_font = QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal)
|
|
47
|
+
self.normal_font.setStrikeOut(False)
|
|
48
|
+
|
|
49
|
+
# create some actions
|
|
50
|
+
printer = QtWidgets.QAction(QtGui.QIcon(), "Print", self)
|
|
51
|
+
printer.setShortcut("Ctrl+P")
|
|
52
|
+
printer.triggered.connect(self.print_list)
|
|
53
|
+
|
|
54
|
+
export = QtWidgets.QAction(QtGui.QIcon(), "Export to Text File", self)
|
|
55
|
+
export.setShortcut("Ctrl+E")
|
|
56
|
+
export.triggered.connect(self.export_list)
|
|
57
|
+
|
|
58
|
+
_quit = QtWidgets.QAction(QtGui.QIcon(), "Exit", self)
|
|
59
|
+
_quit.setShortcut("Ctrl+Q")
|
|
60
|
+
_quit.triggered.connect(self.close)
|
|
61
|
+
|
|
62
|
+
# to-do actions
|
|
63
|
+
add = QtWidgets.QAction(
|
|
64
|
+
QtGui.QIcon("gui/icons/plus.png"), "Add new to-do", self
|
|
65
|
+
)
|
|
66
|
+
add.setShortcut("+")
|
|
67
|
+
add.triggered.connect(self.add_todo)
|
|
68
|
+
|
|
69
|
+
delete = QtWidgets.QAction(
|
|
70
|
+
QtGui.QIcon("gui/icons/minus.png"), "Delete to-do", self
|
|
71
|
+
)
|
|
72
|
+
delete.setShortcut("-")
|
|
73
|
+
delete.triggered.connect(self.delete_todo)
|
|
74
|
+
|
|
75
|
+
toggle = QtWidgets.QAction(
|
|
76
|
+
QtGui.QIcon("gui/icons/todo.png"), "Toggle to-do Status", self
|
|
77
|
+
)
|
|
78
|
+
toggle.setShortcut("%")
|
|
79
|
+
toggle.triggered.connect(self.toggle_todo)
|
|
80
|
+
|
|
81
|
+
# list actions
|
|
82
|
+
list_add = QtWidgets.QAction(QtGui.QIcon(), "Add new list", self)
|
|
83
|
+
list_add.setShortcut("Ctrl++")
|
|
84
|
+
list_add.triggered.connect(self.add_list)
|
|
85
|
+
|
|
86
|
+
list_delete = QtWidgets.QAction(
|
|
87
|
+
QtGui.QIcon("gui/icons/minus.png"), "Delete list", self
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
list_delete.setShortcut("Ctrl+-")
|
|
91
|
+
list_delete.triggered.connect(self.delete_list)
|
|
92
|
+
|
|
93
|
+
list_rename = QtWidgets.QAction(QtGui.QIcon(), "Rename list", self)
|
|
94
|
+
list_rename.setShortcut("Ctrl+R")
|
|
95
|
+
list_rename.triggered.connect(self.rename_list)
|
|
96
|
+
|
|
97
|
+
list_switch = QtWidgets.QAction(QtGui.QIcon(), "Switch List", self)
|
|
98
|
+
list_switch.setShortcut("Ctrl+L")
|
|
99
|
+
list_switch.triggered.connect(self.switch_list)
|
|
100
|
+
|
|
101
|
+
sync_pull = QtWidgets.QAction(
|
|
102
|
+
QtGui.QIcon(), "Get lists from another computer", self
|
|
103
|
+
)
|
|
104
|
+
sync_pull.setShortcut("F6")
|
|
105
|
+
sync_pull.triggered.connect(self.db_sync_pull)
|
|
106
|
+
|
|
107
|
+
sync_push = QtWidgets.QAction(
|
|
108
|
+
QtGui.QIcon(), "Send lists to another computer", self
|
|
109
|
+
)
|
|
110
|
+
sync_push.setShortcut("F7")
|
|
111
|
+
sync_push.triggered.connect(self.db_sync_push)
|
|
112
|
+
|
|
113
|
+
# network server actions
|
|
114
|
+
start_server = QtWidgets.QAction(
|
|
115
|
+
QtGui.QIcon(), "Start the network server", self
|
|
116
|
+
)
|
|
117
|
+
start_server.triggered.connect(self.db_start_server)
|
|
118
|
+
|
|
119
|
+
stop_server = QtWidgets.QAction(QtGui.QIcon(), "Stop the network server", self)
|
|
120
|
+
stop_server.triggered.connect(self.db_stop_server)
|
|
121
|
+
|
|
122
|
+
change_port = QtWidgets.QAction(
|
|
123
|
+
QtGui.QIcon(), "Change network server port", self
|
|
124
|
+
)
|
|
125
|
+
change_port.triggered.connect(self.db_server_port)
|
|
126
|
+
|
|
127
|
+
change_bind_address = QtWidgets.QAction(
|
|
128
|
+
QtGui.QIcon(), "Change network server address", self
|
|
129
|
+
)
|
|
130
|
+
change_bind_address.triggered.connect(self.db_server_bind_address)
|
|
131
|
+
|
|
132
|
+
# fanfare
|
|
133
|
+
about = QtWidgets.QAction(QtGui.QIcon(), "About To-Do", self)
|
|
134
|
+
about.triggered.connect(self.about_todo)
|
|
135
|
+
|
|
136
|
+
about_qt = QtWidgets.QAction(QtGui.QIcon(), "About Qt", self)
|
|
137
|
+
about_qt.triggered.connect(self.about_qt)
|
|
138
|
+
|
|
139
|
+
# create a menu bar
|
|
140
|
+
menu_bar = self.menuBar()
|
|
141
|
+
if menu_bar is not None:
|
|
142
|
+
main_menu = menu_bar.addMenu("&Menu")
|
|
143
|
+
if main_menu is not None:
|
|
144
|
+
main_menu.addAction(printer)
|
|
145
|
+
main_menu.addAction(export)
|
|
146
|
+
main_menu.addAction(_quit)
|
|
147
|
+
else:
|
|
148
|
+
msg = "Could not populate main menu, exiting"
|
|
149
|
+
QtWidgets.QMessageBox.warning(self, "Creation Error", msg)
|
|
150
|
+
logger.log.exception(msg)
|
|
151
|
+
else:
|
|
152
|
+
msg = "Could not create menu bar, exiting"
|
|
153
|
+
QtWidgets.QMessageBox.warning(self, "Creation Error", msg)
|
|
154
|
+
logger.log.exception(msg)
|
|
155
|
+
sys.exit(1)
|
|
156
|
+
|
|
157
|
+
if menu_bar is not None:
|
|
158
|
+
todo_menu = menu_bar.addMenu("&To-Do")
|
|
159
|
+
if todo_menu is not None:
|
|
160
|
+
todo_menu.addAction(add)
|
|
161
|
+
todo_menu.addAction(delete)
|
|
162
|
+
todo_menu.addAction(toggle)
|
|
163
|
+
else:
|
|
164
|
+
msg = "Could not populate to-do menu, exiting"
|
|
165
|
+
QtWidgets.QMessageBox.warning(self, "Creation Error", msg)
|
|
166
|
+
logger.log.exception(msg)
|
|
167
|
+
sys.exit(1)
|
|
168
|
+
else:
|
|
169
|
+
msg = "Menu bar error, exiting"
|
|
170
|
+
QtWidgets.QMessageBox.warning(self, "Creation Error", msg)
|
|
171
|
+
logger.log.exception(msg)
|
|
172
|
+
sys.exit(1)
|
|
173
|
+
|
|
174
|
+
if menu_bar is not None:
|
|
175
|
+
list_menu = menu_bar.addMenu("&List")
|
|
176
|
+
if list_menu is not None:
|
|
177
|
+
list_menu.addAction(list_add)
|
|
178
|
+
list_menu.addAction(list_delete)
|
|
179
|
+
list_menu.addAction(list_rename)
|
|
180
|
+
list_menu.addAction(list_switch)
|
|
181
|
+
else:
|
|
182
|
+
msg = "Could not populate list menu, exiting"
|
|
183
|
+
QtWidgets.QMessageBox.warning(self, "Creation Error", msg)
|
|
184
|
+
logger.log.exception(msg)
|
|
185
|
+
sys.exit(1)
|
|
186
|
+
else:
|
|
187
|
+
msg = "Menu bar error, exiting"
|
|
188
|
+
QtWidgets.QMessageBox.warning(self, "Creation Error", msg)
|
|
189
|
+
logger.log.exception(msg)
|
|
190
|
+
sys.exit(1)
|
|
191
|
+
|
|
192
|
+
if menu_bar is not None:
|
|
193
|
+
sync_menu = menu_bar.addMenu("&Sync")
|
|
194
|
+
if sync_menu is not None:
|
|
195
|
+
sync_menu.addAction(sync_pull)
|
|
196
|
+
sync_menu.addAction(sync_push)
|
|
197
|
+
else:
|
|
198
|
+
msg = "Could not populate sync menu, exiting"
|
|
199
|
+
QtWidgets.QMessageBox.warning(self, "Creation Error", msg)
|
|
200
|
+
logger.log.exception(msg)
|
|
201
|
+
sys.exit(1)
|
|
202
|
+
else:
|
|
203
|
+
msg = "Menu bar error, exiting"
|
|
204
|
+
QtWidgets.QMessageBox.warning(self, "Creation Error", msg)
|
|
205
|
+
logger.log.exception(msg)
|
|
206
|
+
sys.exit(1)
|
|
207
|
+
|
|
208
|
+
if menu_bar is not None:
|
|
209
|
+
server_menu = menu_bar.addMenu("&Server")
|
|
210
|
+
if server_menu is not None:
|
|
211
|
+
server_menu.addAction(start_server)
|
|
212
|
+
server_menu.addAction(stop_server)
|
|
213
|
+
server_menu.addAction(change_port)
|
|
214
|
+
server_menu.addAction(change_bind_address)
|
|
215
|
+
else:
|
|
216
|
+
msg = "Could not populate server menu, exiting"
|
|
217
|
+
QtWidgets.QMessageBox.warning(self, "Creation Error", msg)
|
|
218
|
+
logger.log.exception(msg)
|
|
219
|
+
sys.exit(1)
|
|
220
|
+
else:
|
|
221
|
+
msg = "Menu bar error, exiting"
|
|
222
|
+
QtWidgets.QMessageBox.warning(self, "Creation Error", msg)
|
|
223
|
+
logger.log.exception(msg)
|
|
224
|
+
sys.exit(1)
|
|
225
|
+
|
|
226
|
+
if menu_bar is not None:
|
|
227
|
+
help_menu = menu_bar.addMenu("&Help")
|
|
228
|
+
if help_menu is not None:
|
|
229
|
+
help_menu.addAction(about)
|
|
230
|
+
help_menu.addAction(about_qt)
|
|
231
|
+
else:
|
|
232
|
+
msg = "Could not populate help menu, exiting"
|
|
233
|
+
QtWidgets.QMessageBox.warning(self, "Creation Error", msg)
|
|
234
|
+
logger.log.exception(msg)
|
|
235
|
+
sys.exit(1)
|
|
236
|
+
else:
|
|
237
|
+
msg = "Menu bar error, exiting"
|
|
238
|
+
QtWidgets.QMessageBox.warning(self, "Creation Error", msg)
|
|
239
|
+
logger.log.exception(msg)
|
|
240
|
+
sys.exit(1)
|
|
241
|
+
|
|
242
|
+
# create action toolbar
|
|
243
|
+
toolbar = self.addToolBar("To-Do Actions")
|
|
244
|
+
if toolbar is not None:
|
|
245
|
+
toolbar.addAction(add)
|
|
246
|
+
toolbar.addAction(delete)
|
|
247
|
+
toolbar.addAction(toggle)
|
|
248
|
+
toolbar.addAction(_quit)
|
|
249
|
+
else:
|
|
250
|
+
msg = "Could not create toolbar, exiting"
|
|
251
|
+
QtWidgets.QMessageBox.warning(self, "Creation Error", msg)
|
|
252
|
+
logger.log.exception(msg)
|
|
253
|
+
sys.exit(1)
|
|
254
|
+
|
|
255
|
+
# create table, set it as central widget
|
|
256
|
+
self.table = QtWidgets.QTableWidget(self)
|
|
257
|
+
if self.table is not None:
|
|
258
|
+
self.table.insertColumn(0)
|
|
259
|
+
self.table.insertColumn(1)
|
|
260
|
+
self.table.setHorizontalHeaderLabels(["Priority", "Reminder"])
|
|
261
|
+
self.table.horizontalHeader().setStretchLastSection(True)
|
|
262
|
+
self.table.setToolTip("This is your <u>list</u> of to-do's.")
|
|
263
|
+
self.setCentralWidget(self.table)
|
|
264
|
+
else:
|
|
265
|
+
msg = "Could not create to-do list table, exiting"
|
|
266
|
+
QtWidgets.QMessageBox.critical(self, "Creation Error", msg)
|
|
267
|
+
logger.log.exception(msg)
|
|
268
|
+
sys.exit(1)
|
|
269
|
+
|
|
270
|
+
# create a status bar
|
|
271
|
+
self.progressBar = QtWidgets.QProgressBar()
|
|
272
|
+
self.statusBarLabel = QtWidgets.QLabel()
|
|
273
|
+
self.statusBar = self.statusBar()
|
|
274
|
+
if self.statusBar is not None:
|
|
275
|
+
self.statusBar.addPermanentWidget(self.progressBar)
|
|
276
|
+
self.statusBar.addPermanentWidget(self.statusBarLabel, 1)
|
|
277
|
+
else:
|
|
278
|
+
msg = "Could not create status bar, exiting"
|
|
279
|
+
QtWidgets.QMessageBox.critical(self, "Creation Error", msg)
|
|
280
|
+
logger.log.exception(msg)
|
|
281
|
+
sys.exit(1)
|
|
282
|
+
|
|
283
|
+
# create a system tray icon
|
|
284
|
+
self.tray_icon = QtWidgets.QSystemTrayIcon(
|
|
285
|
+
QtGui.QIcon("gui/icons/todo.png"), self
|
|
286
|
+
)
|
|
287
|
+
self.tray_icon.activated.connect(self.tray_event)
|
|
288
|
+
|
|
289
|
+
tray_exit = QtWidgets.QAction(QtGui.QIcon(), "Exit", self.tray_icon)
|
|
290
|
+
tray_exit.triggered.connect(self.close)
|
|
291
|
+
|
|
292
|
+
tray_menu = QtWidgets.QMenu("&To-Do", self)
|
|
293
|
+
if tray_menu is not None:
|
|
294
|
+
tray_menu.addAction(tray_exit)
|
|
295
|
+
self.tray_icon.setContextMenu(tray_menu)
|
|
296
|
+
self.tray_icon.show()
|
|
297
|
+
else:
|
|
298
|
+
msg = "Could not create status tray menu, exiting"
|
|
299
|
+
QtWidgets.QMessageBox.critical(self, "Creation Error", msg)
|
|
300
|
+
logger.log.exception(msg)
|
|
301
|
+
sys.exit(1)
|
|
302
|
+
|
|
303
|
+
# create a printer if we can
|
|
304
|
+
self.printer = QtPrintSupport.QPrinter()
|
|
305
|
+
|
|
306
|
+
# show the window
|
|
307
|
+
self.show()
|
|
308
|
+
|
|
309
|
+
# read in any saved to-do data
|
|
310
|
+
self.read_todo_data()
|
|
311
|
+
|
|
312
|
+
# draw the table
|
|
313
|
+
self.refresh()
|
|
314
|
+
|
|
315
|
+
logger.log.info("Main window created")
|
|
316
|
+
|
|
317
|
+
def read_todo_data(self):
|
|
318
|
+
"""Read lists of to-dos from database."""
|
|
319
|
+
if os.path.exists(settings.lists_fn):
|
|
320
|
+
self.update_progress_bar(0)
|
|
321
|
+
self.update_status_bar("Reading in JSON data")
|
|
322
|
+
result, msg = json_helpers.read_json_data()
|
|
323
|
+
if not result:
|
|
324
|
+
QtWidgets.QMessageBox.warning(self, "Read Error", str(msg))
|
|
325
|
+
self.update_progress_bar()
|
|
326
|
+
self.update_status_bar()
|
|
327
|
+
else:
|
|
328
|
+
return
|
|
329
|
+
|
|
330
|
+
self.refresh()
|
|
331
|
+
|
|
332
|
+
@error_on_none_db
|
|
333
|
+
def write_todo_data(self, *args, **kwargs):
|
|
334
|
+
"""Write to-do lists to a JSON file."""
|
|
335
|
+
if len(settings.db.todo_lists.keys()) == 0:
|
|
336
|
+
msg = "No to-do information, aborting write"
|
|
337
|
+
QtWidgets.QMessageBox.warning(self, "Write Error", msg)
|
|
338
|
+
return
|
|
339
|
+
|
|
340
|
+
self.update_progress_bar(0)
|
|
341
|
+
self.update_status_bar("Writing JSON data")
|
|
342
|
+
|
|
343
|
+
result, msg = json_helpers.write_json_data()
|
|
344
|
+
if not result:
|
|
345
|
+
QtWidgets.QMessageBox.warning(self, "Write Error", msg)
|
|
346
|
+
self.update_progress_bar()
|
|
347
|
+
self.update_status_bar()
|
|
348
|
+
|
|
349
|
+
def db_sync_pull(self):
|
|
350
|
+
"""Pull lists from another network server."""
|
|
351
|
+
self.update_progress_bar(0)
|
|
352
|
+
self.update_status_bar("Sync Pull")
|
|
353
|
+
SyncDialog(sync_operations["PULL_REQUEST"].name).exec()
|
|
354
|
+
self.write_todo_data()
|
|
355
|
+
self.refresh()
|
|
356
|
+
|
|
357
|
+
def db_sync_push(self):
|
|
358
|
+
"""Push lists to another computer."""
|
|
359
|
+
self.update_progress_bar(0)
|
|
360
|
+
self.update_status_bar("Waiting for input")
|
|
361
|
+
SyncDialog(sync_operations["PUSH_REQUEST"].name).exec()
|
|
362
|
+
self.refresh()
|
|
363
|
+
|
|
364
|
+
@error_on_none_db
|
|
365
|
+
def db_update_active_list(self, list_name, *args, **kwargs):
|
|
366
|
+
"""Update the active list, and save the configuration."""
|
|
367
|
+
settings.options["active_list"] = list_name
|
|
368
|
+
|
|
369
|
+
settings.db.active_list = list_name
|
|
370
|
+
result, msg = settings.db.write_config()
|
|
371
|
+
if not result:
|
|
372
|
+
QtWidgets.QMessageBox.critical(self, "Write Error", msg)
|
|
373
|
+
sys.exit(1)
|
|
374
|
+
else:
|
|
375
|
+
QtWidgets.QMessageBox.information(self, "Write Success", msg)
|
|
376
|
+
|
|
377
|
+
@error_on_none_db
|
|
378
|
+
def db_start_server(self, *args, **kwargs):
|
|
379
|
+
"""Start the database server."""
|
|
380
|
+
if settings.db.server_running():
|
|
381
|
+
QtWidgets.QMessageBox.information(
|
|
382
|
+
self, "Info", "The database server is already running."
|
|
383
|
+
)
|
|
384
|
+
else:
|
|
385
|
+
settings.db.start_server()
|
|
386
|
+
QtWidgets.QMessageBox.information(
|
|
387
|
+
self, "Info", "The database server was started."
|
|
388
|
+
)
|
|
389
|
+
self.refresh()
|
|
390
|
+
|
|
391
|
+
@error_on_none_db
|
|
392
|
+
def db_stop_server(self, *args, **kwargs):
|
|
393
|
+
"""Stop the database server."""
|
|
394
|
+
if not settings.db.server_running():
|
|
395
|
+
QtWidgets.QMessageBox.information(
|
|
396
|
+
self, "Info", "The database server is not running."
|
|
397
|
+
)
|
|
398
|
+
else:
|
|
399
|
+
settings.db.stop_server()
|
|
400
|
+
QtWidgets.QMessageBox.information(
|
|
401
|
+
self, "Info", "The database server was stopped."
|
|
402
|
+
)
|
|
403
|
+
self.refresh()
|
|
404
|
+
|
|
405
|
+
@error_on_none_db
|
|
406
|
+
def db_server_port(self, *args, **kwargs):
|
|
407
|
+
"""Change the port the database server listens too."""
|
|
408
|
+
port, ok = QtWidgets.QInputDialog.getInt(
|
|
409
|
+
self, "Change database server port", "Port: "
|
|
410
|
+
)
|
|
411
|
+
if not ok:
|
|
412
|
+
return
|
|
413
|
+
|
|
414
|
+
if settings.options["port"] == port:
|
|
415
|
+
QtWidgets.QMessageBox.information(
|
|
416
|
+
self, "Info", f"Server is already using port {port}"
|
|
417
|
+
)
|
|
418
|
+
else:
|
|
419
|
+
settings.options["port"] = port
|
|
420
|
+
if settings.db.server_running():
|
|
421
|
+
reply = QtWidgets.QMessageBox.question(
|
|
422
|
+
self,
|
|
423
|
+
"Restart Database Server?",
|
|
424
|
+
"The server needs to be restarted for changes to take effect, would you like to do that now?",
|
|
425
|
+
QtWidgets.QMessageBox.Yes,
|
|
426
|
+
QtWidgets.QMessageBox.No,
|
|
427
|
+
)
|
|
428
|
+
if reply == QtWidgets.QMessageBox.Yes:
|
|
429
|
+
settings.db.restart_server()
|
|
430
|
+
settings.db.write_config()
|
|
431
|
+
self.refresh()
|
|
432
|
+
|
|
433
|
+
@error_on_none_db
|
|
434
|
+
def db_server_bind_address(self, *args, **kwargs):
|
|
435
|
+
"""Bind database server to an ip address."""
|
|
436
|
+
address, ok = QtWidgets.QInputDialog.getText(
|
|
437
|
+
self, "Change server ip address", "IP Address: "
|
|
438
|
+
)
|
|
439
|
+
if not ok:
|
|
440
|
+
return
|
|
441
|
+
|
|
442
|
+
if settings.options["address"] == address:
|
|
443
|
+
QtWidgets.QMessageBox.information(
|
|
444
|
+
self, "Info", f"Server is already bound to {address}"
|
|
445
|
+
)
|
|
446
|
+
else:
|
|
447
|
+
settings.options["address"] = address
|
|
448
|
+
if settings.db.server_running():
|
|
449
|
+
reply = QtWidgets.QMessageBox.question(
|
|
450
|
+
self,
|
|
451
|
+
"Restart Database Server?",
|
|
452
|
+
"The server needs to be restarted for changes to take effect, would you like to do that now?",
|
|
453
|
+
QtWidgets.QMessageBox.Yes,
|
|
454
|
+
QtWidgets.QMessageBox.No,
|
|
455
|
+
)
|
|
456
|
+
if reply == QtWidgets.QMessageBox.Yes:
|
|
457
|
+
settings.db.restart_server()
|
|
458
|
+
settings.db.write_config()
|
|
459
|
+
self.refresh()
|
|
460
|
+
|
|
461
|
+
@error_on_none_db
|
|
462
|
+
def add_list(self, *args, **kwargs):
|
|
463
|
+
"""Add a new list of to-dos."""
|
|
464
|
+
self.update_progress_bar(0)
|
|
465
|
+
self.update_status_bar("Waiting for input")
|
|
466
|
+
|
|
467
|
+
list_name, ok = QtWidgets.QInputDialog.getText(
|
|
468
|
+
self, "Add New List", "Enter a name for the new list: "
|
|
469
|
+
)
|
|
470
|
+
if ok:
|
|
471
|
+
if len(list_name) == 0:
|
|
472
|
+
self.update_progress_bar()
|
|
473
|
+
self.update_status_bar()
|
|
474
|
+
return
|
|
475
|
+
|
|
476
|
+
if list_name not in settings.db.todo_lists.keys():
|
|
477
|
+
settings.db.todo_lists[list_name] = []
|
|
478
|
+
settings.options["active_list"] = list_name
|
|
479
|
+
settings.db.active_list = list_name
|
|
480
|
+
settings.db.write_config()
|
|
481
|
+
self.write_todo_data()
|
|
482
|
+
else:
|
|
483
|
+
QtWidgets.QMessageBox.warning(
|
|
484
|
+
self,
|
|
485
|
+
"Duplicate List",
|
|
486
|
+
f'A list named "{list_name}" already exists.',
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
self.refresh()
|
|
490
|
+
|
|
491
|
+
@error_on_none_db
|
|
492
|
+
def delete_list(self, *args, **kwargs):
|
|
493
|
+
"""Delete user selected list."""
|
|
494
|
+
self.update_progress_bar(0)
|
|
495
|
+
|
|
496
|
+
# if there is more than one list, ask user which one to delete
|
|
497
|
+
if len(settings.db.todo_lists.keys()) > 1:
|
|
498
|
+
list_entry, ok = QtWidgets.QInputDialog.getItem(
|
|
499
|
+
self,
|
|
500
|
+
"Select List",
|
|
501
|
+
"To-Do Lists: ",
|
|
502
|
+
list(settings.db.todo_lists.keys()),
|
|
503
|
+
)
|
|
504
|
+
if not ok:
|
|
505
|
+
self.update_progress_bar()
|
|
506
|
+
return
|
|
507
|
+
|
|
508
|
+
settings.db.todo_total -= len(settings.db.todo_lists[list_entry])
|
|
509
|
+
del settings.db.todo_lists[list_entry]
|
|
510
|
+
|
|
511
|
+
# use list switcher if there is still more than one list
|
|
512
|
+
if len(settings.db.todo_lists) > 1:
|
|
513
|
+
self.switch_list()
|
|
514
|
+
else:
|
|
515
|
+
for list_entry in settings.db.todo_lists.keys():
|
|
516
|
+
self.db_update_active_list(list_entry)
|
|
517
|
+
self.write_todo_data()
|
|
518
|
+
break
|
|
519
|
+
else:
|
|
520
|
+
reply = QtWidgets.QMessageBox.question(
|
|
521
|
+
self,
|
|
522
|
+
"Confirm deletion",
|
|
523
|
+
f'Really delete list "{settings.db.active_list}"?',
|
|
524
|
+
QtWidgets.QMessageBox.Yes,
|
|
525
|
+
QtWidgets.QMessageBox.No,
|
|
526
|
+
)
|
|
527
|
+
if reply == QtWidgets.QMessageBox.No:
|
|
528
|
+
self.update_progress_bar()
|
|
529
|
+
return
|
|
530
|
+
|
|
531
|
+
settings.db.todo_total -= settings.db.todo_count
|
|
532
|
+
del settings.db.todo_lists[settings.db.active_list]
|
|
533
|
+
settings.db.list_count -= 1
|
|
534
|
+
|
|
535
|
+
# reset database
|
|
536
|
+
settings.db.active_list = ""
|
|
537
|
+
settings.options["active_list"] = settings.db.active_list
|
|
538
|
+
settings.db.todo_count = 0
|
|
539
|
+
settings.db.write_config()
|
|
540
|
+
if os.path.exists(settings.lists_fn):
|
|
541
|
+
os.remove(settings.lists_fn)
|
|
542
|
+
|
|
543
|
+
self.refresh()
|
|
544
|
+
|
|
545
|
+
@error_on_none_db
|
|
546
|
+
def rename_list(self, *args, **kwargs):
|
|
547
|
+
"""Rename the active list"""
|
|
548
|
+
self.update_progress_bar(0)
|
|
549
|
+
|
|
550
|
+
list_name, ok = QtWidgets.QInputDialog.getText(
|
|
551
|
+
self, "Rename to-do list", "Enter new name:"
|
|
552
|
+
)
|
|
553
|
+
if ok:
|
|
554
|
+
reply = QtWidgets.QMessageBox.question(
|
|
555
|
+
self,
|
|
556
|
+
"Confirm rename",
|
|
557
|
+
f"Are you sure you want to rename list {settings.db.active_list} to {list_name}",
|
|
558
|
+
QtWidgets.QMessageBox.Yes,
|
|
559
|
+
QtWidgets.QMessageBox.No,
|
|
560
|
+
)
|
|
561
|
+
|
|
562
|
+
if reply == QtWidgets.QMessageBox.No:
|
|
563
|
+
return
|
|
564
|
+
|
|
565
|
+
settings.db.todo_lists[list_name] = settings.db.todo_lists[
|
|
566
|
+
settings.db.active_list
|
|
567
|
+
]
|
|
568
|
+
del settings.db.todo_lists[settings.db.active_list]
|
|
569
|
+
settings.db.active_list = settings.db.todo_lists[list_name]
|
|
570
|
+
settings.db.write_config()
|
|
571
|
+
self.write_todo_data()
|
|
572
|
+
self.refresh()
|
|
573
|
+
|
|
574
|
+
@error_on_none_db
|
|
575
|
+
def switch_list(self, *args, **kwargs):
|
|
576
|
+
"""Switch the active list.
|
|
577
|
+
|
|
578
|
+
Present user with a drop-down dialog of lists,
|
|
579
|
+
set their choice as the active list.
|
|
580
|
+
"""
|
|
581
|
+
self.update_progress_bar(0)
|
|
582
|
+
|
|
583
|
+
if len(settings.db.todo_lists.keys()) == 0:
|
|
584
|
+
return
|
|
585
|
+
|
|
586
|
+
list_entry, ok = QtWidgets.QInputDialog.getItem(
|
|
587
|
+
self, "Select List", "To-Do Lists: ", list(settings.db.todo_lists.keys())
|
|
588
|
+
)
|
|
589
|
+
if ok:
|
|
590
|
+
self.db_update_active_list(list_entry)
|
|
591
|
+
self.write_todo_data()
|
|
592
|
+
|
|
593
|
+
self.refresh()
|
|
594
|
+
|
|
595
|
+
@error_on_none_db
|
|
596
|
+
def export_list(self, fn=None, *args, **kwargs):
|
|
597
|
+
"""Export active list to text file."""
|
|
598
|
+
self.update_progress_bar(0)
|
|
599
|
+
|
|
600
|
+
if not settings.db.todo_count:
|
|
601
|
+
return
|
|
602
|
+
|
|
603
|
+
if fn is None:
|
|
604
|
+
# prompt user for fn
|
|
605
|
+
self.update_status_bar("Waiting for input")
|
|
606
|
+
fn, ok = QtWidgets.QInputDialog.getText(
|
|
607
|
+
self,
|
|
608
|
+
"Save list to text file",
|
|
609
|
+
"Enter name of file to write as text:",
|
|
610
|
+
)
|
|
611
|
+
if not ok:
|
|
612
|
+
return
|
|
613
|
+
|
|
614
|
+
self.update_status_bar(f"Exporting to text file {fn}.")
|
|
615
|
+
settings.db.write_text_file(fn)
|
|
616
|
+
self.update_status_bar(f"finished exporting to {fn}.")
|
|
617
|
+
self.update_progress_bar()
|
|
618
|
+
|
|
619
|
+
def print_list(self):
|
|
620
|
+
"""Print the active list."""
|
|
621
|
+
self.update_progress_bar(0)
|
|
622
|
+
|
|
623
|
+
# check that we have a printer first
|
|
624
|
+
if not self.printer:
|
|
625
|
+
self.update_progress_bar()
|
|
626
|
+
return
|
|
627
|
+
|
|
628
|
+
tmp_fn = ".todo_printer.tmp"
|
|
629
|
+
|
|
630
|
+
accept = QtPrintSupport.QPrintDialog(self.printer).exec()
|
|
631
|
+
if accept:
|
|
632
|
+
self.update_status_bar("Printing")
|
|
633
|
+
|
|
634
|
+
# Write formatted list to temporary file
|
|
635
|
+
self.export_list(tmp_fn)
|
|
636
|
+
if not os.path.exists(tmp_fn):
|
|
637
|
+
return
|
|
638
|
+
|
|
639
|
+
# Read in formatted list as one big string
|
|
640
|
+
string = ""
|
|
641
|
+
with open(tmp_fn, encoding="utf-8") as f:
|
|
642
|
+
for line in f:
|
|
643
|
+
string += line
|
|
644
|
+
|
|
645
|
+
# Remove temporary file
|
|
646
|
+
os.remove(tmp_fn)
|
|
647
|
+
|
|
648
|
+
# Open string as a QTextDocument and then print it
|
|
649
|
+
doc = QtGui.QTextDocument(string)
|
|
650
|
+
doc.print_(self.printer)
|
|
651
|
+
|
|
652
|
+
self.update_progress_bar()
|
|
653
|
+
self.update_status_bar("finished printing")
|
|
654
|
+
|
|
655
|
+
@error_on_none_db
|
|
656
|
+
def add_todo(self, *args, **kwargs):
|
|
657
|
+
"""Add a new to-do to active list."""
|
|
658
|
+
self.update_progress_bar(0)
|
|
659
|
+
|
|
660
|
+
if not settings.db.active_list:
|
|
661
|
+
if settings.db.list_count == 0:
|
|
662
|
+
QtWidgets.QMessageBox.information(
|
|
663
|
+
self,
|
|
664
|
+
"No list",
|
|
665
|
+
"You need to create a list before you add a reminder",
|
|
666
|
+
)
|
|
667
|
+
self.update_progress_bar()
|
|
668
|
+
self.update_status_bar()
|
|
669
|
+
return self.add_list()
|
|
670
|
+
else:
|
|
671
|
+
# ask the user if they would like to switch to an existing list
|
|
672
|
+
self.update_status_bar("Waiting for input")
|
|
673
|
+
reply = QtWidgets.QMessageBox.question(
|
|
674
|
+
self,
|
|
675
|
+
"Set an active list",
|
|
676
|
+
"There is currently no active list set, but lists do exist,"
|
|
677
|
+
"would you like to switch to one of them?",
|
|
678
|
+
QtWidgets.QMessageBox.Yes,
|
|
679
|
+
QtWidgets.QMessageBox.No,
|
|
680
|
+
)
|
|
681
|
+
|
|
682
|
+
# check the user response
|
|
683
|
+
if reply == QtWidgets.QMessageBox.Yes:
|
|
684
|
+
self.switch_list()
|
|
685
|
+
else:
|
|
686
|
+
return
|
|
687
|
+
|
|
688
|
+
# Get a new to-do from user
|
|
689
|
+
AddTodoDialog().exec()
|
|
690
|
+
|
|
691
|
+
self.refresh()
|
|
692
|
+
|
|
693
|
+
@error_on_none_db
|
|
694
|
+
def delete_todo(self, *args, **kwargs):
|
|
695
|
+
"""Delete the currently selected to-do."""
|
|
696
|
+
self.update_progress_bar(0)
|
|
697
|
+
|
|
698
|
+
if self.table is None:
|
|
699
|
+
msg = "To-Do List Table is invalid, exiting"
|
|
700
|
+
QtWidgets.QMessageBox.critical(self, "To-Do List Error", msg)
|
|
701
|
+
logger.log.exception(msg)
|
|
702
|
+
sys.exit(1)
|
|
703
|
+
else:
|
|
704
|
+
if self.table.selectionModel().hasSelection():
|
|
705
|
+
indices = [
|
|
706
|
+
QtCore.QPersistentModelIndex(index)
|
|
707
|
+
for index in self.table.selectionModel().selectedIndexes()
|
|
708
|
+
]
|
|
709
|
+
for index in indices:
|
|
710
|
+
item = self.table.cellWidget(index.row(), 1)
|
|
711
|
+
text = item.text()
|
|
712
|
+
todo = settings.db.todo_index(text)
|
|
713
|
+
del settings.db.todo_lists[settings.db.active_list][todo]
|
|
714
|
+
settings.db.todo_count -= 1
|
|
715
|
+
settings.db.todo_total -= 1
|
|
716
|
+
self.write_todo_data()
|
|
717
|
+
self.table.removeRow(index.row())
|
|
718
|
+
self.refresh()
|
|
719
|
+
else:
|
|
720
|
+
QtWidgets.QMessageBox.warning(
|
|
721
|
+
self, "Delete To-Do", "No reminders selected."
|
|
722
|
+
)
|
|
723
|
+
|
|
724
|
+
@error_on_none_db
|
|
725
|
+
def toggle_todo(self, *args, **kwargs):
|
|
726
|
+
"""Toggle a to-do complete / incomplete."""
|
|
727
|
+
self.update_progress_bar(0)
|
|
728
|
+
|
|
729
|
+
for index in self.table.selectedIndexes():
|
|
730
|
+
item = self.table.cellWidget(index.row(), 1)
|
|
731
|
+
text = item.text()
|
|
732
|
+
todo = settings.db.todo_index(text)
|
|
733
|
+
if not settings.db.todo_lists[settings.db.active_list][todo]["complete"]:
|
|
734
|
+
settings.db.todo_lists[settings.db.active_list][todo]["complete"] = True
|
|
735
|
+
else:
|
|
736
|
+
settings.db.todo_lists[settings.db.active_list][todo][
|
|
737
|
+
"complete"
|
|
738
|
+
] = False
|
|
739
|
+
self.write_todo_data()
|
|
740
|
+
self.refresh()
|
|
741
|
+
|
|
742
|
+
@error_on_none_db
|
|
743
|
+
def change_priority(self, *args, **kwargs):
|
|
744
|
+
"""Change a to-do's priority."""
|
|
745
|
+
for index in self.table.selectedIndexes():
|
|
746
|
+
item_p = self.table.cellWidget(index.row(), 0)
|
|
747
|
+
item_r = self.table.cellWidget(index.row(), 1)
|
|
748
|
+
|
|
749
|
+
text = item_p.currentText()
|
|
750
|
+
if text == "Low":
|
|
751
|
+
priority = 3
|
|
752
|
+
elif text == "Normal":
|
|
753
|
+
priority = 2
|
|
754
|
+
else:
|
|
755
|
+
priority = 1
|
|
756
|
+
|
|
757
|
+
reminder = item_r.text()
|
|
758
|
+
todo = settings.db.todo_index(reminder)
|
|
759
|
+
settings.db.todo_lists[settings.db.active_list][todo]["priority"] = priority
|
|
760
|
+
self.write_todo_data()
|
|
761
|
+
self.refresh()
|
|
762
|
+
|
|
763
|
+
@error_on_none_db
|
|
764
|
+
def edit_reminder(self, *args, **kwargs):
|
|
765
|
+
"""Edit the reminder of a to-do."""
|
|
766
|
+
for index in self.table.selectedIndexes():
|
|
767
|
+
item = self.table.cellWidget(index.row(), 1)
|
|
768
|
+
new_text = item.text()
|
|
769
|
+
settings.db.todo_lists[settings.db.active_list][index.row()][
|
|
770
|
+
"reminder"
|
|
771
|
+
] = new_text
|
|
772
|
+
self.write_todo_data()
|
|
773
|
+
|
|
774
|
+
def about_todo(self):
|
|
775
|
+
"""Display a message box with Program/Author information."""
|
|
776
|
+
text = """<b><u>To-Do v0.2.0</u></b>
|
|
777
|
+
<br><br>To-Do list program that works with multiple To-Do
|
|
778
|
+
lists locally and over a network.
|
|
779
|
+
<br><br>License: <a href="http://www.fsf.org/licenses/gpl.html">GPLv3</a>
|
|
780
|
+
<br><br><b>Copyright (C) 2024 Michael Berry</b>
|
|
781
|
+
"""
|
|
782
|
+
QtWidgets.QMessageBox.about(self, "About To-Do", text)
|
|
783
|
+
|
|
784
|
+
def about_qt(self):
|
|
785
|
+
"""Display information about Qt."""
|
|
786
|
+
QtWidgets.QMessageBox.aboutQt(self, "About Qt")
|
|
787
|
+
|
|
788
|
+
def center(self):
|
|
789
|
+
"""Place the main window in the center of the screen."""
|
|
790
|
+
qt_rectangle = self.frameGeometry()
|
|
791
|
+
center_point = QtWidgets.QDesktopWidget().availableGeometry().center()
|
|
792
|
+
qt_rectangle.moveCenter(center_point)
|
|
793
|
+
self.move(qt_rectangle.topLeft())
|
|
794
|
+
|
|
795
|
+
@error_on_none_db
|
|
796
|
+
def update_progress_bar(self, value=None, *args, **kwargs):
|
|
797
|
+
"""Update the progress bar.
|
|
798
|
+
|
|
799
|
+
Maximum value should be set to the total to-do count,
|
|
800
|
+
while value should be the number of completed todos.
|
|
801
|
+
This makes the progress bar show the total percentage
|
|
802
|
+
of completed to-dos.
|
|
803
|
+
"""
|
|
804
|
+
if value is None:
|
|
805
|
+
return
|
|
806
|
+
|
|
807
|
+
i = 0
|
|
808
|
+
|
|
809
|
+
for list_entry in settings.db.todo_lists:
|
|
810
|
+
for todo in settings.db.todo_lists[list_entry]:
|
|
811
|
+
if todo["complete"]:
|
|
812
|
+
i += 1
|
|
813
|
+
|
|
814
|
+
value = i
|
|
815
|
+
|
|
816
|
+
self.progressBar.reset()
|
|
817
|
+
self.progressBar.setMaximum(settings.db.todo_total)
|
|
818
|
+
self.progressBar.setValue(value)
|
|
819
|
+
|
|
820
|
+
@error_on_none_db
|
|
821
|
+
def update_status_bar(self, msg="Ready", *args, **kwargs):
|
|
822
|
+
"""Update the status bar, display some statistics."""
|
|
823
|
+
if settings.db.server_running():
|
|
824
|
+
server_status = (
|
|
825
|
+
f"Up on {settings.options['address']}: {settings.options['port']}"
|
|
826
|
+
)
|
|
827
|
+
else:
|
|
828
|
+
server_status = "Down"
|
|
829
|
+
|
|
830
|
+
# create our status bar text
|
|
831
|
+
text = f"Lists: {settings.db.list_count} Shown: {settings.db.active_list} To-Do's: {settings.db.todo_count} of {settings.db.todo_total} Status: {msg} Server: {server_status}"
|
|
832
|
+
|
|
833
|
+
self.statusBarLabel.setText(text)
|
|
834
|
+
|
|
835
|
+
@error_on_none_db
|
|
836
|
+
def refresh(self, *args, **kwargs):
|
|
837
|
+
"""Redraw the table and update the progress and status bars."""
|
|
838
|
+
self.update_status_bar("Redrawing table")
|
|
839
|
+
|
|
840
|
+
# clear the table
|
|
841
|
+
self.table.setRowCount(0)
|
|
842
|
+
|
|
843
|
+
# set the table headers
|
|
844
|
+
self.table.setHorizontalHeaderLabels(["Priority", "Reminder"])
|
|
845
|
+
|
|
846
|
+
# make sure we have a valid active list
|
|
847
|
+
if settings.db.active_list not in settings.db.todo_lists:
|
|
848
|
+
self.update_status_bar()
|
|
849
|
+
return
|
|
850
|
+
|
|
851
|
+
# add each to-do in the list to the table, show a progress bar
|
|
852
|
+
i = 0
|
|
853
|
+
settings.db.sort_active_list()
|
|
854
|
+
|
|
855
|
+
# update the progress bar
|
|
856
|
+
self.update_progress_bar(0)
|
|
857
|
+
|
|
858
|
+
for todo in settings.db.todo_lists[settings.db.active_list]:
|
|
859
|
+
# create priority table item
|
|
860
|
+
item_p = QtWidgets.QComboBox(self)
|
|
861
|
+
item_p.addItems(["Low", "Normal", "High"])
|
|
862
|
+
item_p.currentIndexChanged.connect(self.change_priority)
|
|
863
|
+
if todo["priority"] == 1:
|
|
864
|
+
item_p.setCurrentIndex(2)
|
|
865
|
+
elif todo["priority"] == 2:
|
|
866
|
+
item_p.setCurrentIndex(1)
|
|
867
|
+
else:
|
|
868
|
+
item_p.setCurrentIndex(0)
|
|
869
|
+
|
|
870
|
+
# create reminder table item
|
|
871
|
+
item_r = QtWidgets.QLineEdit(todo["reminder"])
|
|
872
|
+
item_r.returnPressed.connect(self.edit_reminder)
|
|
873
|
+
|
|
874
|
+
# set the font
|
|
875
|
+
if todo["complete"] is True:
|
|
876
|
+
item_r.setFont(self.complete_font)
|
|
877
|
+
else:
|
|
878
|
+
item_r.setFont(self.normal_font)
|
|
879
|
+
|
|
880
|
+
# put the items in the table
|
|
881
|
+
row_count = self.table.rowCount()
|
|
882
|
+
assert row_count == i
|
|
883
|
+
self.table.insertRow(i)
|
|
884
|
+
self.table.setCellWidget(i, 0, item_p)
|
|
885
|
+
self.table.setCellWidget(i, 1, item_r)
|
|
886
|
+
i += 1
|
|
887
|
+
|
|
888
|
+
# update the database todo_count
|
|
889
|
+
settings.db.todo_count = len(settings.db.todo_lists[settings.db.active_list])
|
|
890
|
+
settings.db.list_count = len(settings.db.todo_lists.keys())
|
|
891
|
+
|
|
892
|
+
# update progress and status bars
|
|
893
|
+
self.update_progress_bar()
|
|
894
|
+
self.update_status_bar()
|
|
895
|
+
|
|
896
|
+
def tray_event(self, reason=QtWidgets.QSystemTrayIcon.activated, *args, **kwargs):
|
|
897
|
+
"""Hide the main window when the system tray icon is clicked."""
|
|
898
|
+
if reason == QtWidgets.QSystemTrayIcon.activated:
|
|
899
|
+
if self.isVisible():
|
|
900
|
+
self.hide()
|
|
901
|
+
else:
|
|
902
|
+
self.show()
|
|
903
|
+
|
|
904
|
+
@error_on_none_db
|
|
905
|
+
def closeEvent(self, event, *args, **kwargs):
|
|
906
|
+
"""Take care of clean up details."""
|
|
907
|
+
# save configuration
|
|
908
|
+
result, msg = settings.db.write_config()
|
|
909
|
+
if not result:
|
|
910
|
+
QtWidgets.QMessageBox.warning(self, "Write Error", msg)
|
|
911
|
+
|
|
912
|
+
# save todo lists
|
|
913
|
+
self.write_todo_data()
|
|
914
|
+
|
|
915
|
+
# shutdown database network server
|
|
916
|
+
if settings.db.server_running():
|
|
917
|
+
settings.db.net_server.shutdown()
|
|
918
|
+
|
|
919
|
+
# hide the tray icon
|
|
920
|
+
self.tray_icon.hide()
|
|
921
|
+
|
|
922
|
+
logger.log.info("Closing main window, quitting application")
|
|
923
|
+
|
|
924
|
+
# close the window
|
|
925
|
+
event.accept()
|