diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 241dd4ac5fa7095150553e2b6e4fe9228d61c74e..6073eca5d14ce4dec5fb7b1e8f5cba07726c7188 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -42,6 +42,14 @@ job_lint_pydocstyle:
   script:
     - pydocstyle --version
     - pydocstyle --match '.*.py' --convention=numpy soitool test
+
+job_lint_black:
+  stage: lint
+  <<: *docker_runner_tags_definition
+  image: morkolai/soitool-ci
+  script:
+    - black --version
+    - black -l 79 --check --diff soitool test
       
 job_test_gui_ubuntu_vnc:
   stage: test
diff --git a/requirements.txt b/requirements.txt
index a3125a740581d76f738d63ef4eb8c80e78785c78..bbcbfcad0b3ddf945af0e2206ca36faa343937fc 100644
Binary files a/requirements.txt and b/requirements.txt differ
diff --git a/scripts/CodeQualityCheck.ps1 b/scripts/CodeQualityCheck.ps1
index e2894fa734a9e2054caca683ea971f57eb0119d5..09f685c39a22a9cca2a298ea290272c4319f46fc 100644
--- a/scripts/CodeQualityCheck.ps1
+++ b/scripts/CodeQualityCheck.ps1
@@ -31,4 +31,6 @@ for ($i=0; $i -lt $files.Length; $i++){
     bandit $files[$i]
     Write-Output "`n===PYDOCSTYLE===`n"
     pydocstyle.exe --convention=numpy $files[$i]
+    Write-Output "`n===BLACK===`n"
+    black -l 79 --check --diff $files[$i]
 }
diff --git a/scripts/CodeQualityCheck.sh b/scripts/CodeQualityCheck.sh
index 899f9a49d7074d873a2e6ded71a2db4e8efd049c..4cc02886ff10bd9e5b375a6d8bbafa8b4b92fd8f 100644
--- a/scripts/CodeQualityCheck.sh
+++ b/scripts/CodeQualityCheck.sh
@@ -24,4 +24,6 @@ for file in $files; do
     bandit $file
     printf "\n===PYDOCSTYLE===\n"
     pydocstyle --convention=numpy $file
+    printf "\n===BLACK===\n"
+    black -l 79 --check --diff $file
 done
diff --git a/soitool/codebook_row_adder.py b/soitool/codebook_row_adder.py
index 39cc45fe93d85ee91aa93011579d2a286321d274..bf6c350d68efdc9b54d8f2c1a6e7cfc8eb45fd94 100644
--- a/soitool/codebook_row_adder.py
+++ b/soitool/codebook_row_adder.py
@@ -156,16 +156,19 @@ class CodebookRowAdder(QWidget):
         # Reset feedback-label
         self.label_feedback.setText("")
 
-        # Read input and uppercase first character of word and category
+        # Read input
         word_input = self.text_field_word.text()
-        word_input = word_input[0].upper() + word_input[1:]
         category_input = self.text_field_category.text()
-        category_input = category_input[0].upper() + category_input[1:]
         type_input = self.combo_type.currentText()
 
         # If word is not empty
         if len(word_input) > 0:
 
+            # Uppercase first character of word and category (if bot empty)
+            word_input = word_input[0].upper() + word_input[1:]
+            if len(category_input) > 0:
+                category_input = category_input[0].upper() + category_input[1:]
+
             db = Database()
 
             try:
diff --git a/soitool/codebook_to_pdf.py b/soitool/codebook_to_pdf.py
index 1e5ea38669c16b6262e675ff1bed32be58183b53..f7994a06d7640ab7a7555688c329d520d676b198 100644
--- a/soitool/codebook_to_pdf.py
+++ b/soitool/codebook_to_pdf.py
@@ -5,10 +5,10 @@ from reportlab.pdfgen import canvas
 from reportlab.platypus import (
     Table,
     Paragraph,
-    TableStyle,
-    SimpleDocTemplate,
     Spacer,
     PageBreak,
+    TableStyle,
+    SimpleDocTemplate,
 )
 from reportlab.lib.styles import ParagraphStyle
 from reportlab.lib import colors
@@ -179,7 +179,7 @@ class CodeAndDecodebookDocTemplate(SimpleDocTemplate):
     If code- and decodebook use 10 pages each, the total page count will be 20,
     but this class will draw 'Side 1 av 10' through 'Side 10 av 10' for both.
 
-    The first blank page (2 * Pagebreak) added will be marked as a separating
+    The first blank page (2 * PageBreak) added will be marked as a separating
     page, and will not contain 'Side x av y'.
     """
 
diff --git a/soitool/database.py b/soitool/database.py
index ac3e3b8163f5b4677173b44e98695e3b957071b4..7cbca53fae41914765c7206ac2d6317425812578 100644
--- a/soitool/database.py
+++ b/soitool/database.py
@@ -2,6 +2,7 @@
 import os
 import sqlite3
 import json
+from datetime import datetime
 import soitool.coder
 from soitool.enumerates import CodebookSort
 
@@ -10,6 +11,9 @@ DBNAME = "database"
 CURDIR = os.path.dirname(__file__)
 DBPATH = os.path.join(CURDIR, DBNAME)
 
+# Number og seconds in 24h
+SECONDS_IN_24H = 24 * 60 * 60
+
 # DDL-statements for creating tables
 CODEBOOK = (
     "CREATE TABLE CodeBook"
@@ -23,6 +27,8 @@ CATEGORYWORDS = (
 )
 BYHEART = "CREATE TABLE ByHeart(Word VARCHAR PRIMARY KEY)"
 
+LASTUPDATED = "CREATE TABLE LastUpdated(Timestamp DATETIME PRIMARY KEY)"
+
 
 class Database:
     """
