Compare commits

..

13 commits
v0.2 ... main

31 changed files with 3784 additions and 789 deletions

2
.gitignore vendored
View file

@ -1 +1,3 @@
env2
dist
src/__pycache__

View file

@ -1,5 +1,63 @@
# Changelog GarageCalc1
## [0.7.3] - 2021-07-12
## Added
- Nutzung der Zwischenablage
## [0.7.2] - 2021-07-09
## Changed
- Ressourcen befinden sich nun in der Ressourcendatei
## [0.7.1] - 2021-07-09
## Fixed
- Sprachdatei unvollständig
## [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 (".")
- Export nach EXCEL exportiert nun Formeln für die Berechnung des Ergebnis, keine zuvor berechneten Ergebniswerte
- Export nach EXCEL: automatische Spaltenbreite
## [0.5.2] - 2021-07-02
## Fixed
- Verbesserungen in Sprachdatei "hu_HU.ts"
## [0.5.1] - 2021-07-02
## Fixed
- Laden von Zahlen aus der .CSV-Datei als Zahlenwerte, nicht Text
## [0.5] - 2021-07-02
## Added
- Tabelle "Gegenstände": Zeilen sind sortierbar (-> Klick auf Spaltenköpfe)
- Tabelle "Gegenstände": Spalten sind anordenbar
- Beide Tabellen: Rechte Spalte wächst dynamisch ans Ende
- Beide Tabellen: Zusätzliche Spalte "Kommentar" am Ende der Tabelle
- Horizontales Splitter-Control zwischen Tabelle "Garage" und "Gegenstände"
## [0.4.1] - 2021-07-01
## Added
- Dynamisches Layout
- Programm startet maximiert wenn Breite der Auflösung <= 700 pixel, ansonsten 610 * 640
## [0.4] - 2021-06-30
## Added
- Einzelne Zellen lassen sich nun selektieren/kopieren/verschieben/löschen (zusätzlich zu Reihen)
- Kontextmenü für Zellen
## [0.3] - 2021-06-29
### Added
- Warnt beim Beenden falls ungespeicherte Einträge vorhanden sind
- Alle Ergebnisse aufrunden auf 2 Nachkommastellen
## [0.2] - 2021-06-27
### Added
- Möglichkeit Zeilen zu kopieren und einzufügen (sowohl Kontextmenü auf Zeilenüberschrift als auch Tastenkombination Strg+C/Strg+V)

BIN
i18n/de_DE.qm Normal file

Binary file not shown.

383
i18n/de_DE.ts Normal file
View file

@ -0,0 +1,383 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de_DE">
<context>
<name>TableWidget</name>
<message>
<location filename="clsTableWidget.py" line="98"/>
<source>Cut</source>
<translation>Ausschneiden</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="99"/>
<source>Copy</source>
<translation>Kopieren</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="100"/>
<source>Paste</source>
<translation>Einfügen</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="370"/>
<source>Delete</source>
<translation>Löschen</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="117"/>
<source>Cut row</source>
<translation>Zeile ausschneiden</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="118"/>
<source>Copy row</source>
<translation>Zeile kopieren</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="119"/>
<source>Paste row</source>
<translation>Zeile einfügen</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="121"/>
<source>Insert row before</source>
<translation>Zeile oberhalb einfügen</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="122"/>
<source>Insert row after</source>
<translation>Zeile unterhalb einfügen</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="124"/>
<source>Remove row</source>
<translation>Zeile entfernen</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="125"/>
<source>Delete items</source>
<translation>Zellinhalte löschen</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="160"/>
<source>Row Nr.</source>
<translation>Zeile Nr.</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="161"/>
<source>to be removed?</source>
<translation>entfernen?</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="161"/>
<source>Remove</source>
<translation>Entfernen</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="370"/>
<source>Delete cell content?</source>
<translation>Zellinhalt löschen?</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="390"/>
<source>UOM</source>
<translation>Maß.einh.</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="389"/>
<source>Value</source>
<translation>Wert</translation>
</message>
</context>
<context>
<name>main</name>
<message>
<location filename="clsTableWidget.py" line="231"/>
<source>HELLO</source>
<translation type="obsolete">Hallo Welt</translation>
</message>
<message>
<location filename="main.py" line="319"/>
<source>&amp;Settings</source>
<translation>&amp;Einstellungen</translation>
</message>
<message>
<location filename="main.py" line="321"/>
<source>Language</source>
<translation>Sprache</translation>
</message>
<message>
<location filename="main.py" line="233"/>
<source>Stuff</source>
<translation>Gegenstand</translation>
</message>
<message>
<location filename="main.py" line="748"/>
<source>Length</source>
<translation>Länge</translation>
</message>
<message>
<location filename="main.py" line="749"/>
<source>Width</source>
<translation>Breite</translation>
</message>
<message>
<location filename="main.py" line="750"/>
<source>Height</source>
<translation>Höhe</translation>
</message>
<message>
<location filename="main.py" line="751"/>
<source>Weight</source>
<translation>Gewicht</translation>
</message>
<message>
<location filename="main.py" line="716"/>
<source>Dimension of the garage</source>
<translation>Dimension der Garage</translation>
</message>
<message>
<location filename="main.py" line="744"/>
<source>Dimensions of the objects to be stored</source>
<translation>Dimensionen der zu verstauenden Gegenstände</translation>
</message>
<message>
<location filename="main.py" line="836"/>
<source>Result</source>
<translation>Ergebnis</translation>
</message>
<message>
<location filename="main.py" line="839"/>
<source>Volume of the garage</source>
<translation>Volumen der Garage</translation>
</message>
<message>
<location filename="main.py" line="843"/>
<source>Volume of the items</source>
<translation>Volumen der Gegenstände</translation>
</message>
<message>
<location filename="main.py" line="848"/>
<source>Free space in the garage</source>
<translation>Freier Raum in der Garage</translation>
</message>
<message>
<location filename="main.py" line="853"/>
<source>Total weight</source>
<translation>Gesamtgewicht</translation>
</message>
<message>
<location filename="main.py" line="261"/>
<source>New (Ctrl+N)</source>
<translation type="obsolete">Neu (Strg+N)</translation>
</message>
<message>
<location filename="main.py" line="262"/>
<source>Open... (Ctrl+O)</source>
<translation type="obsolete">Öffnen... (Strg+O)</translation>
</message>
<message>
<location filename="main.py" line="263"/>
<source>Save (Ctrl+S)</source>
<translation type="obsolete">Speichern (Strg+S)</translation>
</message>
<message>
<location filename="main.py" line="262"/>
<source>Export to EXCEL...</source>
<translation>Export nach EXCEL...</translation>
</message>
<message>
<location filename="main.py" line="268"/>
<source>Information about the application</source>
<translation>Informationen über das Programm</translation>
</message>
<message>
<location filename="main.py" line="266"/>
<source>Quit the application (Strg+Q)</source>
<translation type="obsolete">Programm beenden (Strg+Q)</translation>
</message>
<message>
<location filename="main.py" line="521"/>
<source>Garage</source>
<translation>Garage</translation>
</message>
<message>
<location filename="main.py" line="448"/>
<source>Quit</source>
<translation>Beenden</translation>
</message>
<message>
<location filename="main.py" line="457"/>
<source>New</source>
<translation>Neu</translation>
</message>
<message>
<location filename="main.py" line="481"/>
<source>Save</source>
<translation>Speichern</translation>
</message>
<message>
<location filename="main.py" line="401"/>
<source> CSV-file</source>
<translation type="obsolete">CSV-Datei</translation>
</message>
<message>
<location filename="main.py" line="707"/>
<source>All files</source>
<translation>Alle Dateien</translation>
</message>
<message>
<location filename="main.py" line="586"/>
<source>file</source>
<translation>Datei</translation>
</message>
<message>
<location filename="main.py" line="587"/>
<source>saved</source>
<translation>gespeichert</translation>
</message>
<message>
<location filename="main.py" line="603"/>
<source>Open</source>
<translation>Öffnen</translation>
</message>
<message>
<location filename="main.py" line="704"/>
<source>Export</source>
<translation>Export</translation>
</message>
<message>
<location filename="main.py" line="463"/>
<source> EXCEL-file</source>
<translation type="obsolete">EXCEL-Datei</translation>
</message>
<message>
<location filename="main.py" line="918"/>
<source>Error in the garage dimension</source>
<translation>Fehler in der Garagen-Dimension</translation>
</message>
<message>
<location filename="main.py" line="979"/>
<source>Error in the dimensions of the objects to be stored</source>
<translation>Fehler in den Dimensionen der zu verstauenden Gegenstände</translation>
</message>
<message>
<location filename="main.py" line="860"/>
<source>Successfully exported to EXCEL</source>
<translation>Erfolgreich nach EXCEL exportiert</translation>
</message>
<message>
<location filename="main.py" line="604"/>
<source>CSV-file</source>
<translation>CSV-Datei</translation>
</message>
<message>
<location filename="main.py" line="705"/>
<source>EXCEL-file</source>
<translation>EXCEL-Datei</translation>
</message>
<message>
<location filename="main.py" line="91"/>
<source>There are unsaved entries. Without saving, all changes are lost. Continue anyway?</source>
<translation>Es gibt ungespeicherte Einträge. Ohne zu speichern, gehen alle Änderungen verloren. Trotzdem fortfahren?</translation>
</message>
<message>
<location filename="main.py" line="147"/>
<source>Garage Space Calculator</source>
<translation type="obsolete">Garagenraum-Rechner</translation>
</message>
<message>
<location filename="utils.py" line="46"/>
<source>Calculates available garage space</source>
<translation>Berechnet zur Verfügung stehenden Garagenraum</translation>
</message>
<message>
<location filename="main.py" line="752"/>
<source>Comment</source>
<translation>Kommentar</translation>
</message>
<message>
<location filename="main.py" line="323"/>
<source>Unit of Measurements</source>
<translation>Maßeinheit</translation>
</message>
<message>
<location filename="main.py" line="324"/>
<source>Length units</source>
<translation>Längeneinheit</translation>
</message>
<message>
<location filename="main.py" line="325"/>
<source>Mass units</source>
<translation>Masseeinheit</translation>
</message>
<message>
<location filename="main.py" line="310"/>
<source>&amp;File</source>
<translation>&amp;Datei</translation>
</message>
<message>
<location filename="main.py" line="371"/>
<source>Help</source>
<translation>Hilfe</translation>
</message>
<message>
<location filename="main.py" line="1084"/>
<source>Do you want to convert all existing stuff of type length to the new unit of measurement (UOM)</source>
<translation>Möchten Sie alle vorhandenen Gegenstände vom Typ Länge auf die neue Maßeinheit umrechnen</translation>
</message>
<message>
<location filename="main.py" line="1119"/>
<source>UOM conversion</source>
<translation>Einheiten Umrechnung</translation>
</message>
<message>
<location filename="main.py" line="1118"/>
<source>Do you want to convert all existing stuff of type mass to the new unit of measurement (UOM)</source>
<translation>Möchten Sie alle vorhandenen Gegenstände vom Typ Gewicht auf die neue Maßeinheit umrechnen</translation>
</message>
<message>
<location filename="main.py" line="265"/>
<source>About Qt</source>
<translation>Über Qt</translation>
</message>
</context>
<context>
<name>utils</name>
<message>
<location filename="utils.py" line="47"/>
<source>Idea</source>
<translation>Idee</translation>
</message>
<message>
<location filename="utils.py" line="45"/>
<source>Used icons: Theme</source>
<translation type="obsolete">Verwendete Icons: Thema</translation>
</message>
<message>
<location filename="utils.py" line="51"/>
<source>from</source>
<translation>von</translation>
</message>
<message>
<location filename="utils.py" line="56"/>
<source>Version</source>
<translation>Version</translation>
</message>
<message>
<location filename="utils.py" line="51"/>
<source>Used icons</source>
<translation>Verwendete Icons</translation>
</message>
<message>
<location filename="utils.py" line="52"/>
<source>Currently opened file</source>
<translation>Aktuell geöffnete Datei</translation>
</message>
<message>
<location filename="utils.py" line="53"/>
<source>Location of the Ini-file</source>
<translation>Dateipfad der Ini-Datei</translation>
</message>
</context>
</TS>

BIN
i18n/hu_HU.qm Normal file

Binary file not shown.

383
i18n/hu_HU.ts Normal file
View file

