unit conversion per cell (and ini settings)

This commit is contained in:
Paul S 2021-07-11 10:41:42 +02:00
parent 6183acf307
commit a6e6370fd6
10 changed files with 1004 additions and 300 deletions

View file

@ -14,13 +14,22 @@ import os
# Third party imports
from PySide2.QtWidgets import QApplication, QTableWidget, QAbstractItemView, QTableWidgetItem, QMenu, \
QMainWindow, QMessageBox
from PySide2.QtCore import Qt, QItemSelectionModel, QCoreApplication
from PySide2.QtGui import QIcon
QMainWindow, QMessageBox, QComboBox, QDialog
from PySide2.QtCore import Qt, QFile, QItemSelectionModel, QCoreApplication, Slot
from PySide2.QtGui import QIcon, QColor, QPalette
from PySide2.QtUiTools import QUiLoader
# local imports
from utils import resource_path, convert_uom_to_length, convert_uom_to_mass
# local globals
SCRIPT_PATH = os.path.abspath(os.path.dirname(__file__))
DEFAULT_UOM_LENGTH = None
DEFAULT_UOM_MASS = None
UI_DLG_UOM = "./ui/dlg_uom.ui"
ICON_CLEAR = SCRIPT_PATH + "./img/icons8-clear-symbol-16.png"
ICON_COPY = SCRIPT_PATH + "./img/icons8-copy-16.png"
ICON_ERASER = SCRIPT_PATH + "/img/icons8-eraser-16.png"
@ -43,11 +52,14 @@ ICON_DEL = SCRIPT_PATH + "/img/icons8-delete-16.png"
# return os.path.join(base_path, relative_path)
class TableWidget(QTableWidget):
def __init__(self, parent=None):
def __init__(self, parent=None, uom_length=DEFAULT_UOM_LENGTH, uom_mass=DEFAULT_UOM_MASS):
super().__init__()
self.parent = parent
self.default_uom_length = uom_length
self.default_uom_mass = uom_mass
# self.setSelectionMode(QAbstractItemView.ContiguousSelection)
self.setSelectionMode(QAbstractItemView.SingleSelection)
@ -70,8 +82,6 @@ class TableWidget(QTableWidget):
self.vertHeader.setSelectionMode(QAbstractItemView.SingleSelection)
self.vertHeader.sectionClicked.connect(self.select_row)
self.vertHeader.setSectionsMovable(True)
# optimize row height
self.resizeRowsToContents()
self.row_selected = False
@ -87,8 +97,6 @@ class TableWidget(QTableWidget):
item_copy = menu.addAction(QIcon(ICON_COPY), QCoreApplication.translate("TableWidget", "Copy") + "\tCtrl+C")
item_paste = menu.addAction(QIcon(ICON_PASTE), QCoreApplication.translate("TableWidget", "Paste") + "\tCtrl+V")
menu.addSeparator()
print(ICON_ERASER)
item_delete = menu.addAction(QIcon(ICON_ERASER), QCoreApplication.translate("TableWidget", "Delete") + "\tDel")
ac = menu.exec_(self.mapToGlobal(position))
@ -183,41 +191,144 @@ class TableWidget(QTableWidget):
if key == Qt.Key_Delete:
self.item_del()
elif key == Qt.Key_F3:
item = self.item(self.currentRow(), self.currentColumn())
try:
self.parent.cols_with_uom_length
self.parent.cols_with_uom_mass
except:
return False
else:
if self.currentColumn() in self.parent.cols_with_uom_length:
self.f3_pressed(item, "UOM_TYPE_LENGTH")
elif self.currentColumn() in self.parent.cols_with_uom_mass:
self.f3_pressed(item, "UOM_TYPE_MASS")
elif key == Qt.Key_Escape:
self.clearSelection()
def item_paste(self):
cur_row = self.currentRow()
cur_col = self.currentColumn()
# ask_confirmation = True
def f3_pressed(self, item, uom_type) -> bool:
if item:
try:
float(item.text().replace(",", "."))
except ValueError:
return False # we've got an existing text here
if self.row_selected:
cur_col = 0
loader = QUiLoader()
path = os.path.join(os.path.dirname(__file__), resource_path(UI_DLG_UOM))
ui_file = QFile(path)
ui_file.open(QFile.ReadOnly)
self.dlg = loader.load(ui_file, self)
ui_file.close()
col = 0
if len(self.clipboard_data) == 1:
data = self.clipboard_data[0]
item = QTableWidgetItem(data)
self.dlg.uom_type = uom_type
if uom_type == "UOM_TYPE_MASS":
self.dlg.cmbUOM.addItems(["kg", "g"])
else: # anticipate uom type length
self.dlg.cmbUOM.addItems(["m", "cm", "mm"])
self.setItem(cur_row, cur_col, item)
item.setSelected(True)
if item:
self.dlg.efValue.setText(item.text())
print("UOM of the cell:", item.data(Qt.UserRole))
self.dlg.cmbUOM.setCurrentText(item.data(Qt.UserRole))
if item.data(Qt.UserRole):
self.old_uom = item.data(Qt.UserRole)
else:
if uom_type == "UOM_TYPE_MASS":
self.old_uom = self.default_uom_mass
else:
self.old_uom = self.default_uom_length
self.dlg.cmbUOM.currentIndexChanged.connect(self.on_cmbUOM_itemChanged)
if self.dlg.exec() == QDialog.Accepted:
if not item:
item = QTableWidgetItem("Dummy")
self.setItem(self.currentRow(), self.currentColumn(), item)
item.setText(self.dlg.efValue.text())
#item.setStyleSheet("border: 1px solid yellow;")
item.setData(Qt.UserRole, self.dlg.cmbUOM.currentText()) ## store UOM-Text at UserRole
item.setData(Qt.UserRole+1, self.dlg.cmbUOM.currentText()) ## store UOM-Type at UserRole+1 (1==UOM_LENGTH, 2==UOM_MASS)
if self.dlg.cmbUOM.currentText() not in (self.default_uom_length, self.default_uom_mass):
item.setData(Qt.BackgroundRole, QColor(Qt.yellow))
item.setToolTip("[" + item.data(Qt.UserRole) + "]")
else:
item.setData(Qt.BackgroundRole, None)
item.setToolTip(None)
return True
@Slot(int)
def on_cmbUOM_itemChanged(self, index):
try:
old_val = float(self.dlg.efValue.text().replace(",", "."))
except ValueError:
# special case: edit field is emppty because user changes UOM first.
self.old_uom = self.dlg.cmbUOM.currentText()
pass
else:
for data in self.clipboard_data:
new_uom = self.dlg.cmbUOM.currentText()
if self.dlg.uom_type == "UOM_TYPE_LENGTH":
new_val = convert_uom_to_length(old_val, self.old_uom, new_uom)
elif self.dlg.uom_type == "UOM_TYPE_MASS":
new_val = convert_uom_to_mass(old_val, self.old_uom, new_uom)
self.dlg.efValue.setText(str(new_val).replace(".", ","))
self.old_uom = new_uom
# def setUOM(self, item, uom):
# if uom not in (DEFAULT_UOM_LENGTH, DEFAULT_UOM_MASS):
# item.setData(Qt.UserRole, uom)
# item.setData(Qt.BackgroundRole, QColor(Qt.yellow))
# item.setToolTip(f"[{uom}]")
# else:
# item.setData(Qt.BackgroundRole, None)
# item.setToolTip(None)
def setUOM(self, item, uom):
item.setData(Qt.UserRole, uom)
if uom not in (self.default_uom_length, self.default_uom_mass):
item.setData(Qt.BackgroundRole, QColor(Qt.yellow))
item.setToolTip(f"[{uom}]")
else:
item.setData(Qt.BackgroundRole, None)
item.setToolTip(None)
def item_paste(self):
if self.clipboard_data:
cur_row = self.currentRow()
cur_col = self.currentColumn()
# ask_confirmation = True
if self.row_selected:
cur_col = 0
col = 0
if len(self.clipboard_data) == 1:
data = self.clipboard_data[0]
item = QTableWidgetItem(data)
# if item:
# if len(item.text()) >0:
# if ask_confirmation:
# msg = QCoreApplication.translate("TableWidget", "Zelle enthält bereits Daten. Überschreiben?")
# reply = QMessageBox.question(self, QCoreApplication.translate("TableWidget", "Überschreiben"), msg, \
# QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
# if reply == QMessageBox.No:
# return False
# ask_confirmation = False
self.setItem(cur_row, col, item)
self.setItem(cur_row, cur_col, item)
item.setSelected(True)
else:
for data in self.clipboard_data:
item = QTableWidgetItem(data)
# if item:
# if len(item.text()) >0:
# if ask_confirmation:
# msg = QCoreApplication.translate("TableWidget", "Zelle enthält bereits Daten. Überschreiben?")
# reply = QMessageBox.question(self, QCoreApplication.translate("TableWidget", "Überschreiben"), msg, \
# QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
# if reply == QMessageBox.No:
# return False
col += 1
# ask_confirmation = False
self.setItem(cur_row, col, item)
item.setSelected(True)
col += 1
def item_cut(self):
self.item_copy()
@ -259,7 +370,10 @@ class TableWidget(QTableWidget):
return False
ask_cofirmation = False
item.setData(Qt.DisplayRole, None)
item.setData(Qt.DisplayRole, None) # remove text
item.setData(Qt.BackgroundRole, None) # remove cell background color
item.setData(Qt.UserRole, None) # remove UOM
item.setToolTip(None) # remove tooltip
if len(sel_idx) == self.columnCount() * self.rowCount():
try:

