diff --git a/scripts/.pylintrc b/scripts/.pylintrc
index 687b3068dd56f50726927545445e5430949ee7da..df5d3009783eb70620b682dffcc59e01062c66fd 100644
--- a/scripts/.pylintrc
+++ b/scripts/.pylintrc
@@ -504,7 +504,7 @@ valid-metaclass-classmethod-first-arg=cls
 max-args=5
 
 # Maximum number of attributes for a class (see R0902).
-max-attributes=7
+max-attributes=15
 
 # Maximum number of boolean expressions in an if statement.
 max-bool-expr=5
diff --git a/soitool/main_window.py b/soitool/main_window.py
index cff2e51fa14c2ccea2091e4f506ecfd1fe51877a..6a7ae08ddafc1efff2c39d839cdabccd5badda48 100644
--- a/soitool/main_window.py
+++ b/soitool/main_window.py
@@ -112,6 +112,8 @@ class SOIWorkspaceWidget(QWidget):
     def __init__(self):
         super().__init__()
 
+        self.soi = SOI()
+
         self.layout_wrapper = QHBoxLayout()
         self.layout_sidebar = QVBoxLayout()
 
@@ -121,7 +123,7 @@ class SOIWorkspaceWidget(QWidget):
         self.button_new_module.setStatusTip("Legg til en ny modul")
         self.button_setup = QPushButton("Oppsett")
         self.list_modules = QListWidget()
-        self.view = ViewArea()
+        self.view = ViewArea(self.soi)
         self.widget_sidebar = QWidget()
         self.widget_sidebar.setFixedWidth(200)
 
@@ -172,8 +174,11 @@ class SOIWorkspaceWidget(QWidget):
             self.list_modules.insertItem(i, item)
 
 
-class ViewArea(QScrollArea):
-    """Widget som kan byttes ut med view, edit etc."""
+class SOI():
+    """Temporary representation of SOI.
+
+    Holds all info about an SOI necessary to view and edit it.
+    """
 
     A4_RATIO = 1.414
 
@@ -185,10 +190,139 @@ class ViewArea(QScrollArea):
     CONTENT_WIDTH = WIDTH - PADDING * 2
     CONTENT_HEIGHT = HEIGHT - PADDING * 2
     HEADER_HEIGHT = 100
+    MODULE_PADDING = 10
 
     def __init__(self):
+
+        # NOTE
+        # * test modules, just to have something show up on screen
+        # * not valid until reorganize has been run, as the positions must be
+        #   updated
+        self.modules = [
+            {
+                "widget": TableModule(),
+                "meta": {
+                    "x": 0,
+                    "y": 0,
+                    "page": 1
+                }
+            },
+            {
+                "widget": TableModule(),
+                "meta": {
+                    "x": 0,
+                    "y": 0,
+                    "page": 1
+                }
+            },
+            {
+                "widget": TableModule(),
+                "meta": {
+                    "x": 0,
+                    "y": 0,
+                    "page": 2
+                }
+            }
+        ]
+
+        self.reorganize()
+
+    def update_module_widget_position(self, module):
+        """Update position of module widget based on meta position.
+
+        This function is very much WIP..
+
+        Parameters
+        ----------
+        module : see description
+            should be dict of fields "meta" and "widget", where "meta" is
+            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
+
+        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
+
+        module["widget"].set_pos(QPoint(new_x, new_y))
+
+    def reorganize(self):
+        """Update x,y positions of modules.
+
+        In the future this is where rectpack will do it's magic, for now it is
+        a WIP just to get some kind of positioning working. The positioning
+        scheme for now is as follows: for each page 1 and 2, position widgets
+        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]
+
+        for module in first_page_modules:
+            module["meta"]["x"] = x
+            module["meta"]["y"] = self.MODULE_PADDING
+
+            self.update_module_widget_position(module)
+
+            widget_width, _ = module["widget"].get_size()
+            x = x + self.MODULE_PADDING + widget_width
+
+        # 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]
+        for module in second_page_modules:
+            module["meta"]["x"] = x
+            module["meta"]["y"] = self.MODULE_PADDING
+
+            self.update_module_widget_position(module)
+
+            widget_width, _ = module["widget"].get_size()
+            x = x + self.MODULE_PADDING + widget_width
+
+
+class ViewArea(QScrollArea):
+    """Widget som kan byttes ut med view, edit etc."""
+
+    def is_widget_in_scene(self, widget):
+        """Indicate wether given widget already has a proxy in the scene."""
+        for page in self.pages:
+            for proxy in page:
+                if proxy.widget() == widget:
+                    return True
+        return False
+
+    def setup_proxies(self):
+        """Set up proxies for the widgets of SOI modules."""
+        for module in self.soi.modules:
+            if not self.is_widget_in_scene(module["widget"]):
+                proxy = self.scene.addWidget(module["widget"])
+
+                while len(self.pages) < module["meta"]["page"]:
+                    self.pages.append(set())
+
+                self.pages[module["meta"]["page"] - 1].add(proxy)
+
+    def mousePressEvent(self, _):
+        """Reorganize modules when pressed.
+
+        This is a temporary way to activate reorganization of widgets. Note
+        that will not be triggered by clicks on modules in the scene
+        """
+        self.soi.reorganize()
+
+    def __init__(self, soi):
         super().__init__()
 