@ -0,0 +1,383 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="de_DE">
<context>
<name>TableWidget</name>
<message>
<location filename="clsTableWidget.py" line="98"/>
<source>Cut</source>
<translation>kivágni</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="99"/>
<source>Copy</source>
<translation>másolás</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="100"/>
<source>Paste</source>
<translation>Beillesztés</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="370"/>
<source>Delete</source>
<translation>Törlés</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="117"/>
<source>Cut row</source>
<translation>Vágott vonal</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="118"/>
<source>Copy row</source>
<translation>Vettem a szöveget</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="119"/>
<source>Paste row</source>
<translation>Beilleszteni a sort</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="121"/>
<source>Insert row before</source>
<translation>A fenti sort beilleszteni</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="122"/>
<source>Insert row after</source>
<translation>Az alábbi sor beillesztése</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="124"/>
<source>Remove row</source>
<translation>Távolítsa el a sort</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="125"/>
<source>Delete items</source>
<translation>Tartalom törlése</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="160"/>
<source>Row Nr.</source>
<translation>Vonalszám.</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="161"/>
<source>to be removed?</source>
<translation>eltávolítani?</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="161"/>
<source>Remove</source>
<translation>A eltávolítása</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="370"/>
<source>Delete cell content?</source>
<translation>Cellatartalom törlése?</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="390"/>
<source>UOM</source>
<translation>Egység</translation>
</message>
<message>
<location filename="clsTableWidget.py" line="389"/>
<source>Value</source>
<translation>Érték</translation>
</message>
</context>
<context>
<name>main</name>
<message>
<location filename="clsTableWidget.py" line="231"/>
<source>HELLO</source>
<translation type="obsolete">Hallo Welt</translation>
</message>
<message>
<location filename="main.py" line="319"/>
<source>&amp;Settings</source>
<translation>&amp;Beállítások</translation>
</message>
<message>
<location filename="main.py" line="321"/>
<source>Language</source>
<translation>Nyelv</translation>
</message>
<message>
<location filename="main.py" line="233"/>
<source>Stuff</source>
<translation>Tárgy</translation>
</message>
<message>
<location filename="main.py" line="748"/>
<source>Length</source>
<translation>Hosszúság</translation>
</message>
<message>
<location filename="main.py" line="749"/>
<source>Width</source>
<translation>Szélesség</translation>
</message>
<message>
<location filename="main.py" line="750"/>
<source>Height</source>
<translation>Magasság</translation>
</message>
<message>
<location filename="main.py" line="751"/>
<source>Weight</source>
<translation>Súly</translation>
</message>
<message>
<location filename="main.py" line="716"/>
<source>Dimension of the garage</source>
<translation>A garázs mérete</translation>
</message>
<message>
<location filename="main.py" line="744"/>
<source>Dimensions of the objects to be stored</source>
<translation>A tárolandó objektumok méretei</translation>
</message>
<message>
<location filename="main.py" line="836"/>
<source>Result</source>
<translation>Eredmény</translation>
</message>
<message>
<location filename="main.py" line="839"/>
<source>Volume of the garage</source>
<translation>A garázs térfogata</translation>
</message>
<message>
<location filename="main.py" line="843"/>
<source>Volume of the items</source>
<translation>A tételek mennyisége</translation>
</message>
<message>
<location filename="main.py" line="848"/>
<source>Free space in the garage</source>
<translation>Szabad hely a garázsban</translation>
</message>
<message>
<location filename="main.py" line="853"/>
<source>Total weight</source>
<translation>Teljes súly</translation>
</message>
<message>
<location filename="main.py" line="261"/>
<source>New (Ctrl+N)</source>
<translation type="obsolete">Új (Ctrl+N)</translation>
</message>
<message>
<location filename="main.py" line="262"/>
<source>Open... (Ctrl+O)</source>
<translation type="obsolete">Nyissa ki (Ctrl+O)</translation>
</message>
<message>
<location filename="main.py" line="263"/>
<source>Save (Ctrl+S)</source>
<translation type="obsolete">Mentés (Ctrl+S)</translation>
</message>
<message>
<location filename="main.py" line="262"/>
<source>Export to EXCEL...</source>
<translation>Exportálás EXCEL-be...</translation>
</message>
<message>
<location filename="main.py" line="268"/>
<source>Information about the application</source>
<translation>Az alkalmazással kapcsolatos információk</translation>
</message>
<message>
<location filename="main.py" line="266"/>
<source>Quit the application (Strg+Q)</source>
<translation type="obsolete">Az alkalmazás kilépése (Ctrl+Q)</translation>
</message>
<message>
<location filename="main.py" line="521"/>
<source>Garage</source>
<translation>Garázs</translation>
</message>
<message>
<location filename="main.py" line="448"/>
<source>Quit</source>
<translation>Kilépés</translation>
</message>
<message>
<location filename="main.py" line="457"/>
<source>New</source>
<translation>Új</translation>
</message>
<message>
<location filename="main.py" line="481"/>
<source>Save</source>
<translation>Mentés</translation>
</message>
<message>
<location filename="main.py" line="401"/>
<source> CSV-file</source>
<translation type="obsolete">CSV-fájl</translation>
</message>
<message>
<location filename="main.py" line="707"/>
<source>All files</source>
<translation>Minden fájl</translation>
</message>
<message>
<location filename="main.py" line="586"/>
<source>file</source>
<translation>fájl</translation>
</message>
<message>
<location filename="main.py" line="587"/>
<source>saved</source>
<translation>mentett</translation>
</message>
<message>
<location filename="main.py" line="603"/>
<source>Open</source>
<translation>Megnyitott</translation>
</message>
<message>
<location filename="main.py" line="704"/>
<source>Export</source>
<translation>Exportálás</translation>
</message>
<message>
<location filename="main.py" line="463"/>
<source> EXCEL-file</source>
<translation type="obsolete">EXCEL-fájl</translation>
</message>
<message>
<location filename="main.py" line="918"/>
<source>Error in the garage dimension</source>
<translation>Hiba a garázs dimenziójában</translation>
</message>
<message>
<location filename="main.py" line="979"/>
<source>Error in the dimensions of the objects to be stored</source>
<translation>Hiba a tárolandó objektumok méreteiben</translation>
</message>
<message>
<location filename="main.py" line="860"/>
<source>Successfully exported to EXCEL</source>
<translation>Sikeresen exportált EXCEL-be</translation>
</message>
<message>
<location filename="main.py" line="604"/>
<source>CSV-file</source>
<translation>CSV-fájl</translation>
</message>
<message>
<location filename="main.py" line="705"/>
<source>EXCEL-file</source>
<translation>EXCEL-fájl</translation>
</message>
<message>
<location filename="main.py" line="91"/>
<source>There are unsaved entries. Without saving, all changes are lost. Continue anyway?</source>
<translation>Vannak mentetlen bejegyzések. Mentés nélkül minden módosítás elveszik. Folytassa mégis?</translation>
</message>
<message>
<location filename="main.py" line="147"/>
<source>Garage Space Calculator</source>
<translation type="obsolete">Garázs hely kalkulátor</translation>
</message>
<message>
<location filename="utils.py" line="46"/>
<source>Calculates available garage space</source>
<translation>Kiszámítja a rendelkezésre álló garázshelyet</translation>
</message>
<message>
<location filename="main.py" line="752"/>
<source>Comment</source>
<translation>Megjegyzés</translation>
</message>
<message>
<location filename="main.py" line="323"/>
<source>Unit of Measurements</source>
<translation>Mérési egység</translation>
</message>
<message>
<location filename="main.py" line="324"/>
<source>Length units</source>
<translation>Hosszúsági egységek</translation>
</message>
<message>
<location filename="main.py" line="325"/>
<source>Mass units</source>
<translation>Tömegegységek</translation>
</message>
<message>
<location filename="main.py" line="310"/>
<source>&amp;File</source>
<translation>&amp;Fájl</translation>
</message>
<message>
<location filename="main.py" line="371"/>
<source>Help</source>
<translation>Segítség</translation>
</message>
<message>
<location filename="main.py" line="1084"/>
<source>Do you want to convert all existing stuff of type length to the new unit of measurement (UOM)</source>
<translation>Át akarja konvertálni az összes meglévő hosszúság típusú anyagot az új mértékegységre</translation>
</message>
<message>
<location filename="main.py" line="1119"/>
<source>UOM conversion</source>
<translation>Egység átváltás</translation>
</message>
<message>
<location filename="main.py" line="1118"/>
<source>Do you want to convert all existing stuff of type mass to the new unit of measurement (UOM)</source>
<translation>Át akarja konvertálni az összes meglévő tömeg típusú anyagot az új mértékegységre</translation>
</message>
<message>
<location filename="main.py" line="265"/>
<source>About Qt</source>
<translation>A Qt-ról</translation>
</message>
</context>
<context>
<name>utils</name>
<message>
<location filename="utils.py" line="47"/>
<source>Idea</source>
<translation>Ötlet</translation>
</message>
<message>
<location filename="utils.py" line="45"/>
<source>Used icons: Theme</source>
<translation type="obsolete">Használt ikonok: Téma</translation>
</message>
<message>
<location filename="utils.py" line="51"/>
<source>from</source>
<translation>a weboldalról</translation>
</message>
<message>
<location filename="utils.py" line="56"/>
<source>Version</source>
<translation>Verzió</translation>
</message>
<message>
<location filename="utils.py" line="51"/>
<source>Used icons</source>
<translation>Használt ikonok</translation>
</message>
<message>
<location filename="utils.py" line="52"/>
<source>Currently opened file</source>
<translation>Jelenleg megnyitott fájl</translation>
</message>
<message>
<location filename="utils.py" line="53"/>
<source>Location of the Ini-file</source>
<translation>Az Ini-fájl helye</translation>
</message>
</context>
</TS>

12
img/icons.qrc Normal file
View file

@ -0,0 +1,12 @@
<RCC>
<qresource prefix="ICONS">
<file alias="ICON_EXPORT">icons8-export-xls-32.png</file>
<file alias="ICON_APP">icons8-garage-32.ico</file>
<file alias="ICON_ABOUT">icons8-information-32.png</file>
<file alias="ICON_NEW">icons8-new-file-32.png</file>
<file alias="ICON_OPEN">icons8-opened-folder-32.png</file>
<file alias="ICON_SAVE">icons8-save-32.png</file>
<file alias="ICON_QT_LOGO">qt_logo_small.png</file>
<file alias="ICON_QUIT">system-shutdown.png</file>
</qresource>
</RCC>

BIN
img/qt_logo_small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

View file

@ -1,5 +1,4 @@
# project: GarageCalc1
# file: requirements.txt
wheel
pyside2==5.15.2
XlsxWriter==1.3.8
pyside2
xlsxwriter

View file

@ -0,0 +1,22 @@
@ECHO OFF
:: --------------------------------------------------------------------------------------------------------------------------------------
:: project: GarageCalc
:: summary: Update or create GarageCalc module file to be imported from Qrc-file
:: file: update_ts_files.cmd
:: date: version author
:: 2021-07-12 1 paul salajean
:: --------------------------------------------------------------------------------------------------------------------------------------
SET prev_dir=%cd%
CD ..
pyside2-rcc --verbose -o .\src\icons_rc.py .\img\icons.qrc
:: for embedded class "clsTableWidget"
pyside2-rcc --verbose -o .\src\clsTableWidget_icons_rc.py .\src\img\icons.qrc
:END
CD %prev_dir%
ECHO Done.
PAUSE

View file

@ -1,36 +1,36 @@
@ECHO OFF
:: --------------------------------------------------------------------------------------------------------------------------------------
:: project: GarageCalc1 Window-Exe Generator
:: summary: create a GarageCalc1-executable for Windows (version with no-console-windows as well as version with console windows for traces)
:: project: GarageCalc Window-Exe Generator
:: summary: create a GarageCalc-executable for Windows (version with no-console-windows as well as version with console windows for traces)
:: file: pyinstaller.cmd
:: date: version author
:: 2021-06-27 1 paul salajean
:: --------------------------------------------------------------------------------------------------------------------------------------
SET version="v0.1"
SET version="v0.4"
SET release_dir="D:\Temp\Prog\ownCloud\profp@uberspace\transfer"
SET prev_dir=%cd%
SET reinstall_venv="true"
SET reinstall_venv="false"
SET do_zip="false"
CD ..
ECHO Creating GarageCalc1 Windows.exe-version in folder %cd%\dist
ECHO Creating GarageCalc Windows.exe-version in folder %cd%\dist
PAUSE
REM pyinstaller --noconfirm --log-level=ERROR ^
REM --onedir --nowindow ^
REM --add-data="README;." ^
REM --add-data="image1.png;img" ^
REM --add-data="img;doc;ui" ^
REM --add-data="LICENSE.txt;changelog.md;GarageCalc1.bat" ^
REM --add-data="LICENSE.txt;changelog.md;GarageCalc.bat" ^
REM --add-binary="libfoo.so;lib" ^
REM --hidden-import=secret1 ^
REM --hidden-import=secret2 ^
REM --icon=.\img\GarageCalc1.ico ^
REM --icon=.\img\GarageCalc.ico ^
REM --debug=imports ^
REM --key=N0T1me40pp0ssum5
REM --paths=.\src ^
REM GarageCalc1.spec
REM GarageCalc.spec
REM The key-string is a string of 16 characters which is used to encrypt each file of Python byte-code before it is stored in the archive inside the executable file.
REM This feature uses the "tinyaes" module internally for the encryption.
REM
@ -55,21 +55,21 @@ python -m pip install -r requirements.txt
:PYINSTALL
IF %reinstall_venv%=="false" CALL .\env2\Scripts\activate.bat
ECHO Running "pyinstaller"...
REM pyinstaller .\main.py --name=GarageCalc1 --noconfirm --console --clean --onedir --log-level=ERROR --hidden-import=PySide2.QtXml --icon=.\img\GarageCalc1.ico --add-data="LICENSE;." --add-data="README.md;." --add-data="changelog.md;." --add-data="*.ui;." --add-data="img;.\img"
pyinstaller .\src\main.py --name=GarageCalc1 --noconfirm --windowed --clean --onefile --log-level=ERROR --hidden-import=PySide2.QtXml ^
REM pyinstaller .\main.py --name=GarageCalc --noconfirm --console --clean --onedir --log-level=ERROR --hidden-import=PySide2.QtXml --icon=.\img\GarageCalc.ico --add-data="LICENSE;." --add-data="README.md;." --add-data="changelog.md;." --add-data="*.ui;." --add-data="img;.\img"
REM --windowed
pyinstaller .\src\main.py --name=GarageCalc --noconfirm --windowed --clean --onefile --log-level=ERROR --hidden-import=PySide2.QtXml ^
--icon=.\img\icons8-garage-32.ico ^
--add-data="LICENSE.txt;." ^
--add-data="README.md;." ^
--add-data="changelog.md;." ^
--add-data="requirements.txt;." ^
--add-data=".\src\*.ui;." ^
--add-data="*.txt;." ^
--add-data="*.md;." ^
--add-data="ui;.\ui" ^
--add-data="i18n;.\i18n" ^
--add-data="img;.\img"
::MOVE .\dist\GarageCalc1\*.md .\dist\
::MOVE .\dist\GarageCalc1\LICENSE .\dist\
::MOVE .\dist\GarageCalc\*.md .\dist\
::MOVE .\dist\GarageCalc\LICENSE .\dist\
::clean-up img-folder
::MOVE .\dist\GarageCalc1\img .\dist\img>NUL
::MOVE .\dist\GarageCalc\img .\dist\img>NUL
::Remove temp dir and files
DEL /Q *.spec>NUL
@ -83,7 +83,7 @@ IF %do_zip%=="false" GOTO END
::-mx5 = This is default (compression is normal).
::-mx7 = Maximum compression.
::-mx9 = Ultra compression.
"C:\Program Files\7-zip\7z.exe" a %release_dir%\GarageCalc1_%version%_portable.exe -mx9 -sfx7z.sfx .\dist\*
"C:\Program Files\7-zip\7z.exe" a %release_dir%\GarageCalc_%version%_portable.exe -mx9 -sfx7z.sfx .\dist\*
::Disable Virtual env
CALL .\env2\Scripts\deactivate.bat

View file

@ -0,0 +1,94 @@
@ECHO OFF
:: --------------------------------------------------------------------------------------------------------------------------------------
:: project: GarageCalc Window-Exe Generator
:: summary: create a GarageCalc-executable for Windows (version with no-console-windows as well as version with console windows for traces)
:: file: pyinstaller.cmd
:: date: version author
:: 2021-06-27 1 paul salajean
:: --------------------------------------------------------------------------------------------------------------------------------------
SET version="v0.4"
SET release_dir="D:\Temp\Prog\ownCloud\profp@uberspace\transfer"
SET prev_dir=%cd%
SET reinstall_venv="true"
SET do_zip="false"
CD ..
ECHO Creating GarageCalc Windows.exe-version in folder %cd%\dist
PAUSE
REM pyinstaller --noconfirm --log-level=ERROR ^
REM --onedir --nowindow ^
REM --add-data="README;." ^
REM --add-data="image1.png;img" ^
REM --add-data="img;doc;ui" ^
REM --add-data="LICENSE.txt;changelog.md;GarageCalc.bat" ^
REM --add-binary="libfoo.so;lib" ^
REM --hidden-import=secret1 ^
REM --hidden-import=secret2 ^
REM --icon=.\img\GarageCalc.ico ^
REM --debug=imports ^
REM --key=N0T1me40pp0ssum5
REM --paths=.\src ^
REM GarageCalc.spec
REM The key-string is a string of 16 characters which is used to encrypt each file of Python byte-code before it is stored in the archive inside the executable file.
REM This feature uses the "tinyaes" module internally for the encryption.
REM
::one dir:
ECHO ...Running...
RMDIR /S /Q .\dist>nul
RMDIR /S /Q .\build>nul
::Use Virtual env
IF %reinstall_venv%=="false" GOTO PYINSTALL
ECHO Installing virtual env as ".\env2"...
RMDIR /S /Q .\env2>NUL
python -m venv env2
CALL .\env2\Scripts\activate.bat
ECHO Installing necessary python packages...
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
:PYINSTALL
IF %reinstall_venv%=="false" CALL .\env2\Scripts\activate.bat
ECHO Running "pyinstaller"...
REM pyinstaller .\main.py --name=GarageCalc --noconfirm --console --clean --onedir --log-level=ERROR --hidden-import=PySide2.QtXml --icon=.\img\GarageCalc.ico --add-data="LICENSE;." --add-data="README.md;." --add-data="changelog.md;." --add-data="*.ui;." --add-data="img;.\img"
REM --windowed
pyinstaller .\src\main.py --name=GarageCalc --noconfirm --windowed --clean --onefile --log-level=ERROR --hidden-import=PySide2.QtXml ^
--icon=.\img\icons8-garage-32.ico ^
--add-data="ui;.\ui" ^
--add-data="i18n;.\i18n"
::MOVE .\dist\GarageCalc\*.md .\dist\
::MOVE .\dist\GarageCalc\LICENSE .\dist\
::clean-up img-folder
::MOVE .\dist\GarageCalc\img .\dist\img>NUL
::Remove temp dir and files
DEL /Q *.spec>NUL
RMDIR /S /Q .\build
::Create self extracting archive
IF %do_zip%=="false" GOTO END
::-mx0 = Don't compress at all - just copy the contents to archive.
::-mx1 = Consumes least time, but compression is low.
::-mx3 = Better than -mx1.
::-mx5 = This is default (compression is normal).
::-mx7 = Maximum compression.
::-mx9 = Ultra compression.
"C:\Program Files\7-zip\7z.exe" a %release_dir%\GarageCalc_%version%_portable.exe -mx9 -sfx7z.sfx .\dist\*
::Disable Virtual env
CALL .\env2\Scripts\deactivate.bat
:END
CD %prev_dir%
ECHO Done. Check %prev_dir%\..\dist
IF %do_zip%=="true" ECHO Done. Check %release_dir%
PAUSE

View file

@ -0,0 +1,22 @@
@ECHO OFF
:: --------------------------------------------------------------------------------------------------------------------------------------
:: project: GarageCalc
:: summary: Update or create GarageCalc ts-files
:: file: update_ts_files.cmd
:: date: version author
:: 2021-06-30 1 paul salajean
:: --------------------------------------------------------------------------------------------------------------------------------------
SET prev_dir=%cd%
CD ..
mkdir .\i18n
pyside2-lupdate -verbose .\src\main.py .\src\utils.py .\src\clsTableWidget.py -ts .\i18n\de_DE.ts
pyside2-lupdate -verbose .\src\main.py .\src\utils.py .\src\clsTableWidget.py -ts .\i18n\hu_HU.ts
:END
CD %prev_dir%
ECHO Done.
PAUSE

373
src/clsTableWidget.py Normal file
View file