@@ -30,9 +36,12 @@ class Database:
 
     Connects to existing db if found, creates new db if not.
     If db is created, tables are created and filled.
+
+    Holds a QTimer that requests an update of CodeBook on every timeout.
     """
 
     def __init__(self):
+
         db_exists = os.path.exists(DBPATH)
 
         if db_exists:
@@ -53,7 +62,7 @@ class Database:
 
     def create_tables(self):
         """Create tables CodeBook, CategoryWords and ByHeart."""
-        stmts = [CODEBOOK, CATEGORYWORDS, BYHEART]
+        stmts = [CODEBOOK, CATEGORYWORDS, BYHEART, LASTUPDATED]
 
         for stmt in stmts:
             self.conn.execute(stmt)
@@ -65,6 +74,7 @@ class Database:
         self.fill_codebook()
         self.fill_by_heart()
         self.fill_category_words()
+        self.fill_last_updated()
         self.conn.commit()
 
     def fill_codebook(self):
@@ -72,9 +82,9 @@ class Database:
         file_path = os.path.join(CURDIR, "testdata/long_codebook.json")
 
         # Load json as dict
-        f = open(file_path, "r", encoding="utf-8")
-        entries = json.load(f)
-        f.close()
+        file = open(file_path, "r", encoding="utf-8")
+        entries = json.load(file)
+        file.close()
 
         # Generate codes
         code_len = soitool.coder.get_code_length_needed(len(entries))
@@ -95,35 +105,45 @@ class Database:
     def fill_by_heart(self):
         """Read data from ByHeart.txt and fill DB-table ByHeart."""
         file_path = os.path.join(CURDIR, "testdata/ByHeart.txt")
-        f = open(file_path, "r", encoding="utf-8")
+        file = open(file_path, "r", encoding="utf-8")
 
         # Loop through words on file and insert them into ByHeart-table
         stmt = "INSERT INTO ByHeart(Word) VALUES(?)"
-        for expr in f:
+        for expr in file:
             self.conn.execute(stmt, (expr.rstrip(),))
-        f.close()
+        file.close()
 
     def fill_category_words(self):
         """Read data from CategoryWords.txt and fill DB-table CategoryWords."""
         file_path = os.path.join(CURDIR, "testdata/CategoryWords.txt")
-        f = open(file_path, "r", encoding="utf-8")
+        file = open(file_path, "r", encoding="utf-8")
 
         # Get number of categories on file
-        no_of_categories = int(f.readline().rstrip())
+        no_of_categories = int(file.readline().rstrip())
 
         # Loop through categories on file
         for _ in range(no_of_categories):
             # Get category and number of words in category
-            line = f.readline().split(", ")
+            line = file.readline().split(", ")
             category = line[0]
             no_of_words = int(line[1].rstrip())
 
             # Loop through words in category and add rows to DB
             stmt = "INSERT INTO CategoryWords(Word, Category) VALUES(?, ?)"
             for _ in range(no_of_words):
-                word = f.readline().rstrip()
+                word = file.readline().rstrip()
                 self.conn.execute(stmt, (word, category,))
-        f.close()
+        file.close()
+
+    def fill_last_updated(self):
+        """Fill table with current date and time."""
+        stmt = "INSERT INTO LastUpdated(Timestamp) VALUES(?)"
+        self.conn.execute(stmt, (str(datetime.now()),))
+
+    def update_last_updated(self):
+        """Update Timestamp in LastUpdated to current time."""
+        stmt = "UPDATE LastUpdated SET Timestamp = ?"
+        self.conn.execute(stmt, (str(datetime.now()),))
 
     def get_categories(self):
         """
@@ -208,13 +228,64 @@ class Database:
         stmt = stmt + "WHERE Word = ?"
         for i in range(number_of_entries):
             self.conn.execute(stmt, (codes.pop(), words[i][0]))
+        # Updates LastUpdated with current time
+        self.update_last_updated()
 
         print("Code in CodeBook updated")
 
