Module soitool.modules.module_base
Base/interface of each module.
Expand source code
"""Base/interface of each module."""
from abc import ABC
from PySide2 import QtGui
from PySide2.QtCore import Qt
def qfont_with_pixel_size(font_family, pixel_size, weight=None):
"""Provide a QFont with given family and pixel size.
Created because QFont does not have a constructor with pixel size as a
parameter.
Parameters
----------
font_family : str
Name of font family. Sent to https://doc.qt.io/qt-5/qfont.html#QFont-1
pixel_size : int
Pixel size. Sent to https://doc.qt.io/qt-5/qfont.html#setPixelSize
weight : QFont.Weight
Weight of font. Sent to https://doc.qt.io/qt-5/qfont.html#QFont-1
"""
if weight is not None:
font = QtGui.QFont(font_family, weight=weight)
else:
font = QtGui.QFont(font_family)
font.setPixelSize(pixel_size)
return font
# Fonts for modules
HEADLINE_FONT = qfont_with_pixel_size("Times New Roman", 34, 100)
SUB_HEADLINE_FONT = qfont_with_pixel_size("Times New Roman", 26, 100)
DEFAULT_FONT = qfont_with_pixel_size("Times New Roman", 23)
class ModuleBase(ABC):
"""Interface for SOI-modules."""
type = None
def __init__(self):
"""Class-variable 'type' should be set by derived class."""
if self.type is None:
raise NotImplementedError
self.headline_font = HEADLINE_FONT
self.setFont(DEFAULT_FONT)
def get_size(self):
"""Abstract method, should be implemented by derived class."""
raise NotImplementedError
def get_data(self):
"""Abstract method, should be implemented by derived class."""
raise NotImplementedError
def prepare_for_pdf_export(self):
"""Abstract method, should be implemented by derived class."""
raise NotImplementedError
@staticmethod
def get_user_friendly_name():
"""Abstract method, should be implemented by derived class."""
raise NotImplementedError
@staticmethod
def get_icon():
"""Abstract method, should be implemented by derived class."""
raise NotImplementedError
def resize_table(table, columns=True, has_headline=False):
"""Resize a given QTableWidget.
On purpose not resizing rows, as this causes different heights from screen
to screen.
Parameters
----------
table : QTableWidget
QTablewidget-instance to resize.
columns : bool
Resizes columns to contents if True, by default True.
has_headline : bool
True if the table has a headline, by default False.
Last column is widened if headline is wider than table.
"""
if columns:
table.resizeColumnsToContents()
# If table has a headline, make sure table is wide enough to fit it.
if has_headline:
last_column_index = table.columnCount() - 1
table.resizeColumnToContents(last_column_index)
width, height = get_table_size(table)
# Get width of headline
headline = table.item(0, 0).text()
headline_width = (
QtGui.QFontMetricsF(HEADLINE_FONT).horizontalAdvance(headline) + 10
)
# If headline is wider than table
if width < headline_width:
difference = headline_width - width
width += difference
old_width = table.columnWidth(last_column_index)
table.setColumnWidth(last_column_index, old_width + difference)
else:
width, height = get_table_size(table)
table.setFixedWidth(width)
table.setFixedHeight(height)
def get_table_size(widget):
"""Calculate and return total width and height of a QTableWidget.
Parameters
----------
widget : QTableWidget
QTableWidget-instance to calculate and return size of.
Returns
-------
Tuple
Total (width, height)
"""
width = 0
height = 0
for i in range(widget.columnCount()):
width += widget.columnWidth(i)
for i in range(widget.rowCount()):
height += widget.rowHeight(i)
# Without the following the size is always slightly off, apparently by 2
# px. This might be due to borders around the table
width += 2
height += 2
return width, height
def set_module_pos(widget, pos):
"""Set position of module (widget).
Parameters
----------
widget : QWidget
Widget to move.
pos : QPoint
Position (x, y).
"""
widget.move(pos)
def prepare_table_for_pdf_export(widget):
"""Prepare QTableWidget for PDF-export.
Deselect cells and clear focus.
Parameters
----------
widget : QTableWidget
Table to prepare.
"""
widget.clearSelection()
widget.clearFocus()
def prepare_line_edit_for_pdf_export(widget):
"""Prepare QLineEdit for PDF-export.
Deselect text and clear focus.
Parameters
----------
widget : QLineEdit
QLineEdit to prepare.
"""
widget.deselect()
widget.clearFocus()
def prepare_text_edit_for_pdf_export(widget):
"""Prepare QTextEdit for PDF-export.
Deselect text and clear focus.
Parameters
----------
widget : QTextEdit
QTextEdit to prepare.
"""
text_cursor = widget.textCursor()
text_cursor.clearSelection()
widget.setTextCursor(text_cursor)
widget.clearFocus()
def is_event_add_row(event):
"""Check if the event is 'CTRL +'.
Parameters
----------
event : QKeyEvent
Event to check.
Returns
-------
bool
True if event is 'CTRL +'.
"""
return (
event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_Plus
)
def is_event_remove_row(event):
"""Check if the event is 'CTRL -'.
Parameters
----------
event : QKeyEvent
Event to check.
Returns
-------
bool
True if event is 'CTRL -'.
"""
# Underline is in practice minus on some computers in this situation. We
# don't know why. For this reason we check both for underline and minus
return event.modifiers() == Qt.ControlModifier and (
event.key() == Qt.Key_Underscore or event.key() == Qt.Key_Minus
)
def is_event_add_column(event):
"""Check if the event is 'SHIFT +'.
Parameters
----------
event : QKeyEvent
Event to check.
Returns
-------
bool
True if event is 'SHIFT +'.
"""
return event.key() == Qt.Key_Question
def is_event_remove_column(event):
"""Check if the event is 'SHIFT -'.
Parameters
----------
event : QKeyEvent
Event to check.
Returns
-------
bool
True if event is 'SHIFT -'.
"""
# Underline is in practice minus on some computers in this situation. We
# don't know why. For this reason we check both for underline and minus
return event.modifiers() == Qt.ShiftModifier and (
event.key() == Qt.Key_Underscore or event.key() == Qt.Key_Minus
)
def is_event_edit_module(event):
"""Check if the event is 'Ctrl R'.
Parameters
----------
event : QKeyEvent
Event to check.
Returns
-------
bool
True if event is 'Ctrl R', false otherwise.
"""
return event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_R
Functions
def get_table_size(widget)
-
Calculate and return total width and height of a QTableWidget.
Parameters
widget
:QTableWidget
- QTableWidget-instance to calculate and return size of.
Returns
Tuple
- Total (width, height)
Expand source code
def get_table_size(widget): """Calculate and return total width and height of a QTableWidget. Parameters ---------- widget : QTableWidget QTableWidget-instance to calculate and return size of. Returns ------- Tuple Total (width, height) """ width = 0 height = 0 for i in range(widget.columnCount()): width += widget.columnWidth(i) for i in range(widget.rowCount()): height += widget.rowHeight(i) # Without the following the size is always slightly off, apparently by 2 # px. This might be due to borders around the table width += 2 height += 2 return width, height
def is_event_add_column(event)
-
Check if the event is 'SHIFT +'.
Parameters
event
:QKeyEvent
- Event to check.
Returns
bool
- True if event is 'SHIFT +'.
Expand source code
def is_event_add_column(event): """Check if the event is 'SHIFT +'. Parameters ---------- event : QKeyEvent Event to check. Returns ------- bool True if event is 'SHIFT +'. """ return event.key() == Qt.Key_Question
def is_event_add_row(event)
-
Check if the event is 'CTRL +'.
Parameters
event
:QKeyEvent
- Event to check.
Returns
bool
- True if event is 'CTRL +'.
Expand source code
def is_event_add_row(event): """Check if the event is 'CTRL +'. Parameters ---------- event : QKeyEvent Event to check. Returns ------- bool True if event is 'CTRL +'. """ return ( event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_Plus )
def is_event_edit_module(event)
-
Check if the event is 'Ctrl R'.
Parameters
event
:QKeyEvent
- Event to check.
Returns
bool
- True if event is 'Ctrl R', false otherwise.
Expand source code
def is_event_edit_module(event): """Check if the event is 'Ctrl R'. Parameters ---------- event : QKeyEvent Event to check. Returns ------- bool True if event is 'Ctrl R', false otherwise. """ return event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_R
def is_event_remove_column(event)
-
Check if the event is 'SHIFT -'.
Parameters
event
:QKeyEvent
- Event to check.
Returns
bool
- True if event is 'SHIFT -'.
Expand source code
def is_event_remove_column(event): """Check if the event is 'SHIFT -'. Parameters ---------- event : QKeyEvent Event to check. Returns ------- bool True if event is 'SHIFT -'. """ # Underline is in practice minus on some computers in this situation. We # don't know why. For this reason we check both for underline and minus return event.modifiers() == Qt.ShiftModifier and ( event.key() == Qt.Key_Underscore or event.key() == Qt.Key_Minus )
def is_event_remove_row(event)
-
Check if the event is 'CTRL -'.
Parameters
event
:QKeyEvent
- Event to check.
Returns
bool
- True if event is 'CTRL -'.
Expand source code
def is_event_remove_row(event): """Check if the event is 'CTRL -'. Parameters ---------- event : QKeyEvent Event to check. Returns ------- bool True if event is 'CTRL -'. """ # Underline is in practice minus on some computers in this situation. We # don't know why. For this reason we check both for underline and minus return event.modifiers() == Qt.ControlModifier and ( event.key() == Qt.Key_Underscore or event.key() == Qt.Key_Minus )
def prepare_line_edit_for_pdf_export(widget)
-
Prepare QLineEdit for PDF-export.
Deselect text and clear focus.
Parameters
widget
:QLineEdit
- QLineEdit to prepare.
Expand source code
def prepare_line_edit_for_pdf_export(widget): """Prepare QLineEdit for PDF-export. Deselect text and clear focus. Parameters ---------- widget : QLineEdit QLineEdit to prepare. """ widget.deselect() widget.clearFocus()
def prepare_table_for_pdf_export(widget)
-
Prepare QTableWidget for PDF-export.
Deselect cells and clear focus.
Parameters
widget
:QTableWidget
- Table to prepare.
Expand source code
def prepare_table_for_pdf_export(widget): """Prepare QTableWidget for PDF-export. Deselect cells and clear focus. Parameters ---------- widget : QTableWidget Table to prepare. """ widget.clearSelection() widget.clearFocus()
def prepare_text_edit_for_pdf_export(widget)
-
Prepare QTextEdit for PDF-export.
Deselect text and clear focus.
Parameters
widget
:QTextEdit
- QTextEdit to prepare.
Expand source code
def prepare_text_edit_for_pdf_export(widget): """Prepare QTextEdit for PDF-export. Deselect text and clear focus. Parameters ---------- widget : QTextEdit QTextEdit to prepare. """ text_cursor = widget.textCursor() text_cursor.clearSelection() widget.setTextCursor(text_cursor) widget.clearFocus()
def qfont_with_pixel_size(font_family, pixel_size, weight=None)
-
Provide a QFont with given family and pixel size.
Created because QFont does not have a constructor with pixel size as a parameter.
Parameters
font_family
:str
- Name of font family. Sent to https://doc.qt.io/qt-5/qfont.html#QFont-1
pixel_size
:int
- Pixel size. Sent to https://doc.qt.io/qt-5/qfont.html#setPixelSize
weight
:QFont.Weight
- Weight of font. Sent to https://doc.qt.io/qt-5/qfont.html#QFont-1
Expand source code
def qfont_with_pixel_size(font_family, pixel_size, weight=None): """Provide a QFont with given family and pixel size. Created because QFont does not have a constructor with pixel size as a parameter. Parameters ---------- font_family : str Name of font family. Sent to https://doc.qt.io/qt-5/qfont.html#QFont-1 pixel_size : int Pixel size. Sent to https://doc.qt.io/qt-5/qfont.html#setPixelSize weight : QFont.Weight Weight of font. Sent to https://doc.qt.io/qt-5/qfont.html#QFont-1 """ if weight is not None: font = QtGui.QFont(font_family, weight=weight) else: font = QtGui.QFont(font_family) font.setPixelSize(pixel_size) return font
def resize_table(table, columns=True, has_headline=False)
-
Resize a given QTableWidget.
On purpose not resizing rows, as this causes different heights from screen to screen.
Parameters
table
:QTableWidget
- QTablewidget-instance to resize.
columns
:bool
- Resizes columns to contents if True, by default True.
has_headline
:bool
- True if the table has a headline, by default False. Last column is widened if headline is wider than table.
Expand source code
def resize_table(table, columns=True, has_headline=False): """Resize a given QTableWidget. On purpose not resizing rows, as this causes different heights from screen to screen. Parameters ---------- table : QTableWidget QTablewidget-instance to resize. columns : bool Resizes columns to contents if True, by default True. has_headline : bool True if the table has a headline, by default False. Last column is widened if headline is wider than table. """ if columns: table.resizeColumnsToContents() # If table has a headline, make sure table is wide enough to fit it. if has_headline: last_column_index = table.columnCount() - 1 table.resizeColumnToContents(last_column_index) width, height = get_table_size(table) # Get width of headline headline = table.item(0, 0).text() headline_width = ( QtGui.QFontMetricsF(HEADLINE_FONT).horizontalAdvance(headline) + 10 ) # If headline is wider than table if width < headline_width: difference = headline_width - width width += difference old_width = table.columnWidth(last_column_index) table.setColumnWidth(last_column_index, old_width + difference) else: width, height = get_table_size(table) table.setFixedWidth(width) table.setFixedHeight(height)
def set_module_pos(widget, pos)
-
Set position of module (widget).
Parameters
widget
:QWidget
- Widget to move.
pos
:QPoint
- Position (x, y).
Expand source code
def set_module_pos(widget, pos): """Set position of module (widget). Parameters ---------- widget : QWidget Widget to move. pos : QPoint Position (x, y). """ widget.move(pos)
Classes
class ModuleBase
-
Interface for SOI-modules.
Class-variable 'type' should be set by derived class.
Expand source code
class ModuleBase(ABC): """Interface for SOI-modules.""" type = None def __init__(self): """Class-variable 'type' should be set by derived class.""" if self.type is None: raise NotImplementedError self.headline_font = HEADLINE_FONT self.setFont(DEFAULT_FONT) def get_size(self): """Abstract method, should be implemented by derived class.""" raise NotImplementedError def get_data(self): """Abstract method, should be implemented by derived class.""" raise NotImplementedError def prepare_for_pdf_export(self): """Abstract method, should be implemented by derived class.""" raise NotImplementedError @staticmethod def get_user_friendly_name(): """Abstract method, should be implemented by derived class.""" raise NotImplementedError @staticmethod def get_icon(): """Abstract method, should be implemented by derived class.""" raise NotImplementedError
Ancestors
- abc.ABC
Subclasses
- CodeTableBase
- CodePhraseModule
- FreeTextModule
- FrequencyTableModule
- PhonebookModule
- PredefinedCodesModule
- TableModule
Class variables
var type
Static methods
def get_icon()
-
Abstract method, should be implemented by derived class.
Expand source code
@staticmethod def get_icon(): """Abstract method, should be implemented by derived class.""" raise NotImplementedError
def get_user_friendly_name()
-
Abstract method, should be implemented by derived class.
Expand source code
@staticmethod def get_user_friendly_name(): """Abstract method, should be implemented by derived class.""" raise NotImplementedError
Methods
def get_data(self)
-
Abstract method, should be implemented by derived class.
Expand source code
def get_data(self): """Abstract method, should be implemented by derived class.""" raise NotImplementedError
def get_size(self)
-
Abstract method, should be implemented by derived class.
Expand source code
def get_size(self): """Abstract method, should be implemented by derived class.""" raise NotImplementedError
def prepare_for_pdf_export(self)
-
Abstract method, should be implemented by derived class.
Expand source code
def prepare_for_pdf_export(self): """Abstract method, should be implemented by derived class.""" raise NotImplementedError