cleaner coupling
This commit is contained in:
@@ -1,7 +1,11 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
from .gui import App
|
||||
from .gui import NoteViewer
|
||||
from .data import Notes
|
||||
|
||||
app = App()
|
||||
app.run()
|
||||
# Load notes
|
||||
notes = Notes("testdata")
|
||||
# View them
|
||||
viewer = NoteViewer(notes)
|
||||
viewer.run()
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
import random
|
||||
from collections import namedtuple
|
||||
|
||||
def test_data():
|
||||
return { "Henri" :
|
||||
@@ -37,30 +39,63 @@ def test_data():
|
||||
},
|
||||
}
|
||||
|
||||
def extract_from_file(path):
|
||||
""" Extract and yields notes from the file at path """
|
||||
pass
|
||||
|
||||
NoteInfo = namedtuple("NoteInfo", ("person", "category", "date", "time", "author", "text"))
|
||||
|
||||
def extract_test():
|
||||
for person in ["Henri", "Étienne", "Julia"]:
|
||||
for category in ["Santé", "Comportement", "Quotidien", "Infos", "Activités"]:
|
||||
for day in range(2, 18):
|
||||
for time in ("Matin", "Soir", "Nuit"):
|
||||
text = random.choice(("Tout va bien", "A l'air un peu triste aujourd'hui", "Bien mangé au repas"))
|
||||
author = random.choice(("Éric", "Mélanie", "Thibault"))
|
||||
date = f"{day} mars 2020"
|
||||
yield NoteInfo(person, category, date, time, author, text)
|
||||
|
||||
|
||||
|
||||
class Notes(dict):
|
||||
""" Store of notes grouped by subject and category """
|
||||
|
||||
def __init__(self, source):
|
||||
self._categories = None
|
||||
super().__init__([data for data in test_data().items()])
|
||||
super().__init__()
|
||||
self.categories = []
|
||||
self.load(source)
|
||||
|
||||
def subjects(self):
|
||||
def load(self, source):
|
||||
if source is "testdata":
|
||||
for note in extract_test():
|
||||
self.insert(note.person, note.category, note.date, (note.time, note.text))
|
||||
|
||||
def insert(self, person, category, date, note):
|
||||
""" Inserts a new note """
|
||||
# Track existing categories
|
||||
if not category in self.categories:
|
||||
self.categories.append(category)
|
||||
# Checks
|
||||
if not person in self:
|
||||
self[person] = { cat: {} for cat in self.categories }
|
||||
if not category in self[person]:
|
||||
self[person][category] = {}
|
||||
# Insertion
|
||||
if not date in self[person][category]:
|
||||
self[person][category][date] = [note]
|
||||
else:
|
||||
self[person][category][date].append(note)
|
||||
|
||||
def persons(self):
|
||||
""" Returns list of subjects """
|
||||
return list(self.keys())
|
||||
|
||||
def categories(self):
|
||||
""" Returns list of categories """
|
||||
if not self._categories:
|
||||
self._categories = ["Santé", "Comportement", "Quotidien", "Infos", "Activité"]
|
||||
return self._categories
|
||||
|
||||
def get(self, subject_idx, category_idx, date_range=None):
|
||||
def get(self, person_idx, category_idx, date_range=None):
|
||||
""" Filter notes by subject, category and date """
|
||||
subject = list(self.subjects())[subject_idx]
|
||||
person = list(self.persons())[person_idx]
|
||||
# TODO: deduplicate categories by using a tuple
|
||||
category = list(self.categories())[category_idx]
|
||||
notes = self[subject][category]
|
||||
category = self.categories[category_idx]
|
||||
notes = self[person][category]
|
||||
if date_range is not None:
|
||||
# TODO: filter by date
|
||||
pass
|
||||
|
||||
70
xerus/gui.py
70
xerus/gui.py
@@ -10,50 +10,60 @@ def new_frame_horiz(parent):
|
||||
frame.pack(fill=tk.X, expand=True)
|
||||
return frame
|
||||
|
||||
|
||||
def render_notes(notes, text_area):
|
||||
# Text
|
||||
for date, notes in notes.items():
|
||||
text_area.insert(tk.INSERT, f"{date}\n\n", "d")
|
||||
for note in notes:
|
||||
text_area.insert(tk.INSERT, f"{note[0]}. ", "t")
|
||||
text_area.insert(tk.INSERT, f"{note[1]}\n")
|
||||
text_area.insert(tk.INSERT, "\n")
|
||||
|
||||
|
||||
|
||||
class App(tk.Frame):
|
||||
class NoteViewer(tk.Frame):
|
||||
|
||||
def __init__(self, master=None):
|
||||
__notes = None
|
||||
|
||||
def __init__(self, notes, master=None):
|
||||
super().__init__(master)
|
||||
self.pack(fill=tk.BOTH, expand=True)
|
||||
self.__create_widgets()
|
||||
self.notes = notes
|
||||
|
||||
def run(self):
|
||||
self.notes = Notes(None)
|
||||
self._create_widgets()
|
||||
""" Launch the viewer """
|
||||
self.mainloop()
|
||||
|
||||
def _set_subject(self):
|
||||
pass
|
||||
@property
|
||||
def notes(self):
|
||||
return self.__notes
|
||||
|
||||
def _set_category(self):
|
||||
pass
|
||||
@notes.setter
|
||||
def notes(self, new_notes):
|
||||
""" Replace loaded notes """
|
||||
self.__notes = new_notes
|
||||
# Reset widgets state
|
||||
self.person_choice.configure(values=new_notes.persons())
|
||||
self.person_choice.current(0)
|
||||
self.category_choice.configure(values=new_notes.categories)
|
||||
self.category_choice.current(0)
|
||||
self.refresh_text(None)
|
||||
|
||||
def _set_date_range(self):
|
||||
pass
|
||||
|
||||
def _refresh_text(self, event):
|
||||
def refresh_text(self, event):
|
||||
self.text.config(state=tk.NORMAL)
|
||||
self.text.delete(1.0, tk.END)
|
||||
render_notes( self.notes.get(self.subjectChoice.current(), self.categoryChoice.current())
|
||||
, self.text)
|
||||
try:
|
||||
render_notes( self.notes.get(self.person_choice.current(), self.category_choice.current())
|
||||
, self.text)
|
||||
except IndexError:
|
||||
self.text.insert(tk.INSERT, "Veuillez sélectionner une personne et une catégorie")
|
||||
self.text.config(state=tk.DISABLED)
|
||||
|
||||
def _create_widgets(self):
|
||||
def __create_widgets(self):
|
||||
def combo_with_buttons(label, values):
|
||||
""" Builds a combo with cycling buttons, and returns the combobox """
|
||||
""" Builds a combo with cycling buttons, and returns the combobox.
|
||||
"""
|
||||
def cycle_choice(cbox, reversed=False):
|
||||
def do_it():
|
||||
def on_click():
|
||||
idx = cbox.current()
|
||||
max_idx = len(cbox["values"]) - 1
|
||||
if reversed:
|
||||
@@ -61,8 +71,8 @@ class App(tk.Frame):
|
||||
else:
|
||||
idx = idx + 1 if idx < max_idx else 0
|
||||
cbox.current(idx)
|
||||
self._refresh_text(None)
|
||||
return do_it
|
||||
self.refresh_text(None)
|
||||
return on_click
|
||||
# Build
|
||||
frame = new_frame_horiz(self.header)
|
||||
label = tk.Label(frame, text=label + " : ")
|
||||
@@ -70,19 +80,26 @@ class App(tk.Frame):
|
||||
cbox = ttk.Combobox(frame, values=values, state="readonly")
|
||||
prev_button = tk.Button(frame, text="<", command=cycle_choice(cbox, reversed=True))
|
||||
next_button = tk.Button(frame, text=">", command=cycle_choice(cbox))
|
||||
# Pack
|
||||
prev_button.pack(side=tk.LEFT)
|
||||
cbox.pack(side=tk.LEFT, fill=tk.X, expand=True)
|
||||
next_button.pack(side=tk.LEFT)
|
||||
# Configure
|
||||
cbox.current(0)
|
||||
cbox.bind("<<ComboboxSelected>>", self._refresh_text)
|
||||
cbox.bind("<<ComboboxSelected>>", self.refresh_text)
|
||||
return cbox
|
||||
|
||||
# Subject and Category selection
|
||||
self.header = tk.Frame(self)
|
||||
self.header.pack(side=tk.TOP, fill=tk.X)
|
||||
self.subjectChoice = combo_with_buttons("Résident", values=self.notes.subjects())
|
||||
self.categoryChoice = combo_with_buttons("Catégorie", values=self.notes.categories())
|
||||
try:
|
||||
persons = self.notes.persons()
|
||||
categories = self.notes.categories
|
||||
except AttributeError: # Init case
|
||||
persons = []
|
||||
categories = []
|
||||
self.person_choice = combo_with_buttons("Résident", values=persons)
|
||||
self.category_choice = combo_with_buttons("Catégorie", values=categories)
|
||||
|
||||
# Text view
|
||||
textView = tk.Frame(self)
|
||||
textView.pack(fill=tk.BOTH, expand=True)
|
||||
@@ -94,7 +111,6 @@ class App(tk.Frame):
|
||||
self.text.pack(fill=tk.BOTH, expand=True)
|
||||
scrollbar.config(command=self.text.yview)
|
||||
|
||||
self._refresh_text(None)
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user