@ -0,0 +1,373 @@
#!/usr/bin/env python3
"""
project: clsTableWidget
file: clsTableWidget.py
summary: Implements my own TableWidget class
author: Paul Salajean (p.salajean[at]gmx.de)
license: GPL
version: 0.1
"""
# Standard library imports
import sys
import os
# Third party imports
from PySide2.QtWidgets import QApplication, QTableWidget, QAbstractItemView, QTableWidgetItem, QMenu, \
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
import icons_rc
import clsTableWidget_icons_rc
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"
# ICON_INSERT = SCRIPT_PATH + "/img/icons8-insert-clip-16.png"
# ICON_APPEND = SCRIPT_PATH + "/img/icons8-append-clip-16.png"
# ICON_PASTE = SCRIPT_PATH + "/img/icons8-paste-16.png"
# ICON_CUT = SCRIPT_PATH + "/img/icons8-scissors-16.png"
# ICON_ADD_ROW = SCRIPT_PATH + "/img/icons8-add-row-16.png"
# ICON_DEL = SCRIPT_PATH + "/img/icons8-delete-16.png"
# def resource_path(relative_path):
# """ Get absolute path to resource, works for dev and for PyInstaller """
# try:
# # PyInstaller creates a temp folder and stores path in _MEIPASS
# base_path = sys._MEIPASS
# print("base_path", base_path)
# except Exception:
# base_path = os.path.abspath(".")
# return os.path.join(base_path, relative_path)
class TableWidget(QTableWidget):
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.clipboard_data: list = None
# self.setSelectionMode(QAbstractItemView.ContiguousSelection)
self.setSelectionMode(QAbstractItemView.SingleSelection)
self.setSelectionBehavior(QTableWidget.SelectItems)
#self.setSelectionBehavior(QTableWidget.SelectRows)
self.setAlternatingRowColors(True)
self.setSortingEnabled(True)
self.horizontalHeader().setSectionsMovable(True)
self.horizontalHeader().setStretchLastSection(True)
# Context-menu
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.on_context_menu)
# self.setEditTriggers(QAbstractItemView.DoubleClicked | QAbstractItemView.EditKeyPressed | QAbstractItemView.AnyKeyPressed)
self.vertHeader = self.verticalHeader()
self.vertHeader.setContextMenuPolicy(Qt.CustomContextMenu)
self.vertHeader.customContextMenuRequested.connect(self.on_rowheadercontext_menu)
self.vertHeader.setSelectionMode(QAbstractItemView.SingleSelection)
self.vertHeader.sectionClicked.connect(self.select_row)
self.vertHeader.setSectionsMovable(True)
self.row_selected = False
def select_row(self, row):
self.setSelectionBehavior(QTableWidget.SelectRows)
self.selectRow(row)
self.setSelectionBehavior(QTableWidget.SelectItems)
self.row_selected = True
def on_context_menu(self, position):
menu = QMenu()
item_cut = menu.addAction(QIcon(u":ICONS/ICON_CUT"), QCoreApplication.translate("TableWidget", "Cut") + "\tCtrl+X")
item_copy = menu.addAction(QIcon(u":ICONS/ICON_COPY"), QCoreApplication.translate("TableWidget", "Copy") + "\tCtrl+C")
item_paste = menu.addAction(QIcon(u":ICONS/ICON_PASTE"), QCoreApplication.translate("TableWidget", "Paste") + "\tCtrl+V")
menu.addSeparator()
item_delete = menu.addAction(QIcon(u":ICONS/ICON_ERASER"), QCoreApplication.translate("TableWidget", "Delete") + "\tDel")
ac = menu.exec_(self.mapToGlobal(position))
if ac == item_cut:
self.item_cut()
elif ac == item_copy:
self.item_copy()
elif ac == item_paste:
self.item_paste()
elif ac == item_delete:
self.item_del()
def on_rowheadercontext_menu(self, position):
menu = QMenu()
row_cut = menu.addAction(QIcon(u":ICONS/ICON_CUT"), QCoreApplication.translate("TableWidget", "Cut row"))
row_copy = menu.addAction(QIcon(u":ICONS/ICON_COPY"), QCoreApplication.translate("TableWidget", "Copy row"))
row_paste = menu.addAction(QIcon(u":ICONS/ICON_PASTE"), QCoreApplication.translate("TableWidget", "Paste row"))
menu.addSeparator()
row_insert_before = menu.addAction(QIcon(u":ICONS/ICON_INSERT"), QCoreApplication.translate("TableWidget", "Insert row before"))
row_insert_after = menu.addAction(QIcon(u":ICONS/ICON_APPEND"), QCoreApplication.translate("TableWidget", "Insert row after"))
menu.addSeparator()
row_remove = menu.addAction(QIcon(u":ICONS/ICON_DEL"), QCoreApplication.translate("TableWidget", "Remove row"))
row_delete_items = menu.addAction(QIcon(u":ICONS/ICON_ERASER"), QCoreApplication.translate("TableWidget", "Delete items"))
ac = menu.exec_(self.mapToGlobal(position))
row = self.vertHeader.logicalIndexAt(position)
if ac == row_cut:
self.item_cut()
elif ac == row_copy:
self.item_copy()
elif ac == row_paste:
self.item_paste()
elif ac == row_insert_before:
self.row_insert(row)
elif ac == row_insert_after:
self.row_insert(row+1)
elif ac == row_remove:
self.row_remove(row)
elif ac == row_delete_items:
self.row_delete_items()
def row_insert(self, row):
self.insertRow(row)
def has_data(self, row):
""" Check if target already contains data. """
# sel_idx = self.selectionModel().selectedIndexes()
for col in range(self.columnCount()):
item = self.item(row, col)
if item:
if len(item.text()) > 0:
return True
return False
def row_remove(self, row):
if self.has_data(row):
msg = QCoreApplication.translate("TableWidget", "Row Nr.") + " " + str(row+1) + " " + QCoreApplication.translate("TableWidget", "to be removed?")
reply = QMessageBox.question(self, QCoreApplication.translate("TableWidget", "Remove"), msg, \
QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
if reply == QMessageBox.No:
return False
self.removeRow(row)
return True
def row_delete_items(self):
self.item_del()
def keyPressEvent(self, event):
super().keyPressEvent(event)
modifiers = QApplication.keyboardModifiers()
key = event.key()
if modifiers == Qt.ControlModifier:
if key == Qt.Key_C:
self.item_copy()
elif key == Qt.Key_V:
self.item_paste()
elif key == Qt.Key_X:
self.item_cut()
elif key == Qt.Key_A:
self.setSelectionMode(QAbstractItemView.ContiguousSelection)
self.selectAll()
self.setSelectionMode(QAbstractItemView.SingleSelection)
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 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
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()
self.retranslateUi_dlg(self.dlg)
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"])
if item:
self.dlg.efValue.setText(item.text())
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:
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):
clip_text = qApp.clipboard().text().rstrip('\n').split("\t")
cur_row = self.currentRow()
cur_col = self.currentColumn()
col = 0
for data in clip_text:
item = QTableWidgetItem(data)
self.setItem(cur_row, cur_col+col, item)
col += 1
def item_cut(self):
self.item_copy()
sel_idx = self.selectedIndexes()
for idx in sel_idx:
item = self.itemFromIndex(idx)
try:
item.setData(Qt.DisplayRole, None)
except AttributeError:
pass
def item_copy(self):
sel_idx = self.selectedIndexes()
sel_rows = self.selectionModel().selectedRows()
if len(sel_idx) == 1:
self.row_selected = False
self.sel_ranges = self.selectedRanges()
clipboard_data = []
for idx in sel_idx:
clipboard_data.append(idx.data(Qt.DisplayRole))
clip_text = "\t".join(str(text or "") for text in clipboard_data)
qApp.clipboard().setText(clip_text)
def item_del(self, ask_cofirmation=True):
sel_idx = self.selectionModel().selectedIndexes()
for idx in sel_idx:
row = idx.row()
col = idx.column()
item = self.item(row, col)
if item:
if self.has_data(row) and ask_cofirmation:
msg = QCoreApplication.translate("TableWidget", "Delete cell content?")
reply = QMessageBox.question(self, QCoreApplication.translate("TableWidget", "Delete"), msg, \
QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
if reply == QMessageBox.No:
return False
ask_cofirmation = False
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:
self.parent.is_modified = False # set parents modification flag (if present)
except AttributeError:
pass
def retranslateUi_dlg(self, dlg):
dlg.setWindowTitle(QCoreApplication.translate("TableWidget","UOM"))
dlg.lblValue.setText(QCoreApplication.translate("TableWidget","Value") + ":")
dlg.lblUOM.setText(QCoreApplication.translate("TableWidget","UOM") + ":")

View file

@ -0,0 +1,438 @@
# Resource object code (Python 3)
# Created by: object code
# Created by: The Resource Compiler for Qt version 5.15.2
# WARNING! All changes made in this file will be lost!
from PySide2 import QtCore
qt_resource_data = b"\
\x00\x00\x01\xd5\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\
\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x01\x8aIDAT8\x8d\xbd\x92MK\
\x02Q\x14\x86\xdf{g&\x0d\x11\x83\xc2,0\x84V\
m*Z\x04\xf5\x17\x82\xa8\x8d\xfb\xc0\xa5FHn\x03\
\x83\x16\x85\xe0\xa2\xd6\xd9o\x886A\xfb@h\x91\xd1\
\x22*\x91\x16\x96E\x1f~\x8c\xce43\xe7\xb6\x98\xb4\
r\xec\x8b\xa0wu\xef9\xefy\xce\x81s\x80?\x8a\
\xb5\x07R+\xbb1\xc8l\xb4\xa3\xdb\x14\xb9\xe5\xd5\xd9\
\xcd\xf7!\xb9\xddc\xf5\xf5\xc4\xcd\xa9\xc9P\xa7z\xf9\
0[\x00\xf0\x01\xc0\x1d#I\x0e\xe6\x979\x07\xe0\xb7\
r \x09\xc2\x85\xb3s\xfb\xdd\xe3\xb3\xbb<\x95\xdfr\
\xdf\x01P\xad\x01\x5c\xaa\x03\x00\xaf\xaa\xce\xdc\xbf*\xbd\
\x94\x09\xa5\x972\x1d7\xd2\x94\xbc\x11\xdb\x19\x0e\x0c\x0f\
\x1c+\x1e\xb7\x04\x00 \x08\xadR[_H\xcc$\xc9\
B\xe0\xd5W\xd8N\xed%\xbb\xbd\xde\x04\xb8};\x86\
\xaaY7\x97\xd7c2\x13\x22\xe8\x1f\x19\xf2\xf8\x06{\
[\xd4\xd3\xbd\xec\x04\x00\x90\x80\xbb\x19#\x03\xe3\xa1\xe9\
\x91\xee\xe6\xbf\x5c\xbcG\xe9\xa2\x18\x94\x01\xa0\xaa\xea\xb0\
\xca\xf5\x16@S\xb5\xc7T43\x07\xb2\xd7\x9c\x8af\
\xe64U{|x\xe7\xa9\xab:\x80/\xee\x80+\x9e\
}\xc6\xd9<\xe3l\x9e+\x9e\xfdO}\x8c\xc8$\x93\
\xa85\xaaE\xe0\x920\xe2\xe9pCa\x95\x88\xc2*\
\x91x:\xdc\xe0\x920\xc8j\xd9@&\x11#2\xe5\
\x9a\xdf\x9b\xbd;\xc9o\xdd\xe6\xf2\xfd6Q\xe8\xcf\x86\
\xb9\x06\x00\x8b\x9b\x8bz\xb3@\xd7\xcd\xb5\xab\x83\xa3.\
\x12\xcc\x05\x00L\xa0T\xf3{\xb3\x9fM\xf6c\xbd\x00\
\xd6\xec\x9b#t\xa1Ts\x00\x00\x00\x00IEND\
\xaeB`\x82\
\x00\x00\x02d\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\
\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x02\x19IDAT8\x8d}\x90=h\
SQ\x18\x86\x9fs\xce\xbd7\xf7'i\x8c\xb9M+\
\xb6\x85\x14\xf1\xa7N.\x1dD\x10\x15Q\x10\xd1\xc1Q\
\x0a\xeeN\xaeE\xc8R\x17AG\x9d\x1c:)\x08*\
\xea\xe0\xe4\xe6*\xa2\xa4\x82\x85\x16\x9a*\xcdO\xff\xf2\
\xdf\xe4\xde\xe3\x10n\xb06\xe9;\x1d\xde\xef\xe5\xf9\xbe\
\xf3\x0a\x06(\x97\xcb\xc9\xd3n\xf6\x89\xeb\xaa\xf3\x00\x8d\
F\xf0\xe5gc\xe5A.\x97\x0b\xff\xcf\x8a\xe8\xf1b\
~q)\x990\xc7\x00\xaa\x8dN\xe2\xea-\xd7\xa8\x94\
\x03\x04p\xd4W|z\xd7\xec&]\xa3\x0a\xb0\xbb\xdb\
\xd9\xb8\xf7h\xee\x0c\x80\x11\x01\xbc\x18\xb6\x9fV\xa9r\
\xdd\xe0\x98/\xf03\x12?#\xfb\x9b\x8eO\x99F\xad\
f\xa5|\xafKw\xaf\xb3\x13\xf9}\x00@\xb1\xaa8\
r\xfb\x06[\xf9\x15^}\xde\xf9w\x84=\x9e$5\
\x93\xa5\xf8\xf6\xc3>\x7f\x1f Rj&;\xc8\x06 \
\x9dq(\xd5\xea\x87\x03\xaa\xdf\x96p[\xdb\x07|%\
\x05\x01&\xa3'''\x17\x17^/\xcf\xcd\xdf91\
\x10\x10\xb6\xda\x5c\xbe>E\xf9O\xad\xefy#q\xb4\
\x0eh\xb7\x14a\xd0T\x02\x1d\x07\x90\x83\x00\x91\x84\xb2\
\x11R!\xa4B\x13\xa0L\x870h#\x90\x98\x96\x95\
\x1c\xfa\x85H\xfe\xb8\x0d\xd8\xa0A\x1a6:\xecb\xdb\
\x1e\x865\xc2r~sx\x07\x91\x8a\x85m~\xe5+\
\x08\x04\xb6\x1bc\x22\x1b\xa7\xb0\xdad\xf6\xd2H?s\
\x08@ \x95\x01\x1a\x84T4\xeb\x0d\x0a\xab\x92\xd9+\
gA\xaa~jh\x07RY 4\x8e\xe7`Z!\
\x8e\xe7\x22\x10\x94\xd6\xb7 \x0c\x08\xc3\xb03\xf4\x02%\
@\x87]\xa4\xe1\xa0\x83\x0a1\xc7\xe6\xdc\x85S\xfd\xb9\
\xee\xb6\xd8k\xb56\x0f\x002\x89\x80\xf2\xfb\x8f\x98\xa6\
\x814\xa6I\xfbm\xd2\x17\xa7QV\xbc\x9f)\xfd\xde\
\x22\xff}\x9d\x8db#\xbe\x0f\xd0hS/\x97z\xd4\
\xed \x96\xd0\xbak\x22%\xca\xf0\x00\xdd\xdb\xac5?\
\xbe\xae\xb1\xe3e4V\xf5Y\xaf\xa9\x01z\xf9\xf8\xcd\
\xd3\xb1\x89\xc4M\xdbuG\x85\x14\xbd%\x1a\xda\xadf\
\xa5\xb0\xb6\xeb\xe8\x98\xf3\xfc\xee\xfdk\x0f\x01\xfe\x02\xe3\
\x0e\xb5\xdf\xd6\x99o.\x00\x00\x00\x00IEND\xae\
B`\x82\
\x00\x00\x01\xfa\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\
\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x01\xafIDAT8\x8d\xc5R\xcfK\
TQ\x18=\xdf\xbd\xef]\xe71\xea@0N!E\
\x0d\x8c\xb61\x91\x86)h\x86\x96m\xa3\xbf\xc06b\
`\xb8qm\xedZ\xb4\x10\x5c\xb8\xf2\x07\xd6\xcaV5\
-[E\x8b@p3\x8b\x01\xb1!\x8a,\x8b\x08r\
\x12\xdf{\xf7\xc7\xe7Bft|\x83\xee\xec\xc0\x07\xf7\
\x9e\xef|\xe7\xbb\x1c.\xf0\xbfA'\x89W\xd3\xcbS\
\xbd\xbe|&\x05{\xa7N2\xf1_\xe3\x9et\x88\x16\
\x1f\xaf\x96\xb2\xca\xce\x8e\x05\xae\xf7\xac\xcd\xcc\x0e\xd5]\
.\x88\x1617\xf1\xf2\xd2\x05\xcf\xae\xde\x90:k\xe3\
\x18\xdc\xa7\xe0\xc8\xc1\xc6q\xbb\x90\x0d\xdag\xa75\x1c\
\xc8\x09\x00x:\xbe\x92\x1a\x08\xf4\x9b\xb2\xd2\xd7\xdb\x1b\
\xfe\x85\xe8\xb9[\x00\x05\x0a\x00\xe0\x0d\xe7@\x99 \xf1\
\x12\xc1`\xba\x96\xe1\xb5JJ\x17\xe5\xb1D82\x88\
\xdeoA\x95\xf3\xf0G\x07A\x9e\x80\xa9\xef$\x0d\x96\
\xa6\x97\x1e\x95z\xcc\xbd4%\x03\xe5\xc8\xc0\xfdl\xc2\
\x1b\x1a\x80i\xfc\xee\x9a\x850,\xdf}\xd6r\xbb[\
\xd3\x1b\xce\x01\x00\xc2\xd75\xa8;yP\xe0'\x0d&\
\xe7\x1fn}\xd3\x98\xaa\x1b\xf1\xfdxC\x0ef@\xbe\
\x84\xaem\x83\xb5E\xfc\xa1\x01\xbft5a \x01\xe0\
\xedz\xf5S\xf9\xe6}\xea\x93\xb8\xd5/8\x05\x00\xdc\
\x8c\xe0~5\x8f\x94\xd6\xc1~\xf9\xd31\xbci\xe4\x86\
l]\xaa\xeb\xd5\x8f\xb7\x8b\x0f\x0a)r#\x96I\x80\
\x08\x06\x84\xa6#\xec\xf3a\x9d\xe4\xbeZ\xb1\xd1\xf1\x91\
\x82\x1f\xe9\x89\xcd\x8b\xbb\x95\xbc\x0e\x0b\x96-\x00 \xa2\
\xa3l-s\x9bs (\xe5\xa9D\xf2\xcfg^\xa4\
/\x87\xd1\x82\x03]\xe9\x16l\x0b$\x10\xee\xd9`\xf2\
4\xcd\xf9\xe0\x00\x19\x1e\xad\x82\xce'*\x04\x00\x00\x00\
\x00IEND\xaeB`\x82\
\x00\x00\x02\x97\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\
\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x02LIDAT8\x8deR\xcfK\
TQ\x14\xfe\xeey\xf7\xbd7o\xc6_3\x8e/u\
\x04\x13\x91\x84\x82Z$-\x5c\x14i\x22(\xb4\x8a \
Z\xf5'\x18T\x7f@\x08\x06\xb6\x0d\x82hY+5\
\xd7\x96-\x84\x16I \x82\xa0\x85\x0e\xa3\xf93\x19\xad\
\xa9\xe9\xbd7\xf7\x9e\x16\xd3\xbc\xdek\xce\xea\xdes\xcf\
w\xbe\xef;\xe7\x0aD\x82\xc1\xe2\xf9\xe4\xecC\xb0\xd9\
\x1b\xcd[N\x22\xad\x89\x83\x93\xc2\xce\x83\xfbO\xefm\
G\xdfd\x14\xfcrjn\xbe\xc5\xe1\xb1\xcc\xf8\x88\xa8\
\xe5M\x12H\xd9\x84r\xb9\x82\xf5\x99E\x02p;\xda\
\x80B\xf0\x937sW\x87\xe4Xk\x9b\x11\x07[\x04\
/`8\x8e\x84!\x8df\xfc\x17\x02\x00\x9e=\x9ey\
\xd4\x9a\x11\x93\xd9,\x89\xe2\x09\xa1ix\x04\xfa\xfb\x0f\
T\xb6\xf2\xd0\x1a Q-\xdc_+\x1c65\xca\x05\
V\xf4\xe9\xd6\xc4\xf8th\x81\xd9\xe8O\x8f\x8e\x0a\x05\
\xa0\x09\x80:.\xc2\xfc\xb2\x8c\xa4i\xe2\xcaP_U\
\xaat\x80\xe1\x0e\x97\xa4s\xe7\xfd\xfc\xca\x0d\x00\xd3\xa1\
\x85h\xa8\xe3\x22\xe4\xe7\x8f\x18\x1c\xf4\xab\x12I\xc2\xb0\
\x9b\x01\xd6 \xe9\x80\x95\x0fh\xae\xc4f\x10\xf5|\xb8\
\xb0\x84\xa4\x1d`\xf9\x03\x90\xc9:\x10d\x81u\x00\x92\
\x0e\xb4\xf2 \xec\x06\xd8\xc9d\xb6n\x0b\xb5\x81\xe5\xfa\
\x5c\x5c\xbe\xde\xf5O64\x88\x12\xd0\xca\x03XCh\
\x0d\xd6J\xc5\x1aX\xb6\xdd\x9c\xb2\xab\xd3\xae\xad\xe0\xf8\
\xc0\xc6j\x01\x82$\xac\x04\xa1\xbb7\x8d\xed\xad\x12\
\x06\xae\xf5\xc5,S\x95IX^\xc0\xb0\xa5\x08\x99\x05\
\x09$\x92\x0e,[\x00Z\xe3\xe0k\xb9\x0e\x1c*\xd0\
\x8a\xcb'k\x9bhl\xcf@\x92\x01\xb0\x86\xdb\x95E\
[G#\x18\x1a\x86L\xd5\x01c\x0d\x88X\xbb\xe7\xcf\
\x82\xa4\x81\xd2&\x83\xa4\x83\x83\xc2\x116V\xf7 \xc8\
\x0c\x8b\xcf]\xcc\xc1\xcd\xb5@U*\xe5X\x83\xa3\xfc\
\xce\xc4\xca\xab\xb7R\x982\xdd\xdf\x9d\x1ad\xe5\x99m\
\xb9\x06\xb4w_\xaac\xd4\x952\x02\xdf;\xad\xdd\xc5\
\xff\x05\x8b\xaf\xdf\xedg;\xd3g\x840\x00\x00ng\
\xf5\xf7\x1e\xee\x9e\x82\xb5\x0f\xad|\x1c\xed\x96\xf2\xc3w\
GzB\x051\x06\x0d\xbe0\xd0S\xc7\xdc\xeaZP\
\x7f\x95\xef\x15\xd6\xfd\x98\x85h\xec\xe5\x8bS\xb3/\x96\
nFsJ\xb1\xfa\xf5\xd3\xfbV\xbb\xff.\xf9\x0b\xb5\
\xf3\x1f\xb8\x9f\xd9\x00\xfb\x98vj\x00\x00\x00\x00IE\
ND\xaeB`\x82\
\x00\x00\x01\xbf\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\
\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x01tIDAT8\x8d\xedQ\xbdK\
Bq\x14=\xbf\x9f\xef=\xf3\xf9\xcc\x0f\xb2!Ql\
\xc8\xc00\xa3\xa9\xa1\xa5!\xe8\x7fh\x11Z\xda\x9b\xda\
\x9a\x0a\x82\x9a\x1aZ\xa2\xa1\xb1?\xa0hM\x84\x06\x95\
\x14\xedK\x02\x1b\xca\xaf\xb4\xe7\x17\xfa~\xfa^\x83\x88\
\x95ZAkg;\x97s\xcf\xbd\xf7\x5c\xe0\x1f\xe4`\
\xf7<\xc9\xdbLR\xb7P\xa9\xb1\x8aJ\xa8\xe9W\xcd\
\xe5j\x85\xd3\x8fYD~\xdc\xea\x94\xfc\x1e\x00\x80|\
\x11yf\xb33\x13]\x11\x97\xbcC\xcb;\x8dA\x9c\
\xbf\x0a\xa7)\x00\x10N\xd7\xb3U\x94\x0f\x04\x80\xc2\xf0\
\x1d\xa7\x9d]\xc8o6\x1e\x08\x0e\x00x\x9b\xf9sU\
\x03\xe8}\x02\xedz\x06\x8a\xd6\x06\x8d\x14\x01\xcf< \
I}\x06t\x90+yH\xa0lM\xa38\xa7\xc0\xb0\
\xa0\xe8\xaf\x017!\xa0\xc5\xfa\xb4TSU\xa2d\
_{\xc3\xdd.\xb9]\xcd\xa0i\xef\x9c\xe5\x95F\xa1\
Q\xa0<\xc5@\x9f\xd2P]\x8e\x9eVS\x09\xd7*\
\xc9\x87\x8d\x97\xbc\xaf\x1c\xbd\xed\xdc\xc44U\xb17\x0c\
\x0e\xbd\xd5\xe9\x93\xccp\x8bF0M\xc3\xa5\x92\x85.\
\x1aK@0\xc4\xba)\x13\xbd\x10\x1f\x98\xde\xf6\xce\xc9\
YaIZ\x01\x05\x16-v\x04\xdf\xf2\x10S\xcd\x92\
1\xdcX\xde\xdc\x0b\x84\x7f\xcc@-4\xd7m\xc1z\
\x9c\x97U\x84r9\x88\xa9fI|dG_\x9b\x01\
`\xe8\xff\xb6\x02\xc7#\x82K\xb7Jt\x98\x14dv\
\xba\xb1\xbfv=L\xfb'\xbc\x03\xc6\xc5\x8a\x1b\x0fd\
\xe3\xa5\x00\x00\x00\x00IEND\xaeB`\x82\
\x00\x00\x02\xef\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\
\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x02\xa4IDAT8\x8d\xa5\x92Ih\
\x94Y\x14\x85\xbf\xf7\xfe\xe1UY\xb1\x0bc\x95C\xa8\
\xc4\xb6\x92\x88!E\x14\xbb\x05Q4\x22\xbd\x13Ap\
\xe5B!\x88\x04\x04]\xb9\xd0]\x89+\x17\xba\xd6\x14\
\xc4i\x97\xc6\x16\x14\xc7\x8d8!\x88\xda(\x89\xd8\x1d\
%\x92D\xd4\xc48\x84T\xd5?\xbc\xfa\x9f\x8bJ*\
q\xd8yv\x97{\xcf\xb9\xf7\x1e\x8e\xe0'8\xbe\xaf\
\xb7\xb1!%\xf6\xb8\xae\x95\x8b\xb4\xf94\xe9qu$\
6t9\x9f\xcf\xeb\xefg\xc5\xdc\xe2\xec\xc1B\xc7\x82\
\x94\xeak\xc8:\xcdMm\x8e]7_\x10\x060\xfe\
V3\xd4\x1fN~\x19\xaf\x9c\xdb\x91\xdf}@ \xcc\
\x0f\x02\x17\x8e\x9c\xde\x95nt\x0b\x1d\xeb\x95\x1a\xb8\xef\
\x11\x8ciL`H\xc6\x05\xc9\xa56\xb1V\x05\xd2\xf0\
\xf0f\xf9\xe9\xf8\xb0\xb7\xb6\xbb\xa7;\x04\xb0g6\xa7\
\x1b\xddB6\xe7\xaa\x87}S\xb4\x17}b3\xd2e\
\xe0\xa3O\xf4\xaa\xcc\x7f\x998\x1b\xb7%V\xdd\xbf\xcc\
\x0d`\x0b\x80\x04X\x90R}\x1d\x1b\x94z~m\x8a\
?Js\xc8s \xbd\x88E/K\x0c\xf5\xfb,o\
w;\xcf\x1f*l\x06\x90\xc7\xf6\x172\x0dY\xa7\xb9\
\xff\x9eG{)\x00\xc0n\xaaG(\xbbF\xb6Z\xd2\
\x05\x0b1\x14\x07\x03~owe\xf27\xf7\x18\x80\
\x5cV\xef\xecmjs\xec`L\xd76W\xdeO\xa2\
:[\x11q\x07{\xe5b\x84kAT\xf5-S\x0a\
\x19\x19\x0c\x89'E3\x80\xb4-\x91K\xc4#\xd0Q\
m\xa3\xf15\xfe\xedAb[s\x88\xb8\x83~\xfe\xae\
\xd6KJ\xf82\x16\xe28\x22^\x15\xb0#/\xf8<\
A\xb5\x9c\x85\xd5\x9cB\xbf\x1aG\xa6\xea\xbey'4\
\xe0\xc4|\xb0\xb4\x0d \xa7Bs\xe9\xc3\x84\x85\x997\
K\xb6[\xd2\xd5\xe1\x7fG\x09\xee\xbc\xc4\xdd\xd4\x02\xb2\
\xfa\xdf{%X\xb2D\xa3}S\x02\x90\xc57\xe1?\
\xa3\xc3v\xd8\x98\xd5\x0c+\xab\xea\xc1\xd0D\xedl\xe3\
k\xfc[\xff\x831D\xc0D\xda\xc2u\xa1\x5c\x14\xd7\
\x01dwOwX\xfal\xfd\x1dS\x86\xe2r\x01J\
\xa0+\xb3~\x00\xa0#*\x06F36\xb95!O\
\x9f\xb9\xc1\xe3\x01\xba`:\x89\x06#\xae\x9c8\xf3\xfa\
\xcfu~S\xdc\xb5\x18y`\xa1G*$\x8cAI\
C\x90\x10\x14\xb36\xad\xab\x03\x9e<q\xcc\x877\xec\
\xd8~x\xcfE\x98N\xa2@\x98S/N\xb5\x08\xd4\
\xa3\x86e\x95\x8e\x15\x9d>\xa5\xb2\x85W\x94\xd4\xd7\x1b\
\xbc\xb0B]\x18p\xf7\xae\x1bx\x93\x95\x9d\xdb\x0f\xef\
\xbd8s\xdc\x0f\x99\xbbp\xb4\xf7\xafy\xf3\xc5I\x95\
\x882R\x0a[\x0a\xa2\xa0L\xb1\x5c\x12\xd7\x1f\x0f\xd0\
\x95?\xd3\xe5}\xcf\xf9%|\x05\xafW\x0di~8\
\xff\xf6\x00\x00\x00\x00IEND\xaeB`\x82\
\x00\x00\x02\xa0\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\
\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x02UIDAT8\x8d\x95\x92\xdfK\
\x93a\x14\xc7\xbf\xcf\xf3\xbes\xbfu\xb5\xad\xcd\xc0j\
\xd9\xca\x0a\x9aJ\x17\x82\xe9\x85At\x13]\xcd\x8b.\
B\xd2Z\xab\x94\x8c\xd0\xff@Q\xaa\x0b)\x0a\xd7+\
B?Xu\x11H\x10\x94\x18\xc4@\x84\x10-o\xcc\
r\x08C\x9c\xb6\xe9\x9an\xaf\xef\xbb=OWS7\
\xb4\xf2\xdc\x9e\xf3\xfd\x9c/\xe7{\x80\xff\xa8\x9e\x0e\xc9\
|\xff\xc6@\xd9v=\xfa/\xb1\xd4\x19\xf4X\x5cG\
\x7f\x95\xd4W\xcf\x05z?<\xde\x15\xe0\xc9\x9d\xa0G\
\xb6\xdbB\xe9\x0aw\x91\xf1\x84\x8b\x88\x95G\xae\x07z\
\xde\x07\xb6\xce\x08\x7f\xdb\xac\x94\xdaB\x89\xfaZ\x93Z\
\xa4\x832\xbf\x04k\xc5\x01dEM\xf5\x85S\xe7K\
\x87>\xbex\xb7#@\xea\x0cz\xd2\xfbl\xa1D]\
\xad\x09\x84\x00\x84@5\x99!\x8fN\xa0\xa4\xa2\x0c\xcc\
`8\x9d\x83\x90Bq\x7f\xfb\xe0IUo\x1c[9\
\xd7`\xa4\x89$\xd8~\xe7f\x93s\xe8'&QZ\
s\x1c\xa9\x1f\x11\xbe26^%\x14\x8a\xed<\xfb\xb6\
ZP\x9c\x8b\xe9\x0c\xd6\x1d\x0e`5\x05\x18t\xc89\
\xc98\x1d\x90\xbfLA\x94e\xd0\x85\xd4\x03\xa1P\x5c\
\xa7\xcb\xb8\xcd`\xb0%\x13\x88*\x1c\xeb\xc5\xc5 Y\
\x06\x88\x22@)@\x08\xf4\xd1EU3\x17\xf1\xfb{\
\xbd\xc3\x02\x00H>\xc9c\x13\xd9\xd0\x19]\xb6<\x17\
\x8b)\x07\xc9\x12\xc8\x06#\x08\x00\xae\xd5\xc2<\xf9U\
\xd5\xce\x86[}]\x8d\xfd\x00 H>\xc9\xe3\xd8\xab\
\x19\xad\x5cK\xd85E\x22\x08\xd9<\x8b\x09\x0c\xd6\xe4\
oD\x19\x85l\xd9\x03\xd3\xf7\x19U\x1f\x8e\xf8\xafu\
7nD)\x16\x8b\xecUM\x95MO\x88\x1dk#\
\xd3\xd0\x9bu\xa0t\x13\xe2\x84\x8a\xfa\xf9Y|\x8e-\
+T\xcd\xdc\xbc\xda\xed\x95\xb6\xde\x8df(\x86\xc3\x9f\
f9\xc0al8\x86tR\x06c</\x99%\x85\
\xcdkc\xcb\x97}]\xde\xa7\x85\xa9\x11\x00x\xd3\x16\
\x188\xa8\xac7\x95\x9f=L\x00\x92\xe7dJ\x15\x16\
fTt\xb4\xf4\xb5<\xdb\xeeg6\xbc\x06[\xa5\xe7\
\x872\xf2%w\x83\x8b\x00\x04\xab#\xd3\xf8\xa93F\
\xc3Y\xda\xd6\xdc\xd7\xfcz;q\x1e\x00\x00^\xb6J\
\xb7\x09g\x17\xb5V\x83%\x1dK\xc5\xe3T\xfc\xa6p\
\xc8\x00\xc09\x89\xdf}\xd8\xd4{\xef\xd6`\x87\xc0\xd9\
p\xfb\xa3+\xe3;AwU\x7f\x00 \xb3\xebsK\
\xbaY4\x00\x00\x00\x00IEND\xaeB`\x82\
\x00\x00\x01\xa0\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\
\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x01UIDAT8\x8d\xa5\x92\xb1O\
\xc2@\x18\xc5\xdf]\xaf\x16\x10\x16&\xc7\xaen\xc6\xd1\
A\xe3\xe2\xe2\xc2\x22\xbb\x09q\x22\x84\x90\xb0\xe8\x02\x03\
\x83\x09\xb1\x83\x9b\x83\xfd\x1b\x8c,F\xe3\xe4d\xe2\xe8\
`\x5c\x8c\x9a\xb8\xa8(\xd8\xd2r\xf4;\x175\x96\x83\
\x04\xe5%\xb7\xbc\xfb\xbe\xf7~\x97\x1c0\xa5\xd8\xb0\xb1\
W;^#\x8e\x8dQ\xc3\x8a\xd4\x9b\x87`\xa7V\xcb\
\xf7\xbf=1<4HY\xdbruyeT\x00\x7f\
|\xa2\xf4\xe9\xf9\x11\x80\x8b\x1fOg2\xc6\xf3\x0a\x83\
+\xcec\xa5z\xc0\x1f\xa5=\x01\x9cY\xb8\xb9\x05\xa5\
\xd3\xa0\x84\x05\xf1\xfc\x02\x00PB 2\x85\xb6\xa0\x05\
DD\x12]\xcf\xe7]/\x86\xc7\x00p\xdfW\x8a\xb1\
\x87i\xa9\xff/\xa7\xec\xdaN\xd9\xb5\x7f{\x02\x00\x0e\
\x9b\xadz2\x93\xa9\x82\xeb\xff\x02\x04\x15t>v7\
\xab\xebu\x8a0\xf7\xe5\xde\xc5\x02Hb\xc1^\x9aO\
\x8ek\xben].\x02\x00)$\x86\xef8\x00\x04^\
\xd0~}\xf71\xee\x04^\xd0n\x16\xdd\x1c#d\x19\
!\xdb,\xba\xb9\x18\xc1$\xe2\xe6\xec\x89\x92\xfe\x01\x00\
03\xb5\x15#\xe0\x86\x92\x14\xd1\xc8E\x8a\x08\xdcP\
\xb2\xe2\xe4{&\xeb\x14L\xd6)T\x9c|/F\x10\
\x86\x83\xc6\xfd\xd9\xd5\x0c)fi\xcdL\x85}9h\
\x00@i\xbf\x14NJ<\xb1>\x01\x07g\x8a\x88\x97\
b:g\x00\x00\x00\x00IEND\xaeB`\x82\
\x00\x00\x03\x09\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\
\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x02\xbeIDAT8\x8d\x8d\x91]H\
Sq\x18\xc6\xdf\xff\xff\x9c\xb3\xb3\x9ds6u\xf3c\
\xe1\xb4\x0f\x19\x14\x85\x22\x98\xd0\x85E\x04\xdd\xec\xca0\
#,M\x0d\x13\xc9\xc2\xe5GTxaA\x91\x8a4\
Y\xa9A\xf8\x05\x09^\x14R\xd0ET\x17\x19XH\
_f\x88b\xb3f\xe96\xf6uv\xb6s\xce<g\
]\xc4 \xa2Y\xef\xe5\xc3\xfb\xfc\xe0y\x1e\x04\xffq\
\xb7/O\x1e\xc5\x04\xda\xdb\xd8U\xd1\x9e\xd4n\x9d\x1f\
\xcdW\x11\x8a\xe3\x7f\x99\x87\xba\x1e\xf4[\xcbv\x0fs\
\x19\xfa\x03I\xad\xbbq4[Q\x95\xad\x09Q\xc5\x9b\
\x02\x9cMN.\xcdl\xb4\x99\xf2\xb3\x191*-\x01\
\x00t\xb7\x8e\xb2\x88\xda\xd8\xaf\xc4\x89\x05\xfb@\xcd\xea\
\xa6\x80\x04\x93~(\xab \xc7\x12\xf6\x86\x14\x89\x17\xa6\
\x00\x00\xb0\xb8Q\x1e1qSm\x03\xd5\x1e\x00\x00r\
3\x00\x9d\xc6U\x18\xccFjevi\x85\xf7\x87\x9f\
\xf44\x0fW]\xe8?5\xfe\xfb\xcf\xa6\x00\x1dG\x17\
`\x82\x00!\x10\xfe\xa6\xd1PG\xc2&\xd7H\xaf}\
\xa4\x98\xe6\xd8\xe3\x94\x96*\x8e\xc7\xe4y\x12\x00\xa0\xa7\
a0\x93\xceN?\x896\x90 K0f\xef\xab\x8c\
\xddh\x18L\xd3\x19\xf5\x16UU\x81\xff\x1141f\
c\xa5\x81\xc9mc\xaci\x16\xcel\xd4+\xb2\xa2\xae\
\xbe\xfc\xf0\x1c9\xaeL\x1ef3\xf4C\x14\xab5\x10\
:\x9a\x0e\xbb=K\x8a O \x02\x95[\xf7\xed*\
!\xb5\x14x\xbda\xc4\xe5f\x02\x00@\x5c\x10\x81_\
\xf5zy\xb7o\xda\xa3\xc6\x8f\x91ZV\xd7\x09\x18\x89\
\xbe\x05\x97\x8d\xa2ug\xf3\x0f\x165\x02F\x85\x11\xd7\
\x1a\xc4B\x11\x88\xb9EP4T\xe8\xfb\xccg\xb7\x12\
\x93\x5crLz\xa5\xf8\x85\x89\x96;u\xcb\xbf:H\
\xa8@j54\xc50'(\x0dU\x1a\xf5\x06\x03\xc2\
zp\x99@\xb0=\xafl\x8f\xf1\xe3\xe37\xef=+\
\x8b'Z\x1d\xf5\x9f\x10\xa0\xc4\x9f=a)*v\x8a\
!\x817X2kH\x96\xd6\x06\x16\xdc\x97\x82\xae\xb5\
>\x12\xa19UQ \x1e\x15_\xb79N\xcf\xfd\xcd\
\x0c\x00\x80\x9b\xafU>k\xb8h+\xf2\xbe],4\
\xccD\x0a\xa3~^`\xd2\xd9\xaf\x8cI\xbf\x0d#\x0c\
\x14K\x978\x9b\x9c\x5c\xaa\xa50\x00\x00\x02\x94h\x1d\
:\xe3s\xe7D\xaa[\x9d\xb5cl\x06w]\x8eI\
\xd2\xcc\xfd\x17O\xcdV\xcbN2\xdb|.\x15\x80\x04\
\x00p4\x8f\x1bd\x90m-\xfd\xb5\xc3v\xa8\x03Z\
\xcfl\xe1\xd7\x82\xb3\x91@\xb4C\xf0\xf3\xd3\x08\xe3\xdc\
\x94\x80\xde\xa6{yRB\xb6\xaaL\xe2Q2\xa7\xcc\
\x8b\xfe\xac\x1d9\xa5\xb4^\xfb\x10\x08\xac\x11\xf8\xe8\xdd\
\x94\x11\x14\x02k\x12*\x9a\xef\xb8Y\xcf'E>\x18\
l\x0fy\x82>\x82\xc0\xaa\xef\xcb\xfa\xd5\x96\xee\xaaw\
\xa9\x00?\x01\x9b\x11$Z\x9c*\xf5$\x00\x00\x00\x00\
IEND\xaeB`\x82\
"
qt_resource_name = b"\
\x00\x05\
\x00M\x843\
\x00I\
\x00C\x00O\x00N\x00S\
\x00\x0b\
\x03xr\xf4\
\x00I\
\x00C\x00O\x00N\x00_\x00I\x00N\x00S\x00E\x00R\x00T\
\x00\x0a\
\x04M\xd8\x05\
\x00I\
\x00C\x00O\x00N\x00_\x00P\x00A\x00S\x00T\x00E\
\x00\x0a\
\x04A\xb9\xe2\
\x00I\
\x00C\x00O\x00N\x00_\x00C\x00L\x00E\x00A\x00R\
\x00\x09\
\x04D\x1fY\
\x00I\
\x00C\x00O\x00N\x00_\x00C\x00O\x00P\x00Y\
\x00\x0c\
\x0c:\xcf'\
\x00I\
\x00C\x00O\x00N\x00_\x00A\x00D\x00D\x00_\x00R\x00O\x00W\
\x00\x08\
\x08D1<\
\x00I\
\x00C\x00O\x00N\x00_\x00D\x00E\x00L\
\x00\x0b\
\x03=o\x22\
\x00I\
\x00C\x00O\x00N\x00_\x00E\x00R\x00A\x00S\x00E\x00R\
\x00\x0b\
\x03\xfeB\xa4\
\x00I\
\x00C\x00O\x00N\x00_\x00A\x00P\x00P\x00E\x00N\x00D\
\x00\x08\
\x08D1\x04\
\x00I\
\x00C\x00O\x00N\x00_\x00C\x00U\x00T\
"
qt_resource_struct = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x09\x00\x00\x00\x02\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\xac\x00\x00\x00\x00\x00\x01\x00\x00\x0d\x90\
\x00\x00\x01zS6^R\
\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01zS7uY\
\x00\x00\x00\xc8\x00\x00\x00\x00\x00\x01\x00\x00\x104\
\x00\x00\x01zS7W\xda\
\x00\x00\x00F\x00\x00\x00\x00\x00\x01\x00\x00\x04A\
\x00\x00\x01zS6\x81\xb2\
\x00\x00\x00`\x00\x00\x00\x00\x00\x01\x00\x00\x06?\
\x00\x00\x01zS4|\xf0\
\x00\x00\x00,\x00\x00\x00\x00\x00\x01\x00\x00\x01\xd9\
\x00\x00\x01zS4\x9c\xfb\
\x00\x00\x00\xe4\x00\x00\x00\x00\x00\x01\x00\x00\x11\xd8\
\x00\x00\x01zS5\xa2\x1a\
\x00\x00\x00\x96\x00\x00\x00\x00\x00\x01\x00\x00\x0a\x9d\
\x00\x00\x01zS<\x13\xb8\
\x00\x00\x00x\x00\x00\x00\x00\x00\x01\x00\x00\x08\xda\
\x00\x00\x01zS7\x10Z\
"
def qInitResources():
QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
def qCleanupResources():
QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
qInitResources()

485
src/icons_rc.py Normal file
View file

@ -0,0 +1,485 @@
# Resource object code (Python 3)
# Created by: object code
# Created by: The Resource Compiler for Qt version 5.15.2
# WARNING! All changes made in this file will be lost!
from PySide2 import QtCore
qt_resource_data = b"\
\x00\x00\x02\xcd\
\x00\
\x00\x10\xbex\x9c\xed\x96]O\xd3P\x18\xc7\x8f\xf1\x0b\
x\xe55\x97~\x0c?\x10\x10\x89\x82\xc4\xa8\xf8\x82H\
D\xca\xc6X\xf6\xc2\xba\x96u\x08-\x03\x95\x898\xa6\
\xb8\xe1\x02\x0eXB$F\x19/\x09/\x91\x18I\xe0\
F'0\xf8{\xceY\x98\xb0\xce\xad\x1b\xa3za\x97\
\x7fO\xf3\x9c\xe7\xf9\xff\x9e\x9e\xf6\xa4#\xe4\x1c\xfdU\
U\x11v&\xfd\x17\x08\xb9H\x08\xb9DEC\xe42\
\xc9\xc4\xff\xd5C\xaa\x16\x92Ru;\xfe\x8e\x84\xe4\xef\
>\xda\x11UlYI5\xedp\xb5=\xe6b\xd7\xc7\
\xe7\x8c\xa8P=c\xe9\xd7A\x9f\xe3\x14\xda\xb8r\xe7\
\x0c\xf1\x0b\xd4\x1b\xe5WR\xe5\xf0\x1d\xf3?*\xa2\xd3\
\xf0\xfd\x0f|\xd9{P\xe8u1V\xbe|\xa3\xfcI\
\xd5\x9d\x15\xafO\xa6\xf8\xf8u:\x88\xe4\xe8\x00\xe4+\
\x16\x1e\x93\x1b]\xba\xf5\x95\xeb\xedP\x16\xbe\xf3\x1c\x96\
\xcbj\xb8\xc7b\xc6#\xd7;\x1f\x7ffH\xce\xcaw\
\xad\x13\x83\x9fw\xa0Z\x07\xd0{\xcb\x8d\xbe\xce\x00\xb4\
\xd0\x07\x0c\xad\xef\x16\x14\xcba\xb9\xacF\xb5\x06\x10X\
\xd8\xe1^\xc7\xbd\x8d\xf0\xb5\xfbn\xf4\xbf\x9c+\xca+\
\xa6\xfe\xd19h\xcd\xae\x92\xf9\xe3n7\x94;^\xa8\
\xe1\x8fP\x1e\xfa!\xd5Z\x0c\xbf\xebrm\x07\x86Z\
\xbc\x18~\x95\x80\xd2$r\xafR\xf93\x832z\x1b\
\xbb\xf0\xac\xd9\x8d\xd5\xa9\x18R\xabq\xec\xae\x84\xb1\xb7\
:\x01l/\x02;+t\x5c\xc2\xde\xda\x04\xdetz\
\x10\x12$\x8cY\xfd\x88\xb8T\xec\x7fKbcz\x12\
\xc1V/\xf5\xb0q\xaf\x92\xf9T\xaf\xed\xdd\x88\xfb|\
Ho\xcer^z3\x91\xb7\x87\xd4J\x14\x9f\x82\x1a\
\x16B#Ho-e\xe2T\xb3\xda0F;\x9c:\
_\xa3\xfc\x09\xc9\x83\xe1\x16\x07g\x16\xebao\xed\xdd\
\x89<\xa6`\xab\x88\xa8\xb7\xbbl\xfe{M\x82Rg\
\xc1\xcf\xe5p\xc9=\x1cn/\xf3Z\xe6Q.\x9f\xef\
\x83\x9b6\xacG\x9fr\xdf\x13=|I@\xa5\xcf\xb6\
\xaf\xc1\x8a\x83\xad\xa4\xae\x87\x8d\xa90\x06n\xdb\xf3z\
\x96\xc2\x1fwuC\xbd\xd1\xc5{H-\x8d\xe5\xac\xc3\
\xacn\x1d\x0e\xb6\x16\xb1\x1e\x1b\xa156\xdd{_\x0e\
\x9f)\x22z\xa159\xe8\xbe\x12\x8a\xee\xbd\x1e\x9a3\
x\xd7\x85\xb7\xb4\xe6O~\xa5\xf2+\xad\xff\xfc\xfc|\
3\x95\x8f\x7f\xdao\x8dQU\x82\xaf\xd2\xef\xec\xd1\xbd\
\xa8\xa1y\xd3\xf9\x95\xba\x7f\xf9\xba\xf8B\xaa\xee84\
\xfb\xf93\xa6\xdc(\x06\xa5\x1a\xe1\xc0c\x89\xc0c\x8b\
\x99+\xcadl\xfe\x7f\xc19\x05OW\x0cR\x9d\x9d\
\xcf\x89\xf7\x02\x5c\xec\xfaLb\x94\xc5\x98Gk\xd1\xd7\
\x93\xe0\x92\xaf:\xf8\xe8\x7f\xf4\x9c\xeb,cL\x19\xbe\
\x90~\xe2\x8dgc\xa6I\x8cs\xb6\xaf\xc1\xe9g\xa3\
\xf9\xef\x9f\x90\x96\xeb\x9d\xfe\xdc}h\xf6\x01z\xb01\
B\xc8\xf9\xb3R!\xf6/K\x03R\xae\
\x00\x00\x03\x06\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\
\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x02\xbbIDATX\x85\xed\x96MH\
TQ\x14\xc7\xffw\xde{\xf3\x1c\x99\x9cQ\x89\xacQ\
H#\xb1\x8dA\xd0\xa6(Z\x88\x8bV}\x80\x18A\
`-\xda\x88\x8bhhQ\x0bi\x13H\x13-j\x11\
DJ\xb9h\x13T`\x0b\xc9\x08\x22%\xda\xb8I\xa1\
\x01E\x19t>\x9cy\xce\xe7\xfb\xba\xef\x9d\x16\xe5\x90\
\xf9&Q\xe7\xd5\xc6\xff\xee\x9c{8\xff\xdf\xbd\xe7\xdd\
\xcb\x03v\xf5\x9f\xc5\x1e\xf4\x0f\xdf\x03\xe8&\x81\x89N\
\x05\x1e\x86\x12\x81\x9e\xe6\x1a\xfd\xe1\xc1\xc1\x1e\xc3\x05\x80\
g\xe6\xc9c5\xa2(0\xc7\x02\xd3$\xcc\xcc\xf1l\
\xa1\xc4\xa73A\x7fw\xb5!<\x04V\xd1\x1c\x00$\
\x89\xa1\xb3]\x0a\xd4\xfb\xc5\xd3\xfbK\xea\xcc\xe8\xe0h\
s5\x01X\xa4\x7f\x98\xce\x1c\xaf\xd9\xb4\x90\x880\x1f\
\xe3XJ\xda\x16\xb7I\xd8\x92\x09\x88\x83\xd8\xd0\x8d\xc7\
}\xb7\xff\x5cs\x9c\xbbc\x13\xc6\xd0\xd6\x22\xa1\xad\x05\
[2\x07\x00\xce!~\x9e\xd6\xc3\x006\x00x\xb6\xda\
l;\x12E\x80\x88$\xa7\xb5\x7f\x02\xf07U\x1c\x81\
\xaa\xd9\xf8\xbe,@I\xab\x00U\xc7,\xd2?\x5c\xee\
$y\x05\xdd2\xe8|E\x80\xa5\xac\x17\xedG\x9bq\
\xa2\xbb\x03\xccS\xf9\x96lW\xdf\xbe.\xc8S\xefg\
\xef8\x03\x10\x90L\xaa\xe8\xea\x09\x82\x1bJ\xd5\xcd\x01\
`%\x9e\xb2\x8ay\xfd\x93\xe37PP\x09\xb2,\xc2\
\x1f\x90]1\x07\x80\xc5\xa8R\xe0\x86=\xe1\x08\x90+\
\x12B\x87\x82\xae\x99sn#\x9d*\xf9\xc8'L:\
\x02\xe4U\x86\xe6\xd6z\xd7\x00\x96\x17r\x90$!\x1a\
\xbe\x7f\xa5\xb8\x11\x80\x80L\x96#t0\xe0\x1a@l\
^\xb1,\xd3\x1e\x03\x1c\xde\x81\xa2F\xf0\xca\x22\xf6\x04\
7\x7f\x9e\xb7\xab\x85h&oY\xf6\x84#@\xb6`\
#\xd4\xe6\xde\xf1s\xd3F:Y\xaa5}\xd6\x94#\
@^\x13\xd0\xd2\xea\xde\xf1\xc7c?\xe7\x7fk\xe8Z\
~#\x00\x01\xca\xaa\x89P\xab{7 6\xb7jq\
N\xef\xd6\xe2u\x0fQQ#h\x9a\x85\x91\xc8\x97\x1d\
\x1b\x05\xebe\xf4^?\x82\x97Of\xb1\xaa\xe8\xe5x\
1\x9a\xd2\xb8iN8\x02\xe4\x8a\xc0\xe1\x0e?Nu\
5\xee\x18\x00\x00\x8c\x82\x82\x0b\x97\x9b\xca\xb1\x9a\xcd \
\x9d\xd0j\xacZ\x9a\x5c\xcb\xad\x1bA\xc1`h\x0a\xc9\
\x18\x7f\x9bD6c\x22\xb1\xa4\xe3\xe3\xf8\x0a\x00T%\
\x97J\xe8\xf0\xfa\x84\xd8\xda\xfc\xd7\x03\x10\x90\xce\x98\xd8\
w@\x86\xa6Z\xf0\xd7\x89\xc8fM4\xee\xf5\x02@\
Ur\xf1\x98\x01n\xd0\xeb\xdf7\xcd\x1e\x0e\x8c\xa4;\
\xdb\xa5\x06\xdd \xc4s\x1e\x9c\xebm\x82\x1b\xd25\x1b\
c\xaf\x12VF\xd1\xbb\xc3\x8f\xae~(\x03D\x06\x9e\
\x9f\x15`\xbf\xb0ljp\xc5\xf9\x97\x04\x81\xd9u\x01\
\xef\x9b\xbe\xbb\x97.2\xb0*\xfda\xecjWU\xd0\
\x0f\xde\xf6\x5c(\x8d\x8f\x0c\x87\x00\x00\x00\x00IEN\
D\xaeB`\x82\
\x00\x00\x03s\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00 \x00\x00\x00 \x08\x03\x00\x00\x00D\xa4\x8a\xc6\
\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\
\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\
\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\
\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x01\x0e\
PLTEGpL\x90r\xa4\x8el\x9f\x8em\xa0\
\x91q\xa3\x8el\xa0\x8en\xa1\x99f\x99\x93s\xa3\x93\
t\xa3\x80\x80\xaa\x93s\xa2\xac\x92\xb1\xad\x93\xb1\x92t\
\xa2\x8el\x9e\x94u\xa4\xad\x92\xb1\x93s\xa3\x92s\xa1\
\xaa\x8f\xb0\x93s\xa3\x92m\x92\x94t\xa3\x95t\xa4\x93\
r\xa3\xab\x8f\xaf\x94r\xa2\x93s\xa2\x93t\xa2\x8em\
\x9f\x8em\xa1\x96\x7f\xaa\x8fm\xa0\x95\x80\xab\x8dl\x9f\
\xbe\xc7\xe2\xc2\xcd\xe7\xc4\xce\xe8\xcc\xd8\xec\xc8\xd3\xea\xce\
\xd9\xed\xc6\xce\xe6\xc3\xcf\xe8\xcd\xd7\xec\xcb\xd6\xeb\xc3\xcd\
\xe7\xc6\xd0\xe8\xd6\xdd\xed\xc8\xd2\xe8\xe4\xe9\xf1\xeb\xef\xf3\
\xd7\xdf\xee\xd3\xda\xec\xe4\xea\xf2\xd0\xd9\xed\xd2\xda\xed\xca\
\xd6\xec\xc2\xce\xe7\xf5\xea\xdb\xf8\xec\xdd\xf7\xeb\xdc\x92s\
\xa4\xd0\xbd\xc6\xfa\xef\xde\xcb\xd6\xec\x92u\xa4\xd1\xbd\xc6\
\xcd\xd5\xea\xc3\xce\xe8\xe0\xe6\xf0\xd3\xdc\xed\xc5\xcf\xe8\xe2\
\xe8\xf2\xcf\xd9\xed\x97{\xaa\xb1\xa9\xcb\xac\xa5\xc9\x95z\
\xaa\xab\xa3\xc8\xc1\xcb\xe1\x93x\xa7\xb4\xc0\xd8\xa2\x9a\xbf\
\xb2\xbd\xd7\x93w\xa7\xb9\xc5\xde\xaa\xb1\xcc\xac\xb7\xd0\xff\
\xff\xff\x0b\x1c\x81T\x00\x00\x00#tRNS\x00\x8f\
\xfc\xfd\x8e\xfc\xfb\x05\xb6\xb6\x06\xb8\xf4\xf5\xbba\xf9\xf5\
\xba\xb8\xf5\xbf\x07\xb7\xb6\xb9\xf5\xbe\xba\xb5\xfd\xfc\xb1\xfe\
\xb0c\xd5%\x08\x00\x00\x00\x01bKGDY\x9a\xb2\
\xf4\x18\x00\x00\x00\x07tIME\x07\xe4\x01\x07\x007\
\x14kk\x96t\x00\x00\x013IDAT8\xcb\xad\
\x93W[\xc20\x18\x85\xab\xa8A\xa5\xee\xbd1\xa65\
\xb6\xee\x8dUP\x01QAPP\xfc\xff\xbf\xc4|\x19\
5\xa3wz.rs\xde\x9co\xe4\x89\xe7\xfd\x83\x06\
\x06\xb1\xa5\xdc\x90\x01\x0c\xef\x10\xa9 \x0c\x03\xb2K\xe9\
\xde\x88\x01`\xe5Gq\x1c\x81\xbf\x7f\x803\x81_?\
r\x81\xc3#\xdd\x8f\x1d\xe0\xf8\xe4\xf4L\xf3\xa9\x9bp\
~q\xa9\xf9\x19@t\xa5\xfb.\xa0\xd7\xa7\x02@\xf9\
\xd1\xb1\x14P\xf3_\x97\x82\x90\x0a\x00\x8d\x17\xfc\x09I\
`\xfb>eSLN\xdd$\xd33\x82\xc0\x8e\xcf\xf6\
\x80f\xe7n\x13\x7f~A\x00\xc2\xbf\xb3^\xa4\x5c\x91\
\x19\x98\xd7\xbf/\xe1\x8a\xa3\xc4_\xe4M\xca\xfdf\x01\
K\x00\xc8\xfa\x0fV\x89GVb\x19\x01\x00\xf9r>\
6.\x08\x9a\x5caM\xae\x8a&\xf5\xfe\x89\x04\xf8\x98\
\xfc>\x03\x0c\xbfZ\x95\x09\x05\x7f\x0d\xc9E\xe9\xf9\xb5\
z\xbd\x06\x80\x87\xd6\xf3\xc8K7I\xe9\x93\xcao4\
x\x82\xf1X\xe0?\xbf\xa8\xfa\xc4\x05 \xde\xf0\xb3\x00\
\xc3w\x80W\xdal\x917\xd2n\xab\xc3\x02:\xef\x1f\
\xddn\xef\xb3\x97\x1e_&\xb0\xd1\xff\xb6\xd4\xdf4\x80\
\xad\xa2\xfd\xf5\x8a\xdb\x7f\xfa\xcb\x96~\x00\xc4Fm\x1c\
q\x94\x90\xba\x00\x00\x00%tEXtdate\
:create\x002019-11-\
14T21:30:38+00:0\
0-z\x13x\x00\x00\x00%tEXtdat\
e:modify\x002019-07\
-15T18:11:24+00:\
00M\xa4\x9d&\x00\x00\x00\x00IEND\xaeB\
`\x82\
\x00\x00\x03\xe2\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00 \x00\x00\x00 \x08\x03\x00\x00\x00D\xa4\x8a\xc6\
\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\
\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\
\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\
\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x01G\
PLTEGpL\x80\x80\xaa\x92t\xa3\x91q\xa2\
\x8em\xa0\x8fn\x9e\x91r\xa2\xa4\x90\xb4\x8fn\xa0\x99\
f\x99\x92q\xa1\xa3\x8d\xb4\x92r\xa2\xa4\x90\xb5\x90p\
\xa1\x94k\xa1\x8em\xa0\x8cn\xa0\x8aj\x9f\x84\x8b\xa5\
\x8dm\xa0\x90o\x9b\x85\x8a\xa4\x8cn\xa0\x92m\x92\x8c\
r\xa0\x8cl\xa1\x8bp\xa0\x8dk\x9f\x8fm\x9f\x83\x8b\
\xa4\x8dn\xa0\xa1\x84\xae\x8fn\xa0\x87\x8d\xa5\x8cm\xa0\
\x8fp\xa3\x8cq\xa1\x8dl\x9f\xfa\xef\xde\xfc\xf2\xe5\xff\
\xf7\xee\xfb\xf1\xe1\xff\xf7\xf0\xfd\xf4\xe9\xf3\xe7\xdd\xbb\xdb\
\xf6\xff\xf7\xef\xfb\xf0\xe2\xfb\xf1\xe2\xff\xf6\xef\xbb\xde\xf9\
\xfc\xf6\xed\xfc\xf3\xe8\xbb\xdc\xf7\xb8\xd5\xf2\x8fo\xa2\xfe\
\xfd\xfa\xff\xfb\xf7\xfc\xf4\xe7\x8fn\xa1\xb8\xa9\xc1\xff\xf8\
\xf1\xfb\xf1\xe3\xfe\xfc\xf8\xff\xfd\xfc\xff\xf8\xf3\xfc\xf3\xe6\
\xff\xfd\xfb\xff\xf8\xf2\x9e\x7f\xa9\x9e\x80\xab\x9d\x7f\xa9\xff\
\xf6\xf0\x9d\x7f\xa8\xd7\xc6\xd3\xf5\xea\xe4\xf8\xec\xdd\xdb\xca\
\xcc\x9b\x82\xa9\xda\xca\xcc\xf3\xe8\xe2\x90r\xa1\x8fq\xa1\
\x8fu\xa2}\xa4\xa8\xbb\xa4\xb9\x89\x8f\xa7t\xc5\xaes\
\xc4\xaer\xca\xaf\xff\xf9\xf4\xf5\xeb\xe4\x91s\xa2u\xbd\
\xadv\xbc\xac\xff\xf7\xf1\xff\xfc\xf9t\xc6\xae|\xa4\xa9\
\xce\xbb\xcd\xcd\xba\xc9\xcb\xb7\xc3\xf7\xec\xdd\xf7\xed\xea\xf1\
\xe4\xd9\x90q\xa1s\xc6\xae\xff\xff\xff\xb9p\xe8\xbe\x00\
\x00\x00&tRNS\x00\x06\x96\xf6\xfb\x86\xb7\xf7\xfc\
\x05\xb6\xf7\x96\xf7\xf6\x13\xfe\xf6\x18\xf4\x93\x17\xf4\xf9\x07\
\xf6I\xdcJ\xfd\xf5\xf6\xa0\xfd\xfa\x94\x19\xdb\xae+\xb7\
l\x00\x00\x00\x01bKGDl\xcc\x010;\x00\x00\
\x00\x07tIME\x07\xe4\x01\x07\x007\x14kk\x96\
t\x00\x00\x01fIDAT8\xcb\x8d\x93\xe9W\x82\
@\x14\xc5\xb1}'*#\xccl\x9fA\xa1\xc5h\xdf\
\xcc\xca(\xcb\xa5\xd4\x04*\xb3\xd46\xff\xff\xef\xc10\
\xc8\x0c\xe89\xdes\xe0\x03\xf7\xf7\xde\xbbo8\xc30\
\xdd*\xd0\xd3\x0b(\xf5\xf5\xd3\xfe\xc0 \x80Hb4\
&J\x92\x0c7\x86H\x7fxdt\xd3\x06\xc4\xadm\
\xe4\xc7w\x80\xc7W\x00\xedK\xc0\xe3[\xc0\xee\x9e\xeb\
\x93\xc0\xd8\xf8\xbe\xa2\x1c\x1c\xc2\xd8\xd11\xf2\xe3'\xa6\
O\x02\x13V\xea\xd33(\x9e#?q\x91\xbc\xa4\x01\
'?\xee\x7fu\x9dL\xb5\x03\xdc|)\xab\x81\x0f \
\xf2\xdb\xf2\x007\xce\x09\xaa\x92j>>\xc0W\xef\x01\
\xc4\xe8-p[\xf8\x816\xf5\x92L\x02\xf8\xff\xc4\xef\
\x08\x1f\x92\x80Y\xaf\x02j\x86\x0c)\xa0M=\x0d\x98\
_\xd2N\xfd\xbd\xe9?d\xb2\xb9<`\x09\x80\xce\xf7\
\xf8T(\x96\x8a\x93\xdcT\x0b\xf0\xf8\xcfeM7t\
mz&\xd8:\x074\xff\xc5\xf6_\xdf\xca\x15\xc3\xd2\
\xfb,\x87\xa7\x00T_\xfd\xa8\xa2|\x99\x82f\xd8\xfa\
\xe4\xe70@\xe5\xcf\x16u\x0chB\xa8\xb5\x05\xb1_\
\xaed8\xaa\xcd;\x80*\xd5\xeb\xd6\xab\x01\xd30O\
t\x08{\x80\xc6\x97\x09|\xfb3,\xfc\xb8\xe7\x07\xe1\
\xef\x1f\xde\xa2\x12Y\xc4[,-\xd3\xb7\x0e\xac45\
CoFV\xd7:\xdc\xd3 \xc7\x0b5\x81\xe7:\xf9\
\x0c\xc3\x06B\xeb\xe1\x00\xcbt\xa3\x7f\x90\xb4\x83\xa9\xe1\
\xcf\xeb\xaf\x00\x00\x00%tEXtdate:\
create\x002019-11-1\
4T21:30:38+00:00\
-z\x13x\x00\x00\x00%tEXtdate\
:modify\x002019-07-\
15T18:11:24+00:0\
0M\xa4\x9d&\x00\x00\x00\x00IEND\xaeB`\
\x82\
\x00\x00\x03G\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00 \x00\x00\x00 \x08\x03\x00\x00\x00D\xa4\x8a\xc6\
\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\
\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\
\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\
\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x01\x1a\
PLTEGpL\x90r\xa4\x8el\x9f\x8fo\xa1\
\x91r\xa5\x80\x80\xaa\x8el\xa0\x9a\x85\xb2\x8eo\xa2\x9c\
\x87\xb3\x8eq\xa1\x92m\x92\x8dn\xa1\x91q\xa3\x91r\
\xa3\x8dl\x9f\xbe\xc7\xe2\xc2\xcd\xe7\xbb\xde\xf9\xc2\xe1\xfa\
\xc9\xe4\xfb\xbc\xdf\xf9\xd7\xec\xfe\xde\xf0\xff\xd9\xed\xfe\xbd\
\xdf\xf9\xc4\xe3\xfb\xde\xef\xff\xbe\xc5\xe1\xbe\xdf\xf9\xcd\xe7\
\xfc\xd1\xe9\xfd\xdd\xef\xff\xc1\xe1\xfa\xbf\xe0\xfa\xdb\xee\xff\
\xb4\xab\xca\x91q\xa1\xb5\xab\xca\xc1\xcb\xe5\xbc\xde\xf9\xce\
\xe8\xfc\xc9\xe6\xfb\xc7\xe4\xfb\xd7\xed\xfe\x90o\xa0\xee\xd9\
\x9c\x90p\xa1\xcb\xe7\xfc\xc0\xe0\xfa\xc3\xe2\xfa\xff\xeb\x9b\
\xd6\xec\xfe\xc0\xcb\xe6\xda\xee\xfe\xd5\xeb\xfd\xbb\xdf\xf9\xca\
\xe6\xfc\xbd\xc4\xe1\xd6\xeb\xfe\xbe\xe0\xf9\xc3\xe3\xfa\x8fo\
\xa1\xd0\xe8\xfd\xc2\xe2\xfa\xbe\xe0\xfa\xda\xef\xfe\x91r\xa2\
\xa6\xa4\xc7\x8fn\xa1\xd8\xe6\xf8\xd7\xeb\xfe\xd1\xea\xfd\xb8\
\xd5\xf2\x8eo\xa2\xaa\x9f\xc5\x8en\xa1\xa6\x9c\xc2\xa8\x9c\
\xc2\x8fn\xa0\xa9\x9c\xc2\xf2\xe6\xd9\xfa\xef\xde\xf2\xe5\xd9\
\xed\xa3\xa1\xeb\x96\x97\x9d\x7f\xa8\xcb\xb7\xc3\xf2\xe0\xc8\x9c\
{\xa4\xef\xd8\xbe\xc5\xaa\xb1\xbf\xc6\xe2\xff\xff\xffSw\
\x1fW\x00\x00\x00\x0ftRNS\x00\x8f\xfc\xf6\x96\x06\
\xfc\xf1\xb7\xf2\xbc\x07\xfb\x8e\x8d\xdc\x9b\x9e\xcf\x00\x00\x00\
\x01bKGD]\x9d\xdf0\x01\x00\x00\x00\x07tI\
ME\x07\xe4\x01\x07\x007\x14kk\x96t\x00\x00\x01\
\x0fIDAT8\xcb\xbd\xd3\xd9R\xc20\x14\x06`\
\x14,\xee\xc7D\xf0W\xdcjU,*\xb8#n\xe0\
\x86\xbbVk\x15,\xbc\xffs\xd8t\x1cI\x9b\x5c\xb8\
\xcc\xf0_d2'\xdf\x9c\xc92I$\xba\x92\x9e^\
R\x92L\xf5u\x801\xc6\x18q>\x9e\xc9N`r\
*7\x0d\x80f\xd2\xfd\x1dAL\x80\xd99>\x0fs\
\xc1Z\x5cZ\xce\x83\xd8\xca\xc0\xe0P\x04\xd8\x05{\x15\
X\xb3\xd7Q,m\x04@\x16!\xd8\xdc\xda6Q\x08\
\x9a\x80vhW\x94\xf6\xd2)\x19\xe4\xac2\xf6+\x07\
\x08\x81%J\xec0)\x83\xca\x11\xca\xc7'b\x83\xc5\
R\x95\x87\x80\x91\x0cj0O\xcf\xce\x83u\xe4/.\
5\xa0~\x85L\xf6Z\xac\xe3\x86\xf3\xdb;\x05\xdc\xd7\
\xe5kzxT\x806\xbf\x02ON\xf4-\x9c\xe7\x18\
p^\xdcH^\xab\xf1c\xba\xb1\x90\x0a\xbc\xb70^\
0\xf1\xb4\xe0\xa7\x1dD\x0f\xf7o\x1d\xfe\x0d\xde\xddF\
C\x1a\x14\xd0\xfc\xf0[-\xff{h*\xc0\x8fE\x06\
F[\x0f\xda\xc3_`\xc4 m\x8c\xd1\xee|\xdcO\
b\xe8h\xa5Q\xd4)\x01\x00\x00\x00%tEXt\
date:create\x002019\
-11-14T21:30:38+\
00:00-z\x13x\x00\x00\x00%tEX\
tdate:modify\x00201\
9-07-15T18:11:24\
+00:00M\xa4\x9d&\x00\x00\x00\x00IE\
ND\xaeB`\x82\
\x00\x00\x02\xbb\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00 \x00\x00\x00 \x08\x03\x00\x00\x00D\xa4\x8a\xc6\
\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\
\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\
\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\
\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x00\xc3\
PLTEGpL\xff\x00\xff\x8cq\x9f\x8br\x9f\
\x8cn\x9f\x8at\x9f\x8bn\x9f\x89t\xa1\x87~\xa2\x8a\
t\x9f\x8dm\x9d\x8au\xa0\x8el\x9f\x8dk\x9f\x82\x92\
\xa5\x82\x91\xa5\x8cl\x9e|\x8a\x9e{\x8a\x9e\x8aq\x9f\
\x8bq\xa0\x8cp\x9e\x84z\x9e\x85z\x9e\x8bo\x9f\x8c\
n\x9e\x8ao\xa0\x8dl\x9f\x8cl\x9f\x8br\xa0\x8cq\
\xa0\x8cn\xa0\x8cn\x9f}\xa1\xa8\x8bk\x9e\x8cr\xa1\
\x8cs\x9f\x8bp\xa0\x8dq\xa0\x8cp\xa0\x8co\x9f\x8d\
m\x9f\x8at\xa0\x89v\x9fx\xb5\xabs\xc6\xaes\xc4\
\xaer\xca\xaf]\xbc\x9d`\xb6\x9eh\xa9\x9e`\xb8\x9d\
\x8dl\x9ft\xc4\xaeu\xc3\xaey\xb3\xabu\xbe\xads\
\xc8\xaf}\xa2\xa8\x8ay\xa1`\xbe\x9fq\x9a\x9e\x86w\
\x9fa\xb6\x9d\xff\xff\xff\xbe\xa83/\x00\x00\x00,t\
RNS\x00\x01j\xed\xfd\xecr\x9a\xfc\x98/\xfb-\
r\xfe\xfeq\xf5\xf4\xf5\xf4\x9b\xf3\xf3\x9ad\xe3\xfco\
\x8f\x8e\xfb\xee\xfe7\xa8\xd0\xec\xfa\xfa\xef\xfd\x96\x95\xe7\
\x83\x7fy\x00\x00\x00\x01bKGD@\xfe\xd9\x5c\xd8\
\x00\x00\x00\x07tIME\x07\xe4\x01\x07\x007\x14k\
k\x96t\x00\x00\x00\xbdIDAT8\xcb\xed\xd1\xd7\
\x0e\x820\x14\x80\xe1\xa2\xa8\x08\xee-8X\x8a(R\
\xc0*C\x90\xf7\x7f+%\x12$\x81\xd6q\xed\x7f\xd1\
\x9b~\xe9I[\x00\xbe\x89\xaaT\xe9Z\x9d\xc2\x83\x06\
c\x1c\x0d\xa6\x89\xddg9\x13Bhr-\x1chw\
`R\xb7\x87\x05}+i\x80\x05\xec\xd0~\xec\xdb#\
\xec\x080\x9e8'g:#\xdcs\xce\x0b\xfc\x82p\
MbK\x01\xa5\x09\xabR \x9ca\xdae]\x0a\x10\
\xccB\xbf\x01Qr=\x9f\x04dE\xddlI 7\
\xe6\x0f\xde\xbd\xa4\xf6\x04\xdaFU\xe4\x02\xd8\xbd\xfe\xc2\
\xf7\x5cI,9>\x08\xe05[\x8acP\x18E\xd6\
\xcdJ\x97\xb0\x08\xf4\xd8\xca\x15\xd3\x05\xb0\xd7Q.\xfd\
\x00>\xed\x0ehs3\x98p\xeef\x9d\x00\x00\x00%\
tEXtdate:create\x00\
2019-11-14T21:30\
:38+00:00-z\x13x\x00\x00\x00\
%tEXtdate:modify\
\x002019-07-21T07:5\
8:48+00:00=s\x85\xdd\x00\x00\
\x00\x00IEND\xaeB`\x82\
\x00\x00\x025\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00\x10\x00\x00\x00\x0c\x08\x03\x00\x00\x00\x5c9\xcd\xb3\
\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\
\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\
\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\
\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x00{\
PLTE\xff\xff\xff\xb2\xda\xb51\xd0?.\xd0<\
7\xd2E\xad\xec\xb2\xe1\xf8\xe3\xa6\xeb\xac4\xd1B\x89\
\xe4\x91U\xd8`\xa0\xe9\xa6\xeb\xfa\xeco\xdeyv\xe0\
\x7f\xf2\xfc\xf2\x93\xe6\x9a\xe5\xf9\xe6|\xe1\x85\xdb\xf6\xdd\
\x96\xe7\x9d\xca\xf3\xce\xb0\xed\xb6\xff\xff\xff\xcb\xf3\xce\x7f\
\xe2\x88\xde\xf7\xe0\xb4\xee\xb9\xc4\xf1\xc8\xba\xef\xbfr\xdf\
|\xfb\xfe\xfc\xd1\xf4\xd4\xd8\xf6\xda\xf8\xfd\xf9b\xdbl\
\xb7\xef\xbcR\xd8];\xd3Hb\xdcmh\xddr\x00\
X\x0c}\x00\x00\x00\x01tRNS\x00@\xe6\xd8f\
\x00\x00\x00\x01bKGD\x00\x88\x05\x1dH\x00\x00\x00\
\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\
\xa8d\x00\x00\x00\x07tIME\x07\xe4\x01\x07\x007\
\x14kk\x96t\x00\x00\x00qIDAT\x08\xd7]\
\xce\xd1\x0e\x820\x0c\x05\xd0\xb2\xab\xa0\xa2\xe0\x809`\
\xc8\x00\x19\xf2\xff_h%3\x994i\x9a{\xda\x87\
\x12E\x02a\xed3\x88\xf3\xe1\x18\xc7\xc9\x09\xe7\xcb\x06\
\xdc\xe9\xf5\x96\xe5w\xc8\xe2\x07e\x05$\xea\xa1u\xed\
\xe1\xbb\xaadp!\x1b\x866\x00e\x80\xee\x19@o\
\x87qz\xa1\xcbg\x0fpEj\x1d\x96\xb7\x03\x04\xf9\
\x7f\xcc\xba\x0d\x11\xd1\xdf\x9b\x9c?>\xbe\x06\x7fR \
a\x1c\x00\x00\x00%tEXtdate:c\
reate\x002019-11-14\
T21:30:38+00:00-\
z\x13x\x00\x00\x00%tEXtdate:\
modify\x002019-06-1\
3T12:59:26+00:00\
\xc7\x190\xe3\x00\x00\x00\x18tEXtSoft\
ware\x00paint.net 4\
.1.6\xfdN\x09\xe8\x00\x00\x00\x00IEND\
\xaeB`\x82\
\x00\x00\x02\xbf\
\x89\
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
\x00\x00 \x00\x00\x00 \x08\x03\x00\x00\x00D\xa4\x8a\xc6\
\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\
\x00\x00\x00 cHRM\x00\x00z%\x00\x00\x80\x83\
\x00\x00\xf9\xff\x00\x00\x80\xe9\x00\x00u0\x00\x00\xea`\
\x00\x00:\x98\x00\x00\x17o\x92_\xc5F\x00\x00\x00~\
PLTE\xff\xff\xff\x80\x80\xaa\x93s\xa2\x8dl\x9f\
\x8fn\xa0\x8fn\x9e\xa7\x92\xb3\xfa\xef\xde\xfc\xf2\xe6\xff\
\xf7\xf0\xfb\xf1\xe2\xfd\xf4\xe8\xf3\xe8\xde\x99f\x99\xba\xde\
\xf9\xff\xfd\xfb\xb2\xdc\xf7\xff\xfa\xf6\xb3\xae\xc7\xff\xff\xff\
\x85\xcb\xf8\xe7\xf5\xfe\x95\xd2\xf9\xef\xf8\xfe\xbf\xe4\xfb\xda\
\xef\xfd\xc4\xe6\xfc\x88\xcc\xf8\xed\xf7\xfe\x8cr\xa0\x8co\
\x9fr\xca\xaf\x86\xcc\xf8\x9b~\xa9\xf7\xec\xdd\x87\x8a\xa4\
s\xc6\xaes\xc8\xaf|\xa7\xa9\x9f\x81\xac\xcd\xb9\xc8\xf7\
\xed\xeaP\xc6\x9ah\x00\x00\x00\x01tRNS\x00@\
\xe6\xd8f\x00\x00\x00\x01bKGD\x00\x88\x05\x1dH\
\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\
\x01\x00\x9a\x9c\x18\x00\x00\x00\x07tIME\x07\xe4\x01\
\x07\x007\x14kk\x96t\x00\x00\x01\x1cIDAT\
8\xcb\xad\xd3\xedn\x83 \x18\x05`\x15\x06E7\xa4\
\x15\xf1\x93Yu\xb6\xee\xfeo\xb0\x80\x9d\x02cK\x96\
\xec\xfcP\x93\xf3\xc8\x8bQ\xa3\xe8\xbf\x12'\x09p\x02\
_\xbc\x1e\x01lr\x22\xe9\x89\x90\x0c\xbfB\xbb\x7fK\
\x10\x05N\x9f\x12\xe0\xf5\x06\xa4Go\x03\xd3k@\xf2\
\xadOUo\x03\xd33\x88qv\xde\xee\xcf\xcf\x1e0\
\xbb\xbe\xec\xf3I\x91\xbb\xc0\xdb\x7fJ\xf4\x02\xdf\x81\xb5\
?\xe2\x83p,\xc0C\xf9+(\x85(9\xa5\x9c\x8b\
\xaa\xa8D\x00\xd4MS\xf3\xb6U\x17-oi\x00t\
}\xd5\x19\xc0\xca\x9a\x85FtU\xbf\x01\xce\xdaR\x09\
\x09\xc0{x\x04U#ju\xff0\x00\x074BT\
\x9c\x16E\xaf6\xd9\x8b\x00P\xb9:\x0f\x19\x00\xfcg\
\xe0ed\x17\xa6A\x0c\xe2'\xf8z?:\x19\xc6\x13\
\x92H\x03)\xe5&\x80\xdbc4\x7f\xcc\x1a\xa8\x93\xf4\
\x81\xee\x15X\x96\xdb0\xdc\x96e\x07w\xb2\xae\xe6\x80\
G\xbc\xae\x13\x9c\x97AE\xf5q\x10\xe0\x11i\xb1\xf7\
\x11\xfc\xb4\xd67\x99\xf4\x94\xbd\x8f\xee0\xf0=\xcdG\
\x1f\xfeW\xe5\xef\xfd\x91\x07\x10E&Q3\xe4w@\
\x00\x00\x00%tEXtdate:cre\
ate\x002019-11-14T2\
1:30:38+00:00-z\x13\
x\x00\x00\x00%tEXtdate:mo\
dify\x002019-08-15T\
00:24:44+00:00p\x93\
\x9d1\x00\x00\x00\x00IEND\xaeB`\x82\
"
qt_resource_name = b"\
\x00\x05\
\x00M\x843\
\x00I\
\x00C\x00O\x00N\x00S\
\x00\x08\
\x08D?\xf0\
\x00I\
\x00C\x00O\x00N\x00_\x00A\x00P\x00P\
\x00\x09\
\x04D\xdf\x9e\
\x00I\
\x00C\x00O\x00N\x00_\x00O\x00P\x00E\x00N\
\x00\x09\
\x04D\xf2\xe4\
\x00I\
\x00C\x00O\x00N\x00_\x00Q\x00U\x00I\x00T\
\x00\x08\
\x08DK\x07\
\x00I\
\x00C\x00O\x00N\x00_\x00N\x00E\x00W\
\x00\x09\
\x04D\xed\xa5\
\x00I\
\x00C\x00O\x00N\x00_\x00S\x00A\x00V\x00E\
\x00\x0a\
\x04<\xc4$\
\x00I\
\x00C\x00O\x00N\x00_\x00A\x00B\x00O\x00U\x00T\
\x00\x0c\
\x0fT\x9b?\
\x00I\
\x00C\x00O\x00N\x00_\x00Q\x00T\x00_\x00L\x00O\x00G\x00O\
\x00\x0b\
\x036\x5c\xf4\
\x00I\
\x00C\x00O\x00N\x00_\x00E\x00X\x00P\x00O\x00R\x00T\
"
qt_resource_struct = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x08\x00\x00\x00\x02\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\xbc\x00\x00\x00\x00\x00\x01\x00\x00\x15{\
\x00\x00\x01o}\x7f\xb8\xc0\
\x00\x00\x00\x84\x00\x00\x00\x00\x00\x01\x00\x00\x10\x83\
\x00\x00\x01o}\x7f\xb8\xc0\
\x00\x00\x00&\x00\x00\x00\x00\x00\x01\x00\x00\x02\xd1\
\x00\x00\x01zJ.\xae4\
\x00\x00\x00l\x00\x00\x00\x00\x00\x01\x00\x00\x0d8\
\x00\x00\x01o}\x7f\xb8\xc0\
\x00\x00\x00>\x00\x00\x00\x00\x00\x01\x00\x00\x05\xdb\
\x00\x00\x01o}\x7f\xb8\xc0\
\x00\x00\x00\x10\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01zJ\xa3d\xd2\
\x00\x00\x00V\x00\x00\x00\x00\x00\x01\x00\x00\x09R\
\x00\x00\x01o}\x7f\xb8\xc0\
\x00\x00\x00\x9e\x00\x00\x00\x00\x00\x01\x00\x00\x13B\
\x00\x00\x01o}\x7f\xb8\xc0\
"
def qInitResources():
QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
def qCleanupResources():
QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
qInitResources()

13
src/img/icons.qrc Normal file
View file

@ -0,0 +1,13 @@
<RCC>
<qresource prefix="ICONS">
<file alias="ICON_CLEAR">icons8-clear-symbol-16.png</file>
<file alias="ICON_COPY">icons8-copy-16.png</file>
<file alias="ICON_ERASER">icons8-eraser-16.png</file>
<file alias="ICON_INSERT">icons8-insert-clip-16.png</file>
<file alias="ICON_APPEND">icons8-append-clip-16.png</file>
<file alias="ICON_PASTE">icons8-paste-16.png</file>
<file alias="ICON_CUT">icons8-scissors-16.png</file>
<file alias="ICON_ADD_ROW">icons8-add-row-16.png</file>
<file alias="ICON_DEL">icons8-delete-16.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 B

BIN
src/img/icons8-copy-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 751 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

BIN
src/img/icons8-paste-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 B

File diff suppressed because it is too large Load diff

View file

@ -1,337 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>604</width>
<height>596</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QGroupBox" name="gbResults">
<property name="geometry">
<rect>
<x>20</x>
<y>440</y>
<width>541</width>
<height>121</height>
</rect>
</property>
<property name="title">
<string>Ergebnis</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<widget class="QLabel" name="lblVol_Garage">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>140</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Volumen der Garage:</string>
</property>
</widget>
<widget class="QLabel" name="lblVol_Stuff">
<property name="geometry">
<rect>
<x>10</x>
<y>40</y>
<width>140</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Volumen der Gegenstände:</string>
</property>
</widget>
<widget class="QLabel" name="lblVol_Free">
<property name="geometry">
<rect>
<x>10</x>
<y>60</y>
<width>140</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Freier Raum i. d. Garage:</string>
</property>
</widget>
<widget class="QLineEdit" name="efVol_Garage">
<property name="geometry">
<rect>
<x>174</x>
<y>20</y>
<width>113</width>
<height>20</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
<widget class="QLineEdit" name="efVol_Stuff">
<property name="geometry">
<rect>
<x>174</x>
<y>40</y>
<width>113</width>
<height>20</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
<widget class="QLineEdit" name="efVol_Free">
<property name="geometry">
<rect>
<x>174</x>
<y>60</y>
<width>113</width>
<height>20</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="lblM3">
<property name="geometry">
<rect>
<x>294</x>
<y>20</y>
<width>47</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>m³</string>
</property>
</widget>
<widget class="QLabel" name="lblM3_2">
<property name="geometry">
<rect>
<x>294</x>
<y>40</y>
<width>47</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>m³</string>
</property>
</widget>
<widget class="QLabel" name="lblM3_3">
<property name="geometry">
<rect>
<x>294</x>
<y>60</y>
<width>47</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>m³</string>
</property>
</widget>
<widget class="QLineEdit" name="efWeight">
<property name="geometry">
<rect>
<x>174</x>
<y>80</y>
<width>113</width>
<height>20</height>
</rect>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
<widget class="QLabel" name="lblM3_4">
<property name="geometry">
<rect>
<x>294</x>
<y>80</y>
<width>47</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>kg</string>
</property>
</widget>
<widget class="QLabel" name="lblVol_Free_2">
<property name="geometry">
<rect>
<x>10</x>
<y>80</y>
<width>140</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Gesamtgewicht:</string>
</property>
</widget>
</widget>
<widget class="QGroupBox" name="gbStuff">
<property name="geometry">
<rect>
<x>20</x>
<y>120</y>
<width>561</width>
<height>301</height>
</rect>
</property>
<property name="title">
<string>Dimensionen der zu verstauenden Gegenstände</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableWidget" name="tableStuff">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<column>
<property name="text">
<string>Gegenstand</string>
</property>
</column>
<column>
<property name="text">
<string>Länge [m]</string>
</property>
</column>
<column>
<property name="text">
<string>Breite [m]</string>
</property>
</column>
<column>
<property name="text">
<string>Höhe [m]</string>
</property>
</column>
<column>
<property name="text">
<string>Gewicht [kg]</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QGroupBox" name="gbGarage">
<property name="geometry">
<rect>
<x>20</x>
<y>20</y>
<width>561</width>
<height>91</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>91</height>
</size>
</property>
<property name="title">
<string>Dimension der Garage</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<widget class="QTableWidget" name="tableGarage">
<property name="geometry">
<rect>
<x>10</x>
<y>23</y>
<width>351</width>
<height>58</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>58</height>
</size>
</property>
<row>
<property name="text">
<string>Garage</string>
</property>
</row>
<column>
<property name="text">
<string>Länge [m]</string>
</property>
</column>
<column>
<property name="text">
<string>Breite [m]</string>
</property>
</column>
<column>
<property name="text">
<string>Höhe [m]</string>
</property>
</column>
</widget>
</widget>
</widget>
<tabstops>
<tabstop>tableGarage</tabstop>
<tabstop>tableStuff</tabstop>
<tabstop>efVol_Garage</tabstop>
<tabstop>efVol_Stuff</tabstop>
<tabstop>efVol_Free</tabstop>
<tabstop>efWeight</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View file

@ -10,14 +10,17 @@ import sys
import os
# Third party imports
from PySide2.QtWidgets import QMessageBox, QApplication, QMainWindow, QTableWidgetItem, QStatusBar, QAction
from PySide2.QtWidgets import QMessageBox, QApplication, QMainWindow, QTableWidgetItem, QStatusBar
from PySide2 import QtCore
from PySide2.QtGui import QIcon, QPixmap
from PySide2.QtCore import QFile, QSize
from PySide2.QtCore import QFile, QSize, Qt
from PySide2.QtUiTools import QUiLoader
# local globals
APP_ICON = "./img/icons8-garage-32.ico"
STD_COL_WIDTH: int = 7
# local imports
import icons_rc
def resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
@ -29,26 +32,128 @@ 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)))
msg.setIconPixmap(QPixmap(u":ICONS/ICON_APP"))
text = "<p align='center'><h1>" + qApp.applicationDisplayName() + " " + \
"<br>" + qApp.applicationVersion() + "</h1>" + \
"<br>" + qApp.applicationName() + "<br>" + \
"<br>" + qApp.description + "<br>" + \
"<br>" + "Idee von: Balazs Fabian" + "<br>" + \
"<br>" + qApp.translate("main", "Calculates available garage space") + "<br>" + \
"<br>" + qApp.translate("utils", "Idea") + ": Balazs Fabian" + "<br>" + \
"<br>" + qApp.copyright + "<br>" \
"<br> <a href='" + qApp.website + "'>" + qApp.website + "</a></p>"
text = text + "<p align='center'>Used icons: Theme 'Cute Color' from <a href='https://icons8.com/'>Icons8</a></p>"
text = text + "<p align='center'>Python version: " + f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro} {sys.version_info.releaselevel}"
text = text + "<p align='center'>" + qApp.translate("utils", "Used icons") + ": 'Cute Color' " + qApp.translate("utils", "from") + " <a href='https://icons8.com/'>Icons8</a></p>"
text = text + "<p align='center'>" + qApp.translate("utils", "Currently opened file") + ": <br>" + opened_file + " </p>"
text = text + "<p align='center'>" + qApp.translate("utils", "Location of the Ini-file") + ": <br>" + ini_file + " </p>"
text = text + "<p align='center'>Python " + qApp.translate("utils", "Version") + ": " + f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro} {sys.version_info.releaselevel}"
text = text + "<br>" + f"{sys.executable}" + "<br>"
text = text + "<br>Qt version: " + f"{QtCore.__version__}"
text = text + "<br>Qt " + qApp.translate("utils", "Version") + ": " + f"{QtCore.__version__}"
msg.setText(text)
msg.setWindowTitle("About")
msg.setStandardButtons(QMessageBox.Ok)
msg.exec_()
def str_iff(input: str, output1: str, output2: str, output3: str) -> str:
""" Return outputs based on length of given input """
str_ret = ""
str_length = len(input)
if str_length < 0:
str_ret = output1
if str_length == 0:
str_ret = output2
if str_length > 0:
str_ret = output3
return str_ret
def fit_col_widths(table, worksheet):
try:
model = table.model().sourceModel()
except AttributeError:
model = table.model()
max_col_lengths = []
dict_max_col_length = {}
sel_indexes = table.selectedIndexes()
sel_rows_idx = table.selectionModel().selectedRows()
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 = []
# get column header
row = 0
col_header_text = str(model.headerData(col_ind, Qt.Horizontal))
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
for row_ind in range(model.rowCount()):
if row_ind in sel_rows:
item = model.item(row_ind, col_ind)
if item:
cur_item_text = item.text()
cur_item_length = len(cur_item_text)
else:
cur_item_length = 0
if not table.isColumnHidden(col_ind): # export only visible column headers
lengths.append(cur_item_length)
if not table.isColumnHidden(col_ind): # export only visible column headers
dict_max_col_length[col_ind] = lengths
col_ind = 0
for col in dict_max_col_length:
lengths = dict_max_col_length[col]
col_width = max(lengths)
## special: enlage first col
if col == 0:
col_width = 20
# debug info
# print(f"worksheet.set_column({col_ind} -> {col_width})")
# worksheet.write(29, col_ind, col_width)
## debug info
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

