diff --git a/changelog.md b/changelog.md
index 3ae34b3..af87779 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,14 @@
# Changelog GarageCalc1
+## [0.7] - 2021-07-09
+## Added
+- Einheiten können pro Zelle mit F3 eingegben/editiert/umgerechnet werden
+- Menü erweitert
+- Ini-Datei erweitert um Standard-Einheiten
+
+## Changed
+- Ini-Datei wird nun im Ordner der Applikation gespeichert/geladen, nicht mehr aus %LOCALAPPDATA%
+
## [0.6] - 2021-07-06
## Added
- Dezimalzahlen werden nun mit Dezimaltrennzeichen Komma (",") eingegeben statt Punkt (".")
diff --git a/i18n/de_DE.qm b/i18n/de_DE.qm
index a3d31e6..eea8d85 100644
Binary files a/i18n/de_DE.qm and b/i18n/de_DE.qm differ
diff --git a/i18n/de_DE.ts b/i18n/de_DE.ts
index ed1c39c..81a9eca 100644
--- a/i18n/de_DE.ts
+++ b/i18n/de_DE.ts
@@ -4,77 +4,77 @@
TableWidget
-
+
Ausschneiden
-
+
Kopieren
-
+
Einfügen
-
+
Löschen
-
+
Zeile ausschneiden
-
+
Zeile kopieren
-
+
Zeile einfügen
-
+
Zeile oberhalb einfügen
-
+
Zeile unterhalb einfügen
-
+
Zeile entfernen
-
+
Zellinhalte löschen
-
+
Zeile Nr.
-
+
entfernen?
-
+
Entfernen
-
+
Zellinhalt löschen?
@@ -87,122 +87,122 @@
Hallo Welt
-
+
&Einstellungen
-
+
Sprache
-
+
Gegenstand
-
+
Länge
-
+
Breite
-
+
Höhe
-
+
Gewicht
-
+
Dimension der Garage
-
+
Dimensionen der zu verstauenden Gegenstände
-
+
Ergebnis
-
+
Volumen der Garage
-
+
Volumen der Gegenstände
-
+
Freier Raum in der Garage
-
+
Gesamtgewicht
-
+
Neu (Strg+N)
-
+
Öffnen... (Strg+O)
-
+
Speichern (Strg+S)
-
+
Export nach EXCEL...
-
+
Informationen über das Programm
-
+
Programm beenden (Strg+Q)
-
+
Garage
-
+
Beenden
-
+
Neu
-
+
Speichern
@@ -212,27 +212,27 @@
CSV-Datei
-
+
Alle Dateien
-
+
Datei
-
+
gespeichert
-
+
Öffnen
-
+
Export
@@ -242,72 +242,127 @@
EXCEL-Datei
-
+
Fehler in der Garagen-Dimension
-
+
Fehler in den Dimensionen der zu verstauenden Gegenstände
-
+
Erfolgreich nach EXCEL exportiert
-
+
CSV-Datei
-
+
EXCEL-Datei
-
+
Es gibt ungespeicherte Einträge. Ohne zu speichern, gehen alle Änderungen verloren. Trotzdem fortfahren?
- Garagenraum-Rechner
+ Garagenraum-Rechner
-
+
Berechnet zur Verfügung stehenden Garagenraum
-
+
Kommentar
+
+
+
+ Maßeinheit
+
+
+
+
+ Längeneinheit
+
+
+
+
+ Masseeinheit
+
+
+
+
+ &Datei
+
+
+
+
+ Hilfe
+
+
+
+
+ Möchten Sie alle vorhandenen Gegenstände vom Typ Länge auf die neue Maßeinheit umrechnen
+
+
+
+
+ Einheiten Umrechnung
+
+
+
+
+ Möchten Sie alle vorhandenen Gegenstände vom Typ Gewicht auf die neue Maßeinheit umrechnen
+
utils
-
+
Idee
- Verwendete Icons: Thema
+ Verwendete Icons: Thema
-
+
von
-
+
Version
+
+
+
+ Verwendete Icons
+
+
+
+
+ Aktuell geöffnete Datei
+
+
+
+
+ Dateipfad der Ini-Datei
+
diff --git a/i18n/hu_HU.qm b/i18n/hu_HU.qm
index 40edbed..3dacaf9 100644
Binary files a/i18n/hu_HU.qm and b/i18n/hu_HU.qm differ
diff --git a/i18n/hu_HU.ts b/i18n/hu_HU.ts
index ec1796c..fda8d22 100644
--- a/i18n/hu_HU.ts
+++ b/i18n/hu_HU.ts
@@ -1,80 +1,80 @@
-
+
TableWidget
-
+
kivágni
-
+
másolás
-
+
Beillesztés
-
+
Törlés
-
+
Vágott vonal
-
+
Vettem a szöveget
-
+
Beilleszteni a sort
-
+
A fenti sort beilleszteni
-
+
Az alábbi sor beillesztése
-
+
Távolítsa el a sort
-
+
Tartalom törlése
-
+
Vonalszám.
-
+
eltávolítani?
-
+
A eltávolítása
-
+
Cellatartalom törlése?
@@ -87,122 +87,122 @@
Hallo Welt
-
+
&Beállítások
-
+
Nyelv
-
+
Tárgy
-
+
Hosszúság
-
+
Szélesség
-
+
Magasság
-
+
Súly
-
+
A garázs mérete
-
+
A tárolandó objektumok méretei
-
+
Eredmény
-
+
A garázs térfogata
-
+
A tételek mennyisége
-
+
Szabad hely a garázsban
-
+
Teljes súly
-
+
Új (Ctrl+N)
-
+
Nyissa ki (Ctrl+O)
-
+
Mentés (Ctrl+S)
-
+
Exportálás EXCEL-be...
-
+
Az alkalmazással kapcsolatos információk
-
+
Az alkalmazás kilépése (Ctrl+Q)
-
+
Garázs
-
+
Kilépés
-
+
Új
-
+
Mentés
@@ -212,27 +212,27 @@
CSV-fájl
-
+
Minden fájl
-
+
fájl
-
+
mentett
-
+
Megnyitott
-
+
Exportálás
@@ -242,72 +242,127 @@
EXCEL-fájl
-
+
Hiba a garázs dimenziójában
-
+
Hiba a tárolandó objektumok méreteiben
-
+
Sikeresen exportált EXCEL-be
-
+
CSV-fájl
-
+
EXCEL-fájl
-
+
Vannak mentetlen bejegyzések. Mentés nélkül minden módosítás elveszik. Folytassa mégis?
- Garázs hely kalkulátor
+ Garázs hely kalkulátor
-
+
Kiszámítja a rendelkezésre álló garázshelyet
-
+
Megjegyzés
+
+
+
+ Mérési egység
+
+
+
+
+ Hosszúsági egységek
+
+
+
+
+ Tömegegységek
+
+
+
+
+ &Fájl
+
+
+
+
+ Segítség
+
+
+
+
+ Át akarja konvertálni az összes meglévő hosszúság típusú anyagot az új mértékegységre
+
+
+
+
+ Egység átváltás
+
+
+
+
+ Át akarja konvertálni az összes meglévő tömeg típusú anyagot az új mértékegységre
+
utils
-
+
Ötlet
- Használt ikonok: Téma
+ Használt ikonok: Téma
-
+
a weboldalról
-
+
Verzió
+
+
+
+ Használt ikonok
+
+
+
+
+ Jelenleg megnyitott fájl
+
+
+
+
+ Az Ini-fájl helye
+
diff --git a/img/qt_logo_small.png b/img/qt_logo_small.png
new file mode 100644
index 0000000..94dfbf2
Binary files /dev/null and b/img/qt_logo_small.png differ
diff --git a/src/clsTableWidget.py b/src/clsTableWidget.py
index 8af1e30..2058bcc 100644
--- a/src/clsTableWidget.py
+++ b/src/clsTableWidget.py
@@ -14,13 +14,22 @@ import os
# Third party imports
from PySide2.QtWidgets import QApplication, QTableWidget, QAbstractItemView, QTableWidgetItem, QMenu, \
- QMainWindow, QMessageBox
-from PySide2.QtCore import Qt, QItemSelectionModel, QCoreApplication
-from PySide2.QtGui import QIcon
+ QMainWindow, QMessageBox, QComboBox, QDialog
+from PySide2.QtCore import Qt, QFile, QItemSelectionModel, QCoreApplication, Slot
+from PySide2.QtGui import QIcon, QColor, QPalette
+from PySide2.QtUiTools import QUiLoader
+
+# local imports
+from utils import resource_path, convert_uom_to_length, convert_uom_to_mass
# local globals
SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__))
+DEFAULT_UOM_LENGTH = None
+DEFAULT_UOM_MASS = None
+
+UI_DLG_UOM = "./ui/dlg_uom.ui"
+
ICON_CLEAR = SCRIPT_PATH + "./img/icons8-clear-symbol-16.png"
ICON_COPY = SCRIPT_PATH + "./img/icons8-copy-16.png"
ICON_ERASER = SCRIPT_PATH + "/img/icons8-eraser-16.png"
@@ -43,11 +52,14 @@ ICON_DEL = SCRIPT_PATH + "/img/icons8-delete-16.png"
# return os.path.join(base_path, relative_path)
class TableWidget(QTableWidget):
- def __init__(self, parent=None):
+ def __init__(self, parent=None, uom_length=DEFAULT_UOM_LENGTH, uom_mass=DEFAULT_UOM_MASS):
super().__init__()
self.parent = parent
+ self.default_uom_length = uom_length
+ self.default_uom_mass = uom_mass
+
# self.setSelectionMode(QAbstractItemView.ContiguousSelection)
self.setSelectionMode(QAbstractItemView.SingleSelection)
@@ -70,8 +82,6 @@ class TableWidget(QTableWidget):
self.vertHeader.setSelectionMode(QAbstractItemView.SingleSelection)
self.vertHeader.sectionClicked.connect(self.select_row)
self.vertHeader.setSectionsMovable(True)
- # optimize row height
- self.resizeRowsToContents()
self.row_selected = False
@@ -87,8 +97,6 @@ class TableWidget(QTableWidget):
item_copy = menu.addAction(QIcon(ICON_COPY), QCoreApplication.translate("TableWidget", "Copy") + "\tCtrl+C")
item_paste = menu.addAction(QIcon(ICON_PASTE), QCoreApplication.translate("TableWidget", "Paste") + "\tCtrl+V")
menu.addSeparator()
-
- print(ICON_ERASER)
item_delete = menu.addAction(QIcon(ICON_ERASER), QCoreApplication.translate("TableWidget", "Delete") + "\tDel")
ac = menu.exec_(self.mapToGlobal(position))
@@ -183,41 +191,144 @@ class TableWidget(QTableWidget):
if key == Qt.Key_Delete:
self.item_del()
+ elif key == Qt.Key_F3:
+ item = self.item(self.currentRow(), self.currentColumn())
+ try:
+ self.parent.cols_with_uom_length
+ self.parent.cols_with_uom_mass
+ except:
+ return False
+ else:
+ if self.currentColumn() in self.parent.cols_with_uom_length:
+ self.f3_pressed(item, "UOM_TYPE_LENGTH")
+ elif self.currentColumn() in self.parent.cols_with_uom_mass:
+ self.f3_pressed(item, "UOM_TYPE_MASS")
+
elif key == Qt.Key_Escape:
self.clearSelection()
- def item_paste(self):
- cur_row = self.currentRow()
- cur_col = self.currentColumn()
- # ask_confirmation = True
+ def f3_pressed(self, item, uom_type) -> bool:
+ if item:
+ try:
+ float(item.text().replace(",", "."))
+ except ValueError:
+ return False # we've got an existing text here
- if self.row_selected:
- cur_col = 0
+ loader = QUiLoader()
+ path = os.path.join(os.path.dirname(__file__), resource_path(UI_DLG_UOM))
+ ui_file = QFile(path)
+ ui_file.open(QFile.ReadOnly)
+ self.dlg = loader.load(ui_file, self)
+ ui_file.close()
- col = 0
- if len(self.clipboard_data) == 1:
- data = self.clipboard_data[0]
- item = QTableWidgetItem(data)
+ self.dlg.uom_type = uom_type
+ if uom_type == "UOM_TYPE_MASS":
+ self.dlg.cmbUOM.addItems(["kg", "g"])
+ else: # anticipate uom type length
+ self.dlg.cmbUOM.addItems(["m", "cm", "mm"])
- self.setItem(cur_row, cur_col, item)
- item.setSelected(True)
+ if item:
+ self.dlg.efValue.setText(item.text())
+ print("UOM of the cell:", item.data(Qt.UserRole))
+ self.dlg.cmbUOM.setCurrentText(item.data(Qt.UserRole))
+ if item.data(Qt.UserRole):
+ self.old_uom = item.data(Qt.UserRole)
+ else:
+ if uom_type == "UOM_TYPE_MASS":
+ self.old_uom = self.default_uom_mass
+ else:
+ self.old_uom = self.default_uom_length
+
+ self.dlg.cmbUOM.currentIndexChanged.connect(self.on_cmbUOM_itemChanged)
+
+ if self.dlg.exec() == QDialog.Accepted:
+ if not item:
+ item = QTableWidgetItem("Dummy")
+ self.setItem(self.currentRow(), self.currentColumn(), item)
+ item.setText(self.dlg.efValue.text())
+ #item.setStyleSheet("border: 1px solid yellow;")
+ item.setData(Qt.UserRole, self.dlg.cmbUOM.currentText()) ## store UOM-Text at UserRole
+
+ item.setData(Qt.UserRole+1, self.dlg.cmbUOM.currentText()) ## store UOM-Type at UserRole+1 (1==UOM_LENGTH, 2==UOM_MASS)
+
+ if self.dlg.cmbUOM.currentText() not in (self.default_uom_length, self.default_uom_mass):
+ item.setData(Qt.BackgroundRole, QColor(Qt.yellow))
+ item.setToolTip("[" + item.data(Qt.UserRole) + "]")
+ else:
+ item.setData(Qt.BackgroundRole, None)
+ item.setToolTip(None)
+
+ return True
+
+ @Slot(int)
+ def on_cmbUOM_itemChanged(self, index):
+ try:
+ old_val = float(self.dlg.efValue.text().replace(",", "."))
+ except ValueError:
+ # special case: edit field is emppty because user changes UOM first.
+ self.old_uom = self.dlg.cmbUOM.currentText()
+ pass
else:
- for data in self.clipboard_data:
+ new_uom = self.dlg.cmbUOM.currentText()
+ if self.dlg.uom_type == "UOM_TYPE_LENGTH":
+ new_val = convert_uom_to_length(old_val, self.old_uom, new_uom)
+ elif self.dlg.uom_type == "UOM_TYPE_MASS":
+ new_val = convert_uom_to_mass(old_val, self.old_uom, new_uom)
+ self.dlg.efValue.setText(str(new_val).replace(".", ","))
+ self.old_uom = new_uom
+
+ # def setUOM(self, item, uom):
+ # if uom not in (DEFAULT_UOM_LENGTH, DEFAULT_UOM_MASS):
+ # item.setData(Qt.UserRole, uom)
+ # item.setData(Qt.BackgroundRole, QColor(Qt.yellow))
+ # item.setToolTip(f"[{uom}]")
+ # else:
+ # item.setData(Qt.BackgroundRole, None)
+ # item.setToolTip(None)
+
+ def setUOM(self, item, uom):
+ item.setData(Qt.UserRole, uom)
+
+ if uom not in (self.default_uom_length, self.default_uom_mass):
+ item.setData(Qt.BackgroundRole, QColor(Qt.yellow))
+ item.setToolTip(f"[{uom}]")
+ else:
+ item.setData(Qt.BackgroundRole, None)
+ item.setToolTip(None)
+
+ def item_paste(self):
+ if self.clipboard_data:
+ cur_row = self.currentRow()
+ cur_col = self.currentColumn()
+ # ask_confirmation = True
+
+ if self.row_selected:
+ cur_col = 0
+
+ col = 0
+ if len(self.clipboard_data) == 1:
+ data = self.clipboard_data[0]
item = QTableWidgetItem(data)
- # if item:
- # if len(item.text()) >0:
- # if ask_confirmation:
- # msg = QCoreApplication.translate("TableWidget", "Zelle enthält bereits Daten. Überschreiben?")
- # reply = QMessageBox.question(self, QCoreApplication.translate("TableWidget", "Überschreiben"), msg, \
- # QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
- # if reply == QMessageBox.No:
- # return False
- # ask_confirmation = False
- self.setItem(cur_row, col, item)
+ self.setItem(cur_row, cur_col, item)
item.setSelected(True)
+ else:
+ for data in self.clipboard_data:
+ item = QTableWidgetItem(data)
+ # if item:
+ # if len(item.text()) >0:
+ # if ask_confirmation:
+ # msg = QCoreApplication.translate("TableWidget", "Zelle enthält bereits Daten. Überschreiben?")
+ # reply = QMessageBox.question(self, QCoreApplication.translate("TableWidget", "Überschreiben"), msg, \
+ # QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
+ # if reply == QMessageBox.No:
+ # return False
- col += 1
+ # ask_confirmation = False
+ self.setItem(cur_row, col, item)
+ item.setSelected(True)
+
+ col += 1
def item_cut(self):
self.item_copy()
@@ -259,7 +370,10 @@ class TableWidget(QTableWidget):
return False
ask_cofirmation = False
- item.setData(Qt.DisplayRole, None)
+ item.setData(Qt.DisplayRole, None) # remove text
+ item.setData(Qt.BackgroundRole, None) # remove cell background color
+ item.setData(Qt.UserRole, None) # remove UOM
+ item.setToolTip(None) # remove tooltip
if len(sel_idx) == self.columnCount() * self.rowCount():
try:
diff --git a/src/main.py b/src/main.py
index 4b5d027..5e9d4f4 100644
--- a/src/main.py
+++ b/src/main.py
@@ -16,21 +16,22 @@ import configparser
# Third party imports
from PySide2.QtWidgets import QApplication, QMainWindow, QTableWidgetItem, QStatusBar, QFileDialog, \
QAbstractItemView, QMenu, QMessageBox, QHBoxLayout, QVBoxLayout, QAction, QActionGroup, QSizePolicy
-from PySide2.QtGui import QIcon
+from PySide2.QtGui import QIcon, QColor
from PySide2.QtCore import QFile, QSize, Qt, QCoreApplication, QTranslator
from PySide2.QtUiTools import QUiLoader
import xlsxwriter
# Local imports
-from utils import show_about, resource_path, str_iff, fit_col_widths
+from utils import show_about, resource_path, str_iff, fit_col_widths, convert_uom_to_length, convert_uom_to_mass, \
+ optimizeTableLayout, table_has_items
# my own classes imports
from clsTableWidget import TableWidget
# Local globals
-APP_VERSION = "v0.6"
+APP_VERSION = "v0.7"
-DIR_APPDATA = os.getenv('LOCALAPPDATA')
+DIR_CURRENT = os.getcwd()
APP_NAME = "Garage Space Calculator"
APP_DISPNAME = "GarageCalc"
@@ -39,6 +40,7 @@ APP_DESCR = "Calculates available garage space"
APP_COPYRIGHT = "(c) Paul Salajean 2021"
APP_WEBSITE = "https://gitlab.com/ProfP303"
APP_DESKTOPFILENAME = APP_DISPNAME
+APP_INI_FILE = os.path.join(DIR_CURRENT, APP_DISPNAME + '.ini')
APP_ICON = "./img/icons8-garage-32.ico"
@@ -48,6 +50,7 @@ ICON_SAVE = "./img/icons8-save-32.png"
ICON_EXPORT = "./img/icons8-export-xls-32.png"
ICON_ABOUT = "./img/icons8-information-32.png"
ICON_QUIT = "./img/system-shutdown.png"
+ICON_QT_LOGO = "./img/qt_logo_small.png"
UI_MAIN = "./ui/main.ui"
@@ -55,10 +58,18 @@ DEFAULT_GARAGE_LENGTH = "6"
DEFAULT_GARAGE_WIDTH = "2,5"
DEFAULT_GARAGE_HEIGHT = "2,5"
-COL_GARAGE_LENGTH = 1
-COL_GARAGE_WIDTH = 2
-COL_GARAGE_HEIGHT = 3
-COL_GARAGE_COMMENT = 4
+DEFAULT_UOM_LENGTH = "m"
+DEFAULT_UOM_MASS = "kg"
+
+COL_GARAGE_LENGTH = 0
+COL_GARAGE_WIDTH = 1
+COL_GARAGE_HEIGHT = 2
+COL_GARAGE_COMMENT = 3
+
+CSV_COL_GARAGE_LENGTH = 1
+CSV_COL_GARAGE_WIDTH = 2
+CSV_COL_GARAGE_HEIGHT = 3
+CSV_COL_GARAGE_COMMENT = 4
COL_STUFF_NAME = 0
COL_STUFF_LENGTH = 1
@@ -67,6 +78,17 @@ COL_STUFF_HEIGHT = 3
COL_STUFF_WEIGHT = 4
COL_STUFF_COMMENT = 5
+CSV_COL_STUFF_NAME = 0
+CSV_COL_STUFF_LENGTH = 1
+CSV_COL_STUFF_LENGTH_UOM = 2
+CSV_COL_STUFF_WIDTH = 3
+CSV_COL_STUFF_WIDTH_UOM = 4
+CSV_COL_STUFF_HEIGHT = 5
+CSV_COL_STUFF_HEIGHT_UOM = 6
+CSV_COL_STUFF_WEIGHT = 7
+CSV_COL_STUFF_WEIGHT_UOM = 8
+CSV_COL_STUFF_COMMENT = 9
+
TBL_STUFF_COL_COUNT = 6
TBL_STUFF_ROW_COUNT = 50
@@ -78,11 +100,14 @@ TXT_UNSAVED_CHANGES = QCoreApplication.translate("main", "There are unsaved entr
CONFIG = configparser.ConfigParser()
TRANSLATOR = QTranslator()
+def my_func():
+ pass
+
####################################################################
def main():
qApp = QApplication(sys.argv)
- global APP_NAME, CONFIG, TRANSLATOR
+ global APP_NAME, CONFIG, TRANSLATOR, DIR_CURRENT, APP_INI_FILE, DEFAULT_UOM_LENGTH, DEFAULT_UOM_MASS
qApp.setApplicationName(APP_NAME)
qApp.setApplicationDisplayName(APP_DISPNAME)
@@ -90,23 +115,34 @@ def main():
qApp.description = APP_DESCR
qApp.copyright = APP_COPYRIGHT
qApp.website = APP_WEBSITE
- qApp.setWindowIcon(QIcon(APP_ICON))
+ qApp.setWindowIcon(QIcon(resource_path(APP_ICON)))
qApp.setDesktopFileName(APP_DESKTOPFILENAME)
+ print("Current dir:", DIR_CURRENT)
+
+ # define ini-file defaults
language = "Deutsch"
- if os.path.exists(os.path.join(DIR_APPDATA, APP_DISPNAME, APP_DISPNAME + '.ini')):
- CONFIG.read(os.path.join(DIR_APPDATA, APP_DISPNAME, APP_DISPNAME + '.ini'))
- language = CONFIG['DEFAULT']['language']
- else:
- CONFIG['DEFAULT']['language'] = language
- if not os.path.exists(os.path.join(DIR_APPDATA, APP_DISPNAME)):
- os.makedirs(os.path.join(DIR_APPDATA, APP_DISPNAME))
+ # read from existing ini-file
+ if os.path.exists(APP_INI_FILE):
+ print("Reading from existing ini-file", APP_INI_FILE)
+ CONFIG.read(APP_INI_FILE)
+ try:
+ language = CONFIG['DEFAULT']['language']
+ DEFAULT_UOM_LENGTH = CONFIG['DEFAULT']['UOM_length']
+ DEFAULT_UOM_MASS = CONFIG['DEFAULT']['UOM_mass']
+ except KeyError:
+ pass # key will be created during saving anyway
- with open(os.path.join(DIR_APPDATA, APP_DISPNAME, APP_DISPNAME + '.ini'), 'w') as configfile: # save
+ else: # create new ini-file
+ print("Creating new ini-file", APP_INI_FILE)
+ CONFIG['DEFAULT']['language'] = language
+ CONFIG['DEFAULT']['UOM_length'] = DEFAULT_UOM_LENGTH
+ CONFIG['DEFAULT']['UOM_mass'] = DEFAULT_UOM_MASS
+
+ with open(APP_INI_FILE, 'w') as configfile: # save
CONFIG.write(configfile)
- print("Current dir:", os.getcwd())
if language == "Deutsch":
print("Loading german language file.")
TRANSLATOR.load(resource_path('./i18n/de_DE'))
@@ -121,7 +157,7 @@ def main():
app_name = qApp.translate("main", APP_NAME)
qApp.setApplicationName(app_name)
- winMain = MainWindow(language)
+ winMain = MainWindow(language, DEFAULT_UOM_LENGTH, DEFAULT_UOM_MASS)
if qApp.primaryScreen().size().width() <= 800:
winMain.showMaximized()
@@ -144,19 +180,18 @@ def create_examples(table):
generated_string1 = "".join(choice(string_format) for x in range(randint(min, max)))
generated_string2 = "".join(choice(string_format) for x in range(randint(min, max)))
- table.setItem(row, 0, QTableWidgetItem(generated_string1))
- table.setItem(row, 1, QTableWidgetItem(str(round(uniform(1.1, 10.2), 2)).replace('.', ',')))
- table.setItem(row, 2, QTableWidgetItem(str(round(uniform(1.5, 10.2), 2)).replace('.', ',')))
- table.setItem(row, 3, QTableWidgetItem(str(round(uniform(1.125, 8.75), 2)).replace('.', ',')))
- table.setItem(row, 4, QTableWidgetItem(str(round(uniform(20, 100), 2)).replace('.', ',')))
- table.setItem(row, 5, QTableWidgetItem(generated_string2))
+ table.setItem(row, COL_STUFF_NAME, QTableWidgetItem(generated_string1))
+ table.setItem(row, COL_STUFF_LENGTH, QTableWidgetItem(str(round(uniform(1.1, 10.2), 2)).replace('.', ',')))
+ table.setItem(row, COL_STUFF_WIDTH, QTableWidgetItem(str(round(uniform(1.5, 10.2), 2)).replace('.', ',')))
+ table.setItem(row, COL_STUFF_HEIGHT, QTableWidgetItem(str(round(uniform(1.125, 8.75), 2)).replace('.', ',')))
+ table.setItem(row, COL_STUFF_WEIGHT, QTableWidgetItem(str(round(uniform(20, 100), 2)).replace('.', ',')))
+ table.setItem(row, COL_STUFF_COMMENT, QTableWidgetItem(generated_string2))
####################################################################
class MainWindow(QMainWindow):
- def __init__(self, language):
+ def __init__(self, language="Deutsch", uom_length=DEFAULT_UOM_LENGTH, uom_mass=DEFAULT_UOM_MASS):
super().__init__()
- self.language = language
self.is_modified = False
self.opened_file = None
self.remembered_row = None
@@ -164,51 +199,33 @@ class MainWindow(QMainWindow):
self.load_ui()
self.init_ui()
self.set_defaults()
- self.create_menu(self.language)
- self.connect_signals()
self.create_actions()
+ self.create_menu(language, uom_length, uom_mass)
+ self.connect_signals()
self.create_toolbar()
self.create_statusbar()
self.statusBar.showMessage(f"{APP_DISPNAME} {APP_VERSION} - {APP_AUTHOR}", 5000)
- self.calc_voluminae()
- self.ui.efWeight.setText(str("0"))
- self.retranslateUi()
# TODO: disable for PROD!
# create_examples(self.ui.tableStuff)
# self.ui.tableGarage.setItem(0, 3, QTableWidgetItem("Garázs az udvaron"))
+ # self.is_modified = False
+ # END TODO
- for col in range(self.ui.tableStuff.columnCount()): # optimize column width
- self.ui.tableStuff.resizeColumnToContents(col)
- self.ui.tableStuff.resizeRowsToContents() # optimize row height
+ self.retranslateUi()
+ optimizeTableLayout(self.ui.tableStuff)
self.ui.tableStuff.setFocus()
- def create_menu(self, language=None):
- menuMain = self.menuBar()
- self.menuSettings = menuMain.addMenu(QCoreApplication.translate("main", "&Settings"))
- self.menuLanguage = self.menuSettings.addMenu(QCoreApplication.translate("main", "Language"))
-
- ag = QActionGroup(self, exclusive=True)
-
- a = ag.addAction(QAction('English', self.menuSettings, checkable=True))
- self.menuLanguage.addAction(a)
-
- a = ag.addAction(QAction('Deutsch', self.menuSettings, checkable=True))
- self.menuLanguage.addAction(a)
-
- a = ag.addAction(QAction('Magyar', self.menuSettings, checkable=True))
- self.menuLanguage.addAction(a)
-
- menuMain.triggered.connect(lambda: self.store_selected_language(self.menuLanguage))
-
- if language:
- [action.setChecked(True) for action in self.menuLanguage.actions() if action.text()==language]
-
def retranslateUi(self):
+ global DEFAULT_UOM_LENGTH, DEFAULT_UOM_MASS
# menus
self.menuSettings.setTitle(QCoreApplication.translate("main", "&Settings"))
- self.menuLanguage.setTitle(QCoreApplication.translate("main", "Language"))
+ self.menuSettings_Language.setTitle(QCoreApplication.translate("main", "Language"))
+
+ self.menuSettings_UOMs.setTitle(QCoreApplication.translate("main", "Unit of Measurements"))
+ self.menuSettings_UOMs_Length.setTitle(QCoreApplication.translate("main", "Length units"))
+ self.menuSettings_UOMs_Mass.setTitle(QCoreApplication.translate("main", "Mass units"))
# tables
self.ui.tableGarage.setVerticalHeaderLabels([
@@ -222,11 +239,11 @@ class MainWindow(QMainWindow):
])
self.ui.tableStuff.setHorizontalHeaderLabels([
- QCoreApplication.translate("main","Stuff"),
- QCoreApplication.translate("main","Length") + " [m]",
- QCoreApplication.translate("main","Width") + " [m]",
- QCoreApplication.translate("main","Height") + " [m]",
- QCoreApplication.translate("main","Weight") + " [kg]",
+ QCoreApplication.translate("main","Stuff"),
+ QCoreApplication.translate("main","Length") + " [" + DEFAULT_UOM_LENGTH + "]",
+ QCoreApplication.translate("main","Width") + " [" + DEFAULT_UOM_LENGTH + "]",
+ QCoreApplication.translate("main","Height") + " [" + DEFAULT_UOM_LENGTH + "]",
+ QCoreApplication.translate("main","Weight") + " [" + DEFAULT_UOM_MASS + "]",
QCoreApplication.translate("main","Comment")
])
@@ -249,6 +266,7 @@ class MainWindow(QMainWindow):
self.actionQuit.setToolTip(QCoreApplication.translate("main","Quit the application (Strg+Q)"))
def load_ui(self):
+ global TableWidget
loader = QUiLoader()
path = os.path.join(os.path.dirname(__file__), resource_path(UI_MAIN))
ui_file = QFile(path)
@@ -256,9 +274,13 @@ class MainWindow(QMainWindow):
self.ui = loader.load(ui_file, self)
ui_file.close()
+ # define columns which contain UOM length and mass
+ self.cols_with_uom_length = [COL_STUFF_LENGTH, COL_STUFF_WIDTH, COL_STUFF_HEIGHT]
+ self.cols_with_uom_mass = [COL_STUFF_WEIGHT]
+
# implement custom class 'TableWidget'
layoutGb = self.ui.gbStuff.layout()
- self.ui.tableStuff = TableWidget(self)
+ self.ui.tableStuff = TableWidget(self, DEFAULT_UOM_LENGTH, DEFAULT_UOM_MASS)
self.ui.tableStuff.setColumnCount(TBL_STUFF_COL_COUNT)
self.ui.tableStuff.setRowCount(TBL_STUFF_ROW_COUNT)
self.ui.tableStuff.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
@@ -268,34 +290,103 @@ class MainWindow(QMainWindow):
layoutGb.addWidget(self.ui.tableStuff)
def create_actions(self):
- self.actionNew = QAction()
- self.actionNew.setIcon(QIcon(resource_path(ICON_NEW)))
+ self.actionNew = QAction(QIcon(resource_path(ICON_NEW)), "&New")
self.actionNew.triggered.connect(self.file_new)
self.actionNew.setShortcut("Ctrl+N")
- self.actionOpen = QAction()
- self.actionOpen.setIcon(QIcon(resource_path(ICON_OPEN)))
+ self.actionOpen = QAction(QIcon(resource_path(ICON_OPEN)), "&Open...")
self.actionOpen.triggered.connect(self.file_open)
self.actionOpen.setShortcut("Ctrl+O")
- self.actionSave = QAction()
- self.actionSave.setIcon(QIcon(resource_path(ICON_SAVE)))
+ self.actionSave = QAction(QIcon(resource_path(ICON_SAVE)), "&Save")
self.actionSave.triggered.connect(self.file_save)
self.actionSave.setShortcut("Ctrl+S")
- self.actionExport = QAction()
- self.actionExport.setIcon(QIcon(resource_path(ICON_EXPORT)))
+ self.actionExport = QAction(QIcon(resource_path(ICON_EXPORT)), "Export to EXCEL...")
self.actionExport.triggered.connect(self.file_export)
- self.actionAbout = QAction()
- self.actionAbout.setIcon(QIcon(resource_path(ICON_ABOUT)))
- self.actionAbout.triggered.connect(show_about)
+ self.actionAbout_Qt = QAction(QIcon(resource_path(ICON_QT_LOGO)), "About Qt")
+ self.actionAbout_Qt.triggered.connect(QApplication.aboutQt)
- self.actionQuit = QAction()
- self.actionQuit.setIcon(QIcon(resource_path(ICON_QUIT)))
- self.actionQuit.triggered.connect(self.app_quit)
+ self.actionAbout = QAction(QIcon(resource_path(ICON_ABOUT)), "About " + qApp.applicationDisplayName())
+ global APP_INI_FILE
+ self.actionAbout.triggered.connect(lambda: show_about(APP_INI_FILE, self.opened_file))
+
+ self.actionQuit = QAction(QIcon(resource_path(ICON_QUIT)), "Quit")
+ self.actionQuit.triggered.connect(self.quit_app)
self.actionQuit.setShortcut("Ctrl+Q")
+ def create_menu(self, language=None, uom_length=None, uom_mass=None):
+ menuMain = self.menuBar()
+ menuFile = menuMain.addMenu(QCoreApplication.translate("main", "&File"))
+ menuFile_New = menuFile.addAction(self.actionNew)
+ menuFile_Open = menuFile.addAction(self.actionOpen)
+ menuFile_Save = menuFile.addAction(self.actionSave)
+ menuFile.addSeparator()
+ menuFile.addAction(self.actionExport)
+ menuFile.addSeparator()
+ menuFile.addAction(self.actionQuit)
+
+ self.menuSettings = menuMain.addMenu(QCoreApplication.translate("main", "&Settings"))
+
+ self.menuSettings_Language = self.menuSettings.addMenu(QCoreApplication.translate("main", "Language"))
+
+ self.menuSettings_UOMs = self.menuSettings.addMenu(QCoreApplication.translate("main", "Unit of Measurements"))
+ self.menuSettings_UOMs_Length = self.menuSettings_UOMs.addMenu(QCoreApplication.translate("main", "Length units"))
+ self.menuSettings_UOMs_Mass = self.menuSettings_UOMs.addMenu(QCoreApplication.translate("main", "Mass units"))
+
+ ag = QActionGroup(self, exclusive=True)
+
+ a = ag.addAction(QAction('English', self.menuSettings, checkable=True))
+ self.menuSettings_Language.addAction(a)
+
+ a = ag.addAction(QAction('Deutsch', self.menuSettings, checkable=True))
+ self.menuSettings_Language.addAction(a)
+
+ a = ag.addAction(QAction('Magyar', self.menuSettings, checkable=True))
+ self.menuSettings_Language.addAction(a)
+
+ self.menuSettings_Language.triggered.connect(lambda: self.store_selected_language(self.menuSettings_Language))
+
+ if language:
+ [action.setChecked(True) for action in self.menuSettings_Language.actions() if action.text()==language]
+
+ ag = QActionGroup(self, exclusive=True)
+
+ a = ag.addAction(QAction("m", self.menuSettings_UOMs_Length, checkable=True))
+ self.menuSettings_UOMs_Length.addAction(a)
+
+ a = ag.addAction(QAction("cm", self.menuSettings_UOMs_Length, checkable=True))
+ self.menuSettings_UOMs_Length.addAction(a)
+
+ a = ag.addAction(QAction("mm", self.menuSettings_UOMs_Length, checkable=True))
+ self.menuSettings_UOMs_Length.addAction(a)
+
+ if uom_length:
+ [action.setChecked(True) for action in self.menuSettings_UOMs_Length.actions() if action.text()==uom_length]
+
+ ag = QActionGroup(self, exclusive=True)
+
+ a = ag.addAction(QAction("kg", self.menuSettings_UOMs_Mass, checkable=True))
+ self.menuSettings_UOMs_Mass.addAction(a)
+
+ a = ag.addAction(QAction("g", self.menuSettings_UOMs_Mass, checkable=True))
+ self.menuSettings_UOMs_Mass.addAction(a)
+
+ self.menuSettings_UOMs_Length.triggered.connect(lambda: self.store_selected_uom_length(self.menuSettings_UOMs_Length))
+ self.menuSettings_UOMs_Mass.triggered.connect(lambda: self.store_selected_uom_mass(self.menuSettings_UOMs_Mass))
+
+ if uom_mass:
+ [action.setChecked(True) for action in self.menuSettings_UOMs_Mass.actions() if action.text()==uom_mass]
+
+ self.menuHelp = menuMain.addMenu(QCoreApplication.translate("main", "Help"))
+ self.menuHelp_About_Qt = self.menuHelp.addAction(self.actionAbout_Qt)
+ self.menuHelp_About = self.menuHelp.addAction(self.actionAbout)
+
+ def create_statusbar(self):
+ self.statusBar = QStatusBar()
+ self.setStatusBar(self.statusBar)
+
def create_toolbar(self):
# Main Toolbar (for all pages/views)
self.toolbar = self.addToolBar('Main Toolbar')
@@ -320,16 +411,18 @@ class MainWindow(QMainWindow):
tblStuff.setRowCount(TBL_STUFF_ROW_COUNT)
- self.is_modified = False
+ # display results
+ self.ui.efVol_Garage.setText("0")
+ self.ui.efVol_Stuff.setText("0")
+ self.ui.efVol_Free.setText("0")
+ self.ui.efWeight.setText("0")
- def create_statusbar(self):
- self.statusBar = QStatusBar()
- self.setStatusBar(self.statusBar)
+ self.is_modified = False
def connect_signals(self):
tblGarage = self.ui.tableGarage
tblStuff = self.ui.tableStuff
-
+
tblGarage.itemChanged.connect(self.on_garage_changed)
tblStuff.itemChanged.connect(self.on_stuff_changed)
@@ -338,7 +431,7 @@ class MainWindow(QMainWindow):
tblStuff = self.ui.tableStuff
# clear garage
- tblGarage.setRowCount(1)
+ # tblGarage.setRowCount(1)
# clear stuff
## tblStuff.clear()
@@ -346,6 +439,8 @@ class MainWindow(QMainWindow):
# tblStuff.setRowCount(TBL_STUFF_ROW_COUNT)
tblStuff.clearContents()
+ tblStuff.sortByColumn(-1, Qt.AscendingOrder) # reset sorting
+
# clear results
self.ui.efVol_Garage.clear()
self.ui.efVol_Stuff.clear()
@@ -353,15 +448,12 @@ class MainWindow(QMainWindow):
self.ui.efWeight.clear()
self.opened_file = None
- if self.opened_file:
- self.setWindowTitle(self.opened_file)
- else:
- self.setWindowTitle(f"{qApp.applicationName()} {APP_VERSION} - {APP_AUTHOR}")
+ self.setWindowTitle(f"{qApp.applicationName()} {APP_VERSION} - {APP_AUTHOR}")
self.ui.efVol_Free.setStyleSheet("")
self.is_modified = False
- def app_quit(self):
+ def quit_app(self):
if self.is_modified:
msg = QCoreApplication.translate("main", TXT_UNSAVED_CHANGES)
reply = QMessageBox.question(self, QCoreApplication.translate("main", "Quit"), msg, \
@@ -377,16 +469,16 @@ class MainWindow(QMainWindow):
QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
if reply == QMessageBox.No:
return False
+
self.init_ui()
self.ui.tableStuff.sortByColumn(-1, Qt.AscendingOrder) # reset sorting
- for col in range(self.ui.tableStuff.columnCount()): # optimize column width
- self.ui.tableStuff.resizeColumnToContents(col)
- self.ui.tableStuff.resizeRowsToContents() # optimize row height
+ optimizeTableLayout(self.ui.tableStuff)
self.ui.tableStuff.setFocus()
def file_save(self):
+ global DEFAULT_UOM_LENGTH, DEFAULT_UOM_MASS
tblGarage = self.ui.tableGarage
tblStuff = self.ui.tableStuff
is_file_saved = False
@@ -413,10 +505,10 @@ class MainWindow(QMainWindow):
garage_height = 0
garage_comment = ""
- item_length = tblGarage.item(0, 0)
- item_width = tblGarage.item(0, 1)
- item_height = tblGarage.item(0, 2)
- item_comment = tblGarage.item(0, 3)
+ item_length = tblGarage.item(0, COL_GARAGE_LENGTH)
+ item_width = tblGarage.item(0, COL_GARAGE_WIDTH)
+ item_height = tblGarage.item(0, COL_GARAGE_HEIGHT)
+ item_comment = tblGarage.item(0, COL_GARAGE_COMMENT)
# loop over table Garage
for row in range(tblGarage.rowCount()):
@@ -443,9 +535,13 @@ class MainWindow(QMainWindow):
for row in range(tblStuff.rowCount()):
stuff_text = None
length = None
+ length_uom = None
width = None
+ width_uom = None
height = None
+ height_uom = None
weight = None
+ weight_uom = None
comment = None
item_stuff = tblStuff.item(row, COL_STUFF_NAME)
@@ -460,25 +556,41 @@ class MainWindow(QMainWindow):
if item_length:
length = item_length.text()
+ if length:
+ length_uom = item_length.data(Qt.UserRole)
+ if not length_uom:
+ length_uom = DEFAULT_UOM_LENGTH
if item_width:
width = item_width.text()
+ if width:
+ width_uom = item_width.data(Qt.UserRole)
+ if not width_uom:
+ width_uom = DEFAULT_UOM_LENGTH
if item_height:
height = item_height.text()
+ if height:
+ height_uom = item_height.data(Qt.UserRole)
+ if not height_uom:
+ height_uom = DEFAULT_UOM_LENGTH
if item_weight:
weight = item_weight.text()
+ if weight:
+ weight_uom = item_weight.data(Qt.UserRole)
+ if not weight_uom:
+ weight_uom = DEFAULT_UOM_MASS
if item_comment:
comment = item_comment.text()
if stuff_text or length or width or height or weight:
- writer.writerow([stuff_text, length, width, height, weight, comment])
+ writer.writerow([stuff_text, length, length_uom, width, width_uom, height, height_uom, weight, weight_uom, comment])
is_file_saved = True
- self.opened_file = os.path.basename(fileName)
- self.setWindowTitle(self.opened_file)
+ self.opened_file = fileName
+ self.setWindowTitle(os.path.basename(fileName))
self.is_modified = False
if is_file_saved:
@@ -507,7 +619,9 @@ class MainWindow(QMainWindow):
options=options)
if fileName:
self.init_ui()
- self.ui.tableStuff.sortByColumn(-1, Qt.AscendingOrder) # reset sorting
+ # disable calc trigger for any cell!
+ tblGarage.itemChanged.disconnect()
+ tblStuff.itemChanged.disconnect()
file = open(fileName, "r", newline='')
reader = csv.reader(file, delimiter=';')
@@ -516,15 +630,15 @@ class MainWindow(QMainWindow):
for row in reader:
if row_idx == 0: # first row (index=0) ist always garage dimension
try:
- garage_length = str(row[COL_GARAGE_LENGTH].replace(".", ","))
- garage_width = str(row[COL_GARAGE_WIDTH].replace(".", ","))
- garage_height = str(row[COL_GARAGE_HEIGHT].replace(".", ","))
- garage_comment = row[COL_GARAGE_COMMENT]
+ garage_length = str(row[CSV_COL_GARAGE_LENGTH].replace(".", ","))
+ garage_width = str(row[CSV_COL_GARAGE_WIDTH].replace(".", ","))
+ garage_height = str(row[CSV_COL_GARAGE_HEIGHT].replace(".", ","))
+ garage_comment = row[CSV_COL_GARAGE_COMMENT]
- tblGarage.setItem(0, 0, QTableWidgetItem(garage_length))
- tblGarage.setItem(0, 1, QTableWidgetItem(garage_width))
- tblGarage.setItem(0, 2, QTableWidgetItem(garage_height))
- tblGarage.setItem(0, 3, QTableWidgetItem(garage_comment))
+ tblGarage.setItem(0, COL_GARAGE_LENGTH, QTableWidgetItem(garage_length))
+ tblGarage.setItem(0, COL_GARAGE_WIDTH, QTableWidgetItem(garage_width))
+ tblGarage.setItem(0, COL_GARAGE_HEIGHT, QTableWidgetItem(garage_height))
+ tblGarage.setItem(0, COL_GARAGE_COMMENT, QTableWidgetItem(garage_comment))
except IndexError as ex:
pass
@@ -532,32 +646,44 @@ class MainWindow(QMainWindow):
if row_idx > 0:
try:
stuff = row[COL_STUFF_NAME]
- stuff_length = str(row[COL_STUFF_LENGTH].replace(".", ","))
- stuff_width = str(row[COL_STUFF_WIDTH].replace(".", ","))
- stuff_height = str(row[COL_STUFF_HEIGHT].replace(".", ","))
- stuff_weight = str(row[COL_STUFF_WEIGHT].replace(".", ","))
- stuff_comment = row[COL_STUFF_COMMENT]
+ stuff_length = str(row[CSV_COL_STUFF_LENGTH].replace(".", ","))
+ stuff_length_uom = row[CSV_COL_STUFF_LENGTH_UOM]
+
+ stuff_width = str(row[CSV_COL_STUFF_WIDTH].replace(".", ","))
+ stuff_width_uom = row[CSV_COL_STUFF_WIDTH_UOM]
+
+ stuff_height = str(row[CSV_COL_STUFF_HEIGHT].replace(".", ","))
+ stuff_height_uom = row[CSV_COL_STUFF_HEIGHT_UOM]
+
+ stuff_weight = str(row[CSV_COL_STUFF_WEIGHT].replace(".", ","))
+ stuff_weight_uom = str(row[CSV_COL_STUFF_WEIGHT_UOM].replace(".", ","))
+
+ stuff_comment = row[CSV_COL_STUFF_COMMENT]
tblStuff.setItem(row_idx - 1, COL_STUFF_NAME, QTableWidgetItem(stuff))
item = QTableWidgetItem()
item.setData(Qt.DisplayRole, stuff_length)
tblStuff.setItem(row_idx - 1, COL_STUFF_LENGTH, item)
+ tblStuff.setUOM(item, stuff_length_uom)
# tblStuff.setItem(row_idx - 1, COL_STUFF_WIDTH, QTableWidgetItem(float(stuff_width)))
item = QTableWidgetItem()
item.setData(Qt.DisplayRole, stuff_width)
tblStuff.setItem(row_idx - 1, COL_STUFF_WIDTH, item)
+ tblStuff.setUOM(item, stuff_width_uom)
#tblStuff.setItem(row_idx - 1, COL_STUFF_HEIGHT, QTableWidgetItem(float(stuff_height)))
item = QTableWidgetItem(stuff_height)
item.setData(Qt.DisplayRole, stuff_height)
tblStuff.setItem(row_idx - 1, COL_STUFF_HEIGHT, item)
+ tblStuff.setUOM(item, stuff_height_uom)
# tblStuff.setItem(row_idx - 1, COL_STUFF_WEIGHT, QTableWidgetItem(float(stuff_weight)))
item = QTableWidgetItem(stuff_weight)
item.setData(Qt.DisplayRole, stuff_weight)
tblStuff.setItem(row_idx - 1, COL_STUFF_WEIGHT, item)
+ tblStuff.setUOM(item, stuff_weight_uom)
tblStuff.setItem(row_idx - 1, COL_STUFF_COMMENT, QTableWidgetItem(stuff_comment))
@@ -566,20 +692,19 @@ class MainWindow(QMainWindow):
row_idx += 1
- tblStuff.setRowCount(TBL_STUFF_ROW_COUNT)
+ # enable calc trigger
+ tblGarage.itemChanged.connect(self.on_garage_changed)
+ tblStuff.itemChanged.connect(self.on_stuff_changed)
+ # fire trigger once
+ self.on_garage_changed()
+ self.on_stuff_changed()
- for col in range(self.ui.tableStuff.columnCount()): # optimize column width
- self.ui.tableStuff.resizeColumnToContents(col)
- self.ui.tableStuff.resizeRowsToContents() # optimize row height
+ optimizeTableLayout(self.ui.tableStuff)
self.ui.tableStuff.setFocus()
+ self.opened_file = fileName
+ self.setWindowTitle(os.path.basename(fileName))
self.is_modified = False
- self.opened_file = os.path.basename(fileName)
-
- if fileName:
- self.setWindowTitle(self.opened_file)
- else:
- self.setWindowTitle(f"{qApp.applicationName()} {APP_VERSION} - {APP_AUTHOR}")
def file_export(self):
tblGarage = self.ui.tableGarage
@@ -601,18 +726,20 @@ class MainWindow(QMainWindow):
start_row = 0
worksheet.write_string(start_row, 0, QCoreApplication.translate("main", "Dimension of the garage"))
+ # table Garage headerts
start_row = 1
-
worksheet.write_string(start_row, COL_STUFF_LENGTH, QCoreApplication.translate("main","Length") + " [m]")
worksheet.write_string(start_row, COL_STUFF_WIDTH, QCoreApplication.translate("main","Width") + " [m]")
worksheet.write_string(start_row, COL_STUFF_HEIGHT, QCoreApplication.translate("main","Height") + " [m]")
worksheet.write_string(start_row, COL_STUFF_COMMENT, QCoreApplication.translate("main","Comment"))
- worksheet.set_column(0, 0, 25)
- worksheet.set_column(1, 3, 10)
- worksheet.set_column(4, 5, 20)
- start_row = 2
+ # TODO: check if this is not done later automatically
+ # worksheet.set_column(0, 0, 25)
+ # worksheet.set_column(1, 3, 10)
+ # worksheet.set_column(4, 5, 20)
+
# loop over table Garage
+ start_row = 2
for row in range(tblGarage.rowCount()):
garage_length = tblGarage.item(0, 0).text()
garage_width = tblGarage.item(0, 1).text()
@@ -627,15 +754,16 @@ class MainWindow(QMainWindow):
start_row = 4
worksheet.write_string(start_row, 0, QCoreApplication.translate("main", "Dimensions of the objects to be stored"))
+ # table Stuff headers
start_row = 5
worksheet.write_string(start_row, COL_STUFF_LENGTH, QCoreApplication.translate("main","Length") + " [m]")
worksheet.write_string(start_row, COL_STUFF_WIDTH, QCoreApplication.translate("main","Width") + " [m]")
worksheet.write_string(start_row, COL_STUFF_HEIGHT, QCoreApplication.translate("main","Height") + " [m]")
worksheet.write_string(start_row, COL_STUFF_WEIGHT, QCoreApplication.translate("main","Weight") + " [kg]")
- worksheet.write_string(start_row, COL_STUFF_COMMENT, QCoreApplication.translate("main","Comment") )
+ worksheet.write_string(start_row, COL_STUFF_COMMENT, QCoreApplication.translate("main","Comment"))
- start_row = 6
# loop over table Stuff
+ start_row = 6
formula = ""
row_idx = start_row
for row in range(tblStuff.rowCount()):
@@ -655,7 +783,12 @@ class MainWindow(QMainWindow):
try:
length = item_length.text()
if length:
- worksheet.write_number(start_row + row, COL_STUFF_LENGTH, float(length.replace(',', '.')))
+ value = float(length.replace(',', '.'))
+ uom = item_length.data(Qt.UserRole)
+ # always convert to "m" for the export
+ if uom != "m":
+ value = convert_uom_to_length(value, uom, "m")
+ worksheet.write_number(start_row + row, COL_STUFF_LENGTH, value) # value
except ValueError:
pass
@@ -663,7 +796,12 @@ class MainWindow(QMainWindow):
try:
width = item_width.text()
if width:
- worksheet.write_number(start_row + row, COL_STUFF_WIDTH, float(width.replace(',', '.')))
+ value = float(width.replace(',', '.'))
+ uom = item_width.data(Qt.UserRole)
+ # always convert to "m" for the export
+ if uom != "m":
+ value = convert_uom_to_length(value, uom, "m")
+ worksheet.write_number(start_row + row, COL_STUFF_WIDTH, value)
except ValueError:
pass
@@ -671,7 +809,12 @@ class MainWindow(QMainWindow):
try:
height = item_height.text()
if height:
- worksheet.write_number(start_row + row, COL_STUFF_HEIGHT, float(height.replace(',', '.')))
+ value = float(height.replace(',', '.'))
+ uom = item_height.data(Qt.UserRole)
+ # always convert to "m" for the export
+ if uom != "m":
+ value = convert_uom_to_length(value, uom, "m")
+ worksheet.write_number(start_row + row, COL_STUFF_HEIGHT, value)
except ValueError:
pass
@@ -679,7 +822,12 @@ class MainWindow(QMainWindow):
try:
weight = item_weight.text()
if weight:
- worksheet.write_number(start_row + row, COL_STUFF_WEIGHT, float(weight.replace(',', '.')))
+ value = float(weight.replace(',', '.'))
+ uom = item_weight.data(Qt.UserRole)
+ # always convert to "kg" for the export
+ if uom != "kg":
+ value = convert_uom_to_mass(value, uom, "kg")
+ worksheet.write_number(start_row + row, COL_STUFF_WEIGHT, value)
except ValueError:
pass
@@ -725,12 +873,17 @@ class MainWindow(QMainWindow):
def on_garage_changed(self):
self.is_modified = True
+ # print("on_garage_changed() calling calc_voluminae()")
self.calc_voluminae()
+ # print("--")
def on_stuff_changed(self):
self.is_modified = True
+ # print("on_stuff_changed() calling calc_voluminae()")
self.calc_voluminae()
+ # print("on_stuff_changed() calling calc_weight()")
self.calc_weight()
+ # print("--")
def get_garage_vol(self):
tblGarage = self.ui.tableGarage
@@ -779,7 +932,9 @@ class MainWindow(QMainWindow):
return garage_vol
def get_stuff_vol(self):
+ global DEFAULT_UOM_LENGTH
tblStuff = self.ui.tableStuff
+
stuff_vol = 0
length = 0
width = 0
@@ -802,6 +957,8 @@ class MainWindow(QMainWindow):
if item_length:
try:
length = float(item_length.text().replace(',', '.'))
+ if item_length.data(Qt.UserRole) and item_length.data(Qt.UserRole) != DEFAULT_UOM_LENGTH:
+ length = convert_uom_to_length(length, item_length.data(Qt.UserRole), DEFAULT_UOM_LENGTH) # convert to std unit
except ValueError:
length = 0
is_error = True
@@ -809,6 +966,8 @@ class MainWindow(QMainWindow):
if item_width:
try:
width = float(item_width.text().replace(',', '.'))
+ if item_width.data(Qt.UserRole) and item_width.data(Qt.UserRole) != DEFAULT_UOM_LENGTH:
+ width = convert_uom_to_length(width, item_width.data(Qt.UserRole), DEFAULT_UOM_LENGTH) # convert to std unit
except ValueError:
width = 0
is_error = True
@@ -816,11 +975,13 @@ class MainWindow(QMainWindow):
if item_height:
try:
height = float(item_height.text().replace(',', '.'))
+ if item_height.data(Qt.UserRole) and item_height.data(Qt.UserRole) != DEFAULT_UOM_LENGTH:
+ height = convert_uom_to_length(height, item_height.data(Qt.UserRole), DEFAULT_UOM_LENGTH) # convert to std unit
except ValueError:
height = 0
is_error = True
- vol = length * width * height
+ vol = convert_uom_to_length(length, DEFAULT_UOM_LENGTH, "m") * convert_uom_to_length(width, DEFAULT_UOM_LENGTH, "m") * convert_uom_to_length(height, DEFAULT_UOM_LENGTH, "m")
stuff_vol = round(stuff_vol + vol, 2)
@@ -832,19 +993,21 @@ class MainWindow(QMainWindow):
return stuff_vol
def calc_voluminae(self):
+ # print("calc_voluminae()")
+ global DEFAULT_UOM_LENGTH
tblGarage = self.ui.tableGarage
# get garage vol
+ # print(" calc_voluminae() calling get_garage_vol()")
garage_vol = self.get_garage_vol()
# print(f"{garage_vol=}")
-
+
# get stuff vol
+ # print(" calc_voluminae() calling get_stuff_vol()")
stuff_vol = self.get_stuff_vol()
- # print(f"{stuff_vol=}")
# get free space
free_vol = garage_vol - stuff_vol
- # print(f"{free_vol=}")
# display results
self.ui.efVol_Garage.setText(f"{str(garage_vol).replace('.', ',')}")
@@ -857,6 +1020,8 @@ class MainWindow(QMainWindow):
self.ui.efVol_Free.setStyleSheet("")
def calc_weight(self):
+ # print("calc_weight()")
+ global DEFAULT_UOM_MASS
tblStuff = self.ui.tableStuff
weight_sum = 0
@@ -865,33 +1030,32 @@ class MainWindow(QMainWindow):
for row in range(row_count):
weight = 0.0
- item = tblStuff.item(row, COL_STUFF_WEIGHT)
- if item:
+ item_weight = tblStuff.item(row, COL_STUFF_WEIGHT)
+ if item_weight:
try:
- weight = float(str(item.text()).replace(',','.'))
+ weight = float(item_weight.text().replace(',', '.'))
+ if item_weight.data(Qt.UserRole) and item_weight.data(Qt.UserRole) != DEFAULT_UOM_MASS:
+ weight = convert_uom_to_mass(weight, item_weight.data(Qt.UserRole), DEFAULT_UOM_MASS) # convert to std unit
except ValueError:
- weight = 0.0
+ weight = 0
- weight_sum = round(weight_sum + weight, 2)
+ weight_sum = round(weight_sum + convert_uom_to_mass(weight, DEFAULT_UOM_MASS, "kg"), 2)
self.ui.efWeight.setText(f"{str(weight_sum).replace('.', ',')}")
def store_selected_language(self, menu):
""" Stores selected menu labels to ini-file. """
# [print(action.text()) for action in menu.actions() if action.isChecked()]
- global CONFIG
+ global CONFIG, DIR_CURRENT, APP_INI_FILE
- print("Current dir:", os.getcwd())
language = "English"
for action in menu.actions():
if action.isChecked():
language = action.text()
CONFIG['DEFAULT']['language'] = language
- if not os.path.exists(os.path.join(DIR_APPDATA, APP_DISPNAME)):
- os.makedirs(os.path.join(DIR_APPDATA, APP_DISPNAME))
- with open(os.path.join(DIR_APPDATA, APP_DISPNAME, APP_DISPNAME + '.ini'), 'w') as configfile: # save
+ with open(APP_INI_FILE, 'w') as configfile: # save
CONFIG.write(configfile)
if language == "Deutsch":
@@ -906,7 +1070,195 @@ class MainWindow(QMainWindow):
TRANSLATOR.load("dummy")
self.retranslateUi()
+ optimizeTableLayout(self.ui.tableStuff)
+ self.ui.tableStuff.setFocus()
+ def store_selected_uom_length(self, menu):
+ """ Stores selected uom to ini-file. """
+ # [print(action.text()) for action in menu.actions() if action.isChecked()]
+ global CONFIG, APP_INI_FILE, DEFAULT_UOM_LENGTH
+
+ selected_uom = ""
+ for action in menu.actions():
+ if action.isChecked():
+ selected_uom = action.text()
+
+ CONFIG['DEFAULT']['UOM_length'] = selected_uom
+
+ with open(APP_INI_FILE, 'w') as configfile: # save
+ CONFIG.write(configfile)
+
+ DEFAULT_UOM_LENGTH = selected_uom
+ self.ui.tableStuff.default_uom_length = DEFAULT_UOM_LENGTH
+
+ if table_has_items(self.ui.tableStuff):
+ msg = QCoreApplication.translate("main", "Do you want to convert all existing stuff of type length to the new unit of measurement (UOM)") + " " + selected_uom + "?"
+ reply = QMessageBox.question(self, QCoreApplication.translate("main", "UOM conversion"), msg, \
+ QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
+ if reply == QMessageBox.No:
+ self.flag_deviating_uoms()
+ self.retranslateUi()
+ optimizeTableLayout(self.ui.tableStuff)
+ return False
+
+ self.convert_length_cells_to_std_uom()
+
+ self.retranslateUi()
+ optimizeTableLayout(self.ui.tableStuff)
+ return True
+
+ def store_selected_uom_mass(self, menu):
+ """ Stores selected uom to ini-file. """
+ # [print(action.text()) for action in menu.actions() if action.isChecked()]
+ global CONFIG, APP_INI_FILE, DEFAULT_UOM_MASS
+
+ selected_uom = ""
+ for action in menu.actions():
+ if action.isChecked():
+ selected_uom = action.text()
+
+ CONFIG['DEFAULT']['UOM_mass'] = selected_uom
+
+ with open(APP_INI_FILE, 'w') as configfile: # save
+ CONFIG.write(configfile)
+
+ DEFAULT_UOM_MASS = selected_uom
+ self.ui.tableStuff.default_uom_mass = DEFAULT_UOM_MASS
+
+ if table_has_items(self.ui.tableStuff):
+ msg = QCoreApplication.translate("main", "Do you want to convert all existing stuff of type mass to the new unit of measurement (UOM)") + " " + selected_uom + "?"
+ reply = QMessageBox.question(self, QCoreApplication.translate("main", "UOM conversion"), msg, \
+ QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
+ if reply == QMessageBox.No:
+ self.flag_deviating_uoms()
+ self.retranslateUi()
+ optimizeTableLayout(self.ui.tableStuff)
+ return False
+
+ self.convert_mass_cells_to_std_uom()
+ self.retranslateUi()
+ optimizeTableLayout(self.ui.tableStuff)
+ return True
+
+ def convert_length_cells_to_std_uom(self):
+ print("convert_length_cells_to_std_uom() called")
+ global DEFAULT_UOM_LENGTH
+
+ tblGarage = self.ui.tableGarage
+ tblStuff = self.ui.tableStuff
+
+ # loop over all items
+ # disable calc trigger for any cell!
+ tblGarage.itemChanged.disconnect()
+ tblStuff.itemChanged.disconnect()
+
+ for row in range(tblStuff.rowCount()):
+ for col in range(tblStuff.columnCount()):
+ item = tblStuff.item(row, col)
+ if item:
+ if col in self.cols_with_uom_length:
+ # read current value
+ value = float(item.text().replace(",", "."))
+
+ # read current UOM
+ uom = item.data(Qt.UserRole)
+
+ # convert to new value
+ if uom != DEFAULT_UOM_LENGTH:
+ new_val = convert_uom_to_length(value, uom, DEFAULT_UOM_LENGTH)
+ # set new value
+ item.setText(str(new_val).replace(".", ","))
+
+ # set new std UOM
+ tblStuff.setUOM(item, DEFAULT_UOM_LENGTH)
+
+ # enable calc trigger
+ tblGarage.itemChanged.connect(self.on_garage_changed)
+ tblStuff.itemChanged.connect(self.on_stuff_changed)
+ # fire trigger once
+ self.on_garage_changed()
+ self.on_stuff_changed()
+
+ def convert_mass_cells_to_std_uom(self):
+ print("convert_mass_cells_to_std_uom() called")
+ global DEFAULT_UOM_MASS
+
+ tblGarage = self.ui.tableGarage
+ tblStuff = self.ui.tableStuff
+
+ # loop over all items
+ # disable calc trigger for any cell!
+ tblGarage.itemChanged.disconnect()
+ tblStuff.itemChanged.disconnect()
+
+ for row in range(tblStuff.rowCount()):
+ for col in range(tblStuff.columnCount()):
+ item = tblStuff.item(row, col)
+ if item:
+ if col in self.cols_with_uom_mass:
+ # read current value
+ value = float(item.text().replace(",", "."))
+
+ # read current UOM
+ uom = item.data(Qt.UserRole)
+
+ if uom != DEFAULT_UOM_MASS:
+ new_val = convert_uom_to_mass(value, uom, DEFAULT_UOM_MASS)
+ # set new value
+ item.setText(str(new_val).replace(".", ","))
+
+ # set new std UOM
+ tblStuff.setUOM(item, DEFAULT_UOM_MASS)
+
+ # enable calc trigger
+ tblGarage.itemChanged.connect(self.on_garage_changed)
+ tblStuff.itemChanged.connect(self.on_stuff_changed)
+ # fire trigger once
+ self.on_garage_changed()
+ self.on_stuff_changed()
+
+ def flag_deviating_uoms(self):
+ print("flag_deviating_uoms() called")
+ global DEFAULT_UOM_LENGTH, DEFAULT_UOM_MASS
+
+ tblGarage = self.ui.tableGarage
+ tblStuff = self.ui.tableStuff
+
+ # loop over all items
+ # disable calc trigger for any cell!
+ tblGarage.itemChanged.disconnect()
+ tblStuff.itemChanged.disconnect()
+
+ for row in range(tblStuff.rowCount()):
+ for col in range(tblStuff.columnCount()):
+ item = tblStuff.item(row, col)
+ if item:
+ uom = item.data(Qt.UserRole)
+ if col in self.cols_with_uom_length:
+ # read current UOM
+ if uom != DEFAULT_UOM_LENGTH:
+ # color the cell
+ item.setData(Qt.BackgroundRole, QColor(Qt.yellow))
+ item.setToolTip(f"[{uom}]")
+ else:
+ # uncolor the cell
+ item.setData(Qt.BackgroundRole, None)
+ item.setToolTip(None)
+
+ elif col in self.cols_with_uom_mass:
+ # read current UOM
+ if uom != DEFAULT_UOM_MASS:
+ # color the cell
+ item.setData(Qt.BackgroundRole, QColor(Qt.yellow))
+ item.setToolTip(f"[{uom}]")
+ else:
+ # uncolor the cell
+ item.setData(Qt.BackgroundRole, None)
+ item.setToolTip(None)
+
+ # enable calc trigger
+ tblGarage.itemChanged.connect(self.on_garage_changed)
+ tblStuff.itemChanged.connect(self.on_stuff_changed)
####################################################################
diff --git a/src/utils.py b/src/utils.py
index c4f9ae8..2e91950 100644
--- a/src/utils.py
+++ b/src/utils.py
@@ -31,7 +31,10 @@ def resource_path(relative_path):
return os.path.join(base_path, relative_path)
-def show_about():
+def show_about(ini_file="", opened_file=""):
+ if not opened_file:
+ opened_file = ""
+
qApp = QApplication.instance()
msg = QMessageBox()
msg.setIconPixmap(QPixmap(resource_path(APP_ICON)))
@@ -44,7 +47,9 @@ def show_about():
"
" + qApp.copyright + "
" \
"
" + qApp.website + "
"
- text = text + "" + qApp.translate("utils", "Used icons: Theme") + " 'Cute Color' " + qApp.translate("utils", "from") + " Icons8
"
+ text = text + "" + qApp.translate("utils", "Used icons") + ": 'Cute Color' " + qApp.translate("utils", "from") + " Icons8
"
+ text = text + "" + qApp.translate("utils", "Currently opened file") + ":
" + opened_file + "
"
+ text = text + "" + qApp.translate("utils", "Location of the Ini-file") + ":
" + ini_file + "
"
text = text + "Python " + qApp.translate("utils", "Version") + ": " + f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro} {sys.version_info.releaselevel}"
text = text + "
" + f"{sys.executable}" + "
"
text = text + "
Qt " + qApp.translate("utils", "Version") + ": " + f"{QtCore.__version__}"
@@ -84,7 +89,7 @@ def fit_col_widths(table, worksheet):
sel_rows = []
for sel_index in sel_rows_idx:
sel_rows.append(sel_index.row())
-
+
for col_ind in range(model.columnCount()):
cur_item_length = 0
lengths = []
@@ -95,7 +100,7 @@ def fit_col_widths(table, worksheet):
if not table.isColumnHidden(col_ind): # export only visible column headers
cur_item_length = len(col_header_text)
lengths.append(cur_item_length)
-
+
# get columns data lengths
row = 1
# iterate over all rows
@@ -129,3 +134,25 @@ def fit_col_widths(table, worksheet):
if col_width > STD_COL_WIDTH: # anticipated default size
worksheet.set_column(col_ind, col_ind, col_width*1.25)
col_ind += 1
+
+def convert_uom_to_length(val, unit_in, unit_out):
+ SI = {'mm':0.001, 'cm':0.01, 'm':1.0}
+ return val*SI[unit_in]/SI[unit_out]
+
+def convert_uom_to_mass(val, unit_in, unit_out):
+ SI = {'g':0.001, 'kg':1.0}
+ return val*SI[unit_in]/SI[unit_out]
+
+def optimizeTableLayout(table):
+ for col in range(table.columnCount()): # optimize column width
+ table.resizeColumnToContents(col)
+ table.resizeRowsToContents() # optimize row height
+
+def table_has_items(tablewidget):
+ for row in range(tablewidget.rowCount()):
+ for col in range(tablewidget.columnCount()):
+ item = tablewidget.item(row, col)
+ if item:
+ return True
+
+ return False
\ No newline at end of file
diff --git a/ui/dlg_uom.ui b/ui/dlg_uom.ui
new file mode 100644
index 0000000..711d806
--- /dev/null
+++ b/ui/dlg_uom.ui
@@ -0,0 +1,92 @@
+
+
+ Dialog
+
+
+
+ 0
+ 0
+ 222
+ 100
+
+
+
+ Dialog
+
+
+ -
+
+
-
+
+
+ Value:
+
+
+
+ -
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ UOM:
+
+
+
+ -
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ Dialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ Dialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+