260 lines
9.9 KiB
Python
260 lines
9.9 KiB
Python
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'
|
||
OBSERV_LIST = 'observ'
|
||
|
||
lists_map = {
|
||
ANAMNEZ_LIST: 'Анамнез',
|
||
OBSERV_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_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):
|
||
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.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.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)
|
||
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)
|
||
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])
|
||
def listrec_row_unselected(self, *a):
|
||
disable_widget([edit_button, remove_button])
|
||
def listrec_filter_changed(self, filter_widget):
|
||
lr_list.unselect_all()
|
||
self.listrec_row_unselected()
|
||
lr_list.invalidate_filter()
|
||
b.add_from_file(open_list_win_file)
|
||
b.connect_signals(OpenListHandler())
|
||
# 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')
|
||
#############
|
||
######
|
||
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
|
||
|