diff --git a/soitool/help_actions.py b/soitool/help_actions.py
index 5c822603179f67b4ef443cd6ebf391be5792f0d2..0d99369a6082c279ce8a5f4caa29ecef07c48739 100644
--- a/soitool/help_actions.py
+++ b/soitool/help_actions.py
@@ -41,9 +41,7 @@ class ShortcutsHelpDialog(QDialog):
         self.layout_label.addRow(
             QLabel("Ã…pne SOI fra database: "), QLabel("Ctrl + D")
         )
-        self.layout_label.addRow(
-            QLabel("Forhåndsvis SOI: "), QLabel("Ctrl + P")
-        )
+        self.layout_label.addRow(QLabel("Eksporter PDF: "), QLabel("Ctrl + P"))
         self.layout_label.addRow(
             QLabel("Lagre i database: "), QLabel("Ctrl + S")
         )
diff --git a/soitool/inline_editable_soi_view.py b/soitool/inline_editable_soi_view.py
index 5bde3a8ba14af685065fa8200d96e2148e36651a..8690ad30f8010d51768593fcbe512b337781f493 100644
--- a/soitool/inline_editable_soi_view.py
+++ b/soitool/inline_editable_soi_view.py
@@ -12,7 +12,6 @@ from PySide2.QtWidgets import (
     QGraphicsProxyWidget,
 )
 from PySide2.QtGui import (
-    QFont,
     QPixmap,
     QBrush,
     QPalette,
@@ -22,6 +21,7 @@ from PySide2.QtPrintSupport import QPrinter
 from soitool.soi import ModuleLargerThanBinError
 from soitool.dialog_wrappers import exec_warning_dialog
 from soitool.serialize_export_import_soi import generate_soi_filename
+from soitool.modules.module_base import qfont_with_pixel_size
 
 # How attachment pages should be numbered. The first page should be numbered
 # by the value of ATTACHMENT_NUMBERING_SCHEME[0], the second page
@@ -419,7 +419,7 @@ class InlineEditableSOIView(QScrollArea):
         label_title = QLabel(self.soi.title)
         label_title.move(x, y + self.soi.HEADER_HEIGHT)
         label_title.setStyleSheet("background-color: rgba(0,0,0,0%)")
-        label_title.setFont(QFont("Times New Roman", 35))
+        label_title.setFont(qfont_with_pixel_size("Times New Roman", 60))
         proxy = self.scene.addWidget(label_title)
         proxy.setRotation(-90)
 
@@ -427,7 +427,7 @@ class InlineEditableSOIView(QScrollArea):
         label_description = QLabel(self.soi.description)
         label_description.move(x + 57, y + self.soi.HEADER_HEIGHT)
         label_description.setStyleSheet("background-color: rgba(0,0,0,0%)")
-        label_description.setFont(QFont("Times New Roman", 15))
+        label_description.setFont(qfont_with_pixel_size("Times New Roman", 25))
         proxy = self.scene.addWidget(label_description)
         proxy.setRotation(-90)
 
@@ -435,7 +435,9 @@ class InlineEditableSOIView(QScrollArea):
         creation_date = soi_date_string_to_user_friendly_string(self.soi.date)
         label_creation_date = QLabel("Opprettet: {}".format(creation_date))
         label_creation_date.setStyleSheet("background-color: rgba(0,0,0,0%)")
-        label_creation_date.setFont(QFont("Times New Roman", 15))
+        label_creation_date.setFont(
+            qfont_with_pixel_size("Times New Roman", 25)
+        )
         # Source: https://stackoverflow.com/a/8638114/3545896
         # CAUTION: does not work if font is set through stylesheet
         label_width = (
@@ -470,7 +472,7 @@ class InlineEditableSOIView(QScrollArea):
             "1 av N", f"{self.copy_current} av {self.copy_total}"
         )
         proxy.label.setStyleSheet("background-color: rgba(0,0,0,0%)")
-        proxy.label.setFont(QFont("Times New Roman", 40))
+        proxy.label.setFont(qfont_with_pixel_size("Times New Roman", 70))
 
         # Need to call this when label of proxy changes. See function docstring
         proxy.update_bounding_rect()
@@ -493,7 +495,9 @@ class InlineEditableSOIView(QScrollArea):
         label_copy_number_header.setStyleSheet(
             "background-color: rgba(0,0,0,0%)"
         )
-        label_copy_number_header.setFont(QFont("Times New Roman", 15))
+        label_copy_number_header.setFont(
+            qfont_with_pixel_size("Times New Roman", 25)
+        )
         # Source: https://stackoverflow.com/a/8638114/3545896
         # CAUTION: does not work if font is set through stylesheet
         label_width = (
@@ -519,7 +523,7 @@ class InlineEditableSOIView(QScrollArea):
                 )
             )
         page_number.setStyleSheet("background-color: rgba(0,0,0,0%)")
