Fixes for webgui and more native gui development

This commit is contained in:
2026-09-16 19:07:10 +02:00
parent 9b45fd3700
commit 2fc74c0677
31 changed files with 2143 additions and 417 deletions
+6 -6
View File
@@ -62,10 +62,10 @@ Optional import some sample data
4. Initialize document storage
Customize path and access rights to your needs
mkdir /var/local/yms
mkdir /var/local/yms/thumb
chown -R www-data /var/local/yms
chmod -R 750 /var/local/yms
mkdir /var/local/lib/yms
mkdir /var/local/lib/yms/thumb
chown -R www-data /var/local/lib/yms
chmod -R 750 /var/local/lib/yms
To grant access for the local gui the directory has to be writeable by a special
group (here as example 'yms'). The user which runs the local gui (here
@@ -75,8 +75,8 @@ group (here as example 'yms'). The user which runs the local gui (here
groupadd yms
usermod -aG yms www-data
usermod -aG yms guiuser
chgrp yms /var/local/yms
chgrp yms /var/local/yms/thumb
chgrp yms /var/local/lib/yms
chgrp yms /var/local/lib/yms/thumb
chmod -R 770 /var/local/yms
4. Setup local GUI
+2 -1
View File
@@ -222,6 +222,7 @@ CREATE TABLE equipment (
CREATE TABLE inventory (
invid int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
invname varchar(80) NOT NULL,
icat tinyint(3) DEFAULT NULL,
conttype enum('storage','box') NOT NULL DEFAULT 'storage',
sid smallint(6) UNSIGNED DEFAULT NULL,
boxid smallint(6) UNSIGNED DEFAULT NULL,
@@ -470,7 +471,7 @@ CREATE TABLE note (
annotation text NOT NULL,
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
created_by smallint(6) DEFAULT NULL,
PRIMARY KEY (noteid)
PRIMARY KEY (noteid),
FOREIGN KEY fk_note_user (created_by)
REFERENCES user(userid)
ON DELETE RESTRICT
+3 -2
View File
@@ -14,7 +14,7 @@ INSERT INTO user (userid, login, pass, displayname, role) VALUES
INSERT INTO settings (userid, sno, valint, valstr) VALUES
(0, 0, 1, NULL), -- Database schema version
(0, 1, 0, NULL), -- No vessel assignment to SYSTEM
(1, 1, 0), NULL, -- No vessel assignment to user "captain"
(1, 1, 0, NULL), -- No vessel assignment to user "captain"
(0, 20, 1280, NULL), -- Image width limit
(0, 21, 1024, NULL), -- Image height limit
(0, 4, NULL, '€'), -- Currency symbol
@@ -72,7 +72,8 @@ INSERT INTO dropdown (ddid, ddval, ddtext) VALUES
(0, 9, 'Kistentypen'),
(0, 10, 'Sicherungsblöcke'), -- fuse locations
(0, 11, 'Kabeltypen'),
(0, 12, 'Technische Kabel-Bezeichnung');
(0, 12, 'Technische Kabel-Bezeichnung'),
(0, 13, 'Inventarkategorien');
INSERT INTO dropdown (ddid, ddval, ddtext, flags) VALUES
(2, 1, 'Lieferant', 'fixed'),
+3 -2
View File
@@ -14,7 +14,7 @@ INSERT INTO user (userid, login, pass, displayname, role) VALUES
INSERT INTO settings (userid, sno, valint, valstr) VALUES
(0, 0, 1, NULL), -- Database schema version
(0, 1, 0, NULL), -- No vessel assignment to SYSTEM
(1, 1, 0), NULL, -- No vessel assignment to user "captain"
(1, 1, 0, NULL), -- No vessel assignment to user "captain"
(0, 20, 1280, NULL), -- Image width limit
(0, 21, 1024, NULL), -- Image height limit
(0, 4, NULL, '€'), -- Currency symbol
@@ -71,7 +71,8 @@ INSERT INTO dropdown (ddid, ddval, ddtext) VALUES
(0, 9, 'box types'),
(0, 10, 'fuse blocks'),
(0, 11, 'cable types'),
(0, 12, 'cable desc. technical');
(0, 12, 'cable desc. technical'),
(0, 13, 'inventory category');
INSERT INTO dropdown (ddid, ddval, ddtext, flags) VALUES
(2, 1, 'Supplier', 'fixed'),
+10
View File
@@ -52,6 +52,16 @@ else
mariadb -e "GRANT SELECT, INSERT, UPDATE, DELETE ON \`${DB_NAME}\`.* TO '${DB_USER}'@'localhost'"
fi
echo "Initializing document storage..."
if ! getent group yms >/dev/null; then
addgroup --system yms
fi
if ! id -nG www-data | tr ' ' '\n' | grep -qx yms; then
adduser www-data yms
fi
mkdir -p /var/lib/yms/thumb
chown -R www-data:yms /var/lib/yms
db_get yms/webgui
if [ "$RET" = "true" ]; then
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
set -e
. /usr/share/debconf/confmodule
case "$1" in
remove|purge)
db_input high yms/remove-info || true
db_go || true
;;
esac
exit 0
+9
View File
@@ -23,3 +23,12 @@ Description: Enable the YMS web interface?
by a web server.
.
Do you want to enable the web interface?
Template: yms/remove-info
Type: note
Description: YMS document storage was not removed
The YMS package has been removed, but the document storage
remains on the system.
.
The directory /var/lib/yms and its contents have not been
deleted.
+2 -3
View File
@@ -29,13 +29,13 @@ $g_mailto_webmaster = 'webmaster@example.com';
// localization
$g_textdomain = 'yms';
$g_timezone = 'Europe/Berlin';
$g_locale = 'de_DE.UTF-8';
$g_locale = 'en_GB.UTF-8';
// vessel base shapes directory
$g_shapedir = '/usr/local/share/yms/shapes';
// documents and images
$g_doc_basepath = '/var/local/yms';
$g_doc_basepath = '/var/local/lib/yms';
$g_doc_maxsize = 1024*1024*16; // 16 MB, please adjust php.ini accordingly!
$g_doc_typemap = array(
'generic' => 'doc',
@@ -50,4 +50,3 @@ $g_storage_limit = 1024; // MB
$g_thumb_size = 120;
$g_rows_pp = 10; // pagination limit
+8 -5
View File
@@ -136,11 +136,14 @@ $g_currsym = $sth->fetchColumn();
// allowed date formats
$g_opt_datefmt = array(
'Y-m-d' => _('YYYY-MM-DD'),
'Y/m/d' => _('YYYY/MM/DD'),
'd.m.Y' => _('DD.MM.YYYY'),
'd/m/Y' => _('DD/MM/YYYY'),
'm-d-Y' => _('MM-DD-YYYY')
'Y-m-d' => _('YYYY-MM-DD'), // ISO / international /technical
'd.m.Y' => _('DD.MM.YYYY'), // Germany / Central & Northern Europe
'd/m/Y' => _('DD/MM/YYYY'), // UK / France / Spain / Italy / Australia / NZ
'd-m-Y' => _('DD-MM-YYYY'), // Netherlands / Denmark / Belgium
'd M Y' => _('DD Mon YYYY'), // nautical documents / logbooks / unambiguous
'm.d.Y' => _('MM.DD.YYYY'), // USA
'm/d/Y' => _('MM/DD/YYYY'), // USA
'Y/m/d' => _('YYYY/MM/DD') // Japan / China
);
$user = User::GetInstance(); // There can be only one
+9 -2
View File
@@ -18,6 +18,7 @@ $opt_storage = db_get_opt_storage($user->vid);
$opt_box = db_get_opt_box($user->vid);
$opt_invcond = db_load_enum('inventory', 'invcond', true, true);
$opt_equipment = db_get_opt_equip($user->vid, [-1 => _('― none ―')]);
$opt_icat = db_get_options(13);
// ========== ACTIONS START ===================================================
@@ -95,6 +96,8 @@ switch ($submit = form_get_action()) {
$p[':price'] = gpc_get_currency($_POST, 'price');
$p[':purchdate'] = gpc_get_date($_POST, 'purchdate');
$p[':invcond'] = gpc_get_string($_POST, 'invcond');
$p[':icat'] = gpc_get_int($_POST, 'icat');
if ($p[':icat'] <= 0) $p[':icat'] = NULL;
$p[':remarks'] = gpc_get_string($_POST, 'remarks', 150);
$p[':eid'] = gpc_get_int($_POST, 'eid');
if ($p[':eid'] <= 0) $p[':eid'] = NULL;
@@ -343,7 +346,7 @@ elseif ($action == ACT_VIEW):
// ========== VARIANT: view single record =====================================
$sql = "SELECT invname, conttype, sid, boxid, number, weight, price, purchdate,"
. " invcond, remarks "
. " invcond, icat, remarks "
. "FROM inventory "
. "WHERE invid=?";
$sth = $pdo->prepare($sql);
@@ -397,6 +400,7 @@ echo "<tr><th>", _('Weight'), "</th><td>", format_float($inventory->weight, 2, '
echo "<tr><th>", _('Price'), "</th><td>", format_currency($inventory->price), "</td></tr>\n";
echo "<tr><th>", _('Purchase date'), "</th><td>", format_date($inventory->purchdate), "</td></tr>\n";
echo "<tr><th>", _('Condition'), "</th><td>", $opt_invcond[$inventory->invcond], "</td></tr>\n";
echo "<tr><th>", _('Category'), "</th><td>", $opt_icat[$inventory->icat], "</td></tr>\n";
echo "<tr><th>", _('Remarks'), "</th><td>", h($inventory->remarks, br:true), "</td></tr>\n";
$tags = db_load_taglist('inv', $id);
@@ -462,7 +466,10 @@ foreach ($cond as $k => $v) {
?>
</select>
</div>
<?php form_create_select('eid', _('Equipment'), $opt_equipment, $inventory->eid); ?>
<?php
form_create_select('icat', _('Category'), $g_opt_none + $opt_icat, $inventory->icat);
form_create_select('eid', _('Equipment'), $opt_equipment, $inventory->eid);
?>
<div class="mb-3">
<label for="remarks" class="form-label"><?=_('Remarks')?></label>
<textarea class="form-control" id="remarks" name="remarks" rows="3"><?=h($inventory->remarks, br:true)?></textarea>
+31
View File
@@ -0,0 +1,31 @@
<?php
/******************************************************************************
* YMS - Yacht Management Software
* Copyright (C) 2024-2026 Thomas Hooge
*
* SPDX-License-Identifier: WTFPL
******************************************************************************
*/
function signalk_get($server, $skpath) {
$url = "$server/signalk/v1/api/" . str_replace('.', '/', $skpath);
var_dump($url);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 3,
CURLOPT_TIMEOUT => 5,
]);
$json = curl_exec($ch);
if ($json === false) {
throw new RuntimeException('Signal K error: ' . curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200) {
throw new RuntimeException('Signal K HTTP-error: ' . $httpCode);
}
return json_decode($json, true, 512, JSON_THROW_ON_ERROR);
}
+1
View File
@@ -291,6 +291,7 @@ if (count($res) > 0) {
echo "<td>", $row['provname'], "</td>";
echo "<td>", $row['number'], ' ', $opt_unit[$row['unit']], "</td>";
echo "<td>", $row['storedate'], ' - ', $row['shelflife'], "</td>";
echo '<td><a title="', _('View'), '" href="provisions.php?f=view&id=', $row['provid'], '"><i class="bi-eye"></i></a></td>';
echo "</tr>\n";
}
echo "</table>\n";
+2
View File
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: WTFPL
from gi.repository import Gtk
def load_from_dict(combobox, dictionary, selected=None, sort=False):
+130
View File
@@ -0,0 +1,130 @@
# SPDX-License-Identifier: WTFPL
"""
Dropdowns and database enums
dropdowns can change
enums are static
"""
class Dropdown:
HULL_TYPE = 1
COMPANY_TYPE = 2
STORAGE_TYPE = 3
EQUIPMENT_CATEGORY = 4
PROVISION_CATEGORY = 5
PROVISION_UNIT = 6
FUSE_TYPE = 7
UNIT = 8
BOX_TYPE = 9
FUSE_BLOCK = 10
CABLE_TYPE = 11
CABLE_TECHNAME = 12
class Lookup:
def __init__(self, db):
self.db = db
self._enums = {}
self._dropdowns = {}
def load(self):
self._load_enums()
self._load_dropdowns()
def _load_enums(self):
"""
TODO translation via gettext needed
"""
db_enums = {
'user.role': ('user', 'role'),
'dropdown.flags': ('dropdown', 'flags'),
'vessel.vtype': ('vessel', 'vtype'),
'storage.capaunit': ('storage', 'capaunit'),
'tagref.objtype': ('tagref', 'objtype'),
'inventory.conttype': ('inventory', 'conttype'),
'inventory.invcond': ('inventory', 'invcond'),
'cable.cablecond': ('cable', 'cablecond'),
'measurement.accuracy': ('measurement', 'accuracy'),
'document.doctype': ('document', 'doctype'),
'document.roleaccess': ('document', 'roleaccess'),
'docref.reftype': ('docref', 'reftype'),
'maintenance.maintstate': ('maintenance', 'maintstate'),
'project.projstate': ('project', 'projstate'),
'task.priority': ('task', 'priority'),
'task.taskstate': ('task', 'taskstate'),
'note.notetype': ('note', 'notetype'),
'checklist.clstate': ('checklist', 'clstate'),
'checkitem.checkresult': ('checkitem', 'checkresult'),
'signalk.objtype': ('signalk', 'objtype'),
'signalk.datatype': ('signalk', 'datatype')
}
for key, (table, column) in db_enums.items():
self._enums[key] = self.db.load_enum(table, column)
def _load_dropdowns(self):
self._dropdowns.clear()
sql = (
"SELECT ddid, ddval, ddtext "
"FROM dropdown "
"WHERE ddid>0 "
"ORDER BY ddid, sort, ddval"
)
self.db.cur.execute(sql)
for ddid, ddval, ddtext in self.db.cur.fetchall():
if ddid not in self._dropdowns:
self._dropdowns[ddid] = {}
self._dropdowns[ddid][ddval] = ddtext
def enum(self, name):
return self._enums[name]
def dropdown(self, ddid):
return self._dropdowns[ddid]
def refresh(self):
# TODO ugly hack please improve
self._load_dropdowns()
class ListDefinition:
pass
"""
EQUIPMENT_LIST = ListDefinition(
name="equipment",
query=
"SELECT
e.eid,
e.ename,
c.name AS manufacturer,
e.model,
e.ecat,
e.weight
FROM equipment e
LEFT JOIN company c
ON c.cid = e.manufacturer"
,
columns=[
Column("ename", _("Name")),
Column("manufacturer", _("Manufacturer")),
Column(
"model",
_("Model")
),
Column(
"ecat",
_("Category"),
formatter=dropdown(Dropdown.EQUIPMENT_CATEGORY)
),
Column(
"weight",
_("Weight"),
formatter=weight()
),
]
)
"""
+1 -1
View File
@@ -7,7 +7,7 @@ class Box(DbRecord):
table = "box"
pk_field = "boxid"
fields = ('boxid', 'sid', 'boxtype', 'parent', 'label', 'color', 'content',
'weight', 'remarks')
'wx', 'wy', 'wz', 'weight', 'weight_net', 'price', 'remarks')
def __init__(self, db, boxid=None):
super().__init__(db, boxid)
+11 -1
View File
@@ -22,14 +22,24 @@ class Vessel(DbRecord):
"WHERE v1.vid>=0 AND v2.vid IS NULL"
)
self.dcur.execute(sql)
row = self.cur.fetchone()
row = self.dcur.fetchone()
if row is None:
# vessel table empty: create first vessel
self.pk_value = 1
else:
# create additional vessel
self.pk_value = row['newid']
self.clear()
self.vid = self.pk_value
self.vesselname = f"Vessel #{self.pk_value}"
self.vtype = 1 # monohull
self._insert()
self.conn.commit()
def save(self):
super().save()
self.conn.commit()
def delete(self):
# there must be no assiciated data!
pass
+2
View File
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: WTFPL
from gi.repository import Gtk
def add_column(treeview, label, index, xalign=None, col_fg=None, col_bg=None, visible=True):
+408 -17
View File
@@ -50,16 +50,20 @@
<object class="GtkNotebook" id="ntb_basedata">
<property name="visible">True</property>
<property name="can-focus">True</property>
<child>
<object class="GtkStack" id="stk_vessel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkBox" id="box_vessel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="lbl_vessel">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">empty</property>
<property name="label" translatable="yes">Ghost</property>
</object>
<packing>
<property name="expand">False</property>
@@ -67,20 +71,400 @@
<property name="position">0</property>
</packing>
</child>
<child>
<!-- n-columns=2 n-rows=14 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Name</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Model</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Year built</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">LoA</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">4</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Draught min</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">8</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Draught</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">7</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Beam</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">6</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">LwL</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">5</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Shipyard</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">9</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Displacement</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">10</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Ballast</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">11</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Default Storage</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">12</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Remarks</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">13</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_vesselname">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_model">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_year_built">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_loa">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">4</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_lwl">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">5</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_beam">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">6</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_draught">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">7</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_draught_min">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">8</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="sls_shipyard">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">9</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_displacement">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">10</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_ballast">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">11</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_storage_def">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">12</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_remarks">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">13</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="cmb_vessel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="hexpand">True</property>
<signal name="changed" handler="on_cmb_vessel_changed" swapped="no"/>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
<property name="width">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButtonBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="layout-style">end</property>
<child>
<object class="GtkButton" id="but_vessel_delete">
<property name="label" translatable="yes">Delete</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_but_vessel_delete_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="secondary">True</property>
</packing>
</child>
<child>
<object class="GtkButton" id="but_vessel_add">
<property name="label" translatable="yes">Add</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_but_vessel_add_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="but_vessel_edit">
<property name="label" translatable="yes">Edit</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_but_vessel_edit_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">page_detail</property>
<property name="title" translatable="yes">page_detail</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box_vessel_edit">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="lbl_vessel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Ghost</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<!-- n-columns=2 n-rows=13 -->
<object class="GtkGrid">
@@ -411,20 +795,6 @@
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="layout-style">end</property>
<child>
<object class="GtkButton" id="but_vessel_add">
<property name="label" translatable="yes">Add</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_but_vessel_add_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="but_vessel_save">
<property name="label" translatable="yes">Save</property>
@@ -433,6 +803,20 @@
<property name="receives-default">True</property>
<signal name="clicked" handler="on_but_vessel_save_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="but_vessel_cancel">
<property name="label" translatable="yes">Cancel</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_but_vessel_cancel_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
@@ -447,6 +831,13 @@
</packing>
</child>
</object>
<packing>
<property name="name">page_edit</property>
<property name="title" translatable="yes">page_edit</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<child type="tab">
<object class="GtkLabel">
+844
View File
@@ -0,0 +1,844 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkAdjustment" id="adj_price">
<property name="upper">90</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
<object class="GtkAdjustment" id="adj_weight">
<property name="upper">100</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
<object class="GtkAdjustment" id="adj_weight_net">
<property name="upper">100</property>
<property name="step-increment">1</property>
<property name="page-increment">10</property>
</object>
<object class="GtkAdjustment" id="adj_width_x">
<property name="upper">9999</property>
<property name="step-increment">10</property>
<property name="page-increment">100</property>
</object>
<object class="GtkAdjustment" id="adj_width_y">
<property name="upper">9999</property>
<property name="step-increment">10</property>
<property name="page-increment">100</property>
</object>
<object class="GtkAdjustment" id="adj_width_z">
<property name="upper">9999</property>
<property name="step-increment">10</property>
<property name="page-increment">100</property>
</object>
<object class="GtkStack" id="topobject">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">8</property>
<child>
<object class="GtkBox" id="box_box">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkExpander">
<property name="visible">True</property>
<property name="can-focus">True</property>
<child>
<!-- n-columns=3 n-rows=3 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Filter Box</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkTreeView" id="tvw_box">
<property name="visible">True</property>
<property name="can-focus">True</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButtonBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="layout-style">end</property>
<child>
<object class="GtkButton" id="but_new">
<property name="label" translatable="yes">New</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_but_new_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="but_edit">
<property name="label" translatable="yes">Edit</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_but_edit_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="but_detail">
<property name="label" translatable="yes">Details</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_but_detail_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">page0</property>
<property name="title" translatable="yes">page0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box_box_detail">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Box Detais</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<!-- n-columns=2 n-rows=8 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Label</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_label">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Placeholder</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Remarks</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">7</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_remarks">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">7</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Content</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_content">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Type</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Color</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Weight</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">4</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_type">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_color">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_weight">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">4</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Weight net</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">5</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_weight_net">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">5</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Price</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">6</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_price">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">6</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButtonBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="layout-style">end</property>
<child>
<object class="GtkButton" id="but_delete">
<property name="label" translatable="yes">Delete</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_but_delete_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="secondary">True</property>
</packing>
</child>
<child>
<object class="GtkButton" id="but_edit2">
<property name="label" translatable="yes">Edit</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_but_edit_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="but_close">
<property name="label" translatable="yes">Close</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_but_close_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">page1</property>
<property name="title" translatable="yes">page1</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box_box_edit">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="lbl_title_edit">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Edit Box</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<!-- n-columns=7 n-rows=9 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Label</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Type</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="ent_label">
<property name="visible">True</property>
<property name="can-focus">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
<property name="width">6</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="cmb_type">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
<property name="width">6</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Dimensions (L x W x H)</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">x</property>
</object>
<packing>
<property name="left-attach">2</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">x</property>
</object>
<packing>
<property name="left-attach">4</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="spi_wx">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="max-length">4</property>
<property name="width-chars">4</property>
<property name="text" translatable="yes">0</property>
<property name="adjustment">adj_width_x</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="spi_wy">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="max-length">4</property>
<property name="width-chars">4</property>
<property name="text" translatable="yes">0</property>
<property name="adjustment">adj_width_y</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="left-attach">3</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="spi_wz">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="max-length">4</property>
<property name="width-chars">4</property>
<property name="text" translatable="yes">0</property>
<property name="adjustment">adj_width_z</property>
<property name="numeric">True</property>
</object>
<packing>
<property name="left-attach">5</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Price</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">5</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Weight</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">6</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Remarks</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">8</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="shadow-type">in</property>
<child>
<object class="GtkTextView" id="txt_remarks">
<property name="visible">True</property>
<property name="can-focus">True</property>
</object>
</child>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">8</property>
<property name="width">6</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Weight net</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">7</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="label" translatable="yes">mm</property>
</object>
<packing>
<property name="left-attach">6</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Content</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="ent_content">
<property name="visible">True</property>
<property name="can-focus">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
<property name="width">6</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="spi_weight_net">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="text" translatable="yes">0</property>
<property name="adjustment">adj_weight_net</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">7</property>
<property name="width">3</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="spi_weight">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="text" translatable="yes">0</property>
<property name="adjustment">adj_weight</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">6</property>
<property name="width">3</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="spi_price">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="text" translatable="yes">0</property>
<property name="adjustment">adj_price</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">5</property>
<property name="width">3</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Colour</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">4</property>
</packing>
</child>
<child>
<object class="GtkButton" id="but_color">
<property name="label" translatable="yes">#FFFFFF</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="relief">half</property>
<signal name="clicked" handler="on_but_color_clicked" swapped="no"/>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">4</property>
<property name="width">3</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButtonBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="layout-style">end</property>
<child>
<object class="GtkButton" id="but_save">
<property name="label" translatable="yes">Save</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_but_save_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="but_cancel">
<property name="label" translatable="yes">Cancel</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<signal name="clicked" handler="on_but_cancel_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="name">page2</property>
<property name="title" translatable="yes">page2</property>
<property name="position">2</property>
</packing>
</child>
</object>
</interface>
+103 -8
View File
@@ -205,7 +205,7 @@
</packing>
</child>
<child>
<!-- n-columns=3 n-rows=3 -->
<!-- n-columns=2 n-rows=7 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
@@ -224,7 +224,7 @@
<object class="GtkLabel" id="lbl_name">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Placeholder</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
@@ -239,7 +239,7 @@
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
<property name="top-attach">6</property>
</packing>
</child>
<child>
@@ -249,23 +249,118 @@
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">6</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Type</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<placeholder/>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Position (x, y, z)</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<placeholder/>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Dimension (x, y, z)</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<placeholder/>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Angle</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">4</property>
</packing>
</child>
<child>
<placeholder/>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Capacity</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">5</property>
</packing>
</child>
<child>
<placeholder/>
<object class="GtkLabel" id="lbl_type">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_position">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_dimension">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_angle">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">4</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="lbl_capacity">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">5</property>
</packing>
</child>
</object>
<packing>
+30 -1
View File
@@ -14,6 +14,7 @@ from gi.repository import GLib, Gtk, Gdk, Rsvg
from .view import View
from yms import gtkutils, combobox, treeview
from yms.lookup import Dropdown
class BaseView(View):
@@ -63,7 +64,15 @@ class BaseView(View):
self.db.cur.execute("INSERT INTO settings (userid, sno, valint) VALUES (0, 1, 0)")
self.db.conn.commit()
else:
# check if vessel from settings exist
self.db.cur.execute("SELECT count(*) FROM vessel WHERE vid=%s", (row[0],))
res = self.db.cur.fetchone()[0]
if res > 0:
self.context.vessel.vid = row[0]
else:
# TODO set vessel to first in list
self.context.vessel.vid = 0
self.context.vessel.vesselname = "Ghost"
# default storage for current vessel
sql = "SELECT sid, sname FROM storage WHERE stype=0 AND vid=%s ORDER BY sname"
@@ -154,6 +163,15 @@ class BaseView(View):
if answer == False:
return
self.context.vessel.create()
model = self.combo['vessel'].get_model()
model.append((self.context.vessel.vid, self.context.vessel.vesselname))
combobox.activate_row(self.combo['vessel'], self.context.vessel.vid)
self.edit_vessel(self.context.vessel)
self.stack['vessel'].set_visible_child(self.box['vessel_edit'])
def on_but_vessel_edit_clicked(self, widget):
self.edit_vessel(self.context.vessel)
self.stack['vessel'].set_visible_child(self.box['vessel_edit'])
def on_but_vessel_save_clicked(self, widget):
print("Save vessel")
@@ -172,6 +190,13 @@ class BaseView(View):
txtbuf = self.text['vessel_remarks'].get_buffer()
vessel.remarks = txtbuf.get_text(txtbuf.get_start_iter(), txtbuf.get_end_iter(), True)
vessel.save()
self.stack['vessel'].set_visible_child(self.box['vessel'])
def on_but_vessel_cancel_clicked(self, widget):
self.stack['vessel'].set_visible_child(self.box['vessel'])
def on_but_vessel_delete_clicked(self, widget):
pass
def on_but_comp_new_clicked(self, widget):
print("New company")
@@ -189,7 +214,11 @@ class BaseView(View):
pass
def display_vessel(self, vessel):
print("Display vessel")
self.label['vesselname'].set_text(vessel.vesselname)
self.label['model'].set_text(vessel.model or '')
self.label['year_built'].set_text(self.format_int(vessel.year_built, default='n/a'))
def edit_vessel(self, vessel):
self.entry['vesselname'].set_text(vessel.vesselname)
self.entry['model'].set_text(vessel.model or '')
self.spin['year_built'].set_value(vessel.year_built or 0)
+94
View File
@@ -0,0 +1,94 @@
# SPDX-License-Identifier: WTFPL
import os
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import GLib, Gtk, Gdk
from .view import View
from yms import gtkutils, combobox, treeview
from yms.model import box
class BoxesView(View):
def __init__(self, context):
super().__init__(context, _("Box"), "boxes.ui")
# box already used for controls so other name here
self.sbox = box.Box(context.db) # current record
self.newrecord = False
self.lst_box = Gtk.ListStore(int, str, str, str)
sql = (
"SELECT b.boxid, b.label, b.content, b.remarks "
"FROM box AS b JOIN storage AS s USING (sid) "
"WHERE s.vid=%s "
"ORDER BY b.label"
)
self.db.cur.execute(sql, (context.vessel.vid,))
for row in self.db.cur.fetchall():
self.lst_box.append(row)
treeview.add_column(self.tree['box'], _('ID'), 0)
treeview.add_column(self.tree['box'], _('Label'), 1)
treeview.add_column(self.tree['box'], _('Content'), 2)
treeview.add_column(self.tree['box'], _('Remarks'), 3)
self.tree['box'].set_model(self.lst_box)
def load_list(self):
pass
def display_record(self):
self.label['label'].set_text(self.sbox.label)
self.label['remarks'].set_text(self.sbox.remarks or '')
def edit_record(self):
self.entry['label'].set_text(self.sbox.label)
self.entry['content'].set_text(self.sbox.content or '')
self.spin['wx'].set_value(self.sbox.wx or 0)
self.spin['wy'].set_value(self.sbox.wy or 0)
self.spin['wz'].set_value(self.sbox.wz or 0)
self.text['remarks'].get_buffer().set_text(self.sbox.remarks or '')
# buttons on list page
def on_but_new_clicked(self, widget):
self.newrecord = True
self.label['title_edit'].set_text("Add new Box")
self.topwidget.set_visible_child(self.box['box_edit'])
def on_but_edit_clicked(self, widget):
self.newrecord = False
self.label['title_edit'].set_text("Edit Box")
sid = treeview.get_value(self.tree['box'], 0)
self.sbox.load(sid)
self.edit_record()
self.topwidget.set_visible_child(self.box['box_edit'])
def on_but_detail_clicked(self, widget):
sid = treeview.get_value(self.tree['box'], 0)
self.sbox.load(sid)
self.display_record()
self.topwidget.set_visible_child(self.box['box_detail'])
# buttons on detail page
# edit2 uses edit callback
def on_but_close_clicked(self, widget):
self.topwidget.set_visible_child(self.box['box'])
def on_but_delete_clicked(self, widget):
self.topwidget.set_visible_child(self.box['box'])
self.newrecord = False
# buttons on edit page
def on_but_save_clicked(self, widget):
print("save not implemented yet")
self.newrecord = False
def on_but_cancel_clicked(self, widget):
self.topwidget.set_visible_child(self.box['box'])
self.newrecord = False
def on_but_color_clicked(self, widget):
pass
+6
View File
@@ -62,3 +62,9 @@ class CablesView(View):
def on_but_cancel_clicked(self, widget):
self.topwidget.set_visible_child(self.box['cables'])
def display_record(self):
pass
def edit_record(self):
pass
+6
View File
@@ -59,3 +59,9 @@ class DocumentsView(View):
def on_but_cancel_clicked(self, widget):
self.topwidget.set_visible_child(self.box['documents'])
def display_record(self):
pass
def edit_record(self):
pass
+6
View File
@@ -64,3 +64,9 @@ class FusesView(View):
def on_but_cancel_clicked(self, widget):
self.topwidget.set_visible_child(self.box['fuses'])
def display_record(self):
pass
def edit_record(self):
pass
+6
View File
@@ -58,3 +58,9 @@ class MaintenanceView(View):
def on_but_cancel_clicked(self, widget):
self.topwidget.set_visible_child(self.box['maintenance'])
def display_record(self):
pass
def edit_record(self):
pass
+6
View File
@@ -68,3 +68,9 @@ class ProjectsView(View):
def on_but_cancel_clicked(self, widget):
self.topwidget.set_visible_child(self.box['projects'])
def display_record(self):
pass
def edit_record(self):
pass
+1 -1
View File
@@ -21,7 +21,7 @@ class StatusView:
gtkutils.init_named_controls(self, builder)
# Generic information
self.label['dbinfo'].set_text("Database: {}".format(context.cfg['db']))
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)
+17 -2
View File
@@ -8,6 +8,7 @@ from gi.repository import GLib, Gtk, Gdk
from .view import View
from yms import gtkutils, combobox, treeview
from yms.model import storage
from yms.lookup import Dropdown
class StorageView(View):
@@ -34,6 +35,14 @@ class StorageView(View):
treeview.add_column(self.tree['storage'], _('Remarks'), 3)
self.tree['storage'].set_model(self.lst_storage)
combodict = self.context.lookup.dropdown(Dropdown.STORAGE_TYPE)
combobox.load_from_dict(self.combo['type'], combodict)
combodict = self.context.lookup.dropdown(Dropdown.STORAGE_TYPE)
combobox.load_from_dict(self.combo['type'], combodict)
combodict = self.context.lookup.enum('storage.capaunit')
combobox.load_from_dict(self.combo['unit'], combodict)
def load_list(self):
pass
@@ -56,9 +65,11 @@ class StorageView(View):
self.topwidget.set_visible_child(self.box['stor_edit'])
def on_but_edit_clicked(self, widget):
sid = treeview.get_value(self.tree['storage'], 0)
if sid is None:
return
self.newrecord = False
self.label['title_edit'].set_text("Edit Storage")
sid = treeview.get_value(self.tree['storage'], 0)
self.storage.load(sid)
self.edit_record()
self.topwidget.set_visible_child(self.box['stor_edit'])
@@ -80,8 +91,12 @@ class StorageView(View):
# buttons on edit page
def on_but_save_clicked(self, widget):
print("save not implemented yet")
self.newrecord = False
# check mandatory fields
sname = self.entry['sname'].get_text().strip()
if not sname:
return
# here be dragons
def on_but_cancel_clicked(self, widget):
self.topwidget.set_visible_child(self.box['storage'])
+6 -6
View File
@@ -27,25 +27,25 @@ class View:
self.topwidget = builder.get_object("topobject")
gtkutils.init_named_controls(self, builder)
def format_int(self, ival, separator=True, suffix=None):
def format_int(self, ival, separator=True, suffix=None, default=''):
if ival is None:
return ''
return default
formatted = locale.format_string("%d", ival, separator)
if suffix:
formatted += f"\u00A0{suffix}"
return formatted
def format_float(self, fval, digits=2, grouping=True, suffix=None):
def format_float(self, fval, digits=2, grouping=True, suffix=None, default=''):
if fval is None:
return ''
return default
formatted = locale.format_string(f"%.{digits}f", fval, grouping)
if suffix:
formatted += f"\u00A0{suffix}"
return formatted
def format_date(self, dval):
def format_date(self, dval, default=''):
if dval is None:
return ''
return default
return dval.strftime(self.context.datefmt)
def on_textview_keypress(self, widget, event):
+15 -7
View File
@@ -37,9 +37,11 @@ from yms import database
from yms import gtkutils, combobox, treeview
from yms.model import user
from yms.model import vessel
from yms.lookup import Lookup
from yms.view.base import BaseView
from yms.view.storage import StorageView
from yms.view.boxes import BoxesView
from yms.view.equipment import EquipmentView
from yms.view.inventory import InventoryView
from yms.view.provisions import ProvisionsView
@@ -57,17 +59,20 @@ class AppContext:
'host': 'localhost',
'db': 'yms',
'user': 'yms',
'docpath': '/var/local/yms',
'docpath': '/var/local/lib/yms',
'shapedir': '/usr/local/share/yms/shapes'
}
# mapping between PHP and Python
datefmt_map = {
'Y-m-d': '%Y.%m.%d',
'Y/m/d': '%Y/%m/%d',
'd.m.Y': '%d.%m.%Y',
'd/m/Y': '%d/%m/%Y',
'm-d-Y': '%m.%d.%Y'
'Y-m-d': '%Y-%m-%d', # ISO / international / technical
'd.m.Y': '%d.%m.%Y', # Germany / Central & Northern Europe
'd/m/Y': '%d/%m/%Y', # UK / France / Spain / Italy / Australia / NZ
'd-m-Y': '%d-%m-%Y', # Netherlands / Denmark / Belgium
'd M Y': '%d %b %Y', # nautical documents / logbooks / unambiguous
'm.d.Y': '%m.%d.%Y', # USA
'm/d/Y': '%m/%d/%Y', # USA
'Y/m/d': '%Y/%m/%d' # Japan / China
}
def __init__(self):
@@ -80,6 +85,7 @@ class AppContext:
def set_db(self, db):
self.db = db
self.lookup = Lookup(db)
def load(self):
self.user = user.User(db, 0)
@@ -97,6 +103,7 @@ class AppContext:
else:
# perhaps create missing record here?
pass
self.lookup.load()
def get_sharepath(self):
path = os.path.realpath(__file__)
@@ -113,6 +120,7 @@ class Frontend:
self.modules = {
"base": BaseView(context),
"storage": StorageView(context),
"box": BoxesView(context),
"equipment": EquipmentView(context),
"inventory": InventoryView(context),
"provisions": ProvisionsView(context),
@@ -195,6 +203,7 @@ if __name__ == "__main__":
context.cfg['host'] = config.get('DB', 'host')
context.cfg['db'] = config.get('DB', 'db')
db = database.Database(context.cfg['host'], context.cfg['db'])
context.set_db(db)
connected = False
if context.cfg['host'] == 'socket':
connected = db.connect_local()
@@ -203,7 +212,6 @@ if __name__ == "__main__":
context.cfg['pass'] = config.get('DB', 'pass')
connected = db.connect(context.cfg['user'], context.cfg['pass'])
if connected:
context.set_db(db)
context.load()
# check if shapedir exists
context.cfg['shapedir'] = config.get('Data', 'shapedir')