diff --git a/xerus/__main__.py b/xerus/__main__.py index ba3ee1f..6c791c8 100644 --- a/xerus/__main__.py +++ b/xerus/__main__.py @@ -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() diff --git a/xerus/data.py b/xerus/data.py index 530850e..fce50f2 100644 --- a/xerus/data.py +++ b/xerus/data.py @@ -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 diff --git a/xerus/gui.py b/xerus/gui.py index 0f46db1..c503a89 100644 --- a/xerus/gui.py +++ b/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("<>", self._refresh_text) + cbox.bind("<>", 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)