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/crypto/AESCipher.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""AESCipher.py
|
|
2
|
+
|
|
3
|
+
AES Cipher class for encrypting and decrypting string data.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import base64
|
|
7
|
+
import hashlib
|
|
8
|
+
|
|
9
|
+
from Cryptodome.Cipher import AES
|
|
10
|
+
from Cryptodome.Random import get_random_bytes
|
|
11
|
+
from Cryptodome.Util.Padding import pad, unpad
|
|
12
|
+
|
|
13
|
+
from todo.core.Logger import Logger
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
logger = Logger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def catch_value_error_exception(func):
|
|
20
|
+
"""Catch ValueError exceptions."""
|
|
21
|
+
|
|
22
|
+
def wrapper(*args, **kwargs):
|
|
23
|
+
"""Wrap around func and catch ValueError exceptions."""
|
|
24
|
+
try:
|
|
25
|
+
result = func(*args, **kwargs)
|
|
26
|
+
return result
|
|
27
|
+
except ValueError as e:
|
|
28
|
+
logger.log.exception(f"AESCipher error: {e}")
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
return wrapper
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class AESCipher:
|
|
35
|
+
"""Implement AES Cipher Block Chaining encryption and decryption."""
|
|
36
|
+
|
|
37
|
+
def __init__(self, key: str) -> None:
|
|
38
|
+
"""Make a fixed sha256 bit length key."""
|
|
39
|
+
self.key = hashlib.sha256(key.encode("utf-8")).digest()
|
|
40
|
+
|
|
41
|
+
@catch_value_error_exception
|
|
42
|
+
def encrypt(self, raw_data: str) -> bytes:
|
|
43
|
+
"""Encrypt raw data."""
|
|
44
|
+
logger.log.info("AESCipher: Encrypting data")
|
|
45
|
+
encoded_data = pad(raw_data.encode("utf-8"), AES.block_size)
|
|
46
|
+
iv = get_random_bytes(AES.block_size)
|
|
47
|
+
cipher = AES.new(self.key, AES.MODE_CBC, iv)
|
|
48
|
+
return base64.b64encode(iv + cipher.encrypt(encoded_data))
|
|
49
|
+
|
|
50
|
+
@catch_value_error_exception
|
|
51
|
+
def decrypt(self, encrypted_data: bytes) -> bytes:
|
|
52
|
+
"""Decrypt encoded data."""
|
|
53
|
+
logger.log.info("AESCipher: decrypting data")
|
|
54
|
+
decoded_data = base64.b64decode(encrypted_data)
|
|
55
|
+
iv = decoded_data[: AES.block_size]
|
|
56
|
+
cipher = AES.new(self.key, AES.MODE_CBC, iv)
|
|
57
|
+
return unpad(cipher.decrypt(decoded_data[AES.block_size :]), AES.block_size)
|
todo/crypto/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""AddTodoDialog.py
|
|
2
|
+
|
|
3
|
+
Simple dialog to create a to-do.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from PyQt5 import QtWidgets
|
|
7
|
+
|
|
8
|
+
from todo.core import error_on_none_db, settings
|
|
9
|
+
from todo.core.Logger import Logger
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
logger = Logger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class AddTodoDialog(QtWidgets.QDialog):
|
|
16
|
+
"""Create a new to-do."""
|
|
17
|
+
|
|
18
|
+
def __init__(self):
|
|
19
|
+
"""Create a simple dialog.
|
|
20
|
+
|
|
21
|
+
Get enough information to create a new to-do.
|
|
22
|
+
"""
|
|
23
|
+
logger.log.info("Creating an add to-do dialog")
|
|
24
|
+
|
|
25
|
+
super().__init__()
|
|
26
|
+
|
|
27
|
+
# reminder
|
|
28
|
+
reminder_label = QtWidgets.QLabel("Reminder", self)
|
|
29
|
+
self.reminder_field = QtWidgets.QLineEdit(self)
|
|
30
|
+
|
|
31
|
+
# priority
|
|
32
|
+
priority_label = QtWidgets.QLabel("Priority", self)
|
|
33
|
+
self.priority_field = QtWidgets.QComboBox(self)
|
|
34
|
+
self.priority_field.addItems(["Low", "Normal", "High"])
|
|
35
|
+
|
|
36
|
+
# add button
|
|
37
|
+
self.add_button = QtWidgets.QPushButton("Add to-do", self)
|
|
38
|
+
self.add_button.clicked.connect(self.get_todo)
|
|
39
|
+
|
|
40
|
+
# create a vertical box layout
|
|
41
|
+
v_box = QtWidgets.QVBoxLayout()
|
|
42
|
+
v_box.addWidget(reminder_label)
|
|
43
|
+
v_box.addWidget(self.reminder_field)
|
|
44
|
+
v_box.addWidget(priority_label)
|
|
45
|
+
v_box.addWidget(self.priority_field)
|
|
46
|
+
v_box.addWidget(self.add_button)
|
|
47
|
+
|
|
48
|
+
# set layout and window title
|
|
49
|
+
self.setLayout(v_box)
|
|
50
|
+
self.setWindowTitle("Add New to-do")
|
|
51
|
+
self.setMinimumWidth(500)
|
|
52
|
+
|
|
53
|
+
logger.log.info("Add to-do dialog created")
|
|
54
|
+
|
|
55
|
+
@error_on_none_db
|
|
56
|
+
def get_todo(self):
|
|
57
|
+
"""Get to-do information and append it to the current list."""
|
|
58
|
+
reminder = self.reminder_field.text()
|
|
59
|
+
if reminder == "":
|
|
60
|
+
QtWidgets.QMessageBox.information(
|
|
61
|
+
self, "Empty reminder", "Reminder cannot be empty"
|
|
62
|
+
)
|
|
63
|
+
return
|
|
64
|
+
|
|
65
|
+
# get to-do information
|
|
66
|
+
todo = {"complete": False, "reminder": reminder}
|
|
67
|
+
priority = self.priority_field.currentText()
|
|
68
|
+
if priority == "High":
|
|
69
|
+
todo["priority"] = 1
|
|
70
|
+
elif priority == "Normal":
|
|
71
|
+
todo["priority"] = 2
|
|
72
|
+
else:
|
|
73
|
+
todo["priority"] = 3
|
|
74
|
+
|
|
75
|
+
# update the database
|
|
76
|
+
if settings.db.todo_lists is not None and settings.db.active_list is not None:
|
|
77
|
+
settings.db.todo_lists[settings.db.active_list].append(todo)
|
|
78
|
+
settings.db.todo_count += 1
|
|
79
|
+
settings.db.todo_total += 1
|
|
80
|
+
else:
|
|
81
|
+
logger.log.exception(
|
|
82
|
+
"Error: settings.db.todo_list or setting.db.active list does not exist, exiting"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
logger.log.info(f"New to-do created: {todo}")
|
|
86
|
+
|
|
87
|
+
self.accept()
|