150 lines
5.6 KiB
Python
150 lines
5.6 KiB
Python
# SPDX-License-Identifier: WTFPL
|
|
|
|
import os
|
|
import re
|
|
from gi.repository import Gtk, Rsvg
|
|
import xml.etree.ElementTree as ET
|
|
|
|
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)
|
|
|
|
# Generic information
|
|
self.label['version'].set_text("YMS version {}".format(context.__version__))
|
|
self.label['dbinfo'].set_text("Database: {} on {}".format(context.cfg['db'], context.cfg['host']))
|
|
|
|
# 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)
|
|
|
|
# Load current config file
|
|
self.label['config'].set_label(context.cfg['cfgfile'])
|
|
cfgfile = os.path.expanduser(context.cfg['cfgfile'])
|
|
try:
|
|
with open(cfgfile, "r", encoding="utf-8") as f:
|
|
contents = f.read()
|
|
except OSError as e:
|
|
contents = f"Could not read file: {e}"
|
|
contents = re.sub(r'(^\s*pass\s*=\s*).*$', r'\1********', contents, flags=re.MULTILINE)
|
|
self.text ['config'].get_buffer().set_text(contents)
|
|
|
|
# data for svg deck plan
|
|
self.svg = None
|
|
self.svg_width = 0
|
|
self.svg_height = 0
|
|
self.svg_scale = 1.0
|
|
self.svg_x = 0.0
|
|
self.svg_y = 0.0
|
|
self.svg_centerline_y = 0.0
|
|
self.load_svg()
|
|
|
|
def load_svg(self):
|
|
if not self.context.vessel.shapefile:
|
|
print("No Shapefile defined for current vessel")
|
|
return
|
|
shapefile = os.path.join(self.context.cfg['shapedir'], self.context.vessel.shapefile)
|
|
if not (os.path.isfile(shapefile) or os.access(shapefile, os.R_OK)):
|
|
print(f"Shapefile '{shapefile}' not found or not readable")
|
|
return
|
|
try:
|
|
self.svg = Rsvg.Handle.new_from_file(shapefile)
|
|
success, width, height = self.svg.get_intrinsic_size_in_pixels()
|
|
if not success:
|
|
raise RuntimeError("SVG has no pixelsize")
|
|
self.svg_width = width
|
|
self.svg_height = height
|
|
print(f"SVG: {self.svg_width} x {self.svg_height}")
|
|
self.area['status'].queue_draw()
|
|
except Exception as e:
|
|
print("Error trying to load svg deck plan:", e)
|
|
return
|
|
# try to detect centerline
|
|
self.svg_centerline_y = None
|
|
try:
|
|
tree = ET.parse(shapefile)
|
|
except Exception as e:
|
|
print("Error reading centerline from svg:", e)
|
|
self.svg_centerline_y = self.svg_height / 2
|
|
return
|
|
root = tree.getroot()
|
|
found = False
|
|
for element in root.iter():
|
|
if element.get("id") == "centerline":
|
|
found = True
|
|
print("\n--- centerline gefunden ---")
|
|
print("Tag:", element.tag)
|
|
print("Attribute:", element.attrib)
|
|
y1 = element.get("y1")
|
|
y2 = element.get("y2")
|
|
if y1 is not None and y2 is not None:
|
|
y1 = float(y1)
|
|
y2 = float(y2)
|
|
if not math.isclose(y1, y2, abs_tol=0.001):
|
|
raise ValueError(f"centerline not horizontal: y1={y1}, y2={y2}")
|
|
# calc arithmetic mean as fallback
|
|
self.centerline_y = (y1 + y2) / 2
|
|
else:
|
|
self.centerline_y = y1
|
|
print(f"centerline: SVG Y = {self.centerline_y}")
|
|
return
|
|
if not found:
|
|
print("No centerline with id='centerline' found!")
|
|
|
|
def on_drw_status_draw(self, area, cr):
|
|
cr.set_source_rgb(0.92, 0.97, 1.0)
|
|
cr.paint()
|
|
|
|
allocation = area.get_allocation()
|
|
scale_x = allocation.width / self.svg_width
|
|
scale_y = allocation.height / self.svg_height
|
|
self.svg_scale = min(scale_x, scale_y)
|
|
|
|
width = self.svg_width * self.svg_scale
|
|
height = self.svg_height * self.svg_scale
|
|
|
|
self.svg_x = (allocation.width - width) / 2
|
|
self.svg_y = (allocation.height - height) / 2
|
|
|
|
cr.save()
|
|
cr.translate(self.svg_x, self.svg_y)
|
|
cr.scale(self.svg_scale, self.svg_scale)
|
|
viewport = Rsvg.Rectangle()
|
|
viewport.x = 0
|
|
viewport.y = 0
|
|
viewport.width = self.svg_width
|
|
viewport.height = self.svg_height
|
|
self.svg.render_document(cr, viewport)
|
|
cr.restore()
|
|
|
|
return False
|
|
|
|
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
|