eldoc/mods/lists.py

292 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject, Gdk
from mods.db import db, List, ListRecord, ListRecordIndex
from mods.files import open_list_win_file, listrecord_row_ui_str, editable_row_ui_str, list_row_ui_str
from mods.utils import show_msg, disable_widget, enable_widget, ConditionalFilter
import re
import peewee
ANAMNEZ_LIST = 'anamnez'
OBSERVE_LIST = 'observ'
lists_map = {
ANAMNEZ_LIST: 'Анамнез',
OBSERVE_LIST: 'Осмотр',
}
for s_id in lists_map:
with db.atomic():
q = List.select().where(List.system_id == s_id)
if not len(q):
List.create(name=lists_map[s_id], system_id=s_id)
class ListRecFilter(ConditionalFilter):
def filter(self, list_id, query):
if query != self.fstr:
self.fstr = query
self.ids = list(map(lambda x: x.id, self.search_func(list_id, query)))
return self.ids
class ListRow(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
@GObject.Property
def name(self):
return self._name
@name.setter
def name_setter(self, value):
self._name = value
class ListRecordRow(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
@GObject.Property
def text(self):
return self._text
@text.setter
def text_setter(self, value):
self._text = value
def get_list(list_id):
with db.atomic():
return List.get_by_id(list_id)
def get_list_by_system_id(s_id):
with db.atomic():
return List.select().where(List.system_id == s_id).get()
def get_listrecord(listrec_id):
with db.atomic():
return ListRecord.get_by_id(listrec_id)
def get_all_list_records(list_id):
with db.atomic():
list_o = List.get_by_id(list_id)
return ListRecord.select().where(ListRecord.list == list_o)
def add_list_record(list_id, text):
with db.atomic():
list_o = List.get_by_id(list_id)
rec = ListRecord.create(list=list_o, text=text)
ListRecordIndex.insert(
{
ListRecordIndex.rowid: rec.id,
ListRecordIndex.text: text
}
).execute()
return rec
def delete_list_record(listrec_id):
with db.atomic():
ListRecord.delete().where(ListRecord.id == listrec_id).execute()
ListRecordIndex.delete().where(ListRecordIndex.rowid == listrec_id).execute()
def change_list_record(listrec_id, new_text):
listrec_o = get_listrecord(listrec_id)
if listrec_o.text == new_text:
return listrec_o
with db.atomic():
ListRecord.update(text=new_text).where(ListRecord.id == listrec_id).execute()
ListRecordIndex.update(text=new_text).where(ListRecordIndex.rowid == listrec_id).execute()
return ListRecord.get_by_id(listrec_id)
def search_list_record(list_id, q):
q = re.sub(r'\s+', ' ', q).strip()
q = ' '.join([ f'{x}*' for x in q.split(' ')])
list_o = get_list(list_id)
with db.atomic():
return (ListRecord.select()
.join(
ListRecordIndex,
on=(ListRecord.id == ListRecordIndex.rowid))
.where((ListRecord.list == list_o) & (ListRecordIndex.match(q)))
.order_by(ListRecordIndex.bm25()))
#####################################################################################################################
def build_list_row(list_o):
b = Gtk.Builder()
b.add_from_string(list_row_ui_str)
win = b.get_object('win')
box = b.get_object('list_box')
b.get_object('name').set_text(list_o.name)
row = ListRow()
row.props.db_id = list_o.id
row.name = list_o.name
win.remove(win.get_children()[0])
row.add(box)
return row
def build_listrecord_row(listrec_o):
b = Gtk.Builder()
b.add_from_string(listrecord_row_ui_str)
win = b.get_object('win')
box = b.get_object('listrecord_box')
b.get_object('text').set_text(listrec_o.text)
row = ListRecordRow()
row.props.db_id = listrec_o.id
row.text = listrec_o.text
win.remove(win.get_children()[0])
row.add(box)
return row
def build_listrec_editable_row(listrec_o=None):
b = Gtk.Builder()
b.add_from_string(editable_row_ui_str)
#b.connect_signals({'editing_done': listrec_editing_done})
win = b.get_object('win')
box = b.get_object('editable_box')
text_input = b.get_object('text_input')
text_input.set_text(listrec_o.text if listrec_o else '')
row = ListRecordRow()
row.props.db_id = listrec_o.id if listrec_o else -1
row.text = listrec_o.text if listrec_o else ''
win.remove(win.get_children()[0])
row.add(box)
return (row, text_input)
def create_open_list_win(list_id, choose=False, parent_list=None):
list_o = get_list(list_id)
b = Gtk.Builder()
listrecord_filter = ListRecFilter(search_list_record)
class OpenListHandler:
def row_add_cancel(self, entry, ev, row):
if ev.keyval == Gdk.KEY_Escape:
lr_list.remove(row)
row.destroy()
lr_list.unselect_all()
self.listrec_row_unselected()
def row_edit_cancel(self, entry, ev, edit_row):
if ev.keyval == Gdk.KEY_Escape:
rec = get_listrecord(edit_row.props.db_id)
row = build_listrecord_row(rec)
lr_list.remove(edit_row)
edit_row.destroy()
lr_list.unselect_all()
lr_list.add(row)
lr_list.show_all()
def enable_buttons_on_add_edit(self, *a):
enable_widget([add_button, edit_button, remove_button, lr_filter])
def remove_row(self, button):
row = lr_list.get_selected_row()
delete_list_record(row.props.db_id)
lr_list.remove(row)
row.destroy()
lr_list.unselect_all()
lr_list.show_all()
self.listrec_row_unselected()
def edit_row(self, button):
row = lr_list.get_selected_row()
rec = get_listrecord(row.props.db_id)
(edit_row, inp) = build_listrec_editable_row(rec)
lr_list.remove(row)
row.destroy()
lr_list.add(edit_row)
inp.grab_focus()
inp.connect('key-release-event', self.row_edit_cancel, edit_row)
inp.connect('activate', self.update_row, edit_row)
inp.connect('destroy', self.enable_buttons_on_add_edit)
lr_list.unselect_all()
disable_widget([add_button, edit_button, remove_button, lr_filter])
lr_list.show_all()
def add_new_row(self, button):
(row, text_input) = build_listrec_editable_row()
lr_list.add(row)
text_input.grab_focus()
text_input.connect('key-release-event', self.row_add_cancel, row)
text_input.connect('activate', self.save_new_row, row)
text_input.connect('destroy', self.enable_buttons_on_add_edit)
lr_list.unselect_all()
disable_widget([add_button, edit_button, remove_button, lr_filter])
lr_list.show_all()
def update_row(self, inp, edit_row):
new_text = re.sub(r'\s+', ' ', inp.get_text()).strip()
if new_text:
try:
rec = change_list_record(edit_row.props.db_id, new_text)
except peewee.IntegrityError:
return show_msg('Такая же запись уже существует', 'В данном списке уже существует\nдругая запись с данным текстом', level='warn')
row = build_listrecord_row(rec)
else:
row = build_listrecord_row(get_listrecord(edit_row.props.db_id))
lr_list.add(row)
lr_list.select_row(row)
lr_list.show_all()
lr_list.remove(edit_row)
edit_row.destroy()
def save_new_row(self, inp, row):
row_text = re.sub(r'\s+', ' ', inp.get_text()).strip()
if row_text:
try:
rec = add_list_record(list_id, row_text)
except peewee.IntegrityError:
return show_msg('Данная запись уже существует', 'В данном списке уже существует\nзапись с данным текстом', level='warn')
new_row = build_listrecord_row(rec)
lr_list.add(new_row)
lr_list.select_row(new_row)
lr_list.show_all()
lr_list.remove(row)
row.destroy()
def listrec_row_selected(self, *a):
enable_widget([edit_button, remove_button])
if choose:
enable_widget([accept_button])
def listrec_row_unselected(self, *a):
disable_widget([edit_button, remove_button])
if choose:
disable_widget([accept_button])
def listrec_filter_changed(self, filter_widget):
lr_list.unselect_all()
self.listrec_row_unselected()
lr_list.invalidate_filter()
def submit(self, button):
from mods.receptions import build_reception_anamnesis_row
exist_rows = list(map(lambda x: x.props.db_id, parent_list.get_children()))
rows = lr_list.get_selected_rows()
for row in rows:
if row.props.db_id not in exist_rows:
anamnesis = get_listrecord(row.props.db_id)
parent_list.add(build_reception_anamnesis_row(anamnesis))
parent_list.show_all()
w.destroy()
b.add_from_file(open_list_win_file)
olh = OpenListHandler()
b.connect_signals(olh)
# Gtk objects
w = b.get_object('open_list_window')
lr_list = b.get_object('listrecord_list')
lr_filter = b.get_object('listrecord_filter')
add_button = b.get_object('add_button')
edit_button = b.get_object('edit_button')
remove_button = b.get_object('remove_button')
list_header = b.get_object('list_win_header')
accept_place_box = b.get_object('accept_place')
sep_place_box = b.get_object('sep_place')
if choose:
sep_place_box.pack_start(Gtk.Separator(orientation=Gtk.Orientation.VERTICAL), True, True, 0)
accept_button_img = Gtk.Image()
accept_button_img.set_from_icon_name('object-select-symbolic', Gtk.IconSize.BUTTON)
accept_button = Gtk.Button()
accept_button.set_image(accept_button_img)
accept_place_box.pack_start(accept_button, True, True, 0)
accept_button.connect('clicked', olh.submit)
#############
######
def listrecord_sort_func(row1, row2, *a):
text1 = row1.props.text
text2 = row2.props.text
return (text1 > text2) - (text1 < text2)
def listrecord_filter_func(row):
fstr = lr_filter.get_text().strip()
if not fstr:
listrecord_filter.reset()
return True
return row.props.db_id in listrecord_filter.filter(list_id, fstr)
######
lr_list.set_sort_func(listrecord_sort_func)
lr_list.set_filter_func(listrecord_filter_func)
list_header.props.title = list_o.name
for lr in get_all_list_records(list_id):
lr_list.add(build_listrecord_row(lr))
return w