92
ui/dlg_uom.ui Normal file
View file

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>222</width>
<height>100</height>
</rect>
</property>
<property name="windowTitle">
<string>UOM</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="lblValue">
<property name="text">
<string>Value:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="efValue">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="lblUOM">
<property name="text">
<string>UOM:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QComboBox" name="cmbUOM"/>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

365
ui/win_main.ui Normal file
View file

@ -0,0 +1,365 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>605</width>
<height>595</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QSplitter" name="splitter">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
<property name="midLineWidth">
<number>0</number>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="opaqueResize">
<bool>true</bool>
</property>
<property name="handleWidth">
<number>5</number>
</property>
<property name="childrenCollapsible">
<bool>true</bool>
</property>
<widget class="QGroupBox" name="gbGarage">
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="title">
<string>Dimension der Garage</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="0">
<item>
<widget class="QTableWidget" name="tableGarage">
<property name="rowCount">
<number>1</number>
</property>
<property name="columnCount">
<number>4</number>
</property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<row>
<property name="text">
<string>Garage</string>
</property>
</row>
<column>
<property name="text">
<string>Länge [m]</string>
</property>
</column>
<column>
<property name="text">
<string>Breite [m]</string>
</property>
</column>
<column>
<property name="text">
<string>Höhe [m]</string>
</property>
</column>
<column>
<property name="text">
<string>Kommentar</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QGroupBox" name="gbStuff">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>350</height>
</size>
</property>
<property name="title">
<string>Dimensionen der zu verstauenden Gegenstände</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2"/>
</widget>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gbResults">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Ergebnis</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="3">
<widget class="QLabel" name="lblM3_3">
<property name="text">
<string>m³</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="lblVol_Garage">
<property name="text">
<string>Volumen der Garage:</string>
</property>
</widget>
</item>
<item row="0" column="4">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="3">
<widget class="QLabel" name="lblM3_4">
<property name="text">
<string>kg</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="lblM3_2">
<property name="text">
<string>m³</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="lblWeight">
<property name="text">
<string>Gesamtgewicht:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="lblM3">
<property name="text">
<string>m³</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLineEdit" name="efVol_Free">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLineEdit" name="efWeight">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="lblVol_Stuff">
<property name="text">
<string>Volumen der Gegenstände:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLineEdit" name="efVol_Garage">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="efVol_Stuff">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="lblVol_Free">
<property name="text">
<string>Freier Raum in der Garage:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
<action name="actionNew">
<property name="icon">
<iconset resource="../img/icons.qrc">
<normaloff>:/ICONS/ICON_NEW</normaloff>:/ICONS/ICON_NEW</iconset>
</property>
<property name="text">
<string>&amp;New</string>
</property>
<property name="toolTip">
<string>New</string>
</property>
<property name="shortcut">
<string>Ctrl+N</string>
</property>
</action>
<action name="actionOpen">
<property name="icon">
<iconset resource="../img/icons.qrc">
<normaloff>:/ICONS/ICON_OPEN</normaloff>:/ICONS/ICON_OPEN</iconset>
</property>
<property name="text">
<string>&amp;Open...</string>
</property>
<property name="toolTip">
<string>Open...</string>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</action>
<action name="actionSave">
<property name="icon">
<iconset resource="../img/icons.qrc">
<normaloff>:/ICONS/ICON_SAVE</normaloff>:/ICONS/ICON_SAVE</iconset>
</property>
<property name="text">
<string>&amp;Save</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
<action name="actionExport">
<property name="icon">
<iconset resource="../img/icons.qrc">
<normaloff>:/ICONS/ICON_EXPORT</normaloff>:/ICONS/ICON_EXPORT</iconset>
</property>
<property name="text">
<string>Export to EXCEL...</string>
</property>
<property name="toolTip">
<string>Export to EXCEL...</string>
</property>
</action>
<action name="actionAbout_Qt">
<property name="icon">
<iconset resource="../img/icons.qrc">
<normaloff>:/ICONS/ICON_QT_LOGO</normaloff>:/ICONS/ICON_QT_LOGO</iconset>
</property>
<property name="text">
<string>About Qt</string>
</property>
</action>
<action name="actionAbout">
<property name="icon">
<iconset resource="../img/icons.qrc">
<normaloff>:/ICONS/ICON_ABOUT</normaloff>:/ICONS/ICON_ABOUT</iconset>
</property>
<property name="text">
<string>Information about the application</string>
</property>
<property name="toolTip">
<string>Information about the application</string>
</property>
</action>
<action name="actionQuit">
<property name="icon">
<iconset resource="../img/icons.qrc">
<normaloff>:/ICONS/ICON_QUIT</normaloff>:/ICONS/ICON_QUIT</iconset>
</property>
<property name="text">
<string>Quit</string>
</property>
<property name="toolTip">
<string>Quit</string>
</property>
<property name="shortcut">
<string>Ctrl+Q</string>
</property>
</action>
</widget>
<resources>
<include location="../img/icons.qrc"/>
</resources>
<connections/>
</ui>