-        page_number.setFont(QFont("Times New Roman", 15))
+        page_number.setFont(qfont_with_pixel_size("Times New Roman", 25))
         # Source: https://stackoverflow.com/a/8638114/3545896
         # CAUTION: does not work if font is set through stylesheet
         label_width = (
@@ -534,7 +538,7 @@ class InlineEditableSOIView(QScrollArea):
         classification.setStyleSheet(
             "background-color: rgba(0,0,0,0%); " "color: red"
         )
-        classification.setFont(QFont("Times New Roman", 35))
+        classification.setFont(qfont_with_pixel_size("Times New Roman", 60))
         # Source: https://stackoverflow.com/a/8638114/3545896
         # CAUTION: does not work if font is set through stylesheet
         label_width = (
@@ -552,7 +556,7 @@ class InlineEditableSOIView(QScrollArea):
         )
         label_valid_from = QLabel("Gyldig fra: {}".format(valid_from))
         label_valid_from.setStyleSheet("background-color: rgba(0,0,0,0%)")
-        label_valid_from.setFont(QFont("Times New Roman", 15))
+        label_valid_from.setFont(qfont_with_pixel_size("Times New Roman", 25))
         # Source: https://stackoverflow.com/a/8638114/3545896
         # CAUTION: does not work if font is set through stylesheet
         label_width = (
@@ -568,7 +572,7 @@ class InlineEditableSOIView(QScrollArea):
         valid_to = soi_date_string_to_user_friendly_string(self.soi.valid_to)
         label_valid_to = QLabel("Gyldig til: {}".format(valid_to))
         label_valid_to.setStyleSheet("background-color: rgba(0,0,0,0%)")
-        label_valid_to.setFont(QFont("Times New Roman", 15))
+        label_valid_to.setFont(qfont_with_pixel_size("Times New Roman", 25))
         # Source: https://stackoverflow.com/a/8638114/3545896
         # CAUTION: does not work if font is set through stylesheet
         label_width = (
diff --git a/soitool/main_window.py b/soitool/main_window.py
index a4571cdf2b3e19a9a05f921c1b42bdc740fc5a4c..5dc81632c957243ee2a1fc6e6560a7ca1d049e92 100644
--- a/soitool/main_window.py
+++ b/soitool/main_window.py
@@ -110,14 +110,14 @@ class MainWindow(QMainWindow):
         new_soi.triggered.connect(self.open_soi_workspace_tab)
 
         # Open file
-        open_file = QAction("Ã…pne", self)
+        open_file = QAction("Ã…pne fra fil", self)
         open_file.setShortcut("Ctrl+o")
         open_file.setStatusTip("Ã…pne en SOI fra fil")
         open_file.triggered.connect(self.import_soi)
         file_menu.addAction(open_file)
 
         # Open file from DB
-        open_file_db = QAction("Ã…pne fra DB", self)
+        open_file_db = QAction("Ã…pne fra database", self)
         open_file_db.setShortcut("Ctrl+d")
         open_file_db.setStatusTip("Ã…pne en SOI fra databasen")
         open_file_db.triggered.connect(self.show_soi_db)
@@ -130,7 +130,7 @@ class MainWindow(QMainWindow):
         file_menu.addAction(preview_soi)
 
         # Save to DB
-        save_soi = QAction("Lagre i DB", self)
+        save_soi = QAction("Lagre i database", self)
         save_soi.setShortcut("Ctrl+s")
         save_soi.setStatusTip("Lagre SOI i databasen")
         save_soi.triggered.connect(self.save_soi_db)
@@ -154,6 +154,7 @@ class MainWindow(QMainWindow):
         # SOI PDF
         export_pdf = QAction("PDF", self)
         export_pdf.setStatusTip("Eksporter til PDF klar for utskrift")
+        export_pdf.setShortcut("Ctrl+p")
         export_pdf.triggered.connect(
             lambda: self.try_export_soi(medium=ExportMedium.PDF)
         )
@@ -169,7 +170,7 @@ class MainWindow(QMainWindow):
         codebook_menu.addAction(codebook)
 
         # Regenerate codebook-codes:
-        regenerate_codes = QAction("Nye koder i db", self)
+        regenerate_codes = QAction("Nye koder i kodebok", self)
         regenerate_codes.setStatusTip("Nye koder lages tilfeldig")
         regenerate_codes.triggered.connect(self.regenerate_codes)
         codebook_menu.addAction(regenerate_codes)
@@ -360,7 +361,7 @@ class MainWindow(QMainWindow):
             soi_db_view = None
             codebook_db_view = None
             for i in range(self.tabs.count()):
-                if self.tabs.tabText(i) == "SOI'er i DB":
+                if self.tabs.tabText(i) == "SOI-er i database":
                     soi_db_view = self.tabs.widget(i).view
                     soi_db_view.setModel(None)
                 elif self.tabs.tabText(i) == "Kodebok":
@@ -377,7 +378,7 @@ class MainWindow(QMainWindow):
             exec_info_dialog(
                 "Valgt tab er ingen SOI-tab",
                 "Den valgte taben inneholder ingen SOI.\n"
-                "Riktig tab må velges for å lagre en SOI i DB.",
+                "Riktig tab må velges for å lagre en SOI i database.",
             )
 
     def show_soi_db(self):
@@ -388,13 +389,13 @@ class MainWindow(QMainWindow):
         """
         # Loop through tabs to look for existing SOI-db-tab:
         for i in range(self.tabs.count()):
-            if self.tabs.tabText(i) == "SOI'er i DB":
+            if self.tabs.tabText(i) == "SOI-er i database":
                 self.tabs.setCurrentIndex(i)
                 break
         # SOI-db-tab does not exist, create, add and select tab
         else:
             tab = SOIDbWidget(self.database, self.tabs)
-            self.tabs.addTab(tab, "SOI'er i DB")
+            self.tabs.addTab(tab, "SOI-er i database")
             self.tabs.setCurrentWidget(tab)
 
     def open_shortcut_help(self):
diff --git a/soitool/modules/code_table_base.py b/soitool/modules/code_table_base.py
index 7a7200938b7cfa487fee33cda2b8821bf57147e8..478bc64449a55dc22a63336299d9ed83d5611253 100644
--- a/soitool/modules/code_table_base.py
+++ b/soitool/modules/code_table_base.py
@@ -5,11 +5,13 @@ Parent-class for AuthenticationBoardModule and SubtractorCodesModule.
 from PySide2.QtWidgets import QTableWidget, QTableWidgetItem
 from PySide2.QtCore import Qt
 from soitool.coder import get_code_set, get_code
+from soitool.modules.code_table_settings import CodeTableSettings
 from soitool.modules.module_base import (
     ModuleBase,
     get_table_size,
     resize_table,
     HEADLINE_FONT,
+    TABLE_CELL_DEFAULT_FONT,
 )
 
 AUTHENTICATIONBOARD_MODULE = "AuthenticationBoardModule"
@@ -28,14 +30,6 @@ class CodeTableBase(ModuleBase, QTableWidget, metaclass=Meta):
     """
 
     def __init__(self, size, data):
-        if self.type not in [
-            AUTHENTICATIONBOARD_MODULE,
-            SUBTRACTORCODES_MODULE,
-        ]:
-            raise ValueError(
-                "Invalid value for class-variable type: "
-                "'{}'".format(self.type)
-            )
         QTableWidget.__init__(self)
         ModuleBase.__init__(self)
 
@@ -44,6 +38,7 @@ class CodeTableBase(ModuleBase, QTableWidget, metaclass=Meta):
         self.verticalHeader().hide()
         self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
         self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+        self.setFont(TABLE_CELL_DEFAULT_FONT)
 
         # Resize table when headline changes
         self.cellChanged.connect(
@@ -51,8 +46,33 @@ class CodeTableBase(ModuleBase, QTableWidget, metaclass=Meta):
                 self, rows=False, columns=False, has_headline=True,
             )
         )
-        # If parameters are None, generate new table
+        # If parameters are None, launch settings-dialog and generate new table
         if size is None and data is None:
+            # Disabling pylint-error
+            # 'Access to member before its definition line'
+            # because the variable is defined in subclass.
+            # pylint: disable=E0203
+            if self.start_no_of_codes > self.maximum_no_of_codes:
+                raise ValueError(
+                    "The value of module-constant 'START_NO_OF_CODES' "
+                    "is larger than module-constant 'MAXIMUM_NO_OF_CODES': "
+                    "{} > {}".format(
+                        self.start_no_of_codes, self.maximum_no_of_codes
+                    )
+                )
+            dialog = CodeTableSettings(self)
+            dialog.exec()
+
+            self.start_headline = dialog.edit_headline.text()
+            self.start_no_of_codes = int(
+                dialog.combo_no_of_codes.currentText()
+            )
+            self.code_length = int(dialog.combo_code_length.currentText())
+            self.space_interval = int(
+                dialog.combo_space_interval.currentText()
+            )
+            self.space_amount = int(dialog.combo_space_amount.currentText())
+
             self.generate_table()
             self.resizeColumnsToContents()
             self.resizeRowsToContents()
@@ -77,10 +97,9 @@ class CodeTableBase(ModuleBase, QTableWidget, metaclass=Meta):
                     item = QTableWidgetItem(
                         cells[i + 1][j]
                     )  # +1 skip headline
-                    if j == 2 and self.type == AUTHENTICATIONBOARD_MODULE:
-                        item.setTextAlignment(Qt.AlignLeft | Qt.AlignVCenter)
-                    else:
+                    if j == 2:
                         item.setTextAlignment(Qt.AlignCenter)
+                        item.setFont(self.code_font)
                     self.setItem(i, j, item)
 
             self.resizeColumnsToContents()
@@ -195,7 +214,7 @@ class CodeTableBase(ModuleBase, QTableWidget, metaclass=Meta):
             # If at least two rows (+ headline-row) exists and a row other than
             # headline-row is selected
             row_index = self.currentRow()
-            if self.rowCount() > 2 and row_index != 0 and row_index != -1:
+            if self.rowCount() > 3 and row_index != 0 and row_index != -1:
                 self.remove_row(row_index)
         else:
             super().keyPressEvent(event)
diff --git a/soitool/modules/code_table_settings.py b/soitool/modules/code_table_settings.py
new file mode 100644
index 0000000000000000000000000000000000000000..83ad828ae2ff239d4c4092e26073f76b6ac2b841
--- /dev/null
+++ b/soitool/modules/code_table_settings.py
@@ -0,0 +1,100 @@
+"""QDialog for setup of CodeTableBase."""
+
+from PySide2.QtWidgets import (
+    QDialog,
+    QVBoxLayout,
+    QHBoxLayout,
+    QLabel,
+    QLineEdit,
+    QComboBox,
+    QFormLayout,
+    QPushButton,
+)
+from PySide2.QtCore import Qt
+
+
+class CodeTableSettings(QDialog):
+    """Setup of CodeTableBase.
+
+    Parameters
+    ----------
+    code_table_base : soitool.modules.code_table_base.CodeTableBase
+        Is used to fetch the modules default values, so that these are
+        pre-selected.
+    """
+
+    def __init__(self, code_table_base):
+        super().__init__()
+
+        # Hide help-button, disable close-button and set window width
+        self.setWindowFlag(Qt.WindowContextHelpButtonHint, False)
+        self.setWindowFlag(Qt.WindowCloseButtonHint, False)
+        self.setFixedWidth(350)
+
+        # Headline
+        self.label_headline = QLabel("Overskrift")
+        self.edit_headline = QLineEdit()
+        self.edit_headline.setText(code_table_base.start_headline)
+
+        # Number of codes
+        self.label_no_of_codes = QLabel("Antall koder")
+        self.combo_no_of_codes = QComboBox()
+        for i in range(2, code_table_base.maximum_no_of_codes + 1):
+            self.combo_no_of_codes.addItem(str(i))
+        self.combo_no_of_codes.setCurrentIndex(
+            code_table_base.start_no_of_codes - 2
+        )
+
+        # Code length
+        self.label_code_length = QLabel("Kodelengde")
+        self.combo_code_length = QComboBox()
+        for i in range(2, 31):
+            self.combo_code_length.addItem(str(i))
+        self.combo_code_length.setCurrentIndex(code_table_base.code_length - 2)
+
+        # Space interval
+        self.label_space_interval = QLabel("Intervall for kodemellomrom")
+        self.combo_space_interval = QComboBox()
+        for i in range(11):
+            self.combo_space_interval.addItem(str(i))
+        self.combo_space_interval.setCurrentIndex(
+            code_table_base.space_interval
+        )
+
+        # Space amount
+        self.label_space_amount = QLabel("Mellomrom per intervall")
+        self.combo_space_amount = QComboBox()
+        for i in range(6):
+            self.combo_space_amount.addItem(str(i))
+        self.combo_space_amount.setCurrentIndex(code_table_base.space_amount)
+
+        # Create-button
+        self.button_create = QPushButton("Opprett")
+        self.button_create.clicked.connect(self.accept)
+
+        self.create_and_set_layout()
+
+    def create_and_set_layout(self):
+        """Create layouts, add widgets and set layout."""
+        # Layout for input-widgets
+        self.form_layout = QFormLayout()
+        self.form_layout.addRow(self.label_headline, self.edit_headline)
+        self.form_layout.addRow(self.label_no_of_codes, self.combo_no_of_codes)
+        self.form_layout.addRow(self.label_code_length, self.combo_code_length)
+        self.form_layout.addRow(
+            self.label_space_interval, self.combo_space_interval
+        )
+        self.form_layout.addRow(
+            self.label_space_amount, self.combo_space_amount
+        )
+
+        # Layout for create-button
+        self.button_layout = QHBoxLayout()
+        self.button_layout.addWidget(self.button_create)
+
+        # Main layout
+        self.main_layout = QVBoxLayout()
+        self.main_layout.addLayout(self.form_layout)
+        self.main_layout.addLayout(self.button_layout)
+
+        self.setLayout(self.main_layout)
diff --git a/soitool/modules/module_authentication_board.py b/soitool/modules/module_authentication_board.py
index 5399ddd044a96a382011def70db29adad7acf48a..06ba84f67f0fee4b0a46b072c50bde45af22b0ea 100644
--- a/soitool/modules/module_authentication_board.py
+++ b/soitool/modules/module_authentication_board.py
@@ -4,10 +4,19 @@ from secrets import choice
 from PySide2.QtWidgets import QTableWidgetItem
 from PySide2 import QtGui
 from PySide2.QtCore import Qt
-from soitool.modules.module_base import resize_table
+from soitool.modules.module_base import (
+    resize_table,
+    qfont_with_pixel_size,
+    TABLE_CELL_DEFAULT_FONT,
+)
 from soitool.modules.code_table_base import CodeTableBase
 
-# Maximum number of codes is len(ROW_IDENTIFIERS)
+# Characters for first column,
+# it's length determines maximum number of codes (rows).
+ROW_IDENTIFIERS = string.ascii_uppercase
+
+# Maximum number of codes depends on ROW_IDENTIFIERS
+MAXIMUM_NO_OF_CODES = len(ROW_IDENTIFIERS)
 START_NO_OF_CODES = 10
 CODE_LENGTH = 25
 
@@ -16,11 +25,9 @@ CODE_LENGTH = 25
 CODE_CHARACTER_TYPE = "ascii"
 
 # Font for authentication codes, should be a monospaced font
-CODE_FONT = QtGui.QFont("Consolas", 10, QtGui.QFont.SansSerif)
-
-# Characters for first column,
-# it's length determines maximum number of codes (rows).
-ROW_IDENTIFIERS = string.ascii_uppercase
+CODE_FONT = qfont_with_pixel_size(
+    "Consolas", TABLE_CELL_DEFAULT_FONT.pixelSize(), QtGui.QFont.SansSerif
+)
 
 # Adds space between sets of characters, 0 => no spaces
 # If code is 123456 and interval is 2, code will be 12 34 56
@@ -33,7 +40,7 @@ HEADLINE_TEXT = "Autentiseringstavle"
 class AuthenticationBoardModule(CodeTableBase):
     """Modified QTableWidget representing SOI-module 'Autentiseringstavle'.
 
-    By default, the widget initializes with a headline, a row-count of
+    The default widget-initialization has a headline, a row-count of
     START_NO_OF_CODES and three columns.
     Row x in the first column contains the character ROW_IDENTIFIERS[x].
     Row x in the second column contains the character x.
@@ -70,6 +77,7 @@ class AuthenticationBoardModule(CodeTableBase):
                 "'{}'".format(CODE_CHARACTER_TYPE)
             )
         self.code_font = CODE_FONT
+        self.maximum_no_of_codes = MAXIMUM_NO_OF_CODES
 
         # Set default values for table to be generated
         if size is None and data is None:
@@ -137,6 +145,7 @@ class AuthenticationBoardModule(CodeTableBase):
             # Insert authentication-code in third column
             item_third = QTableWidgetItem(code)
             item_third.setFont(self.code_font)
+            item_third.setTextAlignment(Qt.AlignCenter)
             item_third.setFlags(item_third.flags() ^ Qt.ItemIsEditable)
             self.setItem(selected_row_index + 1, 2, item_third)
 
diff --git a/soitool/modules/module_base.py b/soitool/modules/module_base.py
index 1d6f055d20dd0a418317e7a77d3e140540159b2d..91d97dbcbade3b85432fbaed1415a3a394663b1d 100644
--- a/soitool/modules/module_base.py
+++ b/soitool/modules/module_base.py
@@ -2,11 +2,34 @@
 from abc import ABC
 from PySide2 import QtGui
 
+
+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
+
+
 # Font for module headline
-HEADLINE_FONT = QtGui.QFont()
-HEADLINE_FONT.setFamily("Arial")
-HEADLINE_FONT.setPointSize(12)
-HEADLINE_FONT.setWeight(100)
+HEADLINE_FONT = qfont_with_pixel_size("Arial", 24, 100)
+
+TABLE_CELL_DEFAULT_FONT = qfont_with_pixel_size("Arial", 16)
 
 
 class ModuleBase(ABC):
diff --git a/soitool/modules/module_freetext.py b/soitool/modules/module_freetext.py
index 95066bceea66e73d73013f3b930fecd92ef1484d..14ede836bcd46425bc8d10a1a198121b566759af 100644
--- a/soitool/modules/module_freetext.py
+++ b/soitool/modules/module_freetext.py
@@ -13,7 +13,11 @@ from PySide2.QtWidgets import (
 )
 from PySide2.QtCore import QSize, Qt
 from PySide2.QtGui import QIcon, QFontMetricsF
-from soitool.modules.module_base import ModuleBase, HEADLINE_FONT
+from soitool.modules.module_base import (
+    ModuleBase,
+    HEADLINE_FONT,
+    qfont_with_pixel_size,
+)
 
 
 class TextEditWithSizeOfContent(QTextEdit):
@@ -113,6 +117,9 @@ class FreeTextModule(ModuleBase, QWidget, metaclass=Meta):
         self.line_edit_header = LineEditWithSizeOfContent()
         self.line_edit_header.setFont(HEADLINE_FONT)
         self.text_edit_body = TextEditWithSizeOfContent()
+        self.text_edit_body.setFont(
+            qfont_with_pixel_size("Arial", HEADLINE_FONT.pixelSize())
+        )
 
         # When the contents of these widgets change we need to manually trigger
         # adjust of size, even on self. Without adjust of size on self the
diff --git a/soitool/modules/module_subtractorcodes.py b/soitool/modules/module_subtractorcodes.py
index 8622f14b415973186a6e8a1e76eef606a0503b05..89d3f5c479e4f153489101b426450849a5a3db59 100644
--- a/soitool/modules/module_subtractorcodes.py
+++ b/soitool/modules/module_subtractorcodes.py
@@ -3,36 +3,44 @@ import string
 from PySide2.QtWidgets import QTableWidgetItem
 from PySide2 import QtGui
 from PySide2.QtCore import Qt
-from soitool.modules.module_base import resize_table
+from soitool.modules.module_base import (
+    resize_table,
+    qfont_with_pixel_size,
+    TABLE_CELL_DEFAULT_FONT,
+)
 from soitool.modules.code_table_base import CodeTableBase
 
-# Maximum number of codes is len(ROW_IDENTIFIERS)/2 columns = 13
-START_NO_OF_CODES = 7
-CODE_LENGTH = 8
-
-# Font for subtractorcodes
-CODE_FONT = QtGui.QFont("Arial", 10, QtGui.QFont.SansSerif)
-
 # Characters for first and second column
 ROW_IDENTIFIERS = string.ascii_uppercase
 
-# Adds space between sets of characters, 0 => no spaces.
-# If code is 12345678 and interval is 2, code will be 1234 5678
+# Maximum number of codes is: number of row identifiers / 2 columns
+# = 13 if identifiers are A-Z
+MAXIMUM_NO_OF_CODES = len(ROW_IDENTIFIERS) // 2
+START_NO_OF_CODES = 7
+CODE_LENGTH = 8
+
+# Adds space between sets of characters, 0 => no spaces
+# If code is 12345678 and interval is 4, code will be 1234 5678
 SPACE_INTERVAL = 4
 SPACE_AMOUNT = 3
 
+# Font for subtractorcodes
+CODE_FONT = qfont_with_pixel_size(
+    "Arial", TABLE_CELL_DEFAULT_FONT.pixelSize(), QtGui.QFont.SansSerif
+)
+
 HEADLINE_TEXT = "Subtraktorkoder"
 
 
 class SubtractorcodesModule(CodeTableBase):
     """Modified QTablewidget representing SOI-module 'Subtraktorkoder'.
 
-    By default, the widget initializes with a headline, a row-count of
+    The default widget-initialization has a headline, a row-count of
     START_NO_OF_CODES and three columns.
-    If there are 2 rows and ROW_IDENTIFIERS is the alphabet, the first
-    column will contain A and B, and the second column will contain C and D.
     The third column contains subtractorcodes of length CODE_LENGTH, spaced out
     for readability if SPACE_INTERVAL and SPACE_AMOUNT larger than 0.
+    If there are 2 rows and ROW_IDENTIFIERS is the alphabet, the first
+    column will contain A and B, and the second column will contain C and D.
 
     If parameters are given, the widget initializes accordingly:
     'size' is a dict: {"width": int, "height": int},
@@ -48,18 +56,17 @@ class SubtractorcodesModule(CodeTableBase):
     def __init__(self, size=None, data=None):
         self.type = "SubtractorcodesModule"
 
-        if START_NO_OF_CODES > 13:
-            raise ValueError(
-                "Invalid value for CONSTANT 'START_NO_OF_CODES': "
-                "'{}'".format(START_NO_OF_CODES)
-            )
-        self.start_headline = HEADLINE_TEXT
-        self.code_length = CODE_LENGTH
-        self.start_no_of_codes = START_NO_OF_CODES
-        self.space_interval = SPACE_INTERVAL
-        self.space_amount = SPACE_AMOUNT
         self.code_character_type = "digits"
         self.code_font = CODE_FONT
+        self.maximum_no_of_codes = MAXIMUM_NO_OF_CODES
+
+        # Set default values for table to be generated
+        if size is None and data is None:
+            self.start_headline = HEADLINE_TEXT
+            self.start_no_of_codes = START_NO_OF_CODES
+            self.code_length = CODE_LENGTH
+            self.space_interval = SPACE_INTERVAL
+            self.space_amount = SPACE_AMOUNT
 
         CodeTableBase.__init__(self, size, data)
 
diff --git a/soitool/modules/module_table.py b/soitool/modules/module_table.py
index 43bef7fb8d9e3ca625877c9ae7dfae4705b3dd93..fff51d7e058351e3df4dde972e1db077481b8316 100644
--- a/soitool/modules/module_table.py
+++ b/soitool/modules/module_table.py
@@ -6,6 +6,7 @@ from soitool.modules.module_base import (
     resize_table,
     get_table_size,
     HEADLINE_FONT,
+    TABLE_CELL_DEFAULT_FONT,
 )
 
 START_ROWS = 2
@@ -42,6 +43,7 @@ class TableModule(ModuleBase, QTableWidget, metaclass=Meta):
         self.verticalHeader().hide()
         self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
         self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
+        self.setFont(TABLE_CELL_DEFAULT_FONT)
 
         # If parameters are None, start as empty table.
         if size is None and data is None:
diff --git a/test/test_module_authentication_and_subtractor.py b/test/test_module_authentication_and_subtractor.py
index b7add13a9c313317cc4167f8cdcdef7abf5e34c6..3eb4195928b69794204c40f25c56212bfa0be4fc 100644
--- a/test/test_module_authentication_and_subtractor.py
+++ b/test/test_module_authentication_and_subtractor.py
@@ -3,7 +3,7 @@ import unittest
 import string
 from PySide2 import QtGui
 from PySide2.QtWidgets import QApplication
-from PySide2.QtCore import Qt
+from PySide2.QtCore import Qt, QTimer
 from PySide2.QtTest import QTest
 from soitool.modules.module_authentication_board import (
     AuthenticationBoardModule,
@@ -39,7 +39,15 @@ class TestDefaultAuthenticationBoardAndSubtractorcodesModule(
 
     def setUp(self):
         """Create new AuthenticationBoardModule."""
+
+        def press_enter_on_active_dialog():
+            active_widget = app.activeModalWidget()
+            QTest.keyClick(active_widget, Qt.Key_Enter)
+
+        QTimer.singleShot(0, press_enter_on_active_dialog)
         self.authentication = AuthenticationBoardModule()
+
+        QTimer.singleShot(0, press_enter_on_active_dialog)
         self.subtractor = SubtractorcodesModule()
 
     def test_default_module(self):
@@ -201,16 +209,16 @@ class TestDefaultAuthenticationBoardAndSubtractorcodesModule(
             self.authentication.item(1, 1).text(), value_to_delete
         )
 
-        # Remove rows until only headline-row and a single code-row exist
-        for _ in range(1, self.authentication.rowCount() - 1):
+        # Remove rows until only headline-row and two code-rows exist
+        for _ in range(1, self.authentication.rowCount()):
             QTest.keyClick(self.authentication, Qt.Key_Down)
             QTest.keyClicks(self.authentication, "_", Qt.ControlModifier)
-        self.assertTrue(self.authentication.rowCount() == 2)
+        self.assertTrue(self.authentication.rowCount() == 3)
         # Try to remove final code-row, should not work
         QTest.keyClick(self.authentication, Qt.Key_Down)
         QTest.keyClicks(self.authentication, "_", Qt.ControlModifier)
         # Assert row was not removed
-        self.assertTrue(self.authentication.rowCount() == 2)
+        self.assertTrue(self.authentication.rowCount() == 3)
 
     def test_add_to_soi_smoke_test(self):
         """Test that module can be added to SOI."""
diff --git a/test/test_resolution_smoke_test.py b/test/test_resolution_smoke_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..479fcf8578c404fb4a69774e8bd7b56096d46bed
--- /dev/null
+++ b/test/test_resolution_smoke_test.py
@@ -0,0 +1,152 @@
+"""Test module that looks for differences in SOI modules across resolutions.
+
+This was written as a regression test for #125. Ideally it should also test the
+header of the SOI, but this is much more complicated to test for..
+
+## Important
+
+This test can not test across different resolutions by itself, this is up to
+the user. Our pipeline will test across a couple of different resolutions.
+"""
+import unittest
+from PySide2.QtWidgets import QApplication
+from PySide2 import QtGui
+from PySide2.QtCore import QTimer, Qt, QSysInfo
+from PySide2.QtTest import QTest
+from PySide2.QtGui import QGuiApplication
+from soitool.soi import SOI
+from soitool.modules.module_authentication_board import (
+    AuthenticationBoardModule,
+)
+from soitool.modules.module_subtractorcodes import SubtractorcodesModule
+from soitool.modules.module_predefined_codes import PredefinedCodesModule
+from soitool.new_module_dialog import MODULE_CHOICES
+from soitool.soi_workspace_widget import DATABASE_MODULES
+from soitool.database import Database
+
+# The error being ignored here is pylint telling us that 'test' is a standard
+# module, so the import should be placed further up. In our case we have an
+# actual custom module called 'test', so pylint is confused.
+# pylint: disable=C0411
+from test.test_database import TESTDBPATH
+
+
+if isinstance(QtGui.qApp, type(None)):
+    app = QApplication([])
+else:
+    app = QtGui.qApp
+
+# Modules with a popup as part of their __init__
+POPUP_MODULES = [
+    AuthenticationBoardModule,
+    SubtractorcodesModule,
+    PredefinedCodesModule,
+]
+
+
+def screen_information():
+    """Get string with information about the screen.
+
+    Returns
+    -------
+    str
+        String with screen information.
+    """
+    screen_string = ""
+    screen = QGuiApplication.primaryScreen()
+    screen_string += "screen.size() -> " + str(screen.size()) + "\n"
+    screen_string += (
+        "screen.physicalDotsPerInchX() -> "
+        + str(screen.physicalDotsPerInchX())
+        + "\n"
+    )
+    screen_string += (
+        "screen.physicalDotsPerInchY() -> "
+        + str(screen.physicalDotsPerInchY())
+        + "\n"
+    )
+    screen_string += (
+        "screen.logicalDotsPerInchX() -> "
+        + str(screen.logicalDotsPerInchX())
+        + "\n"
+    )
+    screen_string += (
+        "screen.logicalDotsPerInchY() -> "
+        + str(screen.logicalDotsPerInchY())
+        + "\n"
+    )
+    screen_string += (
+        "screen.devicePixelRatio() -> " + str(screen.devicePixelRatio()) + "\n"
+    )
+    return screen_string
+
+
+class TestModulesAcrossResolutions(unittest.TestCase):
+    """TestCase for modules across resolutions."""
+
+    @unittest.skipUnless(
+        QSysInfo.productType() == "windows",
+        "Test currently only able to target Windows",
+    )
+    def test_add_all_modules(self):
+        """Add all modules, reorganize, and assert result.
+
+        Expected result was gotten by simply running reorganize and noting down
+        the results. We should get the same result across different
+        resolutions.
+
+        Modules added to SOI must be the same every time the program is ran.
+
+        Test only works on Windows, as the expected result is based on the
+        Windows look-and-feel.
+
+        NOTE: This test needs to be updated when a new module is added,
+        deleted, or changed. It will fail until it is updated.
+        """
+        expected_result = [
+            {"x": 0, "y": 0, "page": 1, "name": "PredefinedCodesModule"},
+            {"x": 640, "y": 0, "page": 1, "name": "AuthenticationBoardModule"},
+            {"x": 1047.5, "y": 0, "page": 1, "name": "SubtractorcodesModule"},
+            {"x": 1273.0, "y": 0, "page": 1, "name": "FreeTextModule"},
+            {"x": 1373.0, "y": 0, "page": 1, "name": "TableModule"},
+        ]
+
+        # For use with modules that require a database
+        database = Database(db_path=TESTDBPATH)
+
+        def press_enter():
+            active_widget = app.activeModalWidget()
+
+            # AuthenticationBoardModule needs special treatment because the
+            # title can contain random info
+            if isinstance(active_widget, AuthenticationBoardModule):
+                # triple click to select existing text for overwrite
+                QTest.mouseDClick(active_widget.edit_headline, Qt.LeftButton)
+                QTest.mouseClick(active_widget.edit_headline, Qt.LeftButton)
+                # need to overwrite text because title otherwise contains
+                # unpredictable text
+                QTest.keyClicks(active_widget.edit_headline, "TestTitle")
+            QTest.keyClick(active_widget, Qt.Key_Enter)
+
+        soi = SOI()
+
+        for module in MODULE_CHOICES:
+            # If we're adding one of the modules with a popup as part of it's
+            # constructor we need to singleShot pressing enter to close it
+            if module in POPUP_MODULES:
+                QTimer.singleShot(0, press_enter)
+
+            if module in DATABASE_MODULES:
+                soi.add_module(module.__name__, module(database=database))
+            else:
+                soi.add_module(module.__name__, module())
+
+        soi.reorganize()
+
+        self.assertEqual(
+            expected_result,
+            [module["meta"] for module in soi.modules],
+            "All modules added to SOI and calling reorganize should result in "
+            "expected 'meta' information. Screen is: \n"
+            + screen_information(),
+        )