+    def seconds_to_next_update(self, period):
+        """
+        Return time to next update of Codebook in seconds.
+
+        Parameters
+        ----------
+        period : int
+            The number of seconds between each update
+
+        Returns
+        -------
+        seconds_to_update : float
+            Time to next update in seconds
+        """
+        stmt = "SELECT Timestamp FROM LastUpdated"
+        last_updated = self.conn.execute(stmt).fetchall()[0][0]
+        # Convert datetime string to datetime object
+        last_updated = datetime.strptime(last_updated, "%Y-%m-%d %H:%M:%S.%f")
+        # Calculate the number of seconds until next update
+        seconds_to_update = (
+            period - (datetime.now() - last_updated).total_seconds()
+        )
+        # Since QTimer does not handle negative values
+        if seconds_to_update <= 0:
+            return 0
+
+        return seconds_to_update
+
+    def update_codebook_auto(self, timer):
+        """
+        Update Codebook if needed and update time for timer.
+
+        Parameters
+        ----------
+        timer : QTimer
+            Timer to set new interval on.
+        """
+        if self.seconds_to_next_update(SECONDS_IN_24H) <= 0:
+            self.update_codebook()
+        timer.setInterval(self.seconds_to_next_update(SECONDS_IN_24H) * 1000)
+
     def add_code_to(self, word, mode="ascii"):
         """
         Generate and insert a code for the new word in DB-table CodeBook.
 
+        This function is espescially designed for when a single word is added
+        to the CodeBook table. A unique code is generate and inserted in
+        Code which for the parameter word from before were NULL. Dependent on
+        the number of entries in the table various actions are performed. If
+        the new word makes the number of entries pass 26^x and the length of
+        the codes does not have he capacity, all the codes are updatet to an
+        appropriate length.
+
         Parameters
         ----------
         word : string
@@ -228,11 +299,18 @@ class Database:
         stmt = "SELECT COUNT(*) FROM CodeBook"
         number_of_entries = self.conn.execute(stmt).fetchall()[0][0]
         stmt = "SELECT Code FROM CodeBook"
-        # Incase db is approximate empty, min code lenght is 2
-        if number_of_entries < 2:
-            actual_code_len = len(self.conn.execute(stmt).fetchall()[1][0])
+        # In special case where table is empty
+        if number_of_entries <= 0:
+            raise ValueError("Can't add code to table with no words.")
+        # In special case table only has a single word
+        if number_of_entries == 1:
+            actual_code_len = soitool.coder.get_code_length_needed(
+                number_of_entries
+            )
         else:
-            actual_code_len = soitool.coder.get_code_length_needed(0)
+            # Since the newly added word's code is NULL and at [0][0],
+            # get [1][0] to get code length from an actual code
+            actual_code_len = len(self.conn.execute(stmt).fetchall()[1][0])
 
         needed_code_len = soitool.coder.get_code_length_needed(
             number_of_entries
@@ -244,7 +322,7 @@ class Database:
             # Get all codes and convert to set
             codes = self.conn.execute(stmt).fetchall()
             codes = {c[:][0] for c in codes}
-            # Get new unique code fro param word
+            # Get new unique code for param word
             code = soitool.coder.get_code(needed_code_len, mode)
             while code in codes:
                 code = soitool.coder.get_code(needed_code_len, mode)
diff --git a/soitool/inline_editable_soi_view.py b/soitool/inline_editable_soi_view.py
index 1734ca3531d101ea5671d735e00d1a28478b1d05..a1aaea031295cc74b1b8a844859c326419186795 100644
--- a/soitool/inline_editable_soi_view.py
+++ b/soitool/inline_editable_soi_view.py
@@ -1,7 +1,13 @@
 """Includes functionality for inline editing of SOI."""
 from PySide2.QtCore import Qt, QRectF, QTimer, QPoint, QMarginsF
-from PySide2.QtWidgets import QApplication, QScrollArea, QLabel, \
-    QGraphicsScene, QGraphicsView, QGraphicsRectItem
+from PySide2.QtWidgets import (
+    QApplication,
+    QScrollArea,
+    QLabel,
+    QGraphicsScene,
+    QGraphicsView,
+    QGraphicsRectItem,
+)
 from PySide2.QtGui import QFont, QPixmap, QBrush, QPalette, QPainter
 from PySide2.QtPrintSupport import QPrinter
 
@@ -90,9 +96,11 @@ class InlineEditableSOIView(QScrollArea):
             ok = painter.begin(printer)
 
             if not ok:
-                raise ValueError("Not able to begin QPainter using QPrinter "
-                                 "based on argument "
-                                 "filename '{}'".format(filename))
+                raise ValueError(
+                    "Not able to begin QPainter using QPrinter "
+                    "based on argument "
+                    "filename '{}'".format(filename)
+                )
 
             # render each page to own PDF page
             for i, modules in enumerate(self.pages):
@@ -100,9 +108,10 @@ class InlineEditableSOIView(QScrollArea):
                 x = 0
                 y = self.soi.HEIGHT * i + self.soi.PADDING * i
 
-                self.scene.render(painter, source=QRectF(x, y,
-                                                         self.soi.WIDTH,
-                                                         self.soi.HEIGHT))
+                self.scene.render(
+                    painter,
+                    source=QRectF(x, y, self.soi.WIDTH, self.soi.HEIGHT),
+                )
 
                 # if there are more pages, newPage
                 if i + 1 < len(self.pages):
@@ -119,8 +128,9 @@ class InlineEditableSOIView(QScrollArea):
 
             # adjust page size
             full_scene_height = y + self.soi.HEIGHT
-            self.scene.setSceneRect(QRectF(0, 0, self.soi.WIDTH,
-                                           full_scene_height))
+            self.scene.setSceneRect(
+                QRectF(0, 0, self.soi.WIDTH, full_scene_height)
+            )
 
             self.draw_page(x, y)
             self.draw_header(x + self.soi.PADDING, y + self.soi.PADDING, i + 1)
@@ -150,30 +160,37 @@ class InlineEditableSOIView(QScrollArea):
         page_number.setFont(QFont("Times New Roman", 50))
         # source: https://stackoverflow.com/a/8638114/3545896
         # CAUTION: does not work if font is set through stylesheet
-        label_width = \
+        label_width = (
             page_number.fontMetrics().boundingRect(page_number.text()).width()
+        )
         page_number.move(x + (self.soi.CONTENT_WIDTH - label_width) / 2, y)
         self.scene.addWidget(page_number)
 
         # classification
         classification = QLabel(self.soi.classification)
-        classification.setStyleSheet("background-color: rgba(0,0,0,0%); "
-                                     "color: red")
+        classification.setStyleSheet(
+            "background-color: rgba(0,0,0,0%); " "color: red"
+        )
         classification.setFont(QFont("Times New Roman", 50))
         # source: https://stackoverflow.com/a/8638114/3545896
         # CAUTION: does not work if font is set through stylesheet
-        label_width = (classification.fontMetrics()
-                       .boundingRect(classification.text()).width())
-        x_pos = x + self.soi.CONTENT_WIDTH - label_width - \
-            self.soi.HEADER_HEIGHT
+        label_width = (
+            classification.fontMetrics()
+            .boundingRect(classification.text())
+            .width()
+        )
+        x_pos = (
+            x + self.soi.CONTENT_WIDTH - label_width - self.soi.HEADER_HEIGHT
+        )
         classification.move(x_pos, y)
         self.scene.addWidget(classification)
 
         # patch
         pixmap = QPixmap(self.soi.icon)
         patch = QLabel()
-        patch.setPixmap(pixmap.scaled(self.soi.HEADER_HEIGHT,
-                                      self.soi.HEADER_HEIGHT))
+        patch.setPixmap(
+            pixmap.scaled(self.soi.HEADER_HEIGHT, self.soi.HEADER_HEIGHT)
+        )
         patch.move(x + self.soi.CONTENT_WIDTH - self.soi.HEADER_HEIGHT, y)
         self.scene.addWidget(patch)
 
@@ -186,19 +203,32 @@ class InlineEditableSOIView(QScrollArea):
         y : int
         """
         # color the page white
