diff --git a/scripts/.pylintrc b/scripts/.pylintrc index 43b2b9bbb126b33d46a4ce3faab76ffb6c1b2b72..bfe23475ab2d623952655a3aa4d8870cb47423f7 100644 --- a/scripts/.pylintrc +++ b/scripts/.pylintrc @@ -141,7 +141,8 @@ disable=print-statement, comprehension-escape, E0611, I1101, - E1101 + E1101, + R0901 # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option diff --git a/soitool/modules/module_base.py b/soitool/modules/module_base.py new file mode 100644 index 0000000000000000000000000000000000000000..92e7e6bc6145a1a1921cb5580c7b8384d77cad51 --- /dev/null +++ b/soitool/modules/module_base.py @@ -0,0 +1,14 @@ +"""Base/interface of each module.""" +from abc import ABC + + +class ModuleBase(ABC): + """Interface for SOI-modules.""" + + def get_size(self): + """Abstract method, should be implemented by derived class.""" + raise NotImplementedError + + def render_onto_pdf(self): + """Abstract method, should be implemented by derived class.""" + raise NotImplementedError diff --git a/soitool/modules/table_module.py b/soitool/modules/table_module.py new file mode 100644 index 0000000000000000000000000000000000000000..50a68289d164a6f0a6ed99d02250ca0a561c6413 --- /dev/null +++ b/soitool/modules/table_module.py @@ -0,0 +1,128 @@ +"""Module containing subclassed SOIModule (QTableWidget, ModuleBase).""" +from PySide2.QtWidgets import QTableWidget, QTableWidgetItem, QShortcut +from PySide2 import QtGui +from module_base import ModuleBase + +HEADER_FONT = QtGui.QFont() +HEADER_FONT.setFamily('Arial') +HEADER_FONT.setPointSize(12) +HEADER_FONT.setWeight(100) + + +class Meta(type(ModuleBase), type(QTableWidget)): + """Used as a metaclass to enable multiple inheritance.""" + + +class TableModule(ModuleBase, QTableWidget, metaclass=Meta): + """Modified QTableWidget. + + Has shortcuts for adding and removing rows and columns. + Also inherits functions from ModuleBase, which is implemented by this class. + """ + + def __init__(self): + """Initialize QTableWidget.""" + QTableWidget.__init__(self) + super(QTableWidget) + + self.horizontalHeader().hide() + self.verticalHeader().hide() + + self.setColumnCount(2) + self.setRowCount(2) + + self.set_header_item(0, "") + self.set_header_item(1, "") + + self.resizeRowsToContents() + self.resizeColumnsToContents() + + self.cellChanged.connect(self.cell_changed) + + self.set_shortcuts() + + def set_header_item(self, column, text): + """Insert item with header-style. + + Item will always be set on header row (top row). + + Parameters + ---------- + column : int + What column index for inserting item. + text : String + What text the item should contain. + """ + item = QTableWidgetItem(text) + item.setBackground(QtGui.QBrush(QtGui.QColor(220, 220, 220))) + item.setFont(HEADER_FONT) + self.setItem(0, column, item) + + def set_shortcuts(self): + """Set shortcuts for adding and removing rows and columns.""" + shortcut_add_col = QShortcut(QtGui.QKeySequence("Shift++"), self) + shortcut_rem_col = QShortcut(QtGui.QKeySequence("Shift+-"), self) + shortcut_add_row = QShortcut(QtGui.QKeySequence("Ctrl++"), self) + shortcut_rem_row = QShortcut(QtGui.QKeySequence("Ctrl+-"), self) + + shortcut_add_col.activated.connect(self.add_column) + shortcut_rem_col.activated.connect(self.remove_column) + shortcut_add_row.activated.connect(self.add_row) + shortcut_rem_row.activated.connect(self.remove_row) + + def add_column(self): + """Add column to the right of selected column.""" + self.insertColumn(self.columnCount()) + + # From selected column, move all columns one step to the right + to_pos = self.columnCount() - 2 # to_pos is target index for columns + while to_pos > self.currentColumn(): + # Loop through all rows + for j in range(self.rowCount()): + item = self.takeItem(j, to_pos) + self.setItem(j, to_pos + 1, item) + to_pos -= 1 + + self.set_header_item(self.currentColumn() + 1, "") + self.resizeColumnsToContents() + + def remove_column(self): + """Remove selected column if two or more columns exist.""" + if self.columnCount() > 1: + self.removeColumn(self.currentColumn()) + + def add_row(self): + """Add row below selected row.""" + self.insertRow(self.currentRow() + 1) + self.resizeRowsToContents() + + def remove_row(self): + """Remove selected row if two or more rows exist (including header).""" + if self.rowCount() > 2: + self.removeRow(self.currentRow()) + + def cell_changed(self): + """Resize rows and columns to contents when a cell changes.""" + self.resizeColumnsToContents() + self.resizeRowsToContents() + + def get_size(self): + """Get size of widget. + + Returns + ------- + Tuple + (width, height) (total) + """ + width = 0 + for i in range(self.columnCount()): + width += self.columnWidth(i) + + height = 0 + for i in range(self.columnCount()): + height += self.rowHeight(i) + + return width, height + + def render_onto_pdf(self): + """Render onto pdf."""