Compare commits
1 Commits
notes
...
checklist_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1fef427bf |
@@ -1 +0,0 @@
|
|||||||
PySide6~=6.0.0
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
import sys
|
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from PySide6.QtCore import QStandardPaths
|
|
||||||
from PySide6.QtGui import QStandardItemModel, QStandardItem, QIcon
|
|
||||||
from PySide6.QtWidgets import QMainWindow, QApplication, QTreeView, QTextEdit, QSplitter, QSizePolicy, QMenuBar, QMenu
|
|
||||||
|
|
||||||
# TODO: Split this out into its own module for handling the FS operations in an abstract manner. We need to relocate
|
|
||||||
# all of this code up to the class.
|
|
||||||
NYTEWORKS_DIR = QStandardPaths.locate(QStandardPaths.AppDataLocation, 'NyteWoks', QStandardPaths.LocateDirectory)
|
|
||||||
if not NYTEWORKS_DIR:
|
|
||||||
# We don't already have a directory in the roaming area
|
|
||||||
NYTEWORKS_DIR = QStandardPaths.standardLocations(QStandardPaths.AppDataLocation)
|
|
||||||
if not NYTEWORKS_DIR:
|
|
||||||
# There are no suitable areas on the system to write our data to. Throw an error and let the user decide where
|
|
||||||
# to store the data if possible.
|
|
||||||
# TODO: Implement some sort of handling for this unfortunate situation...
|
|
||||||
print('Unable to find a suitable location for data on your system.', file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
NYTEWORKS_DIR = Path(NYTEWORKS_DIR[0] + '/Nyteworks')
|
|
||||||
else:
|
|
||||||
NYTEWORKS_DIR = Path(NYTEWORKS_DIR)
|
|
||||||
|
|
||||||
# We have the parent directory, let's get the binder list
|
|
||||||
LIFEFLOW_DIR = NYTEWORKS_DIR / 'LifeFlow'
|
|
||||||
BINDERS_DIR = LIFEFLOW_DIR / 'Binders'
|
|
||||||
|
|
||||||
# Ensure that the binder directory exists
|
|
||||||
BINDERS_DIR.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
# Some business logic that is currently necessary...
|
|
||||||
# TODO: Find a more elegant way to handle the Inbox folder
|
|
||||||
INBOX_DIR = BINDERS_DIR / 'Inbox'
|
|
||||||
Path(INBOX_DIR).mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
|
||||||
def __init__(self, parent=None):
|
|
||||||
super(MainWindow, self).__init__(parent)
|
|
||||||
self.setWindowTitle('LifeFlow - Notes for the Real World')
|
|
||||||
self._create_ui()
|
|
||||||
|
|
||||||
def _create_ui(self):
|
|
||||||
self._setup_menu_bar()
|
|
||||||
self._create_note_tree_view()
|
|
||||||
self.text_area = QTextEdit()
|
|
||||||
self.setCentralWidget(self.note_tree_view)
|
|
||||||
|
|
||||||
self.note_tree_view.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding))
|
|
||||||
self.text_area.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
|
|
||||||
|
|
||||||
self.note_tree_view.clicked.connect(self.selected_note_changed)
|
|
||||||
|
|
||||||
self.splitter = QSplitter()
|
|
||||||
self.splitter.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
|
|
||||||
self.splitter.addWidget(self.note_tree_view)
|
|
||||||
self.splitter.addWidget(self.text_area)
|
|
||||||
|
|
||||||
self.splitter.setSizes([self.note_tree_view.sizeHint().width(), 1000])
|
|
||||||
|
|
||||||
self.setCentralWidget(self.splitter)
|
|
||||||
|
|
||||||
def _setup_menu_bar(self):
|
|
||||||
menuBar = self.menuBar()
|
|
||||||
|
|
||||||
fileMenu = menuBar.addMenu('&File')
|
|
||||||
fileMenu.addAction('Open')
|
|
||||||
fileMenu.addAction('New')
|
|
||||||
fileMenu.addAction('Save')
|
|
||||||
fileMenu.addAction('Save As...')
|
|
||||||
|
|
||||||
editMenu = menuBar.addMenu('&Edit')
|
|
||||||
editMenu.addAction('Undo')
|
|
||||||
editMenu.addAction('Redo')
|
|
||||||
editMenu.addSeparator()
|
|
||||||
editMenu.addAction('Cut')
|
|
||||||
editMenu.addAction('Copy')
|
|
||||||
editMenu.addAction('Paste')
|
|
||||||
|
|
||||||
def _create_note_tree_view(self):
|
|
||||||
self.note_tree_view = QTreeView()
|
|
||||||
self.note_tree_view.setHeaderHidden(True)
|
|
||||||
self.note_tree_view.setModel(self._create_note_model())
|
|
||||||
|
|
||||||
def _create_note_model(self):
|
|
||||||
self.note_tree_model = QStandardItemModel()
|
|
||||||
root = self.note_tree_model.invisibleRootItem()
|
|
||||||
|
|
||||||
# TODO: Investigate what else pathlib might be able to do for us better here.
|
|
||||||
# TODO: Right now the note hierarchy is hard-coded. We need a more generic recursion code and need to consider
|
|
||||||
# how the database will be implemented so that other views fit in the hierarchy.
|
|
||||||
binders = [binder for binder in BINDERS_DIR.iterdir() if binder.is_dir()]
|
|
||||||
for binder in binders:
|
|
||||||
binder_name = binder.parts[-1]
|
|
||||||
binder_item = QStandardItem(binder_name)
|
|
||||||
binder_item.setData(False, 1)
|
|
||||||
notebooks = [notebook for notebook in binder.iterdir() if notebook.is_dir()]
|
|
||||||
for notebook in notebooks:
|
|
||||||
notebook_name = notebook.parts[-1]
|
|
||||||
notebook_item = QStandardItem(notebook_name)
|
|
||||||
notebook_item.setData(False, 1)
|
|
||||||
notes = [note for note in notebook.iterdir() if note.is_file()]
|
|
||||||
for note in notes:
|
|
||||||
note_name = note.parts[-1]
|
|
||||||
note_item = QStandardItem(note_name)
|
|
||||||
note_item.is_note = True
|
|
||||||
note_item.setData(True, 1)
|
|
||||||
notebook_item.appendRow(note_item)
|
|
||||||
binder_item.appendRow(notebook_item)
|
|
||||||
root.appendRow(binder_item)
|
|
||||||
|
|
||||||
return self.note_tree_model
|
|
||||||
|
|
||||||
def selected_note_changed(self, index):
|
|
||||||
item = index.model().itemFromIndex(index)
|
|
||||||
if item.data(1):
|
|
||||||
notebook = item.parent().text()
|
|
||||||
binder = item.parent().parent().text()
|
|
||||||
note = BINDERS_DIR / binder / notebook / item.text()
|
|
||||||
print('I should get:', note)
|
|
||||||
note_text = None
|
|
||||||
with open(note, 'r') as note_file:
|
|
||||||
note_text = note_file.readlines()
|
|
||||||
self.text_area.setText(''.join(note_text))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
app = QApplication()
|
|
||||||
|
|
||||||
window = MainWindow()
|
|
||||||
window.show()
|
|
||||||
|
|
||||||
sys.exit(app.exec_())
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -17,11 +17,12 @@
|
|||||||
|
|
||||||
|
|
||||||
class ChecklistItem:
|
class ChecklistItem:
|
||||||
def __init__(self, task=None):
|
def __init__(self, task=None, schedule=None):
|
||||||
self.task = task
|
self.task = task
|
||||||
self.parent = None
|
self.parent = None
|
||||||
self.children = []
|
self.children = []
|
||||||
self.completed = False
|
self.completed = False
|
||||||
|
self.schedule = schedule
|
||||||
|
|
||||||
def add_child(self, sub_task):
|
def add_child(self, sub_task):
|
||||||
sub_task.set_parent(self)
|
sub_task.set_parent(self)
|
||||||
@@ -30,6 +31,9 @@ class ChecklistItem:
|
|||||||
def mark_task(self):
|
def mark_task(self):
|
||||||
self.completed = True
|
self.completed = True
|
||||||
|
|
||||||
|
for item in self.get_children():
|
||||||
|
item.mark_task()
|
||||||
|
|
||||||
def unmark_task(self):
|
def unmark_task(self):
|
||||||
self.completed = False
|
self.completed = False
|
||||||
|
|
||||||
@@ -45,15 +49,17 @@ class ChecklistItem:
|
|||||||
def get_parent(self):
|
def get_parent(self):
|
||||||
return self.parent
|
return self.parent
|
||||||
|
|
||||||
|
def get_children(self):
|
||||||
|
return self.children
|
||||||
|
|
||||||
class Checklist:
|
def get_schedule(self):
|
||||||
def __init__(self, schedule=0):
|
return self.schedule
|
||||||
self.root = ChecklistItem()
|
|
||||||
self.schedule = schedule
|
|
||||||
|
|
||||||
|
|
||||||
def print_checklist(root):
|
def print_checklist(root):
|
||||||
for item in root.children:
|
for item in root.children:
|
||||||
|
if root.parent is None:
|
||||||
|
print(root.get_task())
|
||||||
|
|
||||||
temp = root
|
temp = root
|
||||||
while temp.get_parent() is not None:
|
while temp.get_parent() is not None:
|
||||||
@@ -69,26 +75,34 @@ def print_checklist(root):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_checklist = Checklist()
|
test_checklist = ChecklistItem("Backpack Checklist")
|
||||||
|
|
||||||
"""
|
"""
|
||||||
As a proof of concept, I'll make a checklist similar to the following, x is complete, o is incomplete:
|
As a proof of concept, I'll make a checklist similar to the following, x is complete, o is incomplete:
|
||||||
Backpack Checklist
|
Backpack Checklist
|
||||||
o back pocket
|
o back pocket
|
||||||
x laptop
|
o laptop
|
||||||
o げんき third edition Japanese textbook and workbook with bonus learning exercises
|
x げんき
|
||||||
|
x げんき workbook
|
||||||
o front pocket
|
o front pocket
|
||||||
o pens
|
o pens
|
||||||
o headphones
|
o headphones
|
||||||
"""
|
"""
|
||||||
|
test_checklist.add_child(ChecklistItem("back pocket"))
|
||||||
|
test_checklist.add_child(ChecklistItem("front pocket"))
|
||||||
|
|
||||||
test_checklist.root.add_child(ChecklistItem("back pocket"))
|
sub_checklist = test_checklist.children[0]
|
||||||
test_checklist.root.children[0].add_child(ChecklistItem("laptop"))
|
sub_checklist.add_child(ChecklistItem("laptop"))
|
||||||
test_checklist.root.children[0].children[0].mark_task()
|
sub_checklist.add_child(ChecklistItem("げんき"))
|
||||||
test_checklist.root.children[0].add_child(ChecklistItem("げんき third edition Japanese textbook and workbook with "
|
|
||||||
"bonus learning exercises"))
|
|
||||||
test_checklist.root.add_child(ChecklistItem("front pocket"))
|
|
||||||
test_checklist.root.children[1].add_child(ChecklistItem("pens"))
|
|
||||||
test_checklist.root.children[1].add_child(ChecklistItem("headphones"))
|
|
||||||
|
|
||||||
print_checklist(test_checklist.root)
|
sub_checklist = sub_checklist.children[1]
|
||||||
|
sub_checklist.add_child(ChecklistItem("げんき workbook"))
|
||||||
|
|
||||||
|
sub_checklist = test_checklist.children[1]
|
||||||
|
sub_checklist.add_child(ChecklistItem("pens"))
|
||||||
|
sub_checklist.add_child(ChecklistItem("headphones"))
|
||||||
|
|
||||||
|
sub_checklist = test_checklist.children[0].children[1]
|
||||||
|
sub_checklist.mark_task()
|
||||||
|
|
||||||
|
print_checklist(test_checklist)
|
||||||
|
|||||||
@@ -1,134 +0,0 @@
|
|||||||
import os
|
|
||||||
import sys
|
|
||||||
import os.path
|
|
||||||
import appdirs
|
|
||||||
import shutil
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
from os.path import join
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
BASE_LOCATION = appdirs.user_data_dir("LifeFlow", "NyteWorks", "0.1.0")
|
|
||||||
NOTES_FOLDER = join(BASE_LOCATION, "Notes")
|
|
||||||
|
|
||||||
#TODO: In the future, the user will be able to change which folder is the default for QuickNotes
|
|
||||||
QUICK_NOTES_FOLDER = join(NOTES_FOLDER, "Inbox")
|
|
||||||
|
|
||||||
if not os.path.exists(BASE_LOCATION):
|
|
||||||
os.makedirs(BASE_LOCATION, exist_ok=True)
|
|
||||||
if not os.path.exists(NOTES_FOLDER):
|
|
||||||
os.makedirs(NOTES_FOLDER, exist_ok=True)
|
|
||||||
if not os.path.exists(QUICK_NOTES_FOLDER):
|
|
||||||
os.makedirs(QUICK_NOTES_FOLDER, exist_ok=True)
|
|
||||||
|
|
||||||
current_notebook = "Inbox"
|
|
||||||
all_notebooks = []
|
|
||||||
for notebook in os.listdir(NOTES_FOLDER):
|
|
||||||
all_notebooks.append(notebook)
|
|
||||||
|
|
||||||
def list_notes(args):
|
|
||||||
if len(args) == 0:
|
|
||||||
print("You have the following notebooks:")
|
|
||||||
notebooks = os.listdir(NOTES_FOLDER)
|
|
||||||
for notebook in notebooks:
|
|
||||||
print("*", notebook)
|
|
||||||
else:
|
|
||||||
notebook = args[0]
|
|
||||||
print("These are the notes in", notebook)
|
|
||||||
notes = os.listdir(join(NOTES_FOLDER, notebook))
|
|
||||||
for note in notes:
|
|
||||||
note = ".".join(note.split(".")[:-1])
|
|
||||||
print(note)
|
|
||||||
|
|
||||||
def select_notebook(args):
|
|
||||||
global all_notebooks
|
|
||||||
global current_notebook
|
|
||||||
if args[0] in all_notebooks:
|
|
||||||
current_notebook = args[0]
|
|
||||||
|
|
||||||
def create_notebook(args):
|
|
||||||
global all_notebooks
|
|
||||||
global current_notebook
|
|
||||||
if len(args) < 1:
|
|
||||||
print("You need a name for your new notebook!", file=sys.stderr)
|
|
||||||
return
|
|
||||||
if not os.path.exists(join(NOTES_FOLDER, args[0])):
|
|
||||||
os.makedirs(join(NOTES_FOLDER, args[0]), exist_ok=True)
|
|
||||||
all_notebooks.append(args[0])
|
|
||||||
current_notebook = args[0]
|
|
||||||
|
|
||||||
def delete(args):
|
|
||||||
global current_notebook
|
|
||||||
global all_notebooks
|
|
||||||
if len(args) < 1:
|
|
||||||
print("Unable to delete nothing.", file=sys.stderr)
|
|
||||||
return
|
|
||||||
if args[0] == 'notebook':
|
|
||||||
if len(args) < 2:
|
|
||||||
print("You need to select a notebook to delete.")
|
|
||||||
else:
|
|
||||||
if args[1] == 'Inbox':
|
|
||||||
print("You cannot delete the Inbox.")
|
|
||||||
return
|
|
||||||
elif args[1] == current_notebook:
|
|
||||||
current_notebook = "Inbox"
|
|
||||||
path = join(NOTES_FOLDER, args[1])
|
|
||||||
if not os.path.exists(path):
|
|
||||||
print("That notebook does not exist.")
|
|
||||||
return
|
|
||||||
print("CHECKING:", path)
|
|
||||||
shutil.rmtree(path)
|
|
||||||
print("Deleted notebook", args[1])
|
|
||||||
else:
|
|
||||||
path = join(NOTES_FOLDER, current_notebook, args[0] + ".txt")
|
|
||||||
print("CHECKING:", path)
|
|
||||||
if not os.path.exists(path):
|
|
||||||
print("That note does not exist.")
|
|
||||||
return
|
|
||||||
os.remove(path)
|
|
||||||
print("Deleted", args[0])
|
|
||||||
|
|
||||||
def add_note(arguments):
|
|
||||||
global current_notebook
|
|
||||||
if current_notebook is None:
|
|
||||||
current_notebook = "Inbox"
|
|
||||||
if len(arguments) == 0:
|
|
||||||
filename = '{date:%Y-%m-%d_%H:%M:%S}.txt'.format(date=datetime.datetime.now())
|
|
||||||
else:
|
|
||||||
#TODO: We need to sanitize this for legal filename
|
|
||||||
filename = " ".join(arguments) + ".txt"
|
|
||||||
filename = join(NOTES_FOLDER, current_notebook, filename)
|
|
||||||
if not os.path.exists(filename):
|
|
||||||
filepath = Path(filename)
|
|
||||||
filepath.touch()
|
|
||||||
os.startfile(join(NOTES_FOLDER, current_notebook, filename))
|
|
||||||
|
|
||||||
def run_tui():
|
|
||||||
global current_notebook
|
|
||||||
valid_commands = {
|
|
||||||
"list": list_notes,
|
|
||||||
"select": select_notebook,
|
|
||||||
"create": create_notebook,
|
|
||||||
"delete": delete,
|
|
||||||
"add": add_note,
|
|
||||||
"quit": exit,
|
|
||||||
}
|
|
||||||
print("Welcome to LifeFlow Notes")
|
|
||||||
print("-------------------------")
|
|
||||||
print()
|
|
||||||
command = None
|
|
||||||
while(command != "quit"):
|
|
||||||
if current_notebook is None:
|
|
||||||
current_notebook = "Inbox"
|
|
||||||
print("You are currently in notebook:", current_notebook)
|
|
||||||
command_parts = input("> ").strip().lower().split(" ")
|
|
||||||
arguments = command_parts[1:]
|
|
||||||
command = command_parts[0]
|
|
||||||
if command not in valid_commands:
|
|
||||||
print("Invalid command. Please input one of: ", file=sys.stderr)
|
|
||||||
for key in valid_commands.keys():
|
|
||||||
print("\t", key)
|
|
||||||
else:
|
|
||||||
valid_commands[command](arguments)
|
|
||||||
if __name__ == '__main__':
|
|
||||||
run_tui()
|
|
||||||
Reference in New Issue
Block a user