Added missing view files to native gui
This commit is contained in:
@@ -0,0 +1,199 @@
|
|||||||
|
# SPDX-License-Identifier: WTFPL
|
||||||
|
|
||||||
|
"""
|
||||||
|
Spezial:
|
||||||
|
Notebook mit Vessel, User, Lists, Company
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import gi
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
gi.require_version('Rsvg', '2.0')
|
||||||
|
from gi.repository import GLib, Gtk, Gdk, Rsvg
|
||||||
|
|
||||||
|
from .view import View
|
||||||
|
from yms import gtkutils, combobox, treeview
|
||||||
|
|
||||||
|
class BaseView(View):
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
super().__init__(context, _("Base Data"), "base.ui")
|
||||||
|
#self.title = _("Base Data")
|
||||||
|
#builder = Gtk.Builder()
|
||||||
|
#builder.set_translation_domain(context.textdomain)
|
||||||
|
#builder.add_from_file(os.path.join(context.ui_path, "base.ui"))
|
||||||
|
#builder.connect_signals(self)
|
||||||
|
#self.topwidget = builder.get_object("topobject")
|
||||||
|
#gtkutils.init_named_controls(self, builder)
|
||||||
|
|
||||||
|
# get current vessel data
|
||||||
|
self.db.cur.execute("SELECT valint FROM settings WHERE userid=0 AND sno=1")
|
||||||
|
row = self.db.cur.fetchone()
|
||||||
|
if not row:
|
||||||
|
self.context.vessel.vid = 0
|
||||||
|
self.context.vessel.vesselname = "Ghost"
|
||||||
|
self.db.cur.execute("INSERT INTO settings (userid, sno, valint) VALUES (0, 1, 0)")
|
||||||
|
self.db.conn.commit()
|
||||||
|
else:
|
||||||
|
self.context.vessel.vid = row[0]
|
||||||
|
|
||||||
|
# get list of vessels
|
||||||
|
vessellist = {}
|
||||||
|
self.db.dcur.execute("SELECT vid, vesselname, model FROM vessel ORDER BY vid")
|
||||||
|
for row in self.db.dcur.fetchall():
|
||||||
|
vessellist[row['vid']] = row['vesselname'] + " - " + row['model']
|
||||||
|
combobox.load_from_dict(self.combo['vessel'], vessellist, self.context.vessel.vid)
|
||||||
|
# vessel load triggered from combobox init
|
||||||
|
|
||||||
|
# prepare lists
|
||||||
|
self.lst_user = Gtk.ListStore(int, str)
|
||||||
|
self.db.cur.execute("SELECT userid, login FROM user WHERE userid > 0 ORDER BY login")
|
||||||
|
for row in self.db.cur.fetchall():
|
||||||
|
print(row)
|
||||||
|
self.lst_user.append(row)
|
||||||
|
treeview.add_column(self.tree['user'], 'ID', 0)
|
||||||
|
treeview.add_column(self.tree['user'], 'Login', 1)
|
||||||
|
self.tree['user'].set_model(self.lst_user)
|
||||||
|
|
||||||
|
# companies
|
||||||
|
"""
|
||||||
|
self.lst_companies = Gtk.ListStore(int, str, str, str)
|
||||||
|
self.db.cur.execute("SELECT compid, compname, comptype FROM company ORDER BY compname")
|
||||||
|
for row in self.db.cur.fetchall():
|
||||||
|
self.lst_user.append(row)
|
||||||
|
treeview.add_column(self.tree['companies'], _('ID'), 0)
|
||||||
|
treeview.add_column(self.tree['companies'], _('Name'), 1)
|
||||||
|
treeview.add_column(self.tree['companies'], _('Type'), 2)
|
||||||
|
self.tree['companies'].set_model(self.lst_companies)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# combos
|
||||||
|
roles = {'captain': 'Captain', 'helmsman': 'Helmsman', 'sailor': 'Sailor'}
|
||||||
|
combobox.load_from_dict(self.combo['user_role'], roles)
|
||||||
|
langs = {'de': 'Deutsch', 'en': 'English'}
|
||||||
|
combobox.load_from_dict(self.combo['user_lang'], langs)
|
||||||
|
|
||||||
|
# load shape of vessel if available
|
||||||
|
if self.context.vessel.vid > 0:
|
||||||
|
self.db.cur.execute("SELECT shapefile FROM vessel WHERE vid=%s", (self.context.vessel.vid, ))
|
||||||
|
filename = self.db.cur.fetchone()[0] or ''
|
||||||
|
shapefilepath = os.path.join(context.cfg['shapedir'], filename)
|
||||||
|
if os.path.isfile(shapefilepath):
|
||||||
|
handle = Rsvg.Handle()
|
||||||
|
self._svg = handle.new_from_file(shapefilepath)
|
||||||
|
#self._svg = handle.new_from_file(os.path.join(sys.path[0], cfg['shapedir'], "elizabethan29.svg"))
|
||||||
|
#viewport = Rsvg.Rectangle()
|
||||||
|
#viewport.x = 0
|
||||||
|
#viewport.y = 0
|
||||||
|
#viewport.width = 320
|
||||||
|
#viewport.height = 240
|
||||||
|
#self._svg.render_document(ctx, viewport)
|
||||||
|
|
||||||
|
# WIP generic remarks handling
|
||||||
|
self.text['vessel_remarks'].set_size_request(200, 70)
|
||||||
|
|
||||||
|
def on_cmb_vessel_changed(self, widget):
|
||||||
|
self.context.vessel.load(combobox.get_list_value(widget))
|
||||||
|
print(self.context.vessel)
|
||||||
|
sql = ("UPDATE settings SET valint=%s WHERE userid=0 AND sno=1")
|
||||||
|
self.db.cur.execute(sql, (self.context.vessel.vid,))
|
||||||
|
self.db.conn.commit()
|
||||||
|
# Show data
|
||||||
|
self.entry['vesselname'].set_text(self.context.vessel.vesselname)
|
||||||
|
self.entry['model'].set_text(self.context.vessel.model)
|
||||||
|
self.text['vessel_remarks'].get_buffer().set_text(self.context.vessel.remarks or '')
|
||||||
|
self.spin['loa'].set_value(9.80)
|
||||||
|
|
||||||
|
def on_but_vessel_add_clicked(self, widget):
|
||||||
|
print("Add vessel")
|
||||||
|
|
||||||
|
def on_but_vessel_save_clicked(self, widget):
|
||||||
|
print("Save vessel")
|
||||||
|
|
||||||
|
def on_but_comp_new_clicked(self, widget):
|
||||||
|
print("New company")
|
||||||
|
|
||||||
|
def on_but_comp_edit_clicked(self, widget):
|
||||||
|
print("Edit company")
|
||||||
|
|
||||||
|
def on_but_comp_detail_clicked(self, widget):
|
||||||
|
print("Company details")
|
||||||
|
|
||||||
|
def on_but_comp_save_clicked(self, widget):
|
||||||
|
print("Save company")
|
||||||
|
|
||||||
|
def on_but_comp_cancel_clicked(self, widget):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def user_display(self):
|
||||||
|
self.entry['user_login'].set_text(self.context.user.login)
|
||||||
|
self.entry['user_displayname'].set_text(self.context.user.displayname)
|
||||||
|
combobox.activate_row(self.combo['user_role'], self.context.user.role)
|
||||||
|
combobox.activate_row(self.combo['user_lang'], self.context.user.language)
|
||||||
|
self.check['user_locked'].set_active('locked' in self.context.user.flags)
|
||||||
|
self.check['user_deleted'].set_active('deleted' in self.context.user.flags)
|
||||||
|
self.entry['user_pass'].set_text('')
|
||||||
|
|
||||||
|
def on_tvw_user_row_activated(self, widget, path, column):
|
||||||
|
# load selected user
|
||||||
|
self.context.user.user_id = treeview.get_value(widget, 0)
|
||||||
|
self.context.user.load()
|
||||||
|
self.user_display()
|
||||||
|
|
||||||
|
def on_but_user_new_clicked(self, widget):
|
||||||
|
# get first free user id and create a new record with name "user<nnn>"
|
||||||
|
self.context.user.create()
|
||||||
|
self.lst_user.append((self.context.user.user_id, self.context.user.login))
|
||||||
|
|
||||||
|
def on_but_user_del_clicked(self, widget):
|
||||||
|
print("Delete user")
|
||||||
|
answer = gtkutils.questionbox(
|
||||||
|
_("Delete user!\n"
|
||||||
|
"Are you sure?"
|
||||||
|
), title="YMS")
|
||||||
|
if answer == False:
|
||||||
|
return
|
||||||
|
self.context.user.delete()
|
||||||
|
selection = self.tree['user'].get_selection()
|
||||||
|
model, tree_iter = selection.get_selected()
|
||||||
|
model.remove(tree_iter)
|
||||||
|
# TODO Select some other user from new list selection
|
||||||
|
self.context.user.user_id = treeview.get_value(self.tree['user'])
|
||||||
|
self.context.user.load()
|
||||||
|
self.user_display()
|
||||||
|
|
||||||
|
def on_but_user_newpass_clicked(self, widget):
|
||||||
|
self.entry['user_pass'].set_text(self.context.user.genpass())
|
||||||
|
|
||||||
|
def on_but_user_save_clicked(self, widget):
|
||||||
|
newlogin = self.entry['user_login'].get_text()
|
||||||
|
# check if changed login exists and throw error in that case
|
||||||
|
if newlogin != self.context.user.login:
|
||||||
|
sql = "SELECT COUNT(login) FROM user WHERE login=%s"
|
||||||
|
self.db.cur.execute(sql, (newlogin, ))
|
||||||
|
if self.db.cur.fetchone()[0] > 0:
|
||||||
|
# TODO set error indicator
|
||||||
|
print("Error: Login already exists!")
|
||||||
|
return
|
||||||
|
sql = "UPDATE user SET login=%s WHERE userid=%s"
|
||||||
|
self.db.cur.execute(sql, (newlogin, self.context.user.user_id))
|
||||||
|
treeview.set_value(self.tree['user'], 1, newlogin)
|
||||||
|
self.context.user.displayname = self.entry['user_displayname'].get_text()
|
||||||
|
self.context.user.role = combobox.get_list_value(self.combo['user_role'])
|
||||||
|
self.context.user.language = combobox.get_list_value(self.combo['user_lang'])
|
||||||
|
self.context.user.flags = []
|
||||||
|
if self.check['user_locked'].get_active(): self.context.user.flags.append('locked')
|
||||||
|
if self.check['user_deleted'].get_active(): self.context.user.flags.append('deleted')
|
||||||
|
self.context.user.save()
|
||||||
|
# password field is different. if filled set new password
|
||||||
|
newpass = self.entry['user_pass'].get_text()
|
||||||
|
if len(newpass) >= 8:
|
||||||
|
try:
|
||||||
|
self.context.user.setpass(newpass)
|
||||||
|
finally:
|
||||||
|
newpass = None
|
||||||
|
self.entry['user_pass'].set_text('')
|
||||||
|
else:
|
||||||
|
# Password to short
|
||||||
|
pass
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# SPDX-License-Identifier: WTFPL
|
||||||
|
|
||||||
|
import os
|
||||||
|
import gi
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import GLib, Gtk, Gdk
|
||||||
|
|
||||||
|
from yms import gtkutils, combobox, treeview
|
||||||
|
|
||||||
|
class DocumentsView:
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
self.title = _("Documents")
|
||||||
|
builder = Gtk.Builder()
|
||||||
|
builder.set_translation_domain(context.textdomain)
|
||||||
|
builder.add_from_file(os.path.join(context.ui_path, "documents.ui"))
|
||||||
|
builder.connect_signals(self)
|
||||||
|
self.topwidget = builder.get_object("topobject")
|
||||||
|
gtkutils.init_named_controls(self, builder)
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# SPDX-License-Identifier: WTFPL
|
||||||
|
|
||||||
|
import os
|
||||||
|
import gi
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import GLib, Gtk, Gdk
|
||||||
|
|
||||||
|
from yms import gtkutils, combobox, treeview
|
||||||
|
|
||||||
|
class EquipmentView:
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
self.title = _("Equipment")
|
||||||
|
builder = Gtk.Builder()
|
||||||
|
builder.set_translation_domain(context.textdomain)
|
||||||
|
builder.add_from_file(os.path.join(context.ui_path, "equipment.ui"))
|
||||||
|
builder.connect_signals(self)
|
||||||
|
self.topwidget = builder.get_object("stk_equipment")
|
||||||
|
gtkutils.init_named_controls(self, builder)
|
||||||
|
|
||||||
|
def on_but_new_clicked(self, widget):
|
||||||
|
self.topwidget.set_visible_child(self.box['equip_edit'])
|
||||||
|
|
||||||
|
def on_but_detail_clicked(self, widget):
|
||||||
|
self.topwidget.set_visible_child(self.box['equip_detail'])
|
||||||
|
|
||||||
|
def on_but_edit_clicked(self, widget):
|
||||||
|
self.topwidget.set_visible_child(self.box['equip_edit'])
|
||||||
|
|
||||||
|
def on_but_edit2_clicked(self, widget):
|
||||||
|
self.topwidget.set_visible_child(self.box['equip_edit'])
|
||||||
|
|
||||||
|
def on_but_close_clicked(self, widget):
|
||||||
|
self.topwidget.set_visible_child(self.box['equip_detail'])
|
||||||
|
|
||||||
|
def on_but_save_clicked(self, widget):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_but_delete_clicked(self, widget):
|
||||||
|
self.topwidget.set_visible_child(self.box['equipment'])
|
||||||
|
|
||||||
|
def on_but_cancel_clicked(self, widget):
|
||||||
|
self.topwidget.set_visible_child(self.box['equipment'])
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# SPDX-License-Identifier: WTFPL
|
||||||
|
|
||||||
|
import os
|
||||||
|
import gi
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import GLib, Gtk, Gdk
|
||||||
|
|
||||||
|
from yms import gtkutils, combobox, treeview
|
||||||
|
|
||||||
|
class InventoryView:
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
self.title = _("Inventory")
|
||||||
|
builder = Gtk.Builder()
|
||||||
|
builder.set_translation_domain(context.textdomain)
|
||||||
|
builder.add_from_file(os.path.join(context.ui_path, "inventory.ui"))
|
||||||
|
builder.connect_signals(self)
|
||||||
|
self.topwidget = builder.get_object("topobject")
|
||||||
|
gtkutils.init_named_controls(self, builder)
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# SPDX-License-Identifier: WTFPL
|
||||||
|
|
||||||
|
import os
|
||||||
|
import gi
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
from yms import gtkutils, combobox, treeview
|
||||||
|
|
||||||
|
class MaintenanceView:
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
self.title = _("Maintenance")
|
||||||
|
builder = Gtk.Builder()
|
||||||
|
builder.set_translation_domain(context.textdomain)
|
||||||
|
builder.add_from_file(os.path.join(context.ui_path, "maintenance.ui"))
|
||||||
|
builder.connect_signals(self)
|
||||||
|
self.topwidget = builder.get_object("topobject")
|
||||||
|
gtkutils.init_named_controls(self, builder)
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# SPDX-License-Identifier: WTFPL
|
||||||
|
|
||||||
|
import os
|
||||||
|
import gi
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
from yms import gtkutils, combobox, treeview
|
||||||
|
|
||||||
|
class ProjectsView:
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
self.title = _("Projects")
|
||||||
|
builder = Gtk.Builder()
|
||||||
|
builder.set_translation_domain(context.textdomain)
|
||||||
|
builder.add_from_file(os.path.join(context.ui_path, "projects.ui"))
|
||||||
|
builder.connect_signals(self)
|
||||||
|
self.topwidget = builder.get_object("topobject")
|
||||||
|
gtkutils.init_named_controls(self, builder)
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# SPDX-License-Identifier: WTFPL
|
||||||
|
|
||||||
|
import os
|
||||||
|
import gi
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
from yms import gtkutils, combobox, treeview
|
||||||
|
|
||||||
|
class ProvisionsView:
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
self.title = _("Provisions")
|
||||||
|
builder = Gtk.Builder()
|
||||||
|
builder.set_translation_domain(context.textdomain)
|
||||||
|
builder.add_from_file(os.path.join(context.ui_path, "provisions.ui"))
|
||||||
|
builder.connect_signals(self)
|
||||||
|
self.topwidget = builder.get_object("topobject")
|
||||||
|
gtkutils.init_named_controls(self, builder)
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# SPDX-License-Identifier: WTFPL
|
||||||
|
|
||||||
|
import os
|
||||||
|
import gi
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
from yms import gtkutils, combobox, treeview
|
||||||
|
|
||||||
|
class StatusView:
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
self.context = context
|
||||||
|
self.title = _("Status")
|
||||||
|
builder = Gtk.Builder()
|
||||||
|
builder.set_translation_domain(context.textdomain)
|
||||||
|
builder.add_from_file(os.path.join(context.ui_path, "status.ui"))
|
||||||
|
builder.connect_signals(self)
|
||||||
|
self.topwidget = builder.get_object("topobject")
|
||||||
|
gtkutils.init_named_controls(self, builder)
|
||||||
|
|
||||||
|
# Load table status info
|
||||||
|
self.lst_tables = Gtk.ListStore(str, int)
|
||||||
|
for row in self.get_table_counts():
|
||||||
|
self.lst_tables.append(row)
|
||||||
|
treeview.add_column(self.tree['tables'], 'Table', 0)
|
||||||
|
treeview.add_column(self.tree['tables'], '# Records', 1)
|
||||||
|
self.tree['tables'].set_model(self.lst_tables)
|
||||||
|
|
||||||
|
def get_table_counts(self):
|
||||||
|
# Detect all tables in database
|
||||||
|
sql= ("SELECT table_name "
|
||||||
|
"FROM information_schema.tables "
|
||||||
|
"WHERE table_schema='yms' AND table_type='BASE TABLE' "
|
||||||
|
"ORDER BY table_name")
|
||||||
|
self.context.db.cur.execute(sql)
|
||||||
|
tables = [row[0] for row in self.context.db.cur.fetchall()]
|
||||||
|
# Loop over tables and get current record count
|
||||||
|
records = []
|
||||||
|
for table in tables:
|
||||||
|
sql = f"SELECT COUNT(*) FROM {table}"
|
||||||
|
self.context.db.cur.execute(sql)
|
||||||
|
records.append((table, self.context.db.cur.fetchone()[0]))
|
||||||
|
return records
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
# SPDX-License-Identifier: WTFPL
|
||||||
|
|
||||||
|
"""
|
||||||
|
Generic view object
|
||||||
|
|
||||||
|
SPDX-License-Identifier: WTFPL
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import gi
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from yms import gtkutils
|
||||||
|
|
||||||
|
class View:
|
||||||
|
def __init__(self, context, title, ui_file):
|
||||||
|
self.context = context
|
||||||
|
self.db = context.db
|
||||||
|
self.vessel = context.vessel
|
||||||
|
self.user = context.user
|
||||||
|
self.title = title
|
||||||
|
builder = Gtk.Builder()
|
||||||
|
builder.set_translation_domain(context.textdomain)
|
||||||
|
builder.add_from_file(os.path.join(context.ui_path, ui_file))
|
||||||
|
builder.connect_signals(self)
|
||||||
|
self.topwidget = builder.get_object("topobject")
|
||||||
|
gtkutils.init_named_controls(self, builder)
|
||||||
|
|
||||||
|
def on_textview_keypress(self, widget, event):
|
||||||
|
# Generic limit length function
|
||||||
|
if event.state & Gdk.ModifierType.CONTROL_MASK:
|
||||||
|
allowed_ctrl_keys = (
|
||||||
|
Gdk.KEY_a,
|
||||||
|
Gdk.KEY_c,
|
||||||
|
Gdk.KEY_x,
|
||||||
|
)
|
||||||
|
if event.keyval in allowed_ctrl_keys:
|
||||||
|
return False
|
||||||
|
allowed_keys = (
|
||||||
|
Gdk.KEY_BackSpace,
|
||||||
|
Gdk.KEY_Delete,
|
||||||
|
Gdk.KEY_Left,
|
||||||
|
Gdk.KEY_Right,
|
||||||
|
Gdk.KEY_Up,
|
||||||
|
Gdk.KEY_Down,
|
||||||
|
Gdk.KEY_Home,
|
||||||
|
Gdk.KEY_End,
|
||||||
|
Gdk.KEY_Page_Up,
|
||||||
|
Gdk.KEY_Page_Down,
|
||||||
|
)
|
||||||
|
print("keypress")
|
||||||
|
if event.keyval in allowed_keys:
|
||||||
|
return False
|
||||||
|
buf = widget.get_buffer()
|
||||||
|
start = buf.get_start_iter()
|
||||||
|
end = buf.get_end_iter()
|
||||||
|
text = buf.get_text(start, end, True)
|
||||||
|
if len(text) >= 150:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def on_textview_paste(self, widget):
|
||||||
|
# Generic limit length function
|
||||||
|
print("paste")
|
||||||
|
buf = widget.get_buffer()
|
||||||
|
start = buf.get_start_iter()
|
||||||
|
end = buf.get_end_iter()
|
||||||
|
text = buf.get_text(start, end, True)
|
||||||
|
if buf.get_has_selection():
|
||||||
|
sel_start, sel_end = buf.get_selection_bounds()
|
||||||
|
selected_text = buf.get_text(sel_start, sel_end, True)
|
||||||
|
current_length = len(text) - len(selected_text)
|
||||||
|
else:
|
||||||
|
current_length = len(text)
|
||||||
|
remaining = 150 - current_length
|
||||||
|
if remaining <= 0:
|
||||||
|
return True
|
||||||
|
clipboard = widget.get_clipboard(Gdk.SELECTION_CLIPBOARD)
|
||||||
|
cliptext = clipboard.wait_for_text()
|
||||||
|
if cliptext:
|
||||||
|
cliptext = cliptext[:remaining]
|
||||||
|
if buf.get_has_selection():
|
||||||
|
sel_start, sel_end = buf.get_selection_bounds()
|
||||||
|
buf.delete(sel_start, sel_end)
|
||||||
|
buf.insert_at_cursor(text)
|
||||||
|
return True
|
||||||
Reference in New Issue
Block a user