summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLouie Shprung <lshprung@scu.edu>2023-12-21 13:17:39 -0800
committerLouie Shprung <lshprung@scu.edu>2023-12-21 13:17:39 -0800
commit65d8cbafe34b946d450ce46703e6449eb9962741 (patch)
tree9cb2bfa4857507207e8740478e5d23d4421ad784 /src
parent11373742d701166f2580cfe67015eac012cda1a9 (diff)
Rename src directory to unique name to avoid install issues
Diffstat (limited to 'src')
-rw-r--r--src/__init__.py0
-rw-r--r--src/add_entry_form.py51
-rw-r--r--src/add_entry_form.ui185
-rw-r--r--src/add_group_form.py47
-rw-r--r--src/add_group_form.ui131
-rw-r--r--src/config.py95
-rw-r--r--src/db_sqlite.py493
-rw-r--r--src/edit_entry_form.py83
-rw-r--r--src/edit_group_form.py63
-rw-r--r--src/entry.py100
-rw-r--r--src/globals.py4
-rw-r--r--src/group.py25
-rw-r--r--src/main.py273
-rw-r--r--src/main.ui207
-rw-r--r--src/preferences_dialog.py70
-rw-r--r--src/preferences_dialog.ui128
-rw-r--r--src/rule.py44
-rw-r--r--src/rules_dialog.py128
18 files changed, 0 insertions, 2127 deletions
diff --git a/src/__init__.py b/src/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/src/__init__.py
+++ /dev/null
diff --git a/src/add_entry_form.py b/src/add_entry_form.py
deleted file mode 100644
index 9a2d260..0000000
--- a/src/add_entry_form.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import os
-import sys
-from PyQt5 import uic
-from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox
-from PyQt5.QtCore import QDate
-from src.entry import Entry
-import src.globals as Globals
-import src.db_sqlite as DB
-
-class addEntryForm(QDialog):
- def __init__(self, parent):
- super().__init__()
- uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)),
- "add_entry_form.ui"), self)
- self.initializeUI(parent)
-
- def initializeUI(self, parent):
- self.displayWidgets(parent)
- self.exec()
-
- def displayWidgets(self, parent):
- self.new_entry_due.setDate(QDate.currentDate())
- self.buttonBox.rejected.connect(self.close)
- self.buttonBox.accepted.connect(lambda: self.handleSubmit(parent))
-
- def handleSubmit(self, parent):
- # Check that the new entry is not blank
- desc_text = self.new_entry_desc.text()
- due_text = ""
- if self.new_entry_due_checkbox.isChecked():
- due_text = self.new_entry_due.date() # due_text is a QDate
- due_alt_text = self.new_entry_due_alt.text()
- link_text = self.new_entry_link.text()
- color_text = self.new_entry_color.text()
- highlight_text = self.new_entry_highlight.text()
-
- if not desc_text:
- QMessageBox.warning(self, "Error Message",
- "Description cannot be blank",
- QMessageBox.Close,
- QMessageBox.Close)
- return
-
- new_id = DB.insertEntry(Entry(0, parent, desc_text, due_text, due_alt_text, link_text, color_text, highlight_text))
- Globals.entries.append(Entry(new_id, parent, desc_text, due_text, due_alt_text, link_text, color_text, highlight_text))
- self.close()
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = addEntryForm()
- sys.exit(app.exec_())
diff --git a/src/add_entry_form.ui b/src/add_entry_form.ui
deleted file mode 100644
index 3f8f9e7..0000000
--- a/src/add_entry_form.ui
+++ /dev/null
@@ -1,185 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>Dialog</class>
- <widget class="QDialog" name="Dialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>400</width>
- <height>266</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Add Entry</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QFormLayout" name="formLayout">
- <item row="1" column="0">
- <widget class="QLabel" name="descriptionLabel">
- <property name="text">
- <string>Description: </string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="new_entry_desc"/>
- </item>
- <item row="0" column="0" colspan="2">
- <widget class="QLabel" name="title">
- <property name="font">
- <font>
- <family>Arial</family>
- <pointsize>18</pointsize>
- </font>
- </property>
- <property name="text">
- <string>Add Entry</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="dueDateLabel">
- <property name="text">
- <string>Due Date: </string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QWidget" name="due_hbox" native="true">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QDateTimeEdit" name="new_entry_due">
- <property name="displayFormat">
- <string>MM/dd/yyyy</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QCheckBox" name="new_entry_due_checkbox">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="dueDateAltLabel">
- <property name="text">
- <string>Due Date (Alt):</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLineEdit" name="new_entry_due_alt"/>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="linkLabel">
- <property name="text">
- <string>Link:</string>
- </property>
- </widget>
- </item>
- <item row="4" column="1">
- <widget class="QLineEdit" name="new_entry_link"/>
- </item>
- <item row="5" column="0">
- <widget class="QLabel" name="colorLabel">
- <property name="text">
- <string>Color:</string>
- </property>
- </widget>
- </item>
- <item row="5" column="1">
- <widget class="QLineEdit" name="new_entry_color"/>
- </item>
- <item row="6" column="0">
- <widget class="QLabel" name="highlightLabel">
- <property name="text">
- <string>Highlight:</string>
- </property>
- </widget>
- </item>
- <item row="6" column="1">
- <widget class="QLineEdit" name="new_entry_highlight"/>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="layoutDirection">
- <enum>Qt::RightToLeft</enum>
- </property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
- </property>
- <property name="centerButtons">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections>
- <connection>
- <sender>buttonBox</sender>
- <signal>accepted()</signal>
- <receiver>Dialog</receiver>
- <slot>accept()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>248</x>
- <y>254</y>
- </hint>
- <hint type="destinationlabel">
- <x>157</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>buttonBox</sender>
- <signal>rejected()</signal>
- <receiver>Dialog</receiver>
- <slot>reject()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>316</x>
- <y>260</y>
- </hint>
- <hint type="destinationlabel">
- <x>286</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- </connections>
-</ui>
diff --git a/src/add_group_form.py b/src/add_group_form.py
deleted file mode 100644
index 4a543e4..0000000
--- a/src/add_group_form.py
+++ /dev/null
@@ -1,47 +0,0 @@
-import os
-import sys
-from PyQt5 import uic
-from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox
-
-import src.globals as Globals
-from src.group import Group
-import src.db_sqlite as DB
-
-class addGroupForm(QDialog):
- """
- Implemented so that it can be used for adding and editing groups
- """
- def __init__(self):
- super().__init__()
- uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)),
- "add_group_form.ui"), self)
- self.initializeUI()
-
- def initializeUI(self):
- self.displayWidgets()
- self.exec()
-
- def displayWidgets(self):
- self.buttonBox.rejected.connect(self.close)
- self.buttonBox.accepted.connect(self.handleSubmit)
-
- def handleSubmit(self):
- name_text = self.new_group_name.text()
- column_text = self.new_group_column.currentText()
- link_text = self.new_group_link.text()
-
- if not name_text:
- QMessageBox.warning(self, "Error Message",
- "Name cannot be blank",
- QMessageBox.Close,
- QMessageBox.Close)
- return
-
- new_id = DB.insertGroup(Group(0, name_text, column_text, link_text))
- Globals.groups.append(Group(new_id, name_text, column_text, link_text))
- self.close()
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = addGroupForm()
- sys.exit(app.exec_())
diff --git a/src/add_group_form.ui b/src/add_group_form.ui
deleted file mode 100644
index c3c5c80..0000000
--- a/src/add_group_form.ui
+++ /dev/null
@@ -1,131 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>Dialog</class>
- <widget class="QDialog" name="Dialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>400</width>
- <height>172</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Add Entry</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QFormLayout" name="formLayout">
- <item row="0" column="0" colspan="2">
- <widget class="QLabel" name="title">
- <property name="font">
- <font>
- <family>Arial</family>
- <pointsize>18</pointsize>
- </font>
- </property>
- <property name="text">
- <string>Add Group</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="descriptionLabel">
- <property name="text">
- <string>Name:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="new_group_name"/>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="dueDateLabel">
- <property name="text">
- <string>Column:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QComboBox" name="new_group_column">
- <item>
- <property name="text">
- <string>Left</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>Right</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="linkLabel">
- <property name="text">
- <string>Link:</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLineEdit" name="new_group_link"/>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="layoutDirection">
- <enum>Qt::RightToLeft</enum>
- </property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
- </property>
- <property name="centerButtons">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections>
- <connection>
- <sender>buttonBox</sender>
- <signal>accepted()</signal>
- <receiver>Dialog</receiver>
- <slot>accept()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>248</x>
- <y>254</y>
- </hint>
- <hint type="destinationlabel">
- <x>157</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- <connection>
- <sender>buttonBox</sender>
- <signal>rejected()</signal>
- <receiver>Dialog</receiver>
- <slot>reject()</slot>
- <hints>
- <hint type="sourcelabel">
- <x>316</x>
- <y>260</y>
- </hint>
- <hint type="destinationlabel">
- <x>286</x>
- <y>274</y>
- </hint>
- </hints>
- </connection>
- </connections>
-</ui>
diff --git a/src/config.py b/src/config.py
deleted file mode 100644
index 0fa034e..0000000
--- a/src/config.py
+++ /dev/null
@@ -1,95 +0,0 @@
-"""
-Handle reading of the config file, which on POSIX-compliant systems will be
-created in ~/.config/assignment-list-pyqt5/config.py
-"""
-
-import configparser
-import os
-import sys
-
-import src.globals as Globals
-
-class Config():
- def __init__(self):
- self.config_path = self.getConfigPath()
-
- if not os.path.exists(self.config_path):
- self.createConfig()
-
- self.loadConfig()
-
- def getConfigPath(self):
- # Windows config path is "$LOCALAPPDATA/assignment-list-pyqt5/config"
- if sys.platform.startswith("win32"):
- return os.path.join(os.path.expandvars("$LOCALAPPDATA"),
- "assignment-list-pyqt5",
- "config")
- # Unix config path is "$HOME/.config/assignment-list-pyqt5/config"
- else:
- return os.path.join(
- os.path.expanduser("~"),
- ".config",
- "assignment-list-pyqt5",
- "config")
-
- def loadConfig(self):
- self.config = configparser.ConfigParser()
-
- try:
- self.config.read(self.config_path)
- except:
- print("Could not parse config file '{}'".format(self.config_path))
-
- if "paths" in self.config:
- if self.config["paths"]["db_path"]:
- Globals.db_path = self.config["paths"]["db_path"]
-
- def createConfig(self):
- self.config = configparser.ConfigParser()
- if sys.platform.startswith("win32"):
- self.config["paths"] = {
- # Windows default DB path is "$APPDATA/assignment-list-pyqt5/data.db"
- "db_path": os.path.join(
- os.path.expandvars("$APPDATA"),
- "assignment-list-pyqt5",
- "data.db"
- )
- }
- else:
- self.config["paths"] = {
- # Unix default DB path is "$HOME/.local/share/assignment-list-pyqt5/data.db"
- "db_path": os.path.join(
- os.path.expanduser("~"),
- ".local",
- "share",
- "assignment-list-pyqt5",
- "data.db"
- )
- }
-
- self.updateConfig()
-
- def updateConfig(self):
- """
- Update the configuration file with values from self.config
- """
- # Attempt to create directory if necessary
- if not os.path.exists(os.path.dirname(self.config_path)):
- try:
- os.mkdir(os.path.dirname(self.config_path))
- except:
- print("Error: Could not create config directory '{}'".format(os.path.dirname(self.config_path)))
- sys.exit(1)
-
- # Attempt to write to file
- try:
- with open(self.config_path, 'w') as configfile:
- self.config.write(configfile)
- except:
- print("Error: Could not open config file '{}'".format(self.config_path))
- sys.exit(1)
-
- print("Successfully created config at {}".format(self.config_path))
-
-if __name__ == "__main__":
- Config()
diff --git a/src/db_sqlite.py b/src/db_sqlite.py
deleted file mode 100644
index 00f4edb..0000000
--- a/src/db_sqlite.py
+++ /dev/null
@@ -1,493 +0,0 @@
-import os
-import sys
-from time import strptime
-from PyQt5.QtCore import QDate
-from PyQt5.QtSql import QSqlDatabase, QSqlQuery
-import src.globals as Globals
-from src.group import Group
-from src.entry import Entry
-from src.rule import Rule
-
-def initDB():
- """
- Check for existing database. If it doesn't exist, build it
- """
- if not os.path.exists(Globals.db_path) or not os.stat(Globals.db_path).st_size:
- createTables()
-
- loadFromTables()
-
-def createTables():
- """
- Create database at a specified Globals.db_path
- """
- print(Globals.db_path)
- database = QSqlDatabase.addDatabase("QSQLITE") # SQlite version 3
- database.setDatabaseName(Globals.db_path)
-
- # Create database parent directory if necessary
- if not os.path.exists(os.path.dirname(Globals.db_path)):
- try:
- os.mkdir(os.path.dirname(Globals.db_path))
- except:
- print("Unable to open data source file.")
- sys.exit(1)
-
- if not database.open():
- print("Unable to open data source file.")
- sys.exit(1) # Error out. TODO consider throwing a dialog instead
-
- query = QSqlQuery()
- # Erase database contents so that we don't have duplicates
- query.exec_("DROP TABLE groups")
- query.exec_("DROP TABLE entries")
- query.exec_("DROP TABLE rules")
-
- query.exec_("""
- CREATE TABLE groups (
- id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,
- name VARCHAR(255) NOT NULL,
- column TINYINT(1) DEFAULT FALSE,
- link VARCHAR(255) NOT NULL,
- hidden TINYINT(1) DEFAULT FALSE
- )
- """)
-
- query.exec_("""
- CREATE TABLE entries (
- id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,
- parent_id REFERENCES groups (id),
- description VARCHAR(255) NOT NULL,
- due_date TEXT DEFAULT NULL,
- alt_due_date VARCHAR(255) DEFAULT NULL,
- link VARCHAR(255) DEFAULT NULL,
- color VARCHAR(255) DEFAULT NULL,
- highlight VARCHAR(255) DEFAULT NULL,
- done TINYINT(1) DEFAULT FALSE,
- hidden TINYINT(1) DEFAULT FALSE
- )
- """)
-
- query.exec_("""
- CREATE TABLE rules (
- id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE NOT NULL,
- entry_id REFERENCES entries (id),
- before_after TINYINT(1) DEFAULT TRUE,
- date TEXT NOT NULL,
- color VARCHAR(255) DEFAULT NULL,
- highlight VARCHAR(255) DEFAULT NULL
- )
- """)
-
- print(database.lastError().text())
-
- database.close()
-
-def loadFromTables():
- """
- Load groups and entries into global variables
- """
- database = QSqlDatabase.addDatabase("QSQLITE") # SQlite version 3
- database.setDatabaseName(Globals.db_path)
-
- if not database.open():
- print("Unable to open data source file.")
- sys.exit(1) # Error out. TODO consider throwing a dialog instead
-
- query = QSqlQuery()
-
- # Load groups
- Globals.groups = [] # Reset local groups array
- query.exec_("SELECT * FROM groups")
- while query.next():
- record = query.record()
- Globals.groups.append(
- Group(
- record.field("id").value(),
- record.field("name").value(),
- record.field("column").value(),
- record.field("link").value(),
- record.field("hidden").value()))
-
- # Load entries
- Globals.entries = [] # Reset local entries array
- query.exec_("SELECT * FROM entries")
- while query.next():
- record = query.record()
- # create a QDate if the due date is set
- if record.field("due_date").value():
- due_date_struct = strptime(record.field("due_date").value(), "%Y-%m-%d")
- due_date = QDate(due_date_struct.tm_year, due_date_struct.tm_mon, due_date_struct.tm_mday)
- else:
- due_date = ""
- Globals.entries.append(
- Entry(
- record.field("id").value(),
- record.field("parent_id").value(),
- record.field("description").value(),
- due_date,
- record.field("alt_due_date").value(),
- record.field("link").value(),
- record.field("color").value(),
- record.field("highlight").value(),
- record.field("done").value(),
- record.field("hidden").value()))
-
- # Load rules
- Globals.rules = [] # Reset local rules array
- query.exec_("SELECT * FROM rules")
- while query.next():
- record = query.record()
- date_struct = strptime(record.field("date").value(), "%Y-%m-%d")
- date = QDate(date_struct.tm_year, date_struct.tm_mon, date_struct.tm_mday)
- Globals.rules.append(
- Rule(
- record.field("id").value(),
- record.field("entry_id").value(),
- "before" if record.field("before_after").value() == 0 else "after",
- date,
- record.field("color").value(),
- record.field("highlight").value()))
-
- database.close()
-
-def insertGroup(new_group):
- """
- Insert group to the database at Globals.db_path
- """
- output = -1
-
- database = QSqlDatabase.addDatabase("QSQLITE") # SQlite version 3
- database.setDatabaseName(Globals.db_path)
-
- if not database.open():
- print("Unable to open data source file.")
- sys.exit(1) # Error out. TODO consider throwing a dialog instead
-
- query = QSqlQuery()
-
- query.prepare("""
- INSERT INTO groups (name, column, link) VALUES (?, ?, ?)
- """)
- query.addBindValue(new_group.name)
- query.addBindValue(new_group.column)
- query.addBindValue(new_group.link)
- query.exec_()
-
- output = query.lastInsertId()
-
- database.close()
-
- return output
-
-def insertEntry(new_entry):
- """
- Insert entry to the database at Globals.db_path
- """
- output = -1
-
- database = QSqlDatabase.addDatabase("QSQLITE") # SQlite version 3
- database.setDatabaseName(Globals.db_path)
-
- if not database.open():
- print("Unable to open data source file.")
- sys.exit(1) # Error out. TODO consider throwing a dialog instead
-
- query = QSqlQuery()
-
- query.prepare("""
- INSERT INTO entries (parent_id, description, due_date, alt_due_date, link, color, highlight) VALUES (:p_id, :desc, :due, :alt_due, :link, :color, :highlight)
- """)
- query.bindValue(":p_id", new_entry.parent_id)
- query.bindValue(":desc", new_entry.desc)
- if new_entry.due:
- query.bindValue(":due", "{0}-{1}-{2}".format(
- new_entry.due.year(),
- new_entry.due.month(),
- new_entry.due.day()))
- else:
- query.bindValue(":due", "")
- query.bindValue(":alt_due", new_entry.due_alt)
- query.bindValue(":link", new_entry.link)
- query.bindValue(":color", new_entry.color)
- query.bindValue(":highlight", new_entry.highlight)
- success = query.exec_()
- # DEBUG
- #print(query.lastError().text())
- #print(query.boundValues())
- #if success:
- # print("Query succeeded")
- #else:
- # print("Query failed")
-
- output = query.lastInsertId()
-
- database.close()
-
- return output
-
-def insertRule(new_rule):
- """
- Insert rule to the database at Globals.db_path
- """
- output = -1
-
- database = QSqlDatabase.addDatabase("QSQLITE") # SQlite version 3
- database.setDatabaseName(Globals.db_path)
-
- if not database.open():
- print("Unable to open data source file.")
- sys.exit(1) # Error out. TODO consider throwing a dialog instead
-
- query = QSqlQuery()
-
- query.prepare("""
- INSERT INTO rules (entry_id, before_after, date, color, highlight) VALUES (:e_id, :when, :date, :color, :highlight)
- """)
- query.bindValue(":e_id", new_rule.entry_id)
- query.bindValue(":when", 0 if new_rule.when.lower() == "before" else 1)
- query.bindValue(":date", "{0}-{1}-{2}".format(
- new_rule.date.year(),
- new_rule.date.month(),
- new_rule.date.day()))
- query.bindValue(":color", new_rule.color)
- query.bindValue(":highlight", new_rule.highlight)
- success = query.exec_()
- # DEBUG
- #print(query.lastError().text())
- #print(query.boundValues())
- #if success:
- # print("Query succeeded")
- #else:
- # print("Query failed")
-
- output = query.lastInsertId()
-
- database.close()
-
- return output
-
-def updateGroup(group):
- """
- Update group by its id
- """
- database = QSqlDatabase.addDatabase("QSQLITE") # SQlite version 3
- database.setDatabaseName(Globals.db_path)
-
- if not database.open():
- print("Unable to open data source file.")
- sys.exit(1) # Error out. TODO consider throwing a dialog instead
-
- query = QSqlQuery()
-
- query.prepare("""
- UPDATE groups SET name = ?, column = ?, link = ?, hidden = ? WHERE id = ?
- """)
- query.addBindValue(group.name)
- query.addBindValue(group.column)
- query.addBindValue(group.link)
- query.addBindValue(group.hidden)
- query.addBindValue(group.id)
- query.exec_()
-
- database.close()
-
-def updateEntry(entry):
- """
- Update entry by its id
- """
- database = QSqlDatabase.addDatabase("QSQLITE") # SQlite version 3
- database.setDatabaseName(Globals.db_path)
-
- if not database.open():
- print("Unable to open data source file.")
- sys.exit(1) # Error out. TODO consider throwing a dialog instead
-
- query = QSqlQuery()
-
- query.prepare("""
- UPDATE entries SET
- description = :desc,
- due_date = :due,
- alt_due_date = :alt_due,
- link = :link,
- color = :color,
- highlight = :highlight,
- done = :done,
- hidden = :hidden
- WHERE id = :id
- """)
- query.bindValue(":desc", entry.desc)
- if entry.due:
- query.bindValue(":due", "{0}-{1}-{2}".format(
- entry.due.year(),
- entry.due.month(),
- entry.due.day()))
- else:
- query.bindValue(":due", "")
- query.bindValue(":alt_due", entry.due_alt)
- query.bindValue(":link", entry.link)
- query.bindValue(":color", entry.color)
- query.bindValue(":highlight", entry.highlight)
- query.bindValue(":done", entry.done)
- query.bindValue(":hidden", entry.hidden)
- query.bindValue(":id", entry.id)
- query.exec_()
-
- database.close()
-
-def updateRule(rule):
- """
- Update rule by its id
- """
- database = QSqlDatabase.addDatabase("QSQLITE") # SQlite version 3
- database.setDatabaseName(Globals.db_path)
-
- if not database.open():
- print("Unable to open data source file.")
- sys.exit(1) # Error out. TODO consider throwing a dialog instead
-
- query = QSqlQuery()
-
- query.prepare("""
- UPDATE rules SET
- before_after = :when,
- date = :date,
- color = :color,
- highlight = :highlight
- WHERE id = :id
- """)
- query.bindValue(":when", 0 if rule.when.lower() == "before" else 1)
- query.bindValue(":date", "{0}-{1}-{2}".format(
- rule.date.year(),
- rule.date.month(),
- rule.date.day()))
- query.bindValue(":color", rule.color)
- query.bindValue(":highlight", rule.highlight)
- query.bindValue(":id", rule.id)
- success = query.exec_()
- # DEBUG
- #print(query.lastError().text())
- #print(query.boundValues())
- #if success:
- # print("Query succeeded")
- #else:
- # print("Query failed")
-
- database.close()
-
-def removeGroup(group_id):
- """
- Remove a group by id from the database
- (actually set hidden to true, don't permanently delete it)
- """
-
- database = QSqlDatabase.addDatabase("QSQLITE") # SQlite version 3
- database.setDatabaseName(Globals.db_path)
-
- if not database.open():
- print("Unable to open data source file.")
- sys.exit(1) # Error out. TODO consider throwing a dialog instead
-
- query = QSqlQuery()
-
- # First, set entries to hidden
- query.prepare("""
- UPDATE entries SET hidden = 1 WHERE parent_id = ?
- """)
- query.addBindValue(group_id)
- query.exec_()
-
- # Now, set the group to hidden
- query.prepare("""
- UPDATE groups SET hidden = 1 WHERE id = ?
- """)
- query.addBindValue(group_id)
- query.exec_()
-
- output = query.numRowsAffected()
- database.close()
- return output
-
-def removeEntry(entry_id):
- """
- Remove a group by id from the database
- (actually set hidden to true, don't permanently delete it)
- """
- database = QSqlDatabase.addDatabase("QSQLITE") # SQlite version 3
- database.setDatabaseName(Globals.db_path)
-
- if not database.open():
- print("Unable to open data source file.")
- sys.exit(1) # Error out. TODO consider throwing a dialog instead
-
- query = QSqlQuery()
-
- # Set entry to hidden
- query.prepare("""
- UPDATE entries SET hidden = 1 WHERE id = ?
- """)
- query.addBindValue(entry_id)
- query.exec_()
-
- output = query.numRowsAffected()
- database.close()
- return output
-
-def removeRule(rule_id):
- """
- Remove a rule by id from the database
- (we do not preserve rules, unlike groups and entries)
- """
- database = QSqlDatabase.addDatabase("QSQLITE") # SQlite version 3
- database.setDatabaseName(Globals.db_path)
-
- if not database.open():
- print("Unable to open data source file.")
- sys.exit(1) # Error out. TODO consider throwing a dialog instead
-
- query = QSqlQuery()
-
- # Set entry to hidden
- query.prepare("""
- DELETE FROM rules WHERE id = ?
- """)
- query.addBindValue(rule_id)
- query.exec_()
-
- output = query.numRowsAffected()
- database.close()
- return output
-
-def cleanHidden():
- """
- Permanently delete removed/hidden groups and entries
- """
- database = QSqlDatabase.addDatabase("QSQLITE") # SQlite version 3
- database.setDatabaseName(Globals.db_path)
-
- if not database.open():
- print("Unable to open data source file.")
- sys.exit(1) # Error out. TODO consider throwing a dialog instead
-
- query = QSqlQuery()
-
- # Remove rules associated with hidden entries
- query.exec_("""
- DELETE FROM rules WHERE id IN (
- SELECT rules.id FROM rules
- INNER JOIN entries ON rules.entry_id = entries.id
- WHERE entries.hidden = 1
- )""")
-
- # Remove hidden entries
- query.exec_("""
- DELETE FROM entries WHERE hidden = 1
- """)
-
- # Remove hidden groups
- query.exec_("""
- DELETE FROM groups WHERE hidden = 1
- """)
-
- database.close()
diff --git a/src/edit_entry_form.py b/src/edit_entry_form.py
deleted file mode 100644
index 3c7f8c2..0000000
--- a/src/edit_entry_form.py
+++ /dev/null
@@ -1,83 +0,0 @@
-import os
-import sys
-from PyQt5 import uic
-from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox
-from PyQt5.QtCore import QDate
-
-import src.globals as Globals
-from src.entry import Entry
-import src.db_sqlite as DB
-
-# Reuses the add_entry_form UI file
-class editEntryForm(QDialog):
- """
- Form to edit/update an entry
- """
- def __init__(self, id):
- self.id = id
- super().__init__()
- uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)),
- "add_entry_form.ui"), self)
- self.initializeUI()
-
- def initializeUI(self):
- self.setWindowTitle("Edit Entry")
- self.displayWidgets()
- self.exec()
-
- def displayWidgets(self):
- entry = list(filter(lambda e: e.id == self.id, Globals.entries))[0]
-
- self.title.setText("Edit Entry")
- self.new_entry_desc.setText(entry.desc)
- self.new_entry_due.setDate(QDate.currentDate())
- if entry.due:
- self.new_entry_due.setDate(entry.due)
- self.new_entry_due_checkbox.setChecked(True)
- else:
- self.new_entry_due_checkbox.setChecked(False)
- self.new_entry_due_alt.setText(entry.due_alt)
- self.new_entry_link.setText(entry.link)
- self.new_entry_color.setText(entry.color)
- self.new_entry_highlight.setText(entry.highlight)
- self.buttonBox.rejected.connect(self.close)
- self.buttonBox.accepted.connect(self.handleSubmit)
-
- def handleSubmit(self):
- desc_text = self.new_entry_desc.text()
- if self.new_entry_due_checkbox.isChecked():
- due_text = self.new_entry_due.date() # due_text is a QDate
- else:
- due_text = "" # due is unchecked
- due_alt_text = self.new_entry_due_alt.text()
- link_text = self.new_entry_link.text()
- color_text = self.new_entry_color.text()
- highlight_text = self.new_entry_highlight.text()
-
- if not desc_text:
- QMessageBox.warning(self, "Error Message",
- "Name cannot be blank",
- QMessageBox.Close,
- QMessageBox.Close)
- return
-
- # Update DB
- entry = list(filter(lambda e: e.id == self.id, Globals.entries))[0]
- entry.desc = desc_text
- entry.due = due_text
- entry.due_alt = due_alt_text
- entry.link = link_text
- entry.color = color_text
- entry.highlight = highlight_text
- DB.updateEntry(entry)
-
- # Update global variables
- Globals.entries = list(filter(lambda e: e.id != self.id, Globals.entries))
- Globals.entries.append(Entry(self.id, entry.parent_id, desc_text, due_text, due_alt_text, link_text, color_text, highlight_text, entry.done, entry.hidden))
- self.close()
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = editEntryForm()
- sys.exit(app.exec_())
-
diff --git a/src/edit_group_form.py b/src/edit_group_form.py
deleted file mode 100644
index cd01162..0000000
--- a/src/edit_group_form.py
+++ /dev/null
@@ -1,63 +0,0 @@
-import os
-import sys
-from PyQt5 import uic
-from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox
-
-import src.globals as Globals
-from src.group import Group
-import src.db_sqlite as DB
-
-class editGroupForm(QDialog):
- """
- Form to edit/update a group
- """
- def __init__(self, id):
- self.id = id
- super().__init__()
- uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)),
- "add_group_form.ui"), self)
- self.initializeUI()
-
- def initializeUI(self):
- self.setWindowTitle("Edit Group")
- self.displayWidgets()
- self.exec()
-
- def displayWidgets(self):
- group = list(filter(lambda g: g.id == self.id, Globals.groups))[0]
-
- self.title.setText("Edit Group")
- self.new_group_name.setText(group.name)
- self.new_group_column.setCurrentIndex(0 if group.column.lower() == "left" else 1)
- self.new_group_link.setText(group.link)
- self.buttonBox.rejected.connect(self.close)
- self.buttonBox.accepted.connect(self.handleSubmit)
-
- def handleSubmit(self):
- name_text = self.new_group_name.text()
- column_text = self.new_group_column.currentText()
- link_text = self.new_group_link.text()
-
- if not name_text:
- QMessageBox.warning(self, "Error Message",
- "Name cannot be blank",
- QMessageBox.Close,
- QMessageBox.Close)
- return
-
- # Update DB
- group = list(filter(lambda g: g.id == self.id, Globals.groups))[0]
- group.name = name_text
- group.column = column_text
- group.link = link_text
- DB.updateGroup(group)
-
- # Update global variables
- Globals.groups = list(filter(lambda g: g.id != self.id, Globals.groups))
- Globals.groups.append(Group(self.id, name_text, column_text, link_text, group.hidden))
- self.close()
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = editGroupForm()
- sys.exit(app.exec_())
diff --git a/src/entry.py b/src/entry.py
deleted file mode 100644
index 3b639ab..0000000
--- a/src/entry.py
+++ /dev/null
@@ -1,100 +0,0 @@
-from datetime import date
-from PyQt5.QtCore import QDate, Qt
-from PyQt5.QtGui import QFont
-from PyQt5.QtWidgets import QHBoxLayout, QLabel
-import src.globals as Globals
-
-class Entry:
- def __init__(self, id, parent_id, desc, due = "", due_alt = "", link = "", color = "", highlight = "", done = False, hidden = False):
- self.id = id
- self.parent_id = parent_id
- self.desc = desc
- self.due = due
- self.due_alt = due_alt
- self.link = link
- self.color = color
- self.highlight = highlight
- self.done = done
- self.hidden = hidden
-
- def buildLayout(self):
- output = QHBoxLayout()
- bullet = QLabel()
- body = QLabel()
-
- output.setContentsMargins(2,2,2,2)
-
- bullet.setFont(QFont("Arial", 11))
- bullet.setMaximumWidth(15)
-
- body.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.LinksAccessibleByMouse)
- body.setFont(QFont("Arial", 11))
- body.setWordWrap(True)
- body.setToolTip("Right-Click for actions")
-
- # Check rules
- relevant_rules = list(filter(lambda r: r.entry_id == self.id, Globals.rules))
- for r in relevant_rules:
- if (r.when.lower() == "before" and r.date > QDate.currentDate()) or (r.when.lower() == "after" and r.date <= QDate.currentDate()):
- if r.color:
- self.color = r.color
- if r.highlight:
- self.highlight = r.highlight
-
- if self.done:
- bullet.setText("\u2713 ")
- bullet.setStyleSheet("""
- QLabel{
- color: green;
- }
- """)
- self.color = "green"
- else:
- bullet.setText("- ")
- output.addWidget(bullet)
-
- if self.due:
- body.setText("{0}/{1}/{2}: ".format(
- self.due.month(),
- self.due.day(),
- self.due.year()
- ))
- elif self.due_alt:
- body.setText("{0}: ".format(
- self.due_alt
- ))
- if self.link:
- body.setOpenExternalLinks(True)
- body.setText(body.text() + "<a href=\"{0}\" style=\"color: {1};\">".format(
- self.link,
- self.color if self.color else "default"
- ))
- body.setText(body.text() + self.desc)
- if self.link:
- body.setText(body.text() + "</a>")
- body.setToolTip("{}".format(self.link))
- output.addWidget(body)
-
- if self.done:
- font = body.font()
- font.setStrikeOut(True)
- body.setFont(font)
- body.setStyleSheet("""
- QLabel{
- color: green;
- }
- """)
-
- else:
- body.setStyleSheet("""
- QLabel{{
- color: {0};
- background-color: {1};
- font-weight: {2};
- }}""".format(
- self.color if self.color else "default",
- self.highlight if self.highlight else "none",
- "bold" if self.due and self.due <= date.today() else "normal"
- ))
-
- return output
diff --git a/src/globals.py b/src/globals.py
deleted file mode 100644
index bb6f717..0000000
--- a/src/globals.py
+++ /dev/null
@@ -1,4 +0,0 @@
-groups = []
-entries = []
-rules = []
-db_path = ""
diff --git a/src/group.py b/src/group.py
deleted file mode 100644
index 18b4836..0000000
--- a/src/group.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from PyQt5.QtCore import Qt
-from PyQt5.QtGui import QFont
-from PyQt5.QtWidgets import QLabel, QVBoxLayout
-import src.globals as Globals
-
-class Group:
- def __init__(self, id, name, column = "left", link = "", hidden = False):
- self.id = id
- self.name = name
- self.column = column
- self.link = link
- self.hidden = hidden
-
- def buildLayout(self):
- output = QVBoxLayout()
- output.setContentsMargins(0, 10, 0, 10)
-
- name = QLabel(self.name)
- name.setTextInteractionFlags(Qt.TextSelectableByMouse)
- name_font = QFont("Arial", 13)
- name_font.setUnderline(True)
- name.setFont(name_font)
- output.addWidget(name)
-
- return output
diff --git a/src/main.py b/src/main.py
deleted file mode 100644
index 88e0cda..0000000
--- a/src/main.py
+++ /dev/null
@@ -1,273 +0,0 @@
-#!/usr/bin/python3
-import os
-import sys
-import time
-from PyQt5 import uic
-from PyQt5.QtWidgets import QAction, QApplication, QMainWindow, QMenu, QMessageBox, QVBoxLayout
-from PyQt5.QtGui import QCursor
-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
-from src.rules_dialog import RulesDialog
-
-class AssignmentList(QMainWindow):
- def __init__(self):
- super().__init__()
- uic.loadUi(os.path.join(os.path.dirname(os.path.abspath(__file__)),
- "main.ui"), self)
-
- self.initializeUI()
-
- def initializeUI(self):
- self.createMenu()
- self.createToolbar()
- Config()
- self.setupDB()
- self.displayWidgets()
- self.show()
-
- def createMenu(self):
- self.actionPreferences.triggered.connect(self.preferences)
- self.actionReload.triggered.connect(self.reload)
- self.actionExit.triggered.connect(self.close)
-
- self.actionAdd_Group.triggered.connect(self.addGroup)
- self.actionClean_Hidden.triggered.connect(self.cleanHidden)
-
- self.actionAbout.triggered.connect(self.aboutDialog)
-
- def createToolbar(self):
- self.toolBar.addAction(self.actionAdd_Group)
-
- def setupDB(self):
- DB.initDB()
-
- def displayWidgets(self):
- self.title.setText(time.strftime("%A, %b %d %Y"))
- self.drawGroups()
-
- 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 editRules(self, id):
- pass
- need_reload = RulesDialog(id)
- if need_reload:
- self.reload()
-
- 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)
-
- rules_act = QAction("Rules")
- rules_act.triggered.connect((lambda id: lambda: self.editRules(id))(entry_id))
- menu.addAction(rules_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 preferences(self):
- # TODO not sure if this is working exactly how I think it does, but it works
- need_reload = PreferencesDialog()
- if need_reload:
- self.reload()
-
- 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))
-
- # Sort the rules
- Globals.rules = sorted(Globals.rules, key=lambda r: (r.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 reload(self):
- Config()
- self.setupDB()
- self.drawGroups()
-
- 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_())
-
diff --git a/src/main.ui b/src/main.ui
deleted file mode 100644
index bc3c0fb..0000000
--- a/src/main.ui
+++ /dev/null
@@ -1,207 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>640</width>
- <height>480</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Assignment List</string>
- </property>
- <widget class="QWidget" name="centralwidget">
- <layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QScrollArea" name="scrollArea">
- <property name="widgetResizable">
- <bool>true</bool>
- </property>
- <widget class="QWidget" name="scrollAreaWidgetContents_3">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>620</width>
- <height>421</height>
- </rect>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <layout class="QVBoxLayout" name="v_box">
- <item>
- <layout class="QHBoxLayout" name="title_h_box">
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QLabel" name="title">
- <property name="font">
- <font>
- <family>Arial</family>
- <pointsize>17</pointsize>
- </font>
- </property>
- <property name="text">
- <string>[DATE]</string>
- </property>
- <property name="textInteractionFlags">
- <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item>
- <layout class="QGridLayout" name="groups_layout">
- <property name="leftMargin">
- <number>20</number>
- </property>
- <property name="topMargin">
- <number>5</number>
- </property>
- <property name="rightMargin">
- <number>20</number>
- </property>
- <property name="bottomMargin">
- <number>5</number>
- </property>
- </layout>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QMenuBar" name="menubar">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>640</width>
- <height>22</height>
- </rect>
- </property>
- <widget class="QMenu" name="menuFile">
- <property name="title">
- <string>File</string>
- </property>
- <addaction name="actionPreferences"/>
- <addaction name="actionReload"/>
- <addaction name="separator"/>
- <addaction name="actionExit"/>
- </widget>
- <widget class="QMenu" name="menuEdit">
- <property name="title">
- <string>Edit</string>
- </property>
- <addaction name="actionAdd_Group"/>
- <addaction name="separator"/>
- <addaction name="actionClean_Hidden"/>
- </widget>
- <widget class="QMenu" name="menuHelp">
- <property name="title">
- <string>Help</string>
- </property>
- <addaction name="actionAbout"/>
- </widget>
- <addaction name="menuFile"/>
- <addaction name="menuEdit"/>
- <addaction name="menuHelp"/>
- </widget>
- <widget class="QToolBar" name="toolBar">
- <property name="windowTitle">
- <string>toolBar</string>
- </property>
- <attribute name="toolBarArea">
- <enum>TopToolBarArea</enum>
- </attribute>
- <attribute name="toolBarBreak">
- <bool>false</bool>
- </attribute>
- </widget>
- <action name="actionPreferences">
- <property name="text">
- <string>Preferences</string>
- </property>
- <property name="shortcut">
- <string>Alt+Return</string>
- </property>
- </action>
- <action name="actionReload">
- <property name="text">
- <string>Reload</string>
- </property>
- <property name="shortcut">
- <string>F5</string>
- </property>
- </action>
- <action name="actionExit">
- <property name="text">
- <string>Exit</string>
- </property>
- <property name="shortcut">
- <string>Ctrl+Q</string>
- </property>
- </action>
- <action name="actionAdd_Group">
- <property name="text">
- <string>Add Group</string>
- </property>
- </action>
- <action name="actionClean_Hidden">
- <property name="text">
- <string>Permanently Delete Removed Groups and Entries</string>
- </property>
- </action>
- <action name="actionAbout">
- <property name="text">
- <string>About</string>
- </property>
- </action>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/preferences_dialog.py b/src/preferences_dialog.py
deleted file mode 100644
index e6d4187..0000000
--- a/src/preferences_dialog.py
+++ /dev/null
@@ -1,70 +0,0 @@
-import os
-import sys
-from PyQt5 import uic
-from PyQt5.QtWidgets import QApplication, QDialog, QFileDialog
-from src.config import Config
-
-class PreferencesDialog(QDialog):
- """
- Implemented to set configuration options in the program
- """
- def __init__(self):
- super().__init__()
- uic.loadUi(os.path.join("src", "preferences_dialog.ui"), self)
-
- # class globals
- self.config = Config()
-
- self.initializeUI()
-
- def initializeUI(self):
- self.displayWidgets()
- self.exec()
-
- def displayWidgets(self):
- # TODO make this a scrollable window
- # FIXME could use some work on sizing
- self.pathsTabLayout()
-
- self.close_button.clicked.connect(self.close)
- self.apply_button.clicked.connect(self.apply)
- self.reload_button.clicked.connect(self.reload)
-
- def pathsTabLayout(self):
- if "paths" in self.config.config:
- self.db_path_edit.setText(self.config.config["paths"]["db_path"])
- self.db_path_button.clicked.connect(self.dbPathDialog)
-
- def dbPathDialog(self):
- file_dialog = QFileDialog(self)
- # TODO create filter to only allow selecting .db files
- new_path = file_dialog.getOpenFileName(self, "Open File")
-
- if new_path[0]:
- self.db_path_edit.setText(new_path[0])
-
- def apply(self):
- """
- Update the configuration in the config file
- """
- # Save paths
- if "paths" in self.config.config:
- try:
- with open(self.db_path_edit.text(), 'a'):
- self.config.config["paths"]["db_path"] = self.db_path_edit.text()
- except:
- print("Warning: db_path '{}' does not exist; skipping".format(self.db_path_edit.text()))
-
- self.config.updateConfig()
-
- def reload(self):
- """
- Update, reload, and close the window
- """
- self.apply()
- self.done(1)
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = PreferencesDialog()
- sys.exit(app.exec_())
diff --git a/src/preferences_dialog.ui b/src/preferences_dialog.ui
deleted file mode 100644
index 244eb26..0000000
--- a/src/preferences_dialog.ui
+++ /dev/null
@@ -1,128 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>Dialog</class>
- <widget class="QDialog" name="Dialog">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>500</width>
- <height>320</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Preferences</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <layout class="QVBoxLayout" name="main_layout">
- <item>
- <widget class="QTabWidget" name="tab_bar">
- <property name="currentIndex">
- <number>0</number>
- </property>
- <widget class="QWidget" name="tab">
- <attribute name="title">
- <string>Paths</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QWidget" name="widget" native="true">
- <layout class="QVBoxLayout" name="verticalLayout_3">
- <item>
- <layout class="QFormLayout" name="paths_tab_layout">
- <item row="0" column="0">
- <widget class="QLabel" name="databaseFileLabel">
- <property name="text">
- <string>Database File:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QWidget" name="db_path_hbox" native="true">
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QLineEdit" name="db_path_edit"/>
- </item>
- <item>
- <widget class="QPushButton" name="db_path_button">
- <property name="maximumSize">
- <size>
- <width>25</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>...</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="buttons_hbox">
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="close_button">
- <property name="text">
- <string>Close</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="apply_button">
- <property name="text">
- <string>Apply</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="reload_button">
- <property name="text">
- <string>Reload</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>
diff --git a/src/rule.py b/src/rule.py
deleted file mode 100644
index 414ccf0..0000000
--- a/src/rule.py
+++ /dev/null
@@ -1,44 +0,0 @@
-
-from PyQt5.QtCore import QDate
-from PyQt5.QtWidgets import QComboBox, QDateTimeEdit, QHBoxLayout, QLineEdit
-
-
-class Rule:
- def __init__(self, id, entry_id, when, date, color = "", highlight = ""):
- self.id = id
- self.entry_id = entry_id
- self.when = when
- self.date = date
- self.color = color
- self.highlight = highlight
-
- def buildLayout(self):
- output = QHBoxLayout()
-
- when_widget = QComboBox()
- when_widget.addItems(["Before", "After"])
- when_widget.setCurrentIndex(0 if self.when.lower() == "before" else 1)
- output.addWidget(when_widget)
-
- date_widget = QDateTimeEdit(QDate.currentDate())
- date_widget.setDisplayFormat("MM/dd/yyyy")
- date_widget.setDate(self.date)
- output.addWidget(date_widget)
-
- output.addStretch()
-
- # TODO Consider making this a color selector widget
- color_widget = QLineEdit()
- color_widget.setPlaceholderText("Color")
- if self.color:
- color_widget.setText(self.color)
- output.addWidget(color_widget)
-
- # TODO Consider making this a color selector widget
- highlight_widget = QLineEdit()
- highlight_widget.setPlaceholderText("Highlight")
- if self.highlight:
- highlight_widget.setText(self.highlight)
- output.addWidget(highlight_widget)
-
- return output
diff --git a/src/rules_dialog.py b/src/rules_dialog.py
deleted file mode 100644
index 0980fdd..0000000
--- a/src/rules_dialog.py
+++ /dev/null
@@ -1,128 +0,0 @@
-import sys
-from PyQt5.QtCore import QDate
-from PyQt5.QtWidgets import QApplication, QDialog, QHBoxLayout, QPushButton, QScrollArea, QVBoxLayout
-from src.config import Config
-from src.rule import Rule
-import src.db_sqlite as DB
-import src.globals as Globals
-
-class RulesDialog(QDialog):
- """
- Show the list of rules associated with an entry
- """
- def __init__(self, entry_id):
- super().__init__()
-
- self.entry_id = entry_id
- # class globals
- self.config = Config()
- self.relevant_rules = self.getRelevantRules()
-
- self.initializeUI()
-
- def initializeUI(self):
- self.resize(500, 320)
- self.setWindowTitle("Rules")
- self.displayWidgets()
- self.exec()
-
- def displayWidgets(self):
- main_layout = QVBoxLayout()
- main_layout_scroll_area = QScrollArea()
- main_layout_scroll_area.setWidgetResizable(True)
- main_layout_scroll_area.setLayout(main_layout)
-
- self.rules_layout = QVBoxLayout()
- self.drawRules()
- main_layout.addLayout(self.rules_layout)
-
- main_layout.addStretch()
- # Create Close and Save buttons
- buttons_hbox = QHBoxLayout()
- buttons_hbox.addStretch()
-
- close_button = QPushButton("Close", self)
- close_button.clicked.connect(self.close)
- buttons_hbox.addWidget(close_button)
-
- save_button = QPushButton("Save", self)
- save_button.clicked.connect(self.save)
- buttons_hbox.addWidget(save_button)
-
- main_layout.addLayout(buttons_hbox)
- self.setLayout(main_layout)
-
- def drawRules(self):
- # 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.rules_layout)
-
- # Draw each rule
- self.r_layouts_dict = {} # Use to help update things in the save() function
- for r in self.relevant_rules:
- r_layout = r.buildLayout()
- self.r_layouts_dict[r.id] = r_layout
- del_button = QPushButton("Delete", self)
- del_button.clicked.connect((lambda id: lambda: self.deleteRule(id))(r.id))
- r_layout.addWidget(del_button)
- self.rules_layout.addLayout(r_layout)
-
- # Draw a button to add rules
- rules_buttons_hbox = QHBoxLayout()
- add_rule_button = QPushButton("Add Rule", self)
- add_rule_button.clicked.connect(self.addRule)
- rules_buttons_hbox.addWidget(add_rule_button)
- rules_buttons_hbox.addStretch()
- self.rules_layout.addLayout(rules_buttons_hbox)
-
- def addRule(self):
- self.apply()
-
- new_rule = Rule(0, self.entry_id, "before", QDate.currentDate())
- new_rule_id = DB.insertRule(new_rule)
- new_rule.id = new_rule_id
- Globals.rules.append(new_rule)
- self.relevant_rules = self.getRelevantRules()
- self.drawRules()
-
- def deleteRule(self, rule_id):
- DB.removeRule(rule_id)
- Globals.rules = list(filter(lambda r: r.id != rule_id, Globals.rules))
- self.relevant_rules = self.getRelevantRules()
- self.drawRules()
-
- def getRelevantRules(self):
- return list(filter(lambda r: r.entry_id == self.entry_id, Globals.rules))
-
- def apply(self):
- for id, layout in self.r_layouts_dict.items():
- updated_rule = Rule(
- id,
- self.entry_id,
- layout.itemAt(0).widget().currentText(),
- layout.itemAt(1).widget().date(),
- layout.itemAt(3).widget().text(),
- layout.itemAt(4).widget().text())
- DB.updateRule(updated_rule)
- Globals.rules = list(filter(lambda r: r.id != id, Globals.rules))
- Globals.rules.append(updated_rule)
-
- def save(self):
- """
- Save any existing rules. Added rules are automatically saved,
- but changing rules is not, hence the need for a manual save
- """
- self.apply()
- self.done(1)
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = RulesDialog()
- sys.exit(app.exec_())