cleaner coupling

This commit is contained in:
2020-04-04 15:35:17 +02:00
parent 01caa47fd1
commit a4bc0c8cf1
3 changed files with 98 additions and 43 deletions

View File

@@ -1,7 +1,11 @@
# -*- coding:utf-8 -*- # -*- coding:utf-8 -*-
from .gui import App from .gui import NoteViewer
from .data import Notes
app = App() # Load notes
app.run() notes = Notes("testdata")
# View them
viewer = NoteViewer(notes)
viewer.run()

View File

@@ -1,4 +1,6 @@
# -*- coding:utf-8 -*- # -*- coding:utf-8 -*-
import random
from collections import namedtuple
def test_data(): def test_data():
return { "Henri" : 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): class Notes(dict):
""" Store of notes grouped by subject and category """ """ Store of notes grouped by subject and category """
def __init__(self, source): def __init__(self, source):
self._categories = None super().__init__()
super().__init__([data for data in test_data().items()]) 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 """ """ Returns list of subjects """
return list(self.keys()) return list(self.keys())
def categories(self): def get(self, person_idx, category_idx, date_range=None):
""" 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):
""" Filter notes by subject, category and date """ """ 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 # TODO: deduplicate categories by using a tuple
category = list(self.categories())[category_idx] category = self.categories[category_idx]
notes = self[subject][category] notes = self[person][category]
if date_range is not None: if date_range is not None:
# TODO: filter by date # TODO: filter by date
pass pass

View File

@@ -10,9 +10,7 @@ def new_frame_horiz(parent):
frame.pack(fill=tk.X, expand=True) frame.pack(fill=tk.X, expand=True)
return frame return frame
def render_notes(notes, text_area): def render_notes(notes, text_area):
# Text
for date, notes in notes.items(): for date, notes in notes.items():
text_area.insert(tk.INSERT, f"{date}\n\n", "d") text_area.insert(tk.INSERT, f"{date}\n\n", "d")
for note in notes: for note in notes:
@@ -21,39 +19,51 @@ def render_notes(notes, text_area):
text_area.insert(tk.INSERT, "\n") text_area.insert(tk.INSERT, "\n")
class NoteViewer(tk.Frame):
class App(tk.Frame): __notes = None
def __init__(self, master=None): def __init__(self, notes, master=None):
super().__init__(master) super().__init__(master)
self.pack(fill=tk.BOTH, expand=True) self.pack(fill=tk.BOTH, expand=True)
self.__create_widgets()
self.notes = notes
def run(self): def run(self):
self.notes = Notes(None) """ Launch the viewer """
self._create_widgets()
self.mainloop() self.mainloop()
def _set_subject(self): @property
pass def notes(self):
return self.__notes
def _set_category(self): @notes.setter
pass 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): def refresh_text(self, event):
pass
def _refresh_text(self, event):
self.text.config(state=tk.NORMAL) self.text.config(state=tk.NORMAL)
self.text.delete(1.0, tk.END) self.text.delete(1.0, tk.END)
render_notes( self.notes.get(self.subjectChoice.current(), self.categoryChoice.current()) try:
render_notes( self.notes.get(self.person_choice.current(), self.category_choice.current())
, self.text) , self.text)
except IndexError:
self.text.insert(tk.INSERT, "Veuillez sélectionner une personne et une catégorie")
self.text.config(state=tk.DISABLED) self.text.config(state=tk.DISABLED)
def _create_widgets(self): def __create_widgets(self):
def combo_with_buttons(label, values): 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 cycle_choice(cbox, reversed=False):
def do_it(): def on_click():
idx = cbox.current() idx = cbox.current()
max_idx = len(cbox["values"]) - 1 max_idx = len(cbox["values"]) - 1
if reversed: if reversed:
@@ -61,8 +71,8 @@ class App(tk.Frame):
else: else:
idx = idx + 1 if idx < max_idx else 0 idx = idx + 1 if idx < max_idx else 0
cbox.current(idx) cbox.current(idx)
self._refresh_text(None) self.refresh_text(None)
return do_it return on_click
# Build # Build
frame = new_frame_horiz(self.header) frame = new_frame_horiz(self.header)
label = tk.Label(frame, text=label + " : ") label = tk.Label(frame, text=label + " : ")
@@ -70,19 +80,26 @@ class App(tk.Frame):
cbox = ttk.Combobox(frame, values=values, state="readonly") cbox = ttk.Combobox(frame, values=values, state="readonly")
prev_button = tk.Button(frame, text="<", command=cycle_choice(cbox, reversed=True)) prev_button = tk.Button(frame, text="<", command=cycle_choice(cbox, reversed=True))
next_button = tk.Button(frame, text=">", command=cycle_choice(cbox)) next_button = tk.Button(frame, text=">", command=cycle_choice(cbox))
# Pack
prev_button.pack(side=tk.LEFT) prev_button.pack(side=tk.LEFT)
cbox.pack(side=tk.LEFT, fill=tk.X, expand=True) cbox.pack(side=tk.LEFT, fill=tk.X, expand=True)
next_button.pack(side=tk.LEFT) next_button.pack(side=tk.LEFT)
# Configure # Configure
cbox.current(0) cbox.bind("<<ComboboxSelected>>", self.refresh_text)
cbox.bind("<<ComboboxSelected>>", self._refresh_text)
return cbox return cbox
# Subject and Category selection # Subject and Category selection
self.header = tk.Frame(self) self.header = tk.Frame(self)
self.header.pack(side=tk.TOP, fill=tk.X) self.header.pack(side=tk.TOP, fill=tk.X)
self.subjectChoice = combo_with_buttons("Résident", values=self.notes.subjects()) try:
self.categoryChoice = combo_with_buttons("Catégorie", values=self.notes.categories()) 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 # Text view
textView = tk.Frame(self) textView = tk.Frame(self)
textView.pack(fill=tk.BOTH, expand=True) textView.pack(fill=tk.BOTH, expand=True)
@@ -94,7 +111,6 @@ class App(tk.Frame):
self.text.pack(fill=tk.BOTH, expand=True) self.text.pack(fill=tk.BOTH, expand=True)
scrollbar.config(command=self.text.yview) scrollbar.config(command=self.text.yview)
self._refresh_text(None)