-        page_background = QGraphicsRectItem(x, y, self.soi.WIDTH,
-                                            self.soi.HEIGHT)
+        page_background = QGraphicsRectItem(
+            x, y, self.soi.WIDTH, self.soi.HEIGHT
+        )
         page_background.setBrush(QBrush(Qt.white))
         self.scene.addItem(page_background)
 
         # draw borders
         self.scene.addRect(x, y, self.soi.WIDTH, self.soi.HEIGHT)
-        self.scene.addRect(x + self.soi.PADDING, y + self.soi.PADDING,
-                           self.soi.CONTENT_WIDTH, self.soi.CONTENT_HEIGHT)
-        self.scene.addRect(x + self.soi.PADDING, y + self.soi.PADDING,
-                           self.soi.CONTENT_WIDTH, self.soi.CONTENT_HEIGHT)
-        self.scene.addRect(x + self.soi.PADDING, y + self.soi.PADDING,
-                           self.soi.CONTENT_WIDTH, self.soi.HEADER_HEIGHT)
+        self.scene.addRect(
+            x + self.soi.PADDING,
+            y + self.soi.PADDING,
+            self.soi.CONTENT_WIDTH,
+            self.soi.CONTENT_HEIGHT,
+        )
+        self.scene.addRect(
+            x + self.soi.PADDING,
+            y + self.soi.PADDING,
+            self.soi.CONTENT_WIDTH,
+            self.soi.CONTENT_HEIGHT,
+        )
+        self.scene.addRect(
+            x + self.soi.PADDING,
+            y + self.soi.PADDING,
+            self.soi.CONTENT_WIDTH,
+            self.soi.HEADER_HEIGHT,
+        )
 
     def setup_scene(self):
         """Prepare scene for use.
@@ -220,6 +250,7 @@ class InlineEditableSOIView(QScrollArea):
         Used to demonstrate zooming only, should be removed once the project
         matures.
         """
+
         def do_on_timeout():
             self.zoom(1 / 1.00005)
 
@@ -244,8 +275,9 @@ class InlineEditableSOIView(QScrollArea):
         # Zoom
         self.view.scale(zoom_factor, zoom_factor)
 
-        pos_old = self.view.mapToScene(QPoint(self.soi.WIDTH / 2,
-                                              self.soi.HEIGHT / 2))
+        pos_old = self.view.mapToScene(
+            QPoint(self.soi.WIDTH / 2, self.soi.HEIGHT / 2)
+        )
         pos_new = self.view.mapToScene(self.soi.WIDTH / 2, self.soi.HEIGHT / 2)
         delta = pos_new - pos_old
         self.view.translate(delta.x(), delta.y())
diff --git a/soitool/main.py b/soitool/main.py
index 8b55ed6c5e7869231b39663df1edfb9672e3d2ea..94daab90f293ea5cacd4b379de9638dc2b27bdfb 100644
--- a/soitool/main.py
+++ b/soitool/main.py
@@ -44,7 +44,7 @@ class CoolWidget(QtWidgets.QWidget):
                 self,
                 "Change text",
                 "Please type something",
-                QtWidgets.QLineEdit.Normal
+                QtWidgets.QLineEdit.Normal,
             )
             if ok:
                 self.qlabel.setText(text)
diff --git a/soitool/main_window.py b/soitool/main_window.py
index b5a3ddbac81db49e2ab0e7b433ceca1b39abffcf..bf2fb3d706c30a3cbeebb7c25d9c9498d6db86e0 100644
--- a/soitool/main_window.py
+++ b/soitool/main_window.py
@@ -17,9 +17,10 @@ from PySide2.QtWidgets import (
     QAction,
 )
 from PySide2.QtGui import QIcon
+from PySide2.QtCore import QTimer
+from soitool.soi_workspace_widget import SOIWorkspaceWidget
 from soitool.codebook import CodeBookTableView
 from soitool.codebook_row_adder import CodebookRowAdder
-from soitool.soi_workspace_widget import SOIWorkspaceWidget
 from soitool.codebook_to_pdf import generate_codebook_pdf
 from soitool.database import Database, DBPATH
 
@@ -40,6 +41,19 @@ class MainWindow(QMainWindow):
         self.setWindowTitle("SOI-tool")
         self.statusBar()
 
+        # Database instance
+        database = Database()
+        # Timer for automatic update of codes in CodeBook
+        self.timer = QTimer()
+        # Interval i set to msec since last 24h update
+        self.timer.setInterval(
+            database.seconds_to_next_update(60 * 60 * 24) * 1000
+        )
+        self.timer.timeout.connect(
+            lambda: database.update_codebook_auto(self.timer)
+        )
+        self.timer.start()
+
         # flytt ut til egen funksjon, for setup av menubar
         menu = self.menuBar()
         file_menu = menu.addMenu("SOI")
@@ -100,7 +114,7 @@ class MainWindow(QMainWindow):
         # Export full codebook
         export_codebook_full = QAction("Stor kodebok", self)
         export_codebook_full.setStatusTip("Eksporter stor kodebok som PDF")
