diff --git a/yms/combobox.py b/yms/combobox.py
index 1bcd7cf..b705f1e 100644
--- a/yms/combobox.py
+++ b/yms/combobox.py
@@ -33,7 +33,7 @@ def refresh_dict(combobox, dictionary, keep_selection=True):
model = combobox.get_model()
selected = get_value(combobox)
model.clear()
- for item in dictionary.iteritems():
+ for item in dictionary.items():
model.append(item)
if keep_selection:
activate_row(combobox, selected)
@@ -70,7 +70,7 @@ def get_value(combobox, decode=False):
if active < 0:
return None
else:
- if type(model) == gtk.TreeStore:
+ if type(model) == Gtk.TreeStore:
it = combobox.get_active_iter()
val = model.get_value(it, 0)
if decode:
diff --git a/yms/model/dbrecord.py b/yms/model/dbrecord.py
index 2a24c7e..5f750e5 100644
--- a/yms/model/dbrecord.py
+++ b/yms/model/dbrecord.py
@@ -18,6 +18,7 @@ class DbRecord:
raise TypeError("DbRecord subclass must define 'fields'")
self.db = db
+ self.cur = db.cur
self.dcur = db.dcur
self.conn = db.conn
self.last_update = None
@@ -32,9 +33,10 @@ class DbRecord:
self.clear()
def clear(self):
+ self.data = {} # for old/new checks
for field in self.fields:
setattr(self, field, None)
- self.data = {} # for old/new checks
+ self.data[field] = None
def load(self, record_id=None):
if record_id is not None:
@@ -47,6 +49,8 @@ class DbRecord:
self.dcur.execute(sql, (self.pk_value,))
self.data = self.dcur.fetchone()
except Exception as e:
+ print(e)
+ print(sql)
self.db.error = e
self.clear()
return False
@@ -83,6 +87,9 @@ class DbRecord:
try:
self.dcur.execute(sql, values)
except Exception as e:
+ print(e)
+ print(sql)
+ print(values)
self.db.error = e
return False
for field in self.fields:
@@ -106,6 +113,9 @@ class DbRecord:
try:
self.dcur.execute(sql, values)
except Exception as e:
+ print(e)
+ print(sql)
+ print(values)
self.db.error = e
return False
self.pk_value = self.dcur.lastrowid
@@ -120,6 +130,8 @@ class DbRecord:
try:
self.dcur.execute(sql, (record_id,))
except Exception as e:
+ print(e)
+ print(sql)
self.db.error = e
return False
if self.dcur.rowcount != 1:
diff --git a/yms/model/document.py b/yms/model/document.py
index 126153b..a3b39bb 100644
--- a/yms/model/document.py
+++ b/yms/model/document.py
@@ -10,6 +10,6 @@ class Document(DbRecord):
'hash', 'docsize', 'doctime', 'docdate', 'title', 'pages', 'remarks',
'roleaccess')
- def __init__(self, db, dicid=None):
+ def __init__(self, db, docid=None):
super().__init__(db, docid)
self.title = _("Document({})")
diff --git a/yms/model/vessel.py b/yms/model/vessel.py
index eeda83b..11add82 100644
--- a/yms/model/vessel.py
+++ b/yms/model/vessel.py
@@ -8,8 +8,28 @@ class Vessel(DbRecord):
pk_field = "vid"
fields = ('vid', 'vtype', 'vesselname', 'model', 'shipyard', 'loa', 'lwl',
'beam', 'draught', 'draught_min', 'displacement', 'ballast',
- 'beltpos_aft', 'beltpos_bow', 'shapefile', 'sid_default', 'remarks')
+ 'beltpos_aft', 'beltpos_bow', 'shapefile', 'sid_default', 'year_built',
+ 'remarks')
def __init__(self, db, vid=None):
super().__init__(db, vid)
self.title = _("Vessel({})")
+
+ def create(self):
+ sql = (
+ "SELECT MIN(v1.vid+1) AS newid "
+ "FROM vessel AS v1 LEFT JOIN vessel AS v2 ON v2.vid=v1.vid+1 "
+ "WHERE v1.vid>=0 AND v2.vid IS NULL"
+ )
+ self.dcur.execute(sql)
+ row = self.cur.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.vesselname = f"Vessel #{self.pk_value}"
+ self.vtype = 1 # monohull
+ self._insert()
+ self.conn.commit()
diff --git a/yms/ui/base.ui b/yms/ui/base.ui
index 54734be..8501b00 100644
--- a/yms/ui/base.ui
+++ b/yms/ui/base.ui
@@ -2,6 +2,46 @@
+
+
+
+
+
+
+
+
0
- 3
+ 4
@@ -126,7 +166,7 @@
0
- 4
+ 5
@@ -137,7 +177,7 @@
0
- 5
+ 6
@@ -148,24 +188,14 @@
0
- 6
+ 7
True
True
- 2
-
-
- 1
- 2
-
-
-
-
- True
- True
+ adj_loa
2
@@ -174,9 +204,10 @@
-
+
True
True
+ adj_lwl
2
@@ -185,9 +216,10 @@
-
+
True
True
+ adj_beam
2
@@ -196,9 +228,10 @@
-
+
True
True
+ adj_draught
2
@@ -206,6 +239,18 @@
6
+
+
+ True
+ True
+ adj_draught_min
+ 2
+
+
+ 1
+ 7
+
+
True
@@ -214,7 +259,7 @@
0
- 8
+ 9
@@ -225,27 +270,29 @@
0
- 9
+ 10
True
True
+ adj_displacement
1
- 8
+ 9
True
True
+ adj_ballast
1
- 9
+ 10
@@ -256,25 +303,7 @@
0
- 11
-
-
-
-
-
- 1
- 11
+ 12
@@ -284,7 +313,7 @@
1
- 10
+ 11
@@ -295,7 +324,7 @@
0
- 10
+ 11
@@ -306,7 +335,7 @@
0
- 7
+ 8
@@ -316,7 +345,57 @@
1
- 7
+ 8
+
+
+
+
+ True
+ True
+ in
+
+
+
+
+
+ 1
+ 12
+
+
+
+
+ True
+ False
+ Year built
+
+
+ 0
+ 2
+
+
+
+
+ True
+ True
+ 0
+ adj_year_built
+
+
+ 1
+ 2
diff --git a/yms/ui/documents.ui b/yms/ui/documents.ui
index ace064b..c44956e 100644
--- a/yms/ui/documents.ui
+++ b/yms/ui/documents.ui
@@ -165,11 +165,12 @@
False
end
-
+
New
True
True
True
+
True
@@ -178,11 +179,12 @@
-
+
Edit
True
True
True
+
True
@@ -191,11 +193,12 @@
-
- Delete
+
+ Details
True
True
True
+
True
@@ -216,5 +219,216 @@
page0
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+ label
+
+
+ False
+ True
+ 0
+
+
+
+
+
+ True
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ end
+
+
+ Delete
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ Edit
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ Close
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 2
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ page1
+ page1
+ 1
+
+
+
+
+ True
+ False
+ vertical
+
+
+
+
+
+
+ True
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ end
+
+
+ Save
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ Cancel
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 2
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ page2
+ page2
+ 2
+
+
diff --git a/yms/ui/equipment.ui b/yms/ui/equipment.ui
index 7d7fc3c..edaf6fe 100644
--- a/yms/ui/equipment.ui
+++ b/yms/ui/equipment.ui
@@ -2,7 +2,7 @@
-
+
True
False
8
@@ -281,6 +281,7 @@
True
True
True
+
True
@@ -311,6 +312,9 @@
True
False
Equipment details
+
+
+
False
@@ -319,7 +323,7 @@
-
+
True
False
@@ -327,7 +331,7 @@
True
False
- label
+ Name
0
@@ -338,7 +342,7 @@
True
False
- label
+ Short name
0
@@ -349,13 +353,227 @@
True
False
- label
+ Manufacturer
0
2
+
+
+ True
+ False
+ Model
+
+
+ 0
+ 3
+
+
+
+
+ True
+ False
+ Serial no.
+
+
+ 0
+ 4
+
+
+
+
+ True
+ False
+ Weight
+
+
+ 0
+ 5
+
+
+
+
+ True
+ False
+ Price
+
+
+ 0
+ 6
+
+
+
+
+ True
+ False
+ Date purchase
+
+
+ 0
+ 7
+
+
+
+
+ True
+ False
+ Supplier
+
+
+ 0
+ 8
+
+
+
+
+ True
+ False
+ Category
+
+
+ 0
+ 9
+
+
+
+
+ True
+ False
+ Remarks
+
+
+ 0
+ 10
+
+
+
+
+ True
+ False
+ Placeholder
+
+
+ 1
+ 0
+
+
+
+
+ True
+ False
+
+
+ 1
+ 1
+
+
+
+
+ True
+ False
+
+
+ 1
+ 2
+
+
+
+
+ True
+ False
+
+
+ 1
+ 3
+
+
+
+
+ True
+ False
+
+
+ 1
+ 4
+
+
+
+
+ True
+ False
+
+
+ 1
+ 5
+
+
+
+
+ True
+ False
+
+
+ 1
+ 6
+
+
+
+
+ True
+ False
+
+
+ 1
+ 7
+
+
+
+
+ True
+ False
+
+
+ 1
+ 8
+
+
+
+
+ True
+ False
+
+
+ 1
+ 9
+
+
+
+
+
+ 1
+ 10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -407,6 +625,7 @@
True
True
True
+
True
@@ -447,6 +666,21 @@
True
False
vertical
+
+
+ True
+ False
+ Edit Equipment
+
+
+
+
+
+ False
+ True
+ 0
+
+
@@ -687,7 +921,7 @@
False
True
- 0
+ 1
@@ -728,7 +962,7 @@
False
True
end
- 1
+ 2
diff --git a/yms/ui/inventory.ui b/yms/ui/inventory.ui
index 2b7db1c..8cd6560 100644
--- a/yms/ui/inventory.ui
+++ b/yms/ui/inventory.ui
@@ -2,6 +2,21 @@
+
+ 1000
+ 1
+ 10
+
+
+ 10000
+ 10
+ 100
+
+
+ 1000
+ 1
+ 10
+
True
False
@@ -166,7 +181,7 @@
2
end
-
+
New
True
True
@@ -179,7 +194,7 @@
-
+
Edit
True
True
@@ -192,7 +207,7 @@
-
+
Details
True
True
@@ -517,8 +532,8 @@
False
end
-
- button
+
+ Delete
True
True
True
@@ -527,14 +542,16 @@
True
True
0
+ True
-
- button
+
+ Edit
True
True
True
+
True
@@ -543,11 +560,12 @@
-
- button
+
+ Close
True
True
True
+
True
@@ -787,6 +805,7 @@
True
True
+ adj_number
1
@@ -797,6 +816,7 @@
True
True
+ adj_weight
2
@@ -808,6 +828,7 @@
True
True
+ adj_price
2
@@ -861,11 +882,12 @@
False
end
-
+
Save
True
True
True
+
True
@@ -874,7 +896,7 @@
-
+
Cancel
True
True
diff --git a/yms/ui/maintenance.ui b/yms/ui/maintenance.ui
index 17ce13d..db09424 100644
--- a/yms/ui/maintenance.ui
+++ b/yms/ui/maintenance.ui
@@ -144,11 +144,12 @@
False
end
-
+
New
True
True
True
+
True
@@ -157,11 +158,12 @@
-
+
Edit
True
True
True
+
True
@@ -170,11 +172,12 @@
-
- Delete
+
+ Details
True
True
True
+
True
@@ -195,5 +198,225 @@
page0
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+ label
+
+
+ False
+ True
+ 0
+
+
+
+
+
+ True
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ end
+
+
+ Delete
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ Edit
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ Close
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 2
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ page1
+ page1
+ 1
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+ label
+
+
+ False
+ True
+ 0
+
+
+
+
+
+ True
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ end
+
+
+ Save
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ Cancel
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 2
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ page2
+ page2
+ 2
+
+
diff --git a/yms/ui/projects.ui b/yms/ui/projects.ui
index 8bc2260..93f5fef 100644
--- a/yms/ui/projects.ui
+++ b/yms/ui/projects.ui
@@ -216,5 +216,224 @@
page0
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+ label
+
+
+ False
+ True
+ 0
+
+
+
+
+
+ True
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ end
+
+
+ Delete
+ True
+ True
+ True
+
+
+ True
+ True
+ 0
+ True
+
+
+
+
+ Edit
+ True
+ True
+ True
+
+
+ True
+ True
+ 1
+
+
+
+
+ Close
+ True
+ True
+ True
+
+
+ True
+ True
+ 2
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ page1
+ page1
+ 1
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+ label
+
+
+ False
+ True
+ 0
+
+
+
+
+
+ True
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ False
+ end
+
+
+
+
+
+ Save
+ True
+ True
+ True
+
+
+ True
+ True
+ 1
+
+
+
+
+ Cancel
+ True
+ True
+ True
+
+
+ True
+ True
+ 2
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ page2
+ page2
+ 2
+
+
diff --git a/yms/ui/provisions.ui b/yms/ui/provisions.ui
index 12fbcb5..f1b36b6 100644
--- a/yms/ui/provisions.ui
+++ b/yms/ui/provisions.ui
@@ -151,11 +151,12 @@
False
end
-
+
New
True
True
True
+
True
@@ -164,11 +165,12 @@
-
+
Edit
True
True
True
+
True
@@ -177,11 +179,12 @@
-
- Delete
+
+ Details
True
True
True
+
True
@@ -452,6 +455,7 @@
True
True
True
+
True
@@ -465,6 +469,7 @@
True
True
True
+
True
@@ -745,7 +750,7 @@
-
+
Edit
True
True
diff --git a/yms/ui/status.ui b/yms/ui/status.ui
index 0f256e2..2a1bf56 100644
--- a/yms/ui/status.ui
+++ b/yms/ui/status.ui
@@ -42,6 +42,17 @@
True
False
vertical
+
+
+ True
+ False
+
+
+ False
+ True
+ 0
+
+
True
@@ -57,15 +68,12 @@ thread in "Segeln Forum"
True
True
- 0
+ 1
-
-
-
diff --git a/yms/ui/storage.ui b/yms/ui/storage.ui
new file mode 100644
index 0000000..39c19a7
--- /dev/null
+++ b/yms/ui/storage.ui
@@ -0,0 +1,762 @@
+
+
+
+
+
+ 90
+ 1
+ 10
+
+
+ 100
+ 1
+ 10
+
+
+ 99999
+ 10
+ 100
+
+
+ 99999
+ 10
+ 100
+
+
+ 99999
+ 10
+ 100
+
+
+ 9999
+ 10
+ 100
+
+
+ 9999
+ 10
+ 100
+
+
+ 9999
+ 10
+ 100
+
+
+ True
+ False
+ 8
+
+
+ True
+ False
+ vertical
+
+
+ True
+ True
+
+
+
+ True
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ False
+ Filter Storage
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ True
+ in
+
+
+ True
+ True
+
+
+
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ end
+
+
+ New
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ Edit
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ Details
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 2
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ page0
+ page0
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+ Storage Detais
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ Name
+
+
+ 0
+ 0
+
+
+
+
+ True
+ False
+ Placeholder
+
+
+ 1
+ 0
+
+
+
+
+ True
+ False
+ Remarks
+
+
+ 0
+ 1
+
+
+
+
+
+ 1
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ end
+
+
+ Delete
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 0
+ True
+
+
+
+
+ Edit
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ Close
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 2
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ page1
+ page1
+ 1
+
+
+
+
+ True
+ False
+ vertical
+
+
+ True
+ False
+ Edit Storage
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ Name
+
+
+ 0
+ 0
+
+
+
+
+ True
+ False
+ Typ
+
+
+ 0
+ 1
+
+
+
+
+ True
+ False
+ Position, mm
+
+
+ 0
+ 2
+
+
+
+
+ True
+ False
+ 4
+ 4
+ X
+
+
+ 1
+ 2
+
+
+
+
+ True
+ False
+ 4
+ 4
+ Y
+
+
+ 3
+ 2
+
+
+
+
+ True
+ False
+ 4
+ 4
+ Z
+
+
+ 5
+ 2
+
+
+
+
+ True
+ True
+ 5
+ 5
+ adj_pos_x
+ True
+
+
+ 2
+ 2
+
+
+
+
+ True
+ True
+ 5
+ 5
+ adj_pos_y
+ True
+
+
+ 4
+ 2
+
+
+
+
+ True
+ True
+ 5
+ 5
+ adj_pos_z
+ True
+
+
+ 6
+ 2
+
+
+
+
+ True
+ True
+
+
+ 1
+ 0
+ 6
+
+
+
+
+ True
+ False
+
+
+ 1
+ 1
+ 6
+
+
+
+
+ True
+ False
+ Width, mm
+
+
+ 0
+ 3
+
+
+
+
+ True
+ False
+ 4
+ 4
+ WX
+
+
+ 1
+ 3
+
+
+
+
+ True
+ False
+ 4
+ 4
+ WY
+
+
+ 3
+ 3
+
+
+
+
+ True
+ False
+ 4
+ 4
+ WZ
+
+
+ 5
+ 3
+
+
+
+
+ True
+ True
+ 4
+ 4
+ 0
+ adj_width_x
+ True
+
+
+ 2
+ 3
+
+
+
+
+ True
+ True
+ 4
+ 4
+ 0
+ adj_width_y
+ True
+
+
+ 4
+ 3
+
+
+
+
+ True
+ True
+ 4
+ 4
+ 0
+ adj_width_z
+ True
+
+
+ 6
+ 3
+
+
+
+
+ True
+ False
+ Angle
+
+
+ 0
+ 4
+
+
+
+
+ True
+ True
+ adj_angle
+
+
+ 2
+ 4
+ 2
+
+
+
+
+ True
+ False
+ Capacity
+
+
+ 0
+ 5
+
+
+
+
+ True
+ True
+ adj_capacity
+
+
+ 2
+ 5
+ 2
+
+
+
+
+ True
+ False
+ Remarks
+
+
+ 0
+ 6
+
+
+
+
+ True
+ True
+ in
+
+
+
+
+
+ 1
+ 6
+ 6
+
+
+
+
+ True
+ False
+
+
+ 5
+ 5
+ 2
+
+
+
+
+ True
+ False
+ Unit
+
+
+ 4
+ 5
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ 1
+
+
+
+
+ True
+ False
+ end
+
+
+ Save
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ Cancel
+ True
+ True
+ True
+
+
+
+ True
+ True
+ 2
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ page2
+ page2
+ 2
+
+
+
+
diff --git a/yms/view/base.py b/yms/view/base.py
index 08e8a9d..52b1eef 100644
--- a/yms/view/base.py
+++ b/yms/view/base.py
@@ -27,6 +27,33 @@ class BaseView(View):
#self.topwidget = builder.get_object("topobject")
#gtkutils.init_named_controls(self, builder)
+ # company types
+ self.db.cur.execute("SELECT ddval, ddtext FROM dropdown WHERE ddid=2 ORDER BY ddval")
+ self.comptype = dict(self.db.cur.fetchall())
+ combobox.load_from_dict(self.combo['flt_type'], {-2: _("─── all ───")} | self.comptype, -1)
+
+ # companies
+ self.lst_companies = Gtk.ListStore(int, str, str, str)
+ self.db.cur.execute("SELECT compid, compname, comptype, remarks FROM company ORDER BY compname")
+ for row in self.db.cur.fetchall():
+ self.lst_companies.append((row[0], row[1], self.comptype[row[2]], row[3]))
+ treeview.add_column(self.tree['companies'], _('ID'), 0)
+ treeview.add_column(self.tree['companies'], _('Name'), 1)
+ treeview.add_column(self.tree['companies'], _('Type'), 2)
+ treeview.add_column(self.tree['companies'], _('Remarks'), 3)
+ 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)
+
+ # shipyard
+ self.db.cur.execute("SELECT compid, compname FROM company WHERE comptype=3 ORDER BY compname")
+ shipyards = dict(self.db.cur.fetchall())
+ combobox.load_from_dict(self.combo['shipyard'], {-1: _("─── none ───")} | shipyards)
+
# get current vessel data
self.db.cur.execute("SELECT valint FROM settings WHERE userid=0 AND sno=1")
row = self.db.cur.fetchone()
@@ -38,11 +65,20 @@ class BaseView(View):
else:
self.context.vessel.vid = row[0]
+ # default storage for current vessel
+ sql = "SELECT sid, sname FROM storage WHERE stype=0 AND vid=%s ORDER BY sname"
+ self.db.cur.execute(sql, (self.context.vessel.vid,))
+ storages = dict(self.db.cur.fetchall())
+ combobox.load_from_dict(self.combo['storage'], {-1: _("─── none ───")} | storages)
+
# 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']
+ vessellist[row['vid']] = (
+ row['vesselname'] if row['model'] is None
+ else row['vesselname'] + " - " + row['model']
+ )
combobox.load_from_dict(self.combo['vessel'], vessellist, self.context.vessel.vid)
# vessel load triggered from combobox init
@@ -73,39 +109,6 @@ class BaseView(View):
treeview.add_column(self.tree['ddlists'], _('Records'), 2)
self.tree['ddlists'].set_model(self.lst_lists)
- # company types
- self.db.cur.execute("SELECT ddval, ddtext FROM dropdown WHERE ddid=2 ORDER BY ddval")
- self.comptype = dict(self.db.cur.fetchall())
- combobox.load_from_dict(self.combo['flt_type'], {-1: _("─── all ───")} | self.comptype, -1)
-
- # companies
- self.lst_companies = Gtk.ListStore(int, str, str, str)
- self.db.cur.execute("SELECT compid, compname, comptype, remarks FROM company ORDER BY compname")
- for row in self.db.cur.fetchall():
- self.lst_companies.append((row[0], row[1], self.comptype[row[2]], row[3]))
- treeview.add_column(self.tree['companies'], _('ID'), 0)
- treeview.add_column(self.tree['companies'], _('Name'), 1)
- treeview.add_column(self.tree['companies'], _('Type'), 2)
- treeview.add_column(self.tree['companies'], _('Remarks'), 3)
- 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)
-
- # shipyard
- self.db.cur.execute("SELECT compid, compname FROM company WHERE comptype=3 ORDER BY compname")
- shipyards = dict(self.db.cur.fetchall())
- combobox.load_from_dict(self.combo['shipyard'], shipyards)
-
- # default storage
- self.lst_storage_dfl = Gtk.ListStore(int, str)
- self.db.cur.execute("SELECT sid, sname FROM storage WHERE stype=0 ORDER BY sname")
- storages = dict(self.db.cur.fetchall())
- combobox.load_from_dict(self.combo['storage'], storages)
-
# 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, ))
@@ -125,23 +128,50 @@ class BaseView(View):
# WIP generic remarks handling
self.text['vessel_remarks'].set_size_request(200, 70)
+ def load_dropdowns(self):
+ # non static dropdown (re-)load feature
+ # default storage for current vessel
+ sql = "SELECT sid, sname FROM storage WHERE stype=0 AND vid=%s ORDER BY sname"
+ self.db.cur.execute(sql, (self.context.vessel.vid,))
+ storages = dict(self.db.cur.fetchall())
+ combobox.refresh_dict(self.combo['storage'], {-1: _("─── none ───")} | storages)
+
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()
+ # Refresh dependent data
+ self.load_dropdowns()
# 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)
+ self.display_vessel(self.context.vessel)
def on_but_vessel_add_clicked(self, widget):
- print("Add vessel")
+ answer = gtkutils.questionbox(
+ _("Add new vessel.\n"
+ "Are you sure?"
+ ), title="YMS")
+ if answer == False:
+ return
+ self.context.vessel.create()
def on_but_vessel_save_clicked(self, widget):
print("Save vessel")
+ vessel = self.context.vessel
+ vessel.vesselname = self.entry['vesselname'].get_text()
+ vessel.model = self.entry['model'].get_text()
+ vessel.year_built = self.spin['year_built'].get_value_as_int()
+ vessel.loa = self.spin['loa'].get_value()
+ vessel.lwl = self.spin['lwl'].get_value()
+ vessel.beam = self.spin['beam'].get_value()
+ vessel.draught = self.spin['draught'].get_value()
+ vessel.draught_min = self.spin['draught_min'].get_value()
+ vessel.displacement = self.spin['displacement'].get_value_as_int()
+ vessel.ballast = self.spin['ballast'].get_value_as_int()
+
+ txtbuf = self.text['vessel_remarks'].get_buffer()
+ vessel.remarks = txtbuf.get_text(txtbuf.get_start_iter(), txtbuf.get_end_iter(), True)
+ vessel.save()
def on_but_comp_new_clicked(self, widget):
print("New company")
@@ -158,20 +188,52 @@ class BaseView(View):
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)
+ def display_vessel(self, vessel):
+ print("Display 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)
+ self.spin['loa'].set_value(vessel.loa or 0)
+ self.spin['lwl'].set_value(vessel.lwl or 0)
+ self.spin['beam'].set_value(vessel.beam or 0)
+ self.spin['draught'].set_value(vessel.draught or 0)
+ self.spin['draught_min'].set_value(vessel.draught_min or 0)
+ self.spin['displacement'].set_value(vessel.displacement or 0)
+ self.spin['ballast'].set_value(vessel.ballast or 0)
+ self.text['vessel_remarks'].get_buffer().set_text(vessel.remarks or '')
+ combobox.activate_row(self.combo['shipyard'], vessel.shipyard or -1)
+ combobox.activate_row(self.combo['storage'], vessel.sid_default or -1)
+
+ def display_user(self, user):
+ self.entry['user_login'].set_text(user.login)
+ self.entry['user_displayname'].set_text(user.displayname)
+ combobox.activate_row(self.combo['user_role'], user.role)
+ combobox.activate_row(self.combo['user_lang'], user.language)
+ self.check['user_locked'].set_active('locked' in user.flags)
+ self.check['user_deleted'].set_active('deleted' in user.flags)
self.entry['user_pass'].set_text('')
+ def display_company(self, company):
+ self.entry['compname'].set_text(company.compname)
+ # Type
+ # Type2
+ self.entry['shortname'].set_text(company.shortname)
+ self.entry['street'].set_text(company.street)
+ self.entry['zip'].set_text(company.zip)
+ self.entry['city'].set_text(company.city)
+ self.entry['country'].set_text(company.country)
+ self.entry['contact'].set_text(company.contact)
+ self.entry['phone'].set_text(company.phone)
+ self.entry['email'].set_text(company.email)
+ self.entry['web'].set_text(company.web)
+ self.entry['customerno'].set_text(company.customerno)
+ self.entry['contractno'].set_text(company.contractno)
+
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()
+ self.display_user(self.context.user)
def on_but_user_new_clicked(self, widget):
# get first free user id and create a new record with name "user"
@@ -193,7 +255,7 @@ class BaseView(View):
# 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()
+ self.display_user(self.context.user)
def on_but_user_newpass_clicked(self, widget):
self.entry['user_pass'].set_text(self.context.user.genpass())
diff --git a/yms/view/documents.py b/yms/view/documents.py
index 7964bf9..55f7199 100644
--- a/yms/view/documents.py
+++ b/yms/view/documents.py
@@ -5,15 +5,57 @@ 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 document
-class DocumentsView:
+class DocumentsView(View):
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)
+ super().__init__(context, _("Documents"), "documents.ui")
+
+ self.doc = document.Document(context.db) # current record
+ self.newrecord = False
+
+ self.lst_documents = Gtk.ListStore(int, str, str, str, int)
+ sql = (
+ "SELECT d.docid, d.doctype, d.filename, d.title, COUNT(r.drid) AS refcount "
+ "FROM document AS d LEFT OUTER JOIN docref AS r USING (docid) "
+ "GROUP BY d.docid, d.doctype, d.filename, d.title "
+ "ORDER BY d.docid"
+ )
+ self.db.cur.execute(sql)
+ for row in self.db.cur.fetchall():
+ self.lst_documents.append(row)
+
+ treeview.add_column(self.tree['documents'], _('ID'), 0)
+ treeview.add_column(self.tree['documents'], _('Type'), 1)
+ treeview.add_column(self.tree['documents'], _('Filename'), 2)
+ treeview.add_column(self.tree['documents'], _('Title'), 3)
+ treeview.add_column(self.tree['documents'], _('References'), 3)
+ self.tree['documents'].set_model(self.lst_documents)
+
+ # buttons on list page
+ def on_but_new_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['doc_edit'])
+
+ def on_but_edit_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['doc_edit'])
+
+ def on_but_detail_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['doc_detail'])
+
+ # buttons on detail page
+ # edit2 uses edit callback
+ def on_but_close_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['documents'])
+
+ def on_but_delete_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['documents'])
+
+ # buttons on edit page
+ def on_but_save_clicked(self, widget):
+ pass
+
+ def on_but_cancel_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['documents'])
diff --git a/yms/view/equipment.py b/yms/view/equipment.py
index 75130ad..78c69e2 100644
--- a/yms/view/equipment.py
+++ b/yms/view/equipment.py
@@ -5,39 +5,60 @@ 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 equipment
-class EquipmentView:
+class EquipmentView(View):
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)
+ super().__init__(context, _("Equipment"), "equipment.ui")
+ self.equip = equipment.Equipment(context.db) # current record
+ self.newrecord = False
+
+ self.lst_equipment = Gtk.ListStore(int, str, str, str, str, str, str)
+ sql = (
+ "SELECT e.eid, e.ename, c.compname, e.model, e.serial, "
+ "DATE_FORMAT(e.purchdate, '{}'), e.remarks "
+ "FROM equipment AS e LEFT OUTER JOIN company AS c ON (e.manufacturer=c.compid) "
+ "WHERE e.vid=%s "
+ "ORDER BY e.ename"
+ ).format("%%d.%%m.%%Y") # TODO format from settings via mapping
+ self.db.cur.execute(sql, (context.vessel.vid,))
+ for row in self.db.cur.fetchall():
+ self.lst_equipment.append(row)
+
+ treeview.add_column(self.tree['equipment'], _('ID'), 0)
+ treeview.add_column(self.tree['equipment'], _('Name'), 1)
+ treeview.add_column(self.tree['equipment'], _('Manufacturer'), 2)
+ treeview.add_column(self.tree['equipment'], _('Model'), 3)
+ treeview.add_column(self.tree['equipment'], _('Serial'), 4)
+ treeview.add_column(self.tree['equipment'], _('Age'), 5)
+ treeview.add_column(self.tree['equipment'], _('Remarks'), 6)
+ self.tree['equipment'].set_model(self.lst_equipment)
+
+ # buttons on list page
def on_but_new_clicked(self, widget):
self.topwidget.set_visible_child(self.box['equip_edit'])
+ def on_but_edit_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'])
-
+ # buttons on detail page
+ # edit2 uses edit callback
def on_but_close_clicked(self, widget):
- self.topwidget.set_visible_child(self.box['equip_detail'])
-
- def on_but_save_clicked(self, widget):
- pass
+ self.topwidget.set_visible_child(self.box['equipment'])
def on_but_delete_clicked(self, widget):
self.topwidget.set_visible_child(self.box['equipment'])
+ # buttons on edit page
+ def on_but_save_clicked(self, widget):
+ pass
+
def on_but_cancel_clicked(self, widget):
self.topwidget.set_visible_child(self.box['equipment'])
diff --git a/yms/view/inventory.py b/yms/view/inventory.py
index efbfc3c..b925662 100644
--- a/yms/view/inventory.py
+++ b/yms/view/inventory.py
@@ -5,15 +5,63 @@ 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 inventory
-class InventoryView:
+class InventoryView(View):
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)
+ super().__init__(context, _("Inventory"), "inventory.ui")
+
+ self.inv = inventory.Inventory(context.db) # current record
+ self.newrecord = False
+
+ # Inventory gets vessel assignment via
+ # - storage direct
+ # - or via box which is assigned to a storage
+ self.lst_inventory = Gtk.ListStore(int, str, str, int, str, str)
+ sql = (
+ "SELECT i.invid, i.invname, s.sname AS container, i.number, i.invcond, i.remarks "
+ "FROM inventory AS i JOIN storage AS s ON (i.conttype='storage' AND i.sid=s.sid) "
+ "WHERE s.vid=%s "
+ "UNION SELECT i.invid, i.invname, b.label AS container, i.number, i.invcond, i.remarks "
+ "FROM inventory AS i JOIN box AS b ON (i.conttype='box' AND i.boxid=b.boxid) JOIN storage AS s ON (b.sid=s.sid) "
+ "WHERE s.vid=%s"
+ )
+ self.db.cur.execute(sql, (context.vessel.vid, context.vessel.vid))
+ for row in self.db.cur.fetchall():
+ self.lst_inventory.append(row)
+
+ treeview.add_column(self.tree['inventory'], _('ID'), 0)
+ treeview.add_column(self.tree['inventory'], _('Name'), 1)
+ treeview.add_column(self.tree['inventory'], _('Container'), 2)
+ treeview.add_column(self.tree['inventory'], _('Number'), 3)
+ treeview.add_column(self.tree['inventory'], _('Condition'), 4)
+ treeview.add_column(self.tree['inventory'], _('Remarks'), 5)
+ self.tree['inventory'].set_model(self.lst_inventory)
+
+ # buttons on list page
+ def on_but_new_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['inv_edit'])
+
+ def on_but_edit_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['inv_edit'])
+
+ def on_but_detail_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['inv_detail'])
+
+ # buttons on detail page
+ # edit2 uses edit callback
+ def on_but_close_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['inventory'])
+
+ def on_but_delete_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['inventory'])
+
+ # buttons on edit page
+ def on_but_save_clicked(self, widget):
+ pass
+
+ def on_but_cancel_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['inventory'])
diff --git a/yms/view/maintenance.py b/yms/view/maintenance.py
index ad9dada..5a0248f 100644
--- a/yms/view/maintenance.py
+++ b/yms/view/maintenance.py
@@ -5,15 +5,56 @@ import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
+from .view import View
from yms import gtkutils, combobox, treeview
+from yms.model import maintenance
-class MaintenanceView:
+class MaintenanceView(View):
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)
+ super().__init__(context, _("Maintenance"), "maintenance.ui")
+
+ self.maint = maintenance.Maintenance(context.db) # current record
+ self.newrecord = False
+
+ self.lst_maintenance = Gtk.ListStore(int, str, str, str)
+ sql = (
+ "SELECT m.maintid, m.activities, e.ename, m.remarks "
+ "FROM maintenance AS m LEFT OUTER JOIN equipment AS e USING (eid) "
+ "WHERE m.vid=%s "
+ "ORDER BY m.maintid"
+ )
+ self.db.cur.execute(sql, (context.vessel.vid,))
+ for row in self.db.cur.fetchall():
+ self.lst_maintenance.append(row)
+
+ treeview.add_column(self.tree['maintenance'], _('ID'), 0)
+ treeview.add_column(self.tree['maintenance'], _('Activities'), 1)
+ treeview.add_column(self.tree['maintenance'], _('Equipment'), 2)
+ treeview.add_column(self.tree['maintenance'], _('Remarks'), 3)
+ self.tree['maintenance'].set_model(self.lst_maintenance)
+
+ # buttons on list page
+ def on_but_new_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['maint_edit'])
+
+ def on_but_edit_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['maint_edit'])
+
+ def on_but_detail_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['maintv_detail'])
+
+ # buttons on detail page
+ # edit2 uses edit callback
+ def on_but_close_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['maintenance'])
+
+ def on_but_delete_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['maintenance'])
+
+ # buttons on edit page
+ def on_but_save_clicked(self, widget):
+ pass
+
+ def on_but_cancel_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['maintenance'])
diff --git a/yms/view/projects.py b/yms/view/projects.py
index 6ea755f..7a74798 100644
--- a/yms/view/projects.py
+++ b/yms/view/projects.py
@@ -5,15 +5,66 @@ import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
+from .view import View
from yms import gtkutils, combobox, treeview
+from yms.model import project
-class ProjectsView:
+class ProjectsView(View):
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)
+ super().__init__(context, _("Projects"), "projects.ui")
+
+ self.project = project.Project(context.db) # current record
+ self.newrecord = False
+
+ self.lst_projects = Gtk.ListStore(int, str, str, int, str, str)
+ sql = (
+ "SELECT projid, projname, startdate, duration, projstate, remarks "
+ "FROM project "
+ "WHERE vid=%s "
+ "ORDER BY projid"
+ )
+ self.db.dcur.execute(sql, (context.vessel.vid,))
+ for row in self.db.dcur.fetchall():
+ data = (
+ row['projid'],
+ row['projname'],
+ self.format_date(row['startdate']),
+ row['duration'],
+ row['projstate'],
+ row['remarks']
+ )
+ self.lst_projects.append(data)
+
+ treeview.add_column(self.tree['projects'], _('ID'), 0)
+ treeview.add_column(self.tree['projects'], _('Name'), 1)
+ treeview.add_column(self.tree['projects'], _('Start date'), 2)
+ treeview.add_column(self.tree['projects'], _('Duration'), 3)
+ treeview.add_column(self.tree['projects'], _('Status'), 4)
+ treeview.add_column(self.tree['projects'], _('Remarks'), 5)
+ self.tree['projects'].set_model(self.lst_projects)
+
+ # buttons on list page
+ def on_but_new_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['proj_edit'])
+
+ def on_but_edit_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['proj_edit'])
+
+ def on_but_detail_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['proj_detail'])
+
+ # buttons on detail page
+ # edit2 uses edit callback
+ def on_but_close_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['projects'])
+
+ def on_but_delete_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['projects'])
+
+ # buttons on edit page
+ def on_but_save_clicked(self, widget):
+ pass
+
+ def on_but_cancel_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['projects'])
diff --git a/yms/view/provisions.py b/yms/view/provisions.py
index 3a721e4..75169c4 100644
--- a/yms/view/provisions.py
+++ b/yms/view/provisions.py
@@ -5,15 +5,71 @@ import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
+from .view import View
from yms import gtkutils, combobox, treeview
+from yms.model import provision
-class ProvisionsView:
+class ProvisionsView(View):
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)
+ super().__init__(context, _("Provisions"), "provisions.ui")
+
+ self.prov = provision.Provision(context.db) # current record
+ self.newrecord = False
+
+ self.load_dropdown()
+
+ self.lst_provisions = Gtk.ListStore(int, str, int, str, str, str)
+ sql = (
+ "SELECT p.provid, p.provname, p.number, p.unit, p.storedate, p.shelflife "
+ "FROM provisions AS p LEFT OUTER JOIN storage AS s USING (sid) "
+ "WHERE s.vid=%s"
+ )
+ self.db.dcur.execute(sql, (context.vessel.vid,))
+ for row in self.db.dcur.fetchall():
+ data = (
+ row['provid'],
+ row['provname'],
+ row['number'],
+ self.prov_unit[row['unit']],
+ self.format_date(row['storedate']),
+ self.format_date(row['shelflife'])
+ )
+ self.lst_provisions.append(data)
+
+ treeview.add_column(self.tree['provisions'], _('ID'), 0)
+ treeview.add_column(self.tree['provisions'], _('Description'), 1)
+ treeview.add_column(self.tree['provisions'], _('Number'), 2)
+ treeview.add_column(self.tree['provisions'], _('Unit'), 3)
+ treeview.add_column(self.tree['provisions'], _('Stored'), 4)
+ treeview.add_column(self.tree['provisions'], _('Best before'), 5)
+ self.tree['provisions'].set_model(self.lst_provisions)
+
+ def load_dropdown(self):
+ self.db.cur.execute("SELECT ddval, ddtext FROM dropdown WHERE ddid=6 ORDER BY ddval")
+ self.prov_unit = dict(self.db.cur.fetchall())
+
+ # buttons on list page
+ def on_but_new_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['prov_edit'])
+
+ def on_but_edit_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['prov_edit'])
+
+ def on_but_detail_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['prov_detail'])
+
+ # buttons on detail page
+ # edit2 uses edit callback
+ def on_but_close_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['provisions'])
+
+ def on_but_delete_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['provisions'])
+
+ # buttons on edit page
+ def on_but_save_clicked(self, widget):
+ pass
+
+ def on_but_cancel_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['provisions'])
diff --git a/yms/view/status.py b/yms/view/status.py
index 108bcd7..9e9dacd 100644
--- a/yms/view/status.py
+++ b/yms/view/status.py
@@ -20,6 +20,9 @@ class StatusView:
self.topwidget = builder.get_object("topobject")
gtkutils.init_named_controls(self, builder)
+ # Generic information
+ self.label['dbinfo'].set_text("Database: {}".format(context.cfg['db']))
+
# Load table status info
self.lst_tables = Gtk.ListStore(str, int)
for row in self.get_table_counts():
diff --git a/yms/view/storage.py b/yms/view/storage.py
new file mode 100644
index 0000000..a9639fa
--- /dev/null
+++ b/yms/view/storage.py
@@ -0,0 +1,88 @@
+# 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 storage
+
+class StorageView(View):
+
+ def __init__(self, context):
+ super().__init__(context, _("Storage"), "storage.ui")
+
+ self.storage = storage.Storage(context.db) # current record
+ self.newrecord = False
+
+ self.lst_storage = Gtk.ListStore(int, str, str, str)
+ sql = (
+ "SELECT sid, sname, CONCAT(x, ',', y, ',', z) AS position, remarks "
+ "FROM storage "
+ "WHERE vid=%s "
+ "ORDER BY sname"
+ )
+ self.db.cur.execute(sql, (context.vessel.vid,))
+ for row in self.db.cur.fetchall():
+ self.lst_storage.append(row)
+
+ treeview.add_column(self.tree['storage'], _('ID'), 0)
+ treeview.add_column(self.tree['storage'], _('Name'), 1)
+ treeview.add_column(self.tree['storage'], _('Position'), 2)
+ treeview.add_column(self.tree['storage'], _('Remarks'), 3)
+ self.tree['storage'].set_model(self.lst_storage)
+
+
+ def load_list(self):
+ pass
+
+ def display_record(self):
+ self.label['name'].set_text(self.storage.sname)
+ self.label['remarks'].set_text(self.storage.remarks or '')
+
+ def edit_record(self):
+ self.entry['sname'].set_text(self.storage.sname)
+ self.spin['x'].set_value(self.storage.x)
+ self.spin['y'].set_value(self.storage.y)
+ self.spin['z'].set_value(self.storage.z)
+ self.text['remarks'].get_buffer().set_text(self.storage.remarks or '')
+
+ # buttons on list page
+ def on_but_new_clicked(self, widget):
+ self.newrecord = True
+ self.label['title_edit'].set_text("Add new Storage")
+ self.topwidget.set_visible_child(self.box['stor_edit'])
+
+ def on_but_edit_clicked(self, widget):
+ 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'])
+
+ def on_but_detail_clicked(self, widget):
+ sid = treeview.get_value(self.tree['storage'], 0)
+ self.storage.load(sid)
+ self.display_record()
+ self.topwidget.set_visible_child(self.box['stor_detail'])
+
+ # buttons on detail page
+ # edit2 uses edit callback
+ def on_but_close_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['storage'])
+
+ def on_but_delete_clicked(self, widget):
+ self.topwidget.set_visible_child(self.box['storage'])
+ 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['storage'])
+ self.newrecord = False
diff --git a/yms/view/view.py b/yms/view/view.py
index 0b5637e..222e49c 100644
--- a/yms/view/view.py
+++ b/yms/view/view.py
@@ -8,10 +8,11 @@ SPDX-License-Identifier: WTFPL
import os
import gi
gi.require_version("Gtk", "3.0")
-from gi.repository import Gtk
+from gi.repository import GLib, Gtk, Gdk
from yms import gtkutils
class View:
+
def __init__(self, context, title, ui_file):
self.context = context
self.db = context.db
@@ -25,6 +26,11 @@ class View:
self.topwidget = builder.get_object("topobject")
gtkutils.init_named_controls(self, builder)
+ def format_date(self, dateval):
+ if dateval is None:
+ return ''
+ return dateval.strftime(self.context.datefmt)
+
def on_textview_keypress(self, widget, event):
# Generic limit length function
if event.state & Gdk.ModifierType.CONTROL_MASK:
diff --git a/ymsgui.py b/ymsgui.py
index 4b00bb3..6178c58 100755
--- a/ymsgui.py
+++ b/ymsgui.py
@@ -14,7 +14,7 @@ Configuration file located at ~/.config/ymsgui.conf:
pass = topsecret
[Documents]
- basepath = /var/local/yms
+ basepath = /var/local/lib/yms
[Data]
shapedir = /usr/local/share/yms/shapes
@@ -39,6 +39,7 @@ from yms.model import user
from yms.model import vessel
from yms.view.base import BaseView
+from yms.view.storage import StorageView
from yms.view.equipment import EquipmentView
from yms.view.inventory import InventoryView
from yms.view.provisions import ProvisionsView
@@ -57,6 +58,15 @@ class AppContext:
'docpath': '/var/local/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'
+ }
def __init__(self):
self.db = None
@@ -64,6 +74,7 @@ class AppContext:
self.vessel = None
self.ui_path = os.path.join(self.get_sharepath(), "yms", "ui")
self.textdomain = "ymsgui"
+ self.datefmt = '%d.%m.%Y'
def set_db(self, db):
self.db = db
@@ -71,6 +82,19 @@ class AppContext:
def load(self):
self.user = user.User(db, 0)
self.vessel = vessel.Vessel(db)
+ # load date format from db settings
+ sql = "SELECT valstr FROM settings WHERE userid=0 AND sno=2"
+ self.db.cur.execute(sql)
+ row = self.db.cur.fetchone()
+ if row is not None:
+ try:
+ self.datefmt = self.datefmt_map[row[0]]
+ except KeyError:
+ # almost impossible case where db value is not in mapping
+ print("internal error: format mapping missinf")
+ else:
+ # perhaps create missing record here?
+ pass
def get_sharepath(self):
path = os.path.realpath(__file__)
@@ -85,6 +109,7 @@ class Frontend:
def __init__(self, context):
self.modules = {
"base": BaseView(context),
+ "storage": StorageView(context),
"equipment": EquipmentView(context),
"inventory": InventoryView(context),
"provisions": ProvisionsView(context),