File diff suppressed because it is too large Load diff

View file

@ -31,7 +31,10 @@ def resource_path(relative_path):
return os.path.join(base_path, relative_path)
def show_about():
def show_about(ini_file="", opened_file=""):
if not opened_file:
opened_file = ""
qApp = QApplication.instance()
msg = QMessageBox()
msg.setIconPixmap(QPixmap(resource_path(APP_ICON)))
@ -44,7 +47,9 @@ def show_about():
"<br>" + qApp.copyright + "<br>" \
"<br> <a href='" + qApp.website + "'>" + qApp.website + "</a></p>"
text = text + "<p align='center'>" + qApp.translate("utils", "Used icons: Theme") + " 'Cute Color' " + qApp.translate("utils", "from") + " <a href='https://icons8.com/'>Icons8</a></p>"
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 " + qApp.translate("utils", "Version") + ": " + f"{QtCore.__version__}"
@ -84,7 +89,7 @@ def fit_col_widths(table, worksheet):
sel_rows = []
for sel_index in sel_rows_idx:
sel_rows.append(sel_index.row())
for col_ind in range(model.columnCount()):
cur_item_length = 0
lengths = []
@ -95,7 +100,7 @@ def fit_col_widths(table, worksheet):
if not table.isColumnHidden(col_ind): # export only visible column headers
cur_item_length = len(col_header_text)
lengths.append(cur_item_length)
# get columns data lengths
row = 1
# iterate over all rows
@ -129,3 +134,25 @@ def fit_col_widths(table, worksheet):
if col_width > STD_COL_WIDTH: # anticipated default size
worksheet.set_column(col_ind, col_ind, col_width*1.25)
col_ind += 1
def convert_uom_to_length(val, unit_in, unit_out):
SI = {'mm':0.001, 'cm':0.01, 'm':1.0}
return val*SI[unit_in]/SI[unit_out]
def convert_uom_to_mass(val, unit_in, unit_out):
SI = {'g':0.001, 'kg':1.0}
return val*SI[unit_in]/SI[unit_out]
def optimizeTableLayout(table):
for col in range(table.columnCount()): # optimize column width
table.resizeColumnToContents(col)
table.resizeRowsToContents() # optimize row height
def table_has_items(tablewidget):
for row in range(tablewidget.rowCount()):
for col in range(tablewidget.columnCount()):
item = tablewidget.item(row, col)
if item:
return True
return False