-        export_codebook_full.triggered.connect(partial(generate_codebook_pdf))
+        export_codebook_full.triggered.connect(generate_codebook_pdf)
         export_codebook.addAction(export_codebook_full)
 
         # Export small codebook
diff --git a/soitool/module_list.py b/soitool/module_list.py
index d8c81252b5a56cb53f6db3f5cf9337c5c2d27270..bf65f8cb421b972260d59a2c0628ca01fa5e1837 100644
--- a/soitool/module_list.py
+++ b/soitool/module_list.py
@@ -26,11 +26,14 @@ class ModuleList(QListWidget):
         super().__init__()
 
         # full import path below to avoid circular dependency
-        if not isinstance(parent,
-                          soitool.soi_workspace_widget.SOIWorkspaceWidget):
-            raise RuntimeError('Only soitool.SOIWorkspaceWidget is '
-                               'acceptable type for parent-variable '
-                               'in class Module_list.')
+        if not isinstance(
+            parent, soitool.soi_workspace_widget.SOIWorkspaceWidget
+        ):
+            raise RuntimeError(
+                "Only soitool.SOIWorkspaceWidget is "
+                "acceptable type for parent-variable "
+                "in class Module_list."
+            )
         self.type = module_type
         self.parent = parent
         self.original_element_name = None
@@ -56,11 +59,14 @@ class ModuleList(QListWidget):
         """Fill list with elements."""
         # Get names of modules/attachments:
         if ModuleType(self.type) == ModuleType.MAIN_MODULE:
-            names = [module["meta"]["name"] for
-                     module in self.parent.soi.modules]
+            names = [
+                module["meta"]["name"] for module in self.parent.soi.modules
+            ]
         elif ModuleType(self.type) == ModuleType.ATTACHMENT_MODULE:
-            names = [attachment["meta"]["name"] for
-                     attachment in self.parent.soi.attachments]
+            names = [
+                attachment["meta"]["name"]
+                for attachment in self.parent.soi.attachments
+            ]
 
         for i, name in enumerate(names):
             item = QListWidgetItem(name)
diff --git a/soitool/modules/module_table.py b/soitool/modules/module_table.py
index 29adbce0881c19645afa7c8e0435eefc6748a197..77808f65a055310e6a299db0d16f067bcd3d4aad 100644
--- a/soitool/modules/module_table.py
+++ b/soitool/modules/module_table.py
@@ -4,7 +4,7 @@ from PySide2 import QtGui, QtCore
 from soitool.modules.module_base import ModuleBase
 
 HEADER_FONT = QtGui.QFont()
-HEADER_FONT.setFamily('Arial')
+HEADER_FONT.setFamily("Arial")
 HEADER_FONT.setPointSize(12)
 HEADER_FONT.setWeight(100)
 
@@ -78,14 +78,20 @@ class TableModule(ModuleBase, QTableWidget, metaclass=Meta):
         """
         if event.key() == QtCore.Qt.Key_Question:
             self.add_column()
-        elif (event.modifiers() == QtCore.Qt.ShiftModifier
-              and event.key() == QtCore.Qt.Key_Underscore):
+        elif (
+            event.modifiers() == QtCore.Qt.ShiftModifier
+            and event.key() == QtCore.Qt.Key_Underscore
+        ):
             self.remove_column()
-        elif (event.modifiers() == QtCore.Qt.ControlModifier
-              and event.key() == QtCore.Qt.Key_Plus):
+        elif (
+            event.modifiers() == QtCore.Qt.ControlModifier
+            and event.key() == QtCore.Qt.Key_Plus
+        ):
             self.add_row()
-        elif (event.modifiers() == QtCore.Qt.ControlModifier
-              and event.key() == QtCore.Qt.Key_Underscore):
+        elif (
+            event.modifiers() == QtCore.Qt.ControlModifier
+            and event.key() == QtCore.Qt.Key_Underscore
+        ):
             self.remove_row()
         else:
             super(TableModule, self).keyPressEvent(event)
diff --git a/soitool/pdf_preview_widget.py b/soitool/pdf_preview_widget.py
index f241cb20cb087efdffcf52ae9057a1d99f47d143..a868be31aa5ba3a0bd7c86b5c829188a12b8689c 100644
--- a/soitool/pdf_preview_widget.py
+++ b/soitool/pdf_preview_widget.py
@@ -24,10 +24,12 @@ class PDFPreviewWidget(QWebEngineView):
 
     def __init__(self, initial_url):
         super().__init__()
-        self.page().settings().setAttribute(QWebEngineSettings.PluginsEnabled,
-                                            True)
+        self.page().settings().setAttribute(
+            QWebEngineSettings.PluginsEnabled, True
+        )
         # the following setting is the default, but explicitly enabling to be
         # explicit
-        self.page().settings().setAttribute(QWebEngineSettings.
-                                            PdfViewerEnabled, True)
+        self.page().settings().setAttribute(
+            QWebEngineSettings.PdfViewerEnabled, True
+        )
         self.load(QUrl(initial_url))
diff --git a/soitool/setup_settings.py b/soitool/setup_settings.py
index 3fef0c0c7d804eeff898b060f91a7e56ea68fa95..1f23448163ae9224e83db8ac1d9ffbecb4fcd7e4 100644
--- a/soitool/setup_settings.py
+++ b/soitool/setup_settings.py
@@ -4,8 +4,16 @@ This dialog is called when a button in soi_workspace_widget is pressed
 
 """
 
-from PySide2.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QFormLayout, \
-    QLabel, QLineEdit, QRadioButton, QPushButton
+from PySide2.QtWidgets import (
+    QDialog,
+    QVBoxLayout,
+    QHBoxLayout,
+    QFormLayout,
+    QLabel,
+    QLineEdit,
+    QRadioButton,
+    QPushButton,
+)
 
 
 class Setup(QDialog):  # pylint: disable = R0902