+        self.soi = soi
+
         self.pages = []
 
         # necessary to make the scroll area fill the space it's given
@@ -198,40 +332,34 @@ class ViewArea(QScrollArea):
         self.scene = QGraphicsScene()
         self.setup_scene()
         self.view = QGraphicsView(self.scene)
-        self.view.scale(0.75, 0.75)
 
         self.setWidget(self.view)
 
-        # fill will dummy pages
-        self.pages.append(0)
-        self.pages.append(0)
-        self.pages.append(0)
-        self.pages.append(0)
-        self.pages.append(0)
+        self.setup_proxies()
 
         self.update_drawn_pages()
 
-        # table to show inline edit works
-        table = TableModule()
-        table.move(self.PADDING + 10, self.PADDING + self.HEADER_HEIGHT + 10)
-        self.scene.addWidget(table)
-
-        self.launch_auto_zoom()
+        # self.launch_auto_zoom()
 
     def update_drawn_pages(self):
-        """Upate pages to reflect pages."""
-        for i, _ in enumerate(self.pages, start=1):
+        """Update drawn pages to reflect self.pages."""
+        for i, modules in enumerate(self.pages, start=1):
 
             x = 0
-            y = self.HEIGHT * max(i - 1, 0) + self.PADDING * max(i - 1, 0)
+            y = self.soi.HEIGHT * max(i - 1, 0) + \
+                self.soi.PADDING * max(i - 1, 0)
 
             # adjust page size
-            full_scene_height = y + self.HEIGHT
-            self.scene.setSceneRect(QRectF(0, 0, self.WIDTH,
+            full_scene_height = y + self.soi.HEIGHT
+            self.scene.setSceneRect(QRectF(0, 0, self.soi.WIDTH,
                                            full_scene_height))
 
             self.draw_page(x, y)
-            self.draw_header(x + self.PADDING, y + self.PADDING, i)
+            self.draw_header(x + self.soi.PADDING, y + self.soi.PADDING, i)
+
+            for module in modules:
+                # redraw of pages requires modules to be moved to front again
+                module.setZValue(1)
 
     def draw_header(self, x, y, page_number):
         """Draw header staring at given position.
@@ -242,39 +370,43 @@ class ViewArea(QScrollArea):
         y : int
         """
         # title
-        label = QLabel("SOI TITLE HERE")
-        label.move(x, y)
-        label.setStyleSheet("background-color: rgba(0,0,0,0%)")
-        label.setFont(QFont("Times New Roman", 50))
-        self.scene.addWidget(label)
+        label_title = QLabel("SOI TITLE HERE")
+        label_title.move(x, y)
+        label_title.setStyleSheet("background-color: rgba(0,0,0,0%)")
+        label_title.setFont(QFont("Times New Roman", 50))
+        self.scene.addWidget(label_title)
 
         # page numbering
-        label = QLabel("{} av {}".format(page_number, len(self.pages)))
-        label.setStyleSheet("background-color: rgba(0,0,0,0%)")
-        label.setFont(QFont("Times New Roman", 50))
+        page_number = QLabel("{} av {}".format(page_number, len(self.pages)))
+        page_number.setStyleSheet("background-color: rgba(0,0,0,0%)")
+        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.fontMetrics().boundingRect(label.text()).width()
-        label.move(x + (self.CONTENT_WIDTH - label_width) / 2, y)
-        self.scene.addWidget(label)
+        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)
 
         # grading
-        label = QLabel("UGRADERT")
-        label.setStyleSheet("background-color: rgba(0,0,0,0%); color: red")
-        label.setFont(QFont("Times New Roman", 50))
+        grading = QLabel("UGRADERT")
+        grading.setStyleSheet("background-color: rgba(0,0,0,0%); color: red")
+        grading.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.fontMetrics().boundingRect(label.text()).width()
-        label.move(x + self.CONTENT_WIDTH - label_width - self.HEADER_HEIGHT,
-                   y)
-        self.scene.addWidget(label)
+        label_width = \
+            grading.fontMetrics().boundingRect(grading.text()).width()
+        x_pos = x + self.soi.CONTENT_WIDTH - label_width - \
+            self.soi.HEADER_HEIGHT
+        grading.move(x_pos, y)
+        self.scene.addWidget(grading)
 
         # patch
         pixmap = QPixmap("soitool/media/HVlogo.png")
-        label = QLabel()
-        label.setPixmap(pixmap.scaled(self.HEADER_HEIGHT, self.HEADER_HEIGHT))
-        label.move(x + self.CONTENT_WIDTH - self.HEADER_HEIGHT, y)
-        self.scene.addWidget(label)
+        patch = QLabel()
+        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)
 
     def draw_page(self, x, y):
         """Draw page starting at given position.
@@ -285,27 +417,25 @@ class ViewArea(QScrollArea):
         y : int
         """
         # color the page white
