cleaner coupling
This commit is contained in:
@@ -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()
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
66
xerus/gui.py
66
xerus/gui.py
@@ -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)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user