@@ -34,8 +42,8 @@ class Setup(QDialog):  # pylint: disable = R0902
         self.layout_setup.addWidget(self.label_header)
         self.head1 = QLabel("Header1")  # Change variablename later
         self.head2 = QLabel("Header2")  # Change variablename later
-        self.hline1 = QLineEdit()    # Change variablename later
-        self.hline2 = QLineEdit()    # Change variablename later
+        self.hline1 = QLineEdit()  # Change variablename later
+        self.hline2 = QLineEdit()  # Change variablename later
         self.layout_header.addRow(self.head1, self.hline1)
         self.layout_header.addRow(self.head2, self.hline2)
         self.layout_setup.addLayout(self.layout_header)
@@ -79,3 +87,7 @@ class Setup(QDialog):  # pylint: disable = R0902
 
         self.button_cancel.clicked.connect(self.reject)  # esc-key (default)
         self.button_save.clicked.connect(self.accept)  # enter-key (default)
+
+    # need two functions, save and cancel
+    # when cancel, clear lineedits and set radiobuttons to default or SOI-parts
+    # when save, lineedits writes to labels and find a way to get radiobuttons
diff --git a/soitool/soi.py b/soitool/soi.py
index 7a4281db04e573965cd4eb7bd8a296fb499fa0c5..4ad77ea0481aa4f83f499bb56eb8acc76bf178fc 100644
--- a/soitool/soi.py
+++ b/soitool/soi.py
@@ -12,7 +12,7 @@ class ModuleType(Enum):
     ATTACHMENT_MODULE = 1
 
 
-class SOI():
+class SOI:
     """Datastructure for SOI.
 
     Holds all info about an SOI necessary to view and edit it.
@@ -72,20 +72,22 @@ class SOI():
     # separate data classes (auto-placement stuff in one class, styling in
     # another, etc).
     # pylint: disable=r0913
-    def __init__(self,
-                 title="Default SOI title",
-                 description="Default SOI description",
-                 version="1",
-                 date=None,
-                 valid_from=None,
-                 valid_to=None,
-                 icon="soitool/media/HVlogo.png",
-                 classification="ugradert",
-                 orientation="landscape",
-                 placement_strategy="auto",
-                 algorithm_bin="BFF",
-                 algorithm_pack="MaxRectsBI",
-                 algorithm_sort="SORT_AREA"):
+    def __init__(
+        self,
+        title="Default SOI title",
+        description="Default SOI description",
+        version="1",
+        date=None,
+        valid_from=None,
+        valid_to=None,
+        icon="soitool/media/HVlogo.png",
+        classification="ugradert",
+        orientation="landscape",
+        placement_strategy="auto",
+        algorithm_bin="BFF",
+        algorithm_pack="MaxRectsBI",
+        algorithm_sort="SORT_AREA",
+    ):
 
         # populate date-related arguments if they are not supplied by the user
         if date is None:
@@ -122,31 +124,16 @@ class SOI():
         self.modules = [
             {
                 "widget": TableModule(),
-                "meta": {
-                    "x": 0,
-                    "y": 0,
-                    "page": 1,
-                    "name": 'Tabell1'
-                }
+                "meta": {"x": 0, "y": 0, "page": 1, "name": "Tabell1"},
             },
             {
                 "widget": TableModule(),
-                "meta": {
-                    "x": 0,
-                    "y": 0,
-                    "page": 1,
-                    "name": 'Tabell2'
-                }
+                "meta": {"x": 0, "y": 0, "page": 1, "name": "Tabell2"},
             },
             {
                 "widget": TableModule(),
-                "meta": {
-                    "x": 0,
-                    "y": 0,
-                    "page": 2,
-                    "name": 'Tabell3'
-                }
-            }
+                "meta": {"x": 0, "y": 0, "page": 2, "name": "Tabell3"},
+            },
         ]
 
         # NOTE
@@ -154,12 +141,7 @@ class SOI():
         self.attachments = [
             {
                 "widget": TableModule(),
-                "meta": {
-                    "x": 0,
-                    "y": 0,
-                    "page": 2,
-                    "name": 'Tabell1'
-                }
+                "meta": {"x": 0, "y": 0, "page": 2, "name": "Tabell1"},
             }
         ]
 
@@ -177,16 +159,22 @@ class SOI():
             itself a dict with fields "x", "y" and "page", and "widget" is a
             widget based on "ModuleBase"
         """
-        distance_to_start_of_next_soi_content_y = self.CONTENT_HEIGHT + \
-            self.PADDING * 2 + self.HEADER_HEIGHT
+        distance_to_start_of_next_soi_content_y = (
+            self.CONTENT_HEIGHT + self.PADDING * 2 + self.HEADER_HEIGHT
+        )
 
-        scene_skip_distance_page_height = \
-            distance_to_start_of_next_soi_content_y * \
-            (module["meta"]["page"] - 1)
+        scene_skip_distance_page_height = (
+            distance_to_start_of_next_soi_content_y
+            * (module["meta"]["page"] - 1)
+        )
 
         new_x = module["meta"]["x"] + self.PADDING
-        new_y = module["meta"]["y"] + self.PADDING + self.HEADER_HEIGHT + \
-            scene_skip_distance_page_height
+        new_y = (
+            module["meta"]["y"]
+            + self.PADDING
+            + self.HEADER_HEIGHT
+            + scene_skip_distance_page_height
+        )
 
         module["widget"].set_pos(QPoint(new_x, new_y))
 
