import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, GObject from mods.files import choose_diagnosis_win_file, diagnosis_row_ui_str from mods.utils import ConditionalFilter, enable_widget, disable_widget from mods.db import DiagnosisCategory, Diagnosis, DiagnosisIndex, db import re class DiagnosisFilter(ConditionalFilter): cat = None def filter(self, query): if query != self.fstr: self.fstr = query self.ids = list(map(lambda x:x.id, self.search_func(self.cat, query))) return self.ids class DiagnosisRow(Gtk.ListBoxRow): @GObject.Property def db_id(self): return self._db_id @db_id.setter def db_id_setter(self, value): self._db_id = value def cats_subcats(cat): cats = [cat] def append_cat(cat_obj): cats.append(cat_obj) for c in cat_obj.subcat: append_cat(c) for c in cat.subcat: append_cat(c) return cats def get_categories(parent=None): with db.atomic(): return DiagnosisCategory.select().where(DiagnosisCategory.parent == parent) def get_reception_diagnosis_items(cat=None): with db.atomic(): if cat: d = list(Diagnosis.select().where(Diagnosis.category == cat).order_by(Diagnosis.code)) return d else: return Diagnosis.select() def get_category(cat_id): with db.atomic(): return DiagnosisCategory.get_by_id(cat_id) def get_giagnosis(diag_id): with db.atomic(): return Diagnosis.get_by_id(diag_id) def search_diagnosises(cat, q): q = re.sub(r'\s+', ' ', q).strip() q = ' '.join([ f'{x}*' for x in q.split(' ')]) with db.atomic(): return (Diagnosis.select() .join( DiagnosisIndex, on=(Diagnosis.id == DiagnosisIndex.rowid)) .where((Diagnosis.category == cat) & (DiagnosisIndex.match(q))) .order_by(DiagnosisIndex.bm25())) diagnosis_filter = DiagnosisFilter(search_diagnosises) ######################################################## def build_diagnosis_row(diagnosis): b = Gtk.Builder() b.add_from_string(diagnosis_row_ui_str) win = b.get_object('win') box = b.get_object('diagnosis_box') b.get_object('title').set_markup(f'{diagnosis.code:<8} {diagnosis.title}') win.remove(win.get_children()[0]) row = DiagnosisRow() row.props.db_id = diagnosis.id row.add(box) return row def create_choose_diagnosis_win(reception_b): b = Gtk.Builder() rd_list = reception_b.get_object('diagnosis_list') class ChooseDiagnosisWinHandler: def cat_selection_changed(self, cat_selection): sel_iter = cat_selection.get_selected()[1] model = cat_selection.get_tree_view().get_model() category = get_category(model.get_value(sel_iter, 1)) diagnosis_filter.cat = category diagnosis_list.unselect_all() self.diagnosis_row_unselected() self.redraw_diagnosis_list(category) def redraw_diagnosis_list(self, cat): for c in diagnosis_list.get_children(): diagnosis_list.remove(c) for d in get_reception_diagnosis_items(cat): diagnosis_list.add(build_diagnosis_row(d)) diagnosis_list.show_all() def diagnosis_row_selected(self, *a): enable_widget([accept_button]) def diagnosis_row_unselected(self, *a): disable_widget([accept_button]) def diagnosis_filter_changed(self, filter_widget): diagnosis_list.unselect_all() self.diagnosis_row_unselected() diagnosis_list.invalidate_filter() def submit(self, button): from mods.receptions import build_reception_diagnosis_row exist_rows = list(map(lambda x: x.props.db_id, rd_list.get_children())) rows = diagnosis_list.get_selected_rows() for row in rows: if row.props.db_id not in exist_rows: diagnosis = get_giagnosis(row.props.db_id) rd_list.add(build_reception_diagnosis_row(diagnosis)) rd_list.show_all() w.destroy() b.add_from_file(choose_diagnosis_win_file) b.connect_signals(ChooseDiagnosisWinHandler()) cat_liststore = b.get_object('category_list') def insert_cat(cat, parent=None): cur_parent = cat_liststore.append(parent, [cat.title, cat.id]) for c in get_categories(cat): insert_cat(c, cur_parent) for c in get_categories(): insert_cat(c) diagnosis_list = b.get_object('diagnosis_list') di_filter = b.get_object('diagnosis_filter') accept_button = b.get_object('accept_button') ##### def diagnosis_filter_func(row): fstr = di_filter.get_text().strip() if not fstr: diagnosis_filter.reset() return True return row.props.db_id in diagnosis_filter.filter(fstr) ##### diagnosis_list.set_filter_func(diagnosis_filter_func) w = b.get_object('choose_diagnosis_window') return w