From 6a71f342f09ea3b7a4b4a978348e7badcd8a7069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Mart=C3=ADnez=20Portela?= Date: Sat, 3 Apr 2021 01:13:41 +0200 Subject: [PATCH] Add base functionality: Show agenda. --- .gitignore | 1 + doc_manager.py | 106 +++++++++++++++++++++++++++++++++++++++++++++++++ main.py | 79 +++++++++++++++++++++++++----------- 3 files changed, 163 insertions(+), 23 deletions(-) create mode 100644 doc_manager.py diff --git a/.gitignore b/.gitignore index bee8a64..083d732 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ __pycache__ +.idea diff --git a/doc_manager.py b/doc_manager.py new file mode 100644 index 0000000..fe1229d --- /dev/null +++ b/doc_manager.py @@ -0,0 +1,106 @@ +import logging +import os +import sys +from datetime import datetime +from typing import List + +import org_rw +from org_rw import OrgTime + + +def is_today(ot: OrgTime): + now = datetime.now() + return ( + (ot.time.year == now.year) + and (ot.time.month == now.month) + and (ot.time.day == now.day) + ) + + +class Agenda: + def __init__(self, /, + with_hour: List[org_rw.Headline], + no_hour: List[org_rw.Headline], + ): + self.with_hour = with_hour + self.no_hour = no_hour + + def print(self): + for item in self.with_hour: + print(item.scheduled.time, item.state, item.title) + + if len(self.with_hour) > 0: + print("--------") + + for item in self.no_hour: + print(item.scheduled.time, item.state, item.title) + + +class DocumentManager: + def __init__(self, basepath): + self.basepath = basepath + + def load(self): + top = os.path.abspath(self.basepath) + + docs = [] + + for root, dirs, files in os.walk(top): + for name in files: + if ".org" not in name: + continue + + path = os.path.join(root, name) + + try: + doc = org_rw.load(open(path), extra_cautious=True) + docs.append(doc) + except Exception as err: + import traceback + + traceback.print_exc() + print(f"== On {path}") + sys.exit(1) + + logging.info("Loaded {} files".format(len(docs))) + + self.docs = docs + + def get_agenda(self) -> Agenda: + + headline_count = 0 + items_in_agenda = [] + now = datetime.now() + + for doc in self.docs: + for hl in doc.getAllHeadlines(): + headline_count += 1 + + if hl.scheduled and isinstance(hl.scheduled, OrgTime): + if is_today(hl.scheduled): + items_in_agenda.append(hl) + elif (hl.scheduled.time.to_datetime() < now) and hl.is_todo: + items_in_agenda.append(hl) + + logging.info("Read {} items".format(headline_count)) + logging.info("{} items in agenda today".format(len(items_in_agenda))) + + items_with_hour = [ + item + for item in items_in_agenda + if item.scheduled and is_today(item.scheduled) and item.scheduled.time.hour + ] + other_items = [ + item + for item in items_in_agenda + if not ( + item.scheduled and is_today(item.scheduled) and item.scheduled.time.hour + ) + ] + + logging.info("{} items today for a specific hour".format(len(items_with_hour))) + + return Agenda( + with_hour=sorted(items_with_hour, key=lambda x: x.scheduled.time), + no_hour=other_items + ) diff --git a/main.py b/main.py index 4f12d2c..de08f09 100755 --- a/main.py +++ b/main.py @@ -8,31 +8,25 @@ import time from PySide2.QtCore import QObject, QThread, Signal, Slot from PySide2.QtWidgets import (QApplication, QDialog, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QProgressBar, QPushButton, - QScrollArea, QTabBar, QVBoxLayout) + QScrollArea, QTabBar, QVBoxLayout, QSplitter, QFrame) -ORG_PATH = os.environ['ORG_PATH'] +import doc_manager + +DOCS_PATH = os.environ['ORG_PATH'] class LoadDoneSignal(QObject): - sig = Signal(str) - + sig = Signal(doc_manager.DocumentManager) class DocumentLoader(QThread): - def __init__(self, parent = None): - QThread.__init__(self, parent) - self.exiting = False + def __init__(self, manager): + QThread.__init__(self, None) + self.manager = manager self.signal = LoadDoneSignal() def run(self): - end = time.time() + 3 - while self.exiting==False: - sys.stdout.write('*') - sys.stdout.flush() - time.sleep(1) - now = time.time() - if now >= end: - self.exiting = True - self.signal.sig.emit('OK') + self.manager.load() + self.signal.sig.emit(self.manager) class Dialog(QDialog): @@ -40,6 +34,7 @@ class Dialog(QDialog): super(Dialog, self).__init__() self.loader = None + self.manager = doc_manager.DocumentManager(DOCS_PATH) layout = QVBoxLayout() @@ -53,7 +48,7 @@ class Dialog(QDialog): layout.setSpacing(0) - self.results = QScrollArea() + self.results = QScrollArea(widgetResizable=True) layout.addWidget(self.results) # Options @@ -81,26 +76,61 @@ class Dialog(QDialog): def startLoad(self): self.edit.setDisabled(True) + self.edit.setVisible(False) self.tabBar.setDisabled(True) self.progressBar.setVisible(True) - self.loader = DocumentLoader() + self.loader = DocumentLoader(self.manager) self.loader.signal.sig.connect(self.longoperationcomplete) + self.loading_start_time = time.time() self.loader.start() def endLoad(self): self.edit.setDisabled(False) + self.edit.setVisible(True) self.tabBar.setDisabled(False) self.progressBar.setVisible(False) self.update_tab() def longoperationcomplete(self, data): - print("Complete with", data) + logging.info("Loading complete in {:.3f}s".format(time.time() - self.loading_start_time)) self.endLoad() def loadAgenda(self): - logging.warning("loadAgenda not yet implemented") + agenda = self.manager.get_agenda() + old = self.results.layout() + + if old: + print("Deleting old") + old.deleteLater() + + layout = QVBoxLayout() + + for item in agenda.with_hour: + text = "{} {} {}".format( + item.scheduled.time, + item.state, + item.title, + ) + label = QLabel(text=text) + layout.addWidget(label) + + # if len(agenda.with_hour) > 0 and len(agenda.no_hour) > 0: + # layout.addWidget(QSplitter()) + + for item in agenda.no_hour: + text = "{} {} {}".format( + item.scheduled.time, + item.state, + item.title, + ) + label = QLabel(text=text) + layout.addWidget(label) + + frame = QFrame(self.results) + frame.setLayout(layout) + self.results.setWidget(frame) def loadNotes(self): logging.warning("loadNotes not yet implemented") @@ -109,7 +139,10 @@ class Dialog(QDialog): logging.warning("loadTasks not yet implemented") # Create the Qt Application -app = QApplication(sys.argv) +if __name__ == '__main__': + logging.basicConfig(level=logging.INFO, format="%(levelname)-8s %(message)s") -dialog = Dialog() -sys.exit(dialog.exec_()) + app = QApplication(sys.argv) + + dialog = Dialog() + sys.exit(dialog.exec_())