summaryrefslogtreecommitdiff
path: root/src/main.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.py')
-rw-r--r--src/main.py295
1 files changed, 295 insertions, 0 deletions
diff --git a/src/main.py b/src/main.py
new file mode 100644
index 0000000..dfdf8a7
--- /dev/null
+++ b/src/main.py
@@ -0,0 +1,295 @@
+#!/usr/bin/python3
+import sys
+import time
+from PyQt5.QtWidgets import QAction, QApplication, QGridLayout, QHBoxLayout, QLabel, QMainWindow, QMenu, QMessageBox, QScrollArea, QToolBar, QVBoxLayout, QWidget
+from PyQt5.QtGui import QCursor, QFont
+from PyQt5.QtCore import QDate, Qt
+from src.config import Config
+from src.preferences_dialog import PreferencesDialog
+from src.add_group_form import addGroupForm
+from src.edit_group_form import editGroupForm
+from src.add_entry_form import addEntryForm
+from src.edit_entry_form import editEntryForm
+import src.globals as Globals
+import src.db_sqlite as DB
+
+class AssignmentList(QMainWindow):
+ def __init__(self):
+ super().__init__()
+
+ self.initializeUI()
+
+ def initializeUI(self):
+ self.resize(640, 480)
+ self.setWindowTitle("Assignment List")
+ self.createMenu()
+ self.createToolbar()
+ Config()
+ self.setupDB()
+ self.displayWidgets()
+ self.show()
+
+ def createMenu(self):
+ menu_bar = self.menuBar()
+ file_menu = menu_bar.addMenu("File")
+ edit_menu = menu_bar.addMenu("Edit")
+ help_menu = menu_bar.addMenu("Help")
+
+ self.preferences_act = QAction("Preferences", self)
+ self.preferences_act.setShortcut("Alt+Return")
+ self.preferences_act.triggered.connect(PreferencesDialog)
+ file_menu.addAction(self.preferences_act)
+ # TODO implement reload of DB that works
+ self.reload_act = QAction("Reload [WIP]", self)
+ self.reload_act.setShortcut("F5")
+ #self.reload_act.triggered.connect(self.reload)
+ file_menu.addAction(self.reload_act)
+ file_menu.addSeparator()
+ exit_act = QAction("Exit", self)
+ exit_act.setShortcut("Ctrl+Q")
+ exit_act.triggered.connect(self.close)
+ file_menu.addAction(exit_act)
+
+ self.add_group_act = QAction("Add Group", self)
+ self.add_group_act.triggered.connect(self.addGroup)
+ edit_menu.addAction(self.add_group_act)
+ edit_menu.addSeparator()
+ self.clean_hidden_act = QAction("Permanently Delete Removed Groups and Entries", self)
+ self.clean_hidden_act.triggered.connect(self.cleanHidden)
+ edit_menu.addAction(self.clean_hidden_act)
+
+ about_act = QAction("About", self)
+ about_act.triggered.connect(self.aboutDialog)
+ help_menu.addAction(about_act)
+
+ def createToolbar(self):
+ tool_bar = QToolBar("Toolbar")
+ self.addToolBar(tool_bar)
+
+ tool_bar.addAction(self.add_group_act)
+
+ def setupDB(self):
+ DB.initDB()
+
+ def displayWidgets(self):
+ main_widget_scroll_area = QScrollArea(self)
+ main_widget_scroll_area.setWidgetResizable(True)
+ main_widget = QWidget()
+ self.setCentralWidget(main_widget_scroll_area)
+
+ title = QLabel(time.strftime("%A, %b %d %Y"))
+ title.setFont(QFont("Arial", 17))
+ title.setTextInteractionFlags(Qt.TextSelectableByMouse)
+
+ title_h_box = QHBoxLayout()
+ title_h_box.addStretch()
+ title_h_box.addWidget(title)
+ title_h_box.addStretch()
+
+ self.groups_layout = QGridLayout()
+ self.groups_layout.setContentsMargins(20, 5, 20, 5)
+ self.drawGroups()
+
+ v_box = QVBoxLayout()
+ v_box.addLayout(title_h_box)
+ v_box.addLayout(self.groups_layout)
+ v_box.addStretch()
+
+ main_widget.setLayout(v_box)
+ main_widget_scroll_area.setWidget(main_widget)
+
+ def addGroup(self):
+ """
+ Open the 'addGroup' form
+ """
+ old_count = len(Globals.groups)
+ self.create_new_group_dialog = addGroupForm()
+ if old_count != len(Globals.groups):
+ self.drawGroups()
+
+ def editGroup(self, id):
+ """
+ Open the 'editGroup' form
+ """
+ self.create_edit_group_dialog = editGroupForm(id)
+ self.drawGroups()
+
+ def removeGroup(self, id):
+ """
+ Delete a group with a given id
+ """
+ # TODO might want to add a warning
+ # TODO might want to make part of the a destructor in the Group class
+ removed = DB.removeGroup(id)
+ if removed > 0:
+ Globals.entries = list(filter(lambda e: e.parent_id != id, Globals.entries))
+ Globals.groups = list(filter(lambda g: g.id != id, Globals.groups))
+ self.drawGroups()
+
+ def groupContextMenu(self, group_id):
+ menu = QMenu()
+
+ add_entry_act = QAction("Add Entry")
+ add_entry_act.triggered.connect((lambda id: lambda: self.addEntry(id))(group_id))
+ menu.addAction(add_entry_act)
+
+ edit_group_act = QAction("Edit Group")
+ edit_group_act.triggered.connect((lambda id: lambda: self.editGroup(id))(group_id))
+ menu.addAction(edit_group_act)
+
+ del_group_act = QAction("Remove Group")
+ del_group_act.triggered.connect((lambda id: lambda: self.removeGroup(id))(group_id))
+ menu.addAction(del_group_act)
+
+ menu.exec_(QCursor.pos())
+
+ def addEntry(self, parent):
+ """
+ Open the 'addEntry' form
+ """
+ old_count = len(Globals.entries)
+ self.create_new_entry_dialog = addEntryForm(parent)
+ if old_count != len(Globals.entries):
+ self.drawGroups() # TODO see if we can do this with only redrawing a single group
+
+ def editEntry(self, id):
+ """
+ Open the 'editEntry' form
+ """
+ self.create_edit_entry_dialog = editEntryForm(id)
+ self.drawGroups()
+
+ def toggleDoneEntry(self, id):
+ """
+ Toggle the 'done' flag on the entry with the given id
+ """
+ entry = list(filter(lambda e: e.id == id, Globals.entries))[0]
+ if entry.done:
+ entry.done = False
+ else:
+ entry.done = True
+ DB.updateEntry(entry)
+ Globals.entries = list(filter(lambda e: e.id != id, Globals.entries))
+ Globals.entries.append(entry)
+ self.drawGroups()
+
+ def removeEntry(self, id):
+ """
+ Delete an entry with a given id
+ """
+ # TODO might want to add a warning
+ # TODO might want to make part of the a destructor in the Entry class
+ removed = DB.removeEntry(id)
+ if removed > 0:
+ Globals.entries = list(filter(lambda e: e.id != id, Globals.entries))
+ self.drawGroups()
+
+ def entryContextMenu(self, entry_id):
+ menu = QMenu()
+
+ edit_entry_act = QAction("Edit Entry")
+ edit_entry_act.triggered.connect((lambda id: lambda: self.editEntry(id))(entry_id))
+ menu.addAction(edit_entry_act)
+
+ mark_done_act = QAction("Done", checkable=True)
+ if list(filter(lambda e: e.id == entry_id, Globals.entries))[0].done:
+ mark_done_act.setChecked(True)
+ mark_done_act.triggered.connect((lambda id: lambda: self.toggleDoneEntry(id))(entry_id))
+ menu.addAction(mark_done_act)
+
+ del_entry_act = QAction("Remove Entry")
+ del_entry_act.triggered.connect((lambda id: lambda: self.removeEntry(id))(entry_id))
+ menu.addAction(del_entry_act)
+
+ menu.exec_(QCursor.pos())
+
+ def cleanHidden(self):
+ """
+ Permanently delete removed groups and entries from db
+ """
+ # TODO consider creating a warning dialogue for this
+ DB.cleanHidden()
+
+ def drawGroups(self):
+ """
+ Redraw the groups_layout
+ """
+ # Remove all children from layout
+ def recursiveClear(layout):
+ while layout.count():
+ child = layout.takeAt(0)
+ if child.widget():
+ child.widget().deleteLater()
+ elif child.layout():
+ recursiveClear(child)
+
+ recursiveClear(self.groups_layout)
+
+ # Sort the groups
+ Globals.groups = sorted(Globals.groups, key=lambda g: g.id)
+
+ # Sort the entries
+ Globals.entries = sorted(Globals.entries, key=lambda e: (e.parent_id, (e.due if e.due else QDate.currentDate()), e.done, e.id))
+
+ # Create columns as vertical boxes
+ column_left = QVBoxLayout()
+ column_right = QVBoxLayout()
+
+ for g in Globals.groups:
+ # skip if this group is set to hidden
+ if g.hidden:
+ continue
+
+ g_layout = g.buildLayout()
+
+ # Create custom context menu
+ g_layout.itemAt(0).widget().setToolTip("Right-Click for actions")
+ g_layout.itemAt(0).widget().setContextMenuPolicy(Qt.CustomContextMenu)
+ g_layout.itemAt(0).widget().customContextMenuRequested.connect((lambda id: lambda: self.groupContextMenu(id))(g.id))
+
+ # Draw entries belonging to this group
+ g_layout.addLayout(self.drawEntries(g.id))
+
+ if g.column.lower() == "left":
+ column_left.addLayout(g_layout)
+ else:
+ column_right.addLayout(g_layout)
+
+ column_left.addStretch()
+ column_right.addStretch()
+
+ self.groups_layout.addLayout(column_left, 0, 0)
+ self.groups_layout.addLayout(column_right, 0, 1)
+
+ def drawEntries(self, group_id):
+ """
+ Redraw the entries of a specific group
+ """
+ # TODO consider having code to remove existing widgets to make this function more modular
+ entries = list(filter(lambda e: e.parent_id == group_id, Globals.entries))
+ entries_vbox = QVBoxLayout()
+ entries_vbox.setContentsMargins(5, 0, 0, 0)
+
+ for e in entries:
+ # skip if this entry is set to hidden
+ if e.hidden:
+ continue
+
+ e_layout = e.buildLayout()
+ entries_vbox.addLayout(e_layout)
+
+ # Create custom context menu
+ e_layout.itemAt(1).widget().setContextMenuPolicy(Qt.CustomContextMenu)
+ e_layout.itemAt(1).widget().customContextMenuRequested.connect((lambda id: lambda: self.entryContextMenu(id))(e.id))
+
+ return entries_vbox
+
+ def aboutDialog(self):
+ QMessageBox.about(self, "About Assignment List",
+ "Created by Louie S. - 2023")
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ window = AssignmentList()
+ sys.exit(app.exec_())
+