@@ -199,8 +187,9 @@ class SOI():
         next to each other from left to right
         """
         x = self.MODULE_PADDING
-        first_page_modules = [module for module in self.modules
-                              if module["meta"]["page"] == 1]
+        first_page_modules = [
+            module for module in self.modules if module["meta"]["page"] == 1
+        ]
 
         for module in first_page_modules:
             module["meta"]["x"] = x
@@ -214,8 +203,9 @@ class SOI():
         # NOTE the following is simply duplicated.. left like this to KISS
         # will be replaced by rectpack anyways
         x = self.MODULE_PADDING
-        second_page_modules = [module for module in self.modules
-                               if module["meta"]["page"] == 2]
+        second_page_modules = [
+            module for module in self.modules if module["meta"]["page"] == 2
+        ]
         for module in second_page_modules:
             module["meta"]["x"] = x
             module["meta"]["y"] = self.MODULE_PADDING
diff --git a/soitool/soi_workspace_widget.py b/soitool/soi_workspace_widget.py
index 76b5531b35690ce19984de8cdd938edd232b8bb6..c2ea49e1dc3b8edb05fb38cf181269781f2080a6 100644
--- a/soitool/soi_workspace_widget.py
+++ b/soitool/soi_workspace_widget.py
@@ -3,8 +3,13 @@
 Meant for use inside of tabs in our program.
 
 """
-from PySide2.QtWidgets import QWidget, QHBoxLayout, QVBoxLayout, QPushButton, \
-    QLabel
+from PySide2.QtWidgets import (
+    QWidget,
+    QHBoxLayout,
+    QVBoxLayout,
+    QPushButton,
+    QLabel,
+)
 from soitool.soi import SOI, ModuleType
 from soitool.module_list import ModuleList
 from soitool.inline_editable_soi_view import InlineEditableSOIView
diff --git a/test/test_codebook_to_pdf.py b/test/test_codebook_to_pdf.py
index 8a312c9b3961874874d06985d9f6bfefc6cb5a1e..5aa94bee06349f604c97f6065d7c10d0dc8112ab 100644
--- a/test/test_codebook_to_pdf.py
+++ b/test/test_codebook_to_pdf.py
@@ -19,7 +19,7 @@ class ExportTest(unittest.TestCase):
 
         # Assert correct filename for full codebook
         expected = f"Kodebok_{today}.pdf"
-        actual = codebook_to_pdf.generate_filename()
+        actual = codebook_to_pdf.generate_filename(small=False)
         self.assertEqual(expected, actual)
 
         # Assert correct filename for small codebook
@@ -31,7 +31,7 @@ class ExportTest(unittest.TestCase):
         """Test generated PDF-file exist."""
         # Test full codebook (default)
         codebook_to_pdf.generate_codebook_pdf()
-        file_name = codebook_to_pdf.generate_filename()
+        file_name = codebook_to_pdf.generate_filename(small=False)
         file_path_full = os.path.join(SOITOOL_ROOT_PATH, file_name)
         # Assert file exists
         self.assertTrue(os.path.exists(file_path_full))
diff --git a/test/test_database.py b/test/test_database.py
index 65f7cbbeefa25986503a0d4449cfbff9676860c4..5f020b5e963d622c02d68b6088a9cf1673035257 100644
--- a/test/test_database.py
+++ b/test/test_database.py
@@ -3,6 +3,8 @@ import os
 from pathlib import Path
 import unittest
 import json
+from time import sleep
+from datetime import datetime
 from soitool.database import Database
 from soitool.coder import get_code_length_needed
 
@@ -105,6 +107,34 @@ class DatabaseTest(unittest.TestCase):
             self.assertEqual(entry["type"], actual[i][2])
             self.assertRegex(actual[i][3], "[A-Z]{" + str(code_len) + "}")
 
+    def test_last_updated(self):
+        """Assert table LastUpdated is filled when db is created."""
+        stmt = "SELECT Timestamp FROM LastUpdated"
+        # [:19] to skip microseconds
+        last_update = self.database.conn.execute(stmt).fetchall()[0][0][:19]
+        # Using raw string to not make backslash escape character
+        self.assertRegex(
+            last_update, r"(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})"
+        )
+
+    def test_update_last_updated(self):
+        """Assert that the time gets updated when running method."""
+        # Get two datetimes that should only differ by sleep_time
+        stmt = "SELECT Timestamp FROM LastUpdated"
+        self.database.update_last_updated()
+        first_time = self.database.conn.execute(stmt).fetchall()[0][0]
+        sleep_time = 2
+        sleep(sleep_time)
+        self.database.update_last_updated()
+        second_time = self.database.conn.execute(stmt).fetchall()[0][0]
+        # Converts from string to datetime object
+        first_time = datetime.strptime(first_time, "%Y-%m-%d %H:%M:%S.%f")
+        second_time = datetime.strptime(second_time, "%Y-%m-%d %H:%M:%S.%f")
+        # Calculates difference in seconds
+        time_diff = (second_time - first_time).total_seconds()
+        # Compares difference with sleep_time
+        self.assertAlmostEqual(time_diff, sleep_time, delta=0.2)
+
     def test_get_categories(self):
         """Assert function get_categories works as expected."""
         file_path = os.path.join(TESTDATA_PATH, "CategoryWords.txt")
@@ -175,18 +205,17 @@ class DatabaseTest(unittest.TestCase):
 
     def test_update_codebook(self):
         """Test that the codes get updated."""
-        # Get number of entries
-        stmt = "SELECT COUNT(*) FROM CodeBook ORDER BY Word"
-        number_of_entries = self.database.conn.execute(stmt).fetchall()[0][0]
-        # Get old and updated word-code combinations
-        stmt = "SELECT Word, Code FROM CodeBook"
-        old = self.database.conn.execute(stmt).fetchall()
+        # Get entries before and after update
+        stmt = "SELECT Word, Code FROM CodeBook ORDER BY Word"
+        old_entries = self.database.conn.execute(stmt).fetchall()
         self.database.update_codebook()
-        updated = self.database.conn.execute(stmt).fetchall()
-        # Collect approximately score of not updated pairs
+        new_entries = self.database.conn.execute(stmt).fetchall()
+        # Collect approximately score of not updated pairs since there is a
+        # chance for a word to get the same code again
         pairs = 0
+        number_of_entries = len(old_entries)
         for i in range(0, number_of_entries, 2):
-            if old[i]["Code"] == updated[i]["Code"]:
+            if old_entries[i]["Code"] == new_entries[i]["Code"]:
                 pairs = pairs + 1
         # Test that at least some of the test are new
         self.assertTrue(pairs < number_of_entries)
@@ -195,11 +224,11 @@ class DatabaseTest(unittest.TestCase):
         """Test code length gets extended when number of entries makes it."""
         three_letter_len = 26 ** 2
         stmt_count = "SELECT COUNT(*) FROM CodeBook"
-        numb_of_entries = self.database.conn.execute(stmt_count).fetchall()[0][
+        number_of_entries = self.database.conn.execute(stmt_count).fetchall()[
             0
-        ]
+        ][0]
         # Codes only gets extended when number of entries pass 26**x
-        if numb_of_entries == (three_letter_len):
+        if number_of_entries == (three_letter_len):
             # Get length of current codes
             stmt_code = "SELECT Code FROM CodeBook"
             code_len = len(
@@ -211,20 +240,42 @@ class DatabaseTest(unittest.TestCase):
             self.database.conn.execute(stmt, ("676", "676", None))
             self.database.update_codebook()
             # Check that entry got inserted
-            numb_of_entries = self.database.conn.execute(
+            number_of_entries = self.database.conn.execute(
                 stmt_count
             ).fetchall()[0][0]
-            self.assertEqual(numb_of_entries, three_letter_len + 1)
+            self.assertEqual(number_of_entries, three_letter_len + 1)
             # Test that codes got extended length
             code_len = len(
                 self.database.conn.execute(stmt_code).fetchall()[0][0]
             )
-            self.assertEqual(code_len, get_code_length_needed(numb_of_entries))
+            self.assertEqual(
+                code_len, get_code_length_needed(number_of_entries)
+            )
 
         else:
             print("ERROR: Database is not 675 entries long, cant run test")
             self.assertTrue(False)  # pylint: disable=W1503
 
+    def test_seconds_to_next_update(self):
+        """Compares (24h - time slept) and the function return value."""
+        seconds_in_24h = 24 * 60 * 60
+        # Insert current time LastUpdated table in db
+        self.database.update_last_updated()
+        # Sleeps to make time difference
+        sleep_time = 2
+        sleep(sleep_time)
+        # Calculates expected return value and gets return value
+        expected_time = seconds_in_24h - sleep_time
+        actual_time = self.database.seconds_to_next_update(seconds_in_24h)
+        # Compares expected and function return value with
+        self.assertAlmostEqual(expected_time, actual_time, delta=0.2)
+
+    def teset_seconds_to_next_update_complete_period(self):
+        """Check that seconds to next update can returns 0 and not negative."""
+        self.database.update_last_updated()
+        sleep(2)
+        self.assertEqual(0, self.database.seconds_to_next_update(1))
+
     def test_add_code(self):
         """Test add a single code to CodeBook."""
         testdata = ("Testword", "Testcategory")
diff --git a/test/test_main.py b/test/test_main.py
index 3255793a528443b4115c6ffccb8e029aeec7f9ab..3b116e47582079a8925993f2f5595a87f5b72448 100644
--- a/test/test_main.py
+++ b/test/test_main.py
@@ -51,8 +51,7 @@ class TestMain(unittest.TestCase):
     def test_starts_up(self):
         """Test at widget kan starte opp."""
         self.assertEqual(
-            self.widget.qlabel.text(),
-            self.test_text1,
+            self.widget.qlabel.text(), self.test_text1,
         )
         self.assertTrue(self.widget.isVisible())
 
@@ -65,9 +64,7 @@ class TestMain(unittest.TestCase):
             # child_line_edit (a child of the active widget)
             active_widget = app.activeModalWidget()
 
-            child_line_edit = active_widget.findChild(
-                QtWidgets.QLineEdit
-            )
+            child_line_edit = active_widget.findChild(QtWidgets.QLineEdit)
 
             QtTest.QTest.keyClicks(child_line_edit, self.test_text2)
             QtTest.QTest.keyClick(child_line_edit, QtCore.Qt.Key_Enter)
@@ -76,8 +73,7 @@ class TestMain(unittest.TestCase):
         QtTest.QTest.mouseClick(self.widget.button, QtCore.Qt.LeftButton)
 
         self.assertEqual(
-            self.widget.qlabel.text(),
-            self.test_text2,
+            self.widget.qlabel.text(), self.test_text2,
         )
 
     def test_change_text_not_ok(self):
@@ -102,10 +98,9 @@ class TestMain(unittest.TestCase):
         QtTest.QTest.mouseClick(self.widget.button, QtCore.Qt.LeftButton)
 
         self.assertNotEqual(
-            self.widget.qlabel.text(),
-            self.test_text2,
+            self.widget.qlabel.text(), self.test_text2,
         )
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     unittest.main()
diff --git a/test/test_main_window.py b/test/test_main_window.py
index 5e6290c7ac066f54a4cf05b4192380b956f4393f..894f10cfe69f9b803ad1bb558db9d559f5ed1de8 100644
--- a/test/test_main_window.py
+++ b/test/test_main_window.py
@@ -31,5 +31,5 @@ class TestMainWindow(unittest.TestCase):
         self.assertEqual(expected, actual)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     unittest.main()