-        page_background = QGraphicsRectItem(x, y, self.WIDTH, self.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.WIDTH, self.HEIGHT)
-        self.scene.addRect(x + self.PADDING, y + self.PADDING,
-                           self.CONTENT_WIDTH, self.CONTENT_HEIGHT)
-        self.scene.addRect(x + self.PADDING, y + self.PADDING,
-                           self.CONTENT_WIDTH, self.CONTENT_HEIGHT)
-        self.scene.addRect(x + self.PADDING, y + self.PADDING,
-                           self.CONTENT_WIDTH, self.HEADER_HEIGHT)
+        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)
 
     def setup_scene(self):
         """Prepare scene for use.
 
         Draws borders, background, etc.
         """
-        self.scene.setSceneRect(QRectF(0, 0, self.WIDTH,
-                                       self.HEIGHT * 3 + self.PADDING * 2))
-
         # sets the background color of the scene to be the appropriate
         # system-specific background color
         # source: https://stackoverflow.com/a/23880531/3545896
@@ -344,8 +474,9 @@ class ViewArea(QScrollArea):
         # Zoom
         self.view.scale(zoom_factor, zoom_factor)
 
-        pos_old = self.view.mapToScene(QPoint(self.WIDTH / 2, self.HEIGHT / 2))
-        pos_new = self.view.mapToScene(self.WIDTH / 2, self.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())
 
@@ -353,5 +484,5 @@ class ViewArea(QScrollArea):
 if __name__ == "__main__":
     app = QApplication(sys.argv)
     WINDOW = MainWindow()
-    WINDOW.show()
+    WINDOW.showMaximized()
     app.exec_()
diff --git a/soitool/modules/module_base.py b/soitool/modules/module_base.py
index 92e7e6bc6145a1a1921cb5580c7b8384d77cad51..630cdaeb4c5e7b982b52b49413cbde406abedb74 100644
--- a/soitool/modules/module_base.py
+++ b/soitool/modules/module_base.py
@@ -9,6 +9,10 @@ class ModuleBase(ABC):
         """Abstract method, should be implemented by derived class."""
         raise NotImplementedError
 
+    def set_pos(self, pos):
+        """Abstract method, should be implemented by derived class."""
+        raise NotImplementedError
+
     def render_onto_pdf(self):
         """Abstract method, should be implemented by derived class."""
         raise NotImplementedError
diff --git a/soitool/modules/module_table.py b/soitool/modules/module_table.py
index 5931f44367ab453627696db75da18337498496c9..12f25cc0b8dfd799f762d6c52977e0c7cdb2e7d7 100644
--- a/soitool/modules/module_table.py
+++ b/soitool/modules/module_table.py
@@ -27,6 +27,9 @@ class TableModule(ModuleBase, QTableWidget, metaclass=Meta):
     Functionality for adding and removing columns and rows is implemented.
     """
 
+    def set_pos(self, pos):
+        self.move(pos)
+
     def __init__(self):
         """Initialize QTableWidget."""
         QTableWidget.__init__(self)