diff --git a/src/simudator/gui/cpu_graphics_scene.py b/src/simudator/gui/cpu_graphics_scene.py
index a64e417b1dfa6a4b9d834bb031373a2f9364a3f1..60a5072200e9cee55cc295990f1ed7204e181cdf 100644
--- a/src/simudator/gui/cpu_graphics_scene.py
+++ b/src/simudator/gui/cpu_graphics_scene.py
@@ -4,19 +4,10 @@ from json.decoder import JSONDecodeError
 from qtpy.QtCore import QPointF
 from qtpy.QtCore import Signal as pyqtSignal
 from qtpy.QtCore import Slot
-from qtpy.QtWidgets import (
-    QErrorMessage,
-    QFileDialog,
-    QGraphicsItem,
-    QGraphicsScene,
-    QMessageBox,
-)
-
-from simudator.core.processor import Processor
+from qtpy.QtWidgets import QErrorMessage, QFileDialog, QGraphicsScene, QMessageBox
+
 from simudator.gui.color_scheme import ColorScheme
-from simudator.gui.module_graphics_item.module_graphics_item import ModuleGraphicsItem
-from simudator.gui.orientation import Orientation
-from simudator.gui.port_graphics_item import PortGraphicsItem
+from simudator.gui.module_graphics_item.module_widget import ModuleWidget
 from simudator.gui.signal_graphics_item import SignalGraphicsItem
 
 
@@ -32,8 +23,8 @@ class CpuGraphicsScene(QGraphicsScene):
 
     def __init__(self):
         super().__init__()
-        self._module_graphics_items = dict()
-        self._signal_graphics_items = []
+        self._modules: dict[str, ModuleWidget] = {}
+        self._signals: list[SignalGraphicsItem] = []
         self._error_msg_box = QErrorMessage()
         self.setBackgroundBrush(ColorScheme.Window)
 
@@ -42,49 +33,24 @@ class CpuGraphicsScene(QGraphicsScene):
         Reset all graphical signals to their default visual representation
         when initialised.
         """
-        for graphics_signal in self._signal_graphics_items:
+        for graphics_signal in self._signals:
             graphics_signal.reset()
 
-    def add_module(self, item: ModuleGraphicsItem) -> None:
-        """
-        Add a graphical module item to the processor scene at a position
-        according to the default layout.
-
-        Parameters
-        ----------
-        item : ModuleGraphicsItem
-            Graphical module item to add to the scene.
+    def add_module_widget(self, widget: ModuleWidget) -> None:
         """
-        self._module_graphics_items[item.name] = item
-        self._place_module_default(item)
+        Add a module widget to the processor scene.
 
-    def _place_module_default(self, item: ModuleGraphicsItem) -> None:
-        """
-        Place a graphical module item at a position according to the default
-        layout, i.e. placing all module items along a diagonal.
+        Module widgets are placed by default along a diagonal.
 
         Parameters
         ----------
-        item : ModuleGraphicsItem
-        """
-        placement = len(self._module_graphics_items) * self.MODULE_SPACEING
-        item.setPos(placement, placement)
-        self.addItem(item)
-
-    def move_module_to(self, item: ModuleGraphicsItem, pos_x: int, pos_y: int) -> None:
+        widget : ModuleWidget
+            Module widget to add to the scene.
         """
-        Place an existing graphical module item at some position.
-
-        Parameters
-        ----------
-        item : ModuleGraphicsItem
-           Graphical module item to place at a position.
-        pos_x : int
-            Position on x-axis to place the module item at.
-        pos_y : int
-            Position on y-axis to place the module item at.
-        """
-        item.setPos(pos_x * self.MODULE_SPACEING, pos_y * self.MODULE_SPACEING)
+        self._modules[widget.get_name()] = widget
+        self.addItem(widget)
+        placement = len(self._modules) * self.MODULE_SPACEING
+        widget.setPos(placement, placement)
 
     def add_all_signals(self) -> None:
         """
@@ -95,7 +61,7 @@ class CpuGraphicsScene(QGraphicsScene):
         # (Every port keeps a reference to a simulation signal which has
         # a name)
         signal_to_ports = {}
-        for module_w in self._module_graphics_items.values():
+        for module_w in self._modules.values():
             ports = module_w.getPorts()
             for port in ports:
                 s_name = port.getSignalName()
@@ -111,49 +77,26 @@ class CpuGraphicsScene(QGraphicsScene):
                 port_1 = module_graphics_items[0]
                 port_2 = module_graphics_items[1]
                 signal_w = SignalGraphicsItem(port_1, port_2)
-                self._signal_graphics_items.append(signal_w)
+                self._signals.append(signal_w)
                 self.addItem(signal_w)
                 port_1.moved.connect(signal_w.move)
                 port_2.moved.connect(signal_w.move)
                 port_1.toggled.connect(signal_w.toggleVisibility)
                 port_2.toggled.connect(signal_w.toggleVisibility)
 
-    def get_modules(self) -> list[ModuleGraphicsItem]:
-        """
-        Get a list of all graphical module items in the scene.
-
-        Returns
-        -------
-        list[ModuleGraphicsItem]
-            List of graphical module items in the scene.
-        """
-        return list(self._module_graphics_items.values())
-
-    def get_signals(self) -> list[SignalGraphicsItem]:
-        """
-        Get a list of all graphical signal items in the scene.
-
-        Returns
-        -------
-        list[SignalGraphicsItem]
-            List of graphical signal items in the scene.
-        """
-        return self._signal_graphics_items
-
-    def mousePressEvent(self, event):
-        super().mousePressEvent(event)
-
     @Slot()
     def load_layout(self) -> None:
         """
         Prompt the user for a layout file and load the layout from the file.
+
+        If at any point this function would fail, the default layout
+        is loaded instead.
         """
 
         # Prompt the user for a file
         dialog = QFileDialog()
         dialog.setFileMode(QFileDialog.AnyFile)
         dialog.setAcceptMode(QFileDialog.AcceptOpen)
-        dialog.setDirectory("~/simudator")  # TODO: does this work when exported?
         path = dialog.getOpenFileName()[0]
 
         # If no file was selected, do nothing
@@ -175,23 +118,6 @@ class CpuGraphicsScene(QGraphicsScene):
                 self.parent(), "SimuDator", "File loaded succesfully."
             )
 
-    def _save_layout_to_file(self, file_path: str) -> None:
-        """
-        Save the layout of the scene to file.
-
-        Parameters
-        ----------
-        file_path : str
-            Path to the file to save to layout to.
-        """
-        layout_str = ""
-        for graphics_item in self._module_graphics_items.values():
-            layout_str += graphics_item.save_state_as_str() + "\n"
-
-        file = open(file_path, "w")
-        file.write(layout_str)
-        file.close()
-
     @Slot(bool)
     def show_all_signals(self, value: bool) -> None:
         """
@@ -202,7 +128,7 @@ class CpuGraphicsScene(QGraphicsScene):
         value : bool
             ``True`` to show all graphical signals, ``False`` to hide them.
         """
-        for item in self._signal_graphics_items:
+        for item in self._signals:
             item.setVisible(value)
 
     @Slot(bool)
@@ -216,7 +142,7 @@ class CpuGraphicsScene(QGraphicsScene):
         value : bool
             ``True`` to show the port names, ``False`` to hide them.
         """
-        for item in self._module_graphics_items.values():
+        for item in self._modules.values():
             for port in item.ports:
                 port.setNameVisibility(value)
 
@@ -231,12 +157,11 @@ class CpuGraphicsScene(QGraphicsScene):
             ``True`` to lock the layout, ``False`` to unlock it.
         """
 
-        for item in self._module_graphics_items.values():
-            item.setFlag(QGraphicsItem.ItemIsMovable, not value)
-            item.setLocked(value)
+        for widget in self._modules.values():
+            widget.set_is_locked(value)
 
-        for item in self._signal_graphics_items:
-            item.setFlag(QGraphicsItem.ItemIsMovable, not value)
+        for item in self._signals:
+            item.setFlag(item.GraphicsItemFlag.ItemIsMovable, not value)
 
             # We use this value so lines in the signal can not be moved or edited
             item.is_locked = value
@@ -244,7 +169,8 @@ class CpuGraphicsScene(QGraphicsScene):
     @Slot()
     def save_layout(self) -> None:
         """
-        Prompt the user for a file and save the scene layout to the file.
+        Prompt the user for a file and save the scene layout to the
+        selected file.
 
         This overwrites the previous content of the file.
         """
@@ -255,34 +181,31 @@ class CpuGraphicsScene(QGraphicsScene):
         path = dialog.getSaveFileName()[0]
 
         # Open the given file erasing the previous content
-        with open(path, "w") as fp:
-            graphics_modules_data = {}
-            ports_data = {}
-            graphics_signals_data = {}
-
-            graphics_modules = self.get_modules()
-            for graphics_module in graphics_modules:
-                pos = (graphics_module.x(), graphics_module.y())
-                graphics_modules_data[graphics_module.getName()] = pos
-
-                for port in graphics_module.getPorts():
-                    visibility = port.isVisible()
-                    orientation = int(port.getOrientation())
-                    data = (port.x(), port.y(), orientation, visibility)
-                    ports_data[port.getID()] = data
-
-            for graphics_signal in self.get_signals():
-                visibility = graphics_signal.isVisible()
-                points = []
-                for point in graphics_signal.getPoints():
-                    points.append((point.x(), point.y()))
-                data = (points, visibility)
-                graphics_signals_data[graphics_signal.getID()] = data
-
-            data = (graphics_modules_data, ports_data, graphics_signals_data)
-            json.dump(data, fp)
-
-        fp.close()
+        try:
+            with open(path, "w") as fp:
+                module_data = {}
+                signal_data = {}
+
+                for name, module in self._modules.items():
+                    module_data[name] = module.save_layout_data()
+
+                for graphics_signal in self._signals:
+                    visibility = graphics_signal.isVisible()
+                    points = []
+                    for point in graphics_signal.getPoints():
+                        points.append((point.x(), point.y()))
+                    data = (points, visibility)
+                    signal_data[graphics_signal.getID()] = data
+
+                json.dump(
+                    {
+                        "module_data": module_data,
+                        "signal_data": signal_data,
+                    },
+                    fp,
+                )
+        except OSError:
+            self._error_msg_box.showMessage("Failed to load layout.", "save_layout_err")
 
     @Slot()
     def load_default_layout(self) -> None:
@@ -291,58 +214,38 @@ class CpuGraphicsScene(QGraphicsScene):
         layout, i.e. along a diagonal.
         """
         counter = 0
-        for key in self._module_graphics_items:
-            module_graphic = self._module_graphics_items[key]
-            module_graphic.showPorts()
+        for widget in self._modules.values():
             counter += 1
-            self.move_module_to(module_graphic, counter, counter)
+            widget.setPos(
+                counter * self.MODULE_SPACEING, counter * self.MODULE_SPACEING
+            )
+
         self.reset_signals()
 
     def load_layout_from_file(self, file_path: str) -> None:
         """
         Load a layout from a file.
 
-        If at anypoint this function would error, the default layout
-        is loaded instead.
-
         Parameters
         ----------
         file_path : str
             Path to a file containing a layout for the processor scene.
         """
-        graphics_modules = self._module_graphics_items
-        ports = {}
-        graphics_signals = {}
-
-        for graphics_module in graphics_modules.values():
-            for port in graphics_module.getPorts():
-                ports[port.getID()] = port
+        signals = {}
 
-        for graphics_signal in self.get_signals():
-            graphics_signals[graphics_signal.getID()] = graphics_signal
+        for graphics_signal in self._signals:
+            signals[graphics_signal.getID()] = graphics_signal
 
         # Open the file in 'read-only'
         with open(file_path, 'rb') as fp:
             data = json.load(fp)
-            graphics_modules_data = data[0]
-            ports_data = data[1]
-            graphics_signals_data = data[2]
 
-            for g_module_name, g_module_data in graphics_modules_data.items():
-                g_module = graphics_modules[g_module_name]
-                x = g_module_data[0]
-                y = g_module_data[1]
-                self._load_module(g_module, x, y)
+            for module_name, module_data in data["module_data"].items():
+                self._modules[module_name].load_layout_data(module_data)
 
-            for port_id, port_data in ports_data.items():
-                port = ports[int(port_id)]
-                self._load_port(port, *port_data)
-
-            for g_signal_id, g_signal_data in graphics_signals_data.items():
-                g_signal = graphics_signals[int(g_signal_id)]
-                self._load_signal(g_signal, *g_signal_data)
-
-        fp.close()
+            for signal_id, signal_data in data["signal_data"]:
+                signal = signals[int(signal_id)]
+                self._load_signal(signal, *signal_data)
 
     def _load_signal(
         self,
@@ -372,56 +275,3 @@ class CpuGraphicsScene(QGraphicsScene):
         # Set the new points
         signal.setPoints(qpoints)
         signal.setVisible(visibility)
-
-    def _load_module(
-        self,
-        module: ModuleGraphicsItem,
-        pos_x: float,
-        pos_y: float,
-    ) -> None:
-        """
-        Set the position of a graphical module in the scene. Helper method
-        for loading a layout from file.
-
-        Parameters
-        ----------
-        module : ModuleGraphicsItem
-            Graphical module of which to set the position.
-        pos_x : float
-            Position on the x-axis in the scene.
-        pos_y : float
-            Position on the y-axis in the scene.
-        """
-        module.setX(pos_x)
-        module.setY(pos_y)
-
-    def _load_port(
-        self,
-        port: PortGraphicsItem,
-        pos_x: float,
-        pos_y: float,
-        orientation: Orientation,
-        visibility: bool,
-    ) -> None:
-        """
-        Set position, orientation and visibility of a port of a graphical
-        module. Helper method for loading a layout from file.
-
-        Parameters
-        ----------
-        port : PortGraphicsItem
-            Port to modify.
-        pos_x : float
-            Position on the x-axis in the scene.
-        pos_y : float
-            Position on the y-axis in the scene.
-        orientation : Orientation
-            Orientation of the port.
-        visibility : bool
-            Visibility of the port. ``True`` to show the port, ``False`` to
-            hide it.
-        """
-        port.setOrientation(orientation)
-        port.setX(pos_x)
-        port.setY(pos_y)
-        port.setVisible(visibility)
diff --git a/src/simudator/gui/gui.py b/src/simudator/gui/gui.py
index 63c39edcea6018b47973b3e2fa9edb5997e1d0e6..75885705fb35e823c1c3f032e5fb147fa8d5b922 100644
--- a/src/simudator/gui/gui.py
+++ b/src/simudator/gui/gui.py
@@ -282,19 +282,10 @@ class GUI(QMainWindow):
         dlg.setText(message)
         dlg.exec()
 
-    def add_module_graphics_item(self, item: ModuleGraphicsItem) -> None:
-        """
-        Add a module graphics item to the graphics scene and connect its
-        QT signals and slots.
-        """
-        self._graphics_scene.add_module(item)
-        self.connectModuleActions(item.getActionSignals())
-        self._processor_handler.changed.connect(item.update)
-
     def add_module_widget(self, widget: ModuleWidget) -> None:
         """
         Add a module widget to the processor scene and connect its QT signals
-        and slots.
+        and slots appropriately.
 
         Parameters
         ----------
@@ -302,7 +293,7 @@ class GUI(QMainWindow):
         The module widget to add to the processor scene.
         """
         self._processor_handler.changed.connect(widget.update)
-        self._graphics_scene.addItem(widget)
+        self._graphics_scene.add_module_widget(widget)
         widget.state_changed.connect(self._processor_handler.handle_module_change)
 
     def add_all_signals(self) -> None:
diff --git a/src/simudator/gui/module_graphics_item/actions.py b/src/simudator/gui/module_graphics_item/actions.py
index c1abb1f5f37d1f974e2816e03fe39a8af5e1a6c8..1e4bb49a7d35d4b9ba0589e0dc7acc04d4db4f66 100644
--- a/src/simudator/gui/module_graphics_item/actions.py
+++ b/src/simudator/gui/module_graphics_item/actions.py
@@ -49,13 +49,15 @@ def edit_state_action(module: Module, module_widget: ModuleWidget) -> QAction:
 def toggle_ports_action(module_widget: ModuleWidget) -> QAction:
     """
     Create a QAction for toggling the visibility of port widgets of a module
-    widget.
+    widget. The action is connected to the ``locked`` signal of the module
+    widget to enable or disable the action when the module is locked or
+    unlocked.
 
     Parameters
     ----------
     module_widget : ModuleWidget
-        The module for which its ports should be toggled to visible or invisible
-        using a QAction.
+        The module for which its ports should be toggled to visible or
+        invisible using a QAction.
 
     Returns
     -------
@@ -63,5 +65,5 @@ def toggle_ports_action(module_widget: ModuleWidget) -> QAction:
     """
     action = QAction("Toggle ports", module_widget)
     action.triggered.connect(module_widget.toggle_ports)
+    module_widget.locked.connect(action.setDisabled)
     return action
-
diff --git a/src/simudator/gui/module_graphics_item/module_widget.py b/src/simudator/gui/module_graphics_item/module_widget.py
index 53bfaf40c443c01069d313908f2fc630c89b69df..37a6e26bb54221fc24a0696c8e21e1257a4cf980 100644
--- a/src/simudator/gui/module_graphics_item/module_widget.py
+++ b/src/simudator/gui/module_graphics_item/module_widget.py
@@ -1,3 +1,5 @@
+from typing import Any
+
 from qtpy.QtCore import Property, QRectF, Qt
 from qtpy.QtCore import Signal as pyqtSignal
 from qtpy.QtCore import Slot
@@ -53,6 +55,7 @@ class ModuleWidget(QGraphicsWidget):
     _DEFAULT_PADDING = 5
 
     state_changed = pyqtSignal()
+    locked = pyqtSignal(bool)
 
     def __init__(
         self,
@@ -78,6 +81,8 @@ class ModuleWidget(QGraphicsWidget):
         self._text_font = self._DEFAULT_TEXT_FONT
         self._padding = self._DEFAULT_PADDING
 
+        self._is_locked = False
+
         # Set the size of the module depending on the number of state variables
         width = self._DEFAULT_WIDTH
         height = self._DEFAULT_HEIGHT
@@ -196,6 +201,18 @@ class ModuleWidget(QGraphicsWidget):
         menu.addActions(self.actions())
         menu.exec_(event.screenPos())
 
+    def get_name(self) -> str:
+        """
+        Return the name of this module widget. This is the same name as that of
+        the module that the widget displays.
+
+        Returns
+        -------
+        str
+            The name of the module widget.
+        """
+        return self._module.get_state()["name"]
+
     def get_state_vars(self) -> dict[str, FormatInfo]:
         """
         Return a mapping from displayed state variables of the displayed
@@ -211,6 +228,39 @@ class ModuleWidget(QGraphicsWidget):
         """
         return self._state_vars
 
+    def is_locked(self) -> bool:
+        """
+        Return ``True`` if the module widget is locked, otherwise ``False`` is
+        returned.
+
+        Returns
+        -------
+        bool
+           ``True`` if locked, ``False`` otherwise.
+        """
+        return self._is_locked
+
+    def set_is_locked(self, value: bool) -> None:
+        """
+        Set whether the module widget is locked or not. Locking a module widget
+        makes it unmoveable and emits the ``locked`` signal. Locking a module
+        widget also locks its port widgets.
+
+        A module widget is not locked by default.
+
+        Parameters
+        ----------
+        value : bool
+            ``True`` to lock the module widget, ``False`` to unlock it.
+        """
+        self._is_locked = value
+        self.setFlag(QGraphicsItem.ItemIsMovable, not value)
+
+        for port in self._port_widgets:
+            port.set_is_locked(value)
+
+        self.locked.emit(value)
+
     @Slot()
     def set_format(self, state_var: str, format: Format) -> None:
         """
@@ -229,6 +279,42 @@ class ModuleWidget(QGraphicsWidget):
         self._state_vars[state_var].selected_format = format
         self.update()
 
+    def save_layout_data(self) -> dict[str, Any]:
+        """
+        Return information about the module widget that is relevant for its
+        presentation in a processor scene.
+
+        Returns
+        -------
+        dict[str, Any]
+            Dictionary containing layout-relevant data about the module widget.
+        """
+        port_data = [port.save_layout_data() for port in self._port_widgets]
+        return {
+            "x": self.x(),
+            "y": self.y(),
+            "ports": port_data,
+        }
+
+    def load_layout_data(self, data: dict[str, Any]) -> None:
+        """
+        Load layout-relevant information about the module widget. The provided
+        data should contain x- and y-position and a list of port layout data as
+        the keys "x", "y" and "ports", respectively.
+
+        Parameters
+        ----------
+        data : dict[str, Any]
+            Dictionary containing layout data about the port widget.
+
+        """
+        self.setX(data["x"])
+        self.setY(data["y"])
+
+        port_data = data["ports"]
+        for i, port in enumerate(self._port_widgets):
+            port.load_layout_data(port_data[i])
+
     def outline_width(self) -> float:
         """Return the outline pen width.
 
diff --git a/src/simudator/gui/port_widget.py b/src/simudator/gui/port_widget.py
index b35555f3a0de8563b985d8eff0dde463d2c36740..d087eb3eba156da3f43b99b3a9f5e300a1d78d2d 100644
--- a/src/simudator/gui/port_widget.py
+++ b/src/simudator/gui/port_widget.py
@@ -1,4 +1,5 @@
 from enum import IntEnum
+from typing import Any
 
 from qtpy.QtCore import Property, QPointF, QRectF, Qt
 from qtpy.QtCore import Signal as pyqtSignal
@@ -80,6 +81,8 @@ class PortWidget(QGraphicsWidget):
         self.set_label_visible(True)
         self.set_text_font(self._DEFAULT_TEXT_FONT)
 
+        self._is_locked = False
+
         self.setFlag(QGraphicsItem.ItemIsMovable)
 
     def paint(
@@ -168,6 +171,33 @@ class PortWidget(QGraphicsWidget):
 
         return QRectF(x, y, text_width, text_height)
 
+    def is_locked(self) -> bool:
+        """
+        Return ``True`` if the port widget is locked, otherwise ``False`` is
+        returned.
+
+        Returns
+        -------
+        bool
+           ``True`` if locked, ``False`` otherwise.
+        """
+        return self._is_locked
+
+    def set_is_locked(self, value: bool) -> None:
+        """
+        Set whether the port widget is locked or not. Locking a port widget
+        makes it unmoveable and disables the actions in the context menu.
+
+        A port widget is not locked by default.
+
+        Parameters
+        ----------
+        value : bool
+            ``True`` to lock the port widget, ``False`` to unlock it.
+        """
+        self._is_locked = value
+        self.setFlag(self.GraphicsItemFlag.ItemIsMovable, not value)
+
     def shape(self) -> QPainterPath:
         path = QPainterPath()
         path.addRect(self.boundingRect())
@@ -212,13 +242,13 @@ class PortWidget(QGraphicsWidget):
         menu = QMenu()
         hide_signal_action = QAction("Toggle signal visibility", menu)
         hide_signal_action.triggered.connect(self.signal_toggled)
-        # hide_signal_action.setEnabled(not self.isEnabled)
+        hide_signal_action.setDisabled(self._is_locked)
 
         hide_port_action = QAction("Toggle port visibility", menu)
         hide_port_action.triggered.connect(
             lambda: self.setVisible(not self.isVisible())
         )
-        # hide_port_action.setEnabled(not self.isLocked)
+        hide_port_action.setDisabled(self._is_locked)
 
         menu.addAction(hide_signal_action)
         menu.addAction(hide_port_action)
@@ -257,6 +287,38 @@ class PortWidget(QGraphicsWidget):
                 self.set_orientation(Orientation.UP)
             self.update(self.boundingRect())
 
+    def save_layout_data(self) -> dict[str, Any]:
+        """
+        Return information about the port widget that is relevant for its
+        presentation in a processor scene.
+
+        Returns
+        -------
+        dict[str, Any]
+            Dictionary containing layout-relevant data about the port widget.
+        """
+        return {
+            "x": self.x(),
+            "y": self.y(),
+            "label_visible": self.label_visible,
+        }
+
+    def load_layout_data(self, data: dict[str, Any]) -> None:
+        """
+        Load layout-relevant information about the port widget. The provided
+        data should contain x- and y-position and label visibility as the
+        keys "x", "y" and "label_visible", respectively.
+
+        Parameters
+        ----------
+        data : dict[str, Any]
+            Dictionary containing layout data about the port widget.
+
+        """
+        self.setX(data["x"])
+        self.setY(data["y"])
+        self.set_label_visible(data["label_visible"])
+
     def line_length(self) -> float:
         """
         Return the length of the port line.
diff --git a/src/simudator/processor/mia/mia.py b/src/simudator/processor/mia/mia.py
index eb52e58dabea5bc3e02b62ac1e12a4511046c7d5..cbf307b5f37c76406a5166d12d9dc3c8a5dad0d1 100644
--- a/src/simudator/processor/mia/mia.py
+++ b/src/simudator/processor/mia/mia.py
@@ -1,9 +1,16 @@
 import sys
 
 from simudator.cli.cli import CLI
+from simudator.core.module import Module
 from simudator.core.modules.integer_register import IntegerRegister
 from simudator.core.processor import Processor, Signal
+from simudator.gui.formatting import Format, FormatInfo
 from simudator.gui.gui import GUI
+from simudator.gui.module_graphics_item.actions import (
+    edit_state_action,
+    toggle_ports_action,
+)
+from simudator.gui.module_graphics_item.module_widget import ModuleWidget
 from simudator.processor.mia.gui import (
     AluGraphicsItem,
     ArGraphicsItem,
@@ -320,6 +327,22 @@ class MIA_CPU(Processor):
         micro_memory_state = self._micro_memory.get_state()
         return micro_memory_state["halt"]
 
+    def _create_register_widget(self, module: Module) -> ModuleWidget:
+        bit_length = module.get_parameter()["bit_length"]
+        state_vars = {
+            "value": FormatInfo(
+                FormatInfo.NUMERICAL_FORMATS, Format.Hex, bit_length=bit_length
+            )
+        }
+        widget = ModuleWidget(module, state_vars, [])
+        widget.addActions(
+            [
+                edit_state_action(module, widget),
+                toggle_ports_action(widget),
+            ]
+        )
+        return widget
+
     def launch_gui(self):
         from qtpy import QtCore
         from qtpy.QtWidgets import QApplication
@@ -330,64 +353,52 @@ class MIA_CPU(Processor):
         self.reset()
         gui = GUI(self)
 
-        asr = self.get_module("ASR")
-        ir = self.get_module("IR")
-        pm = self.get_module("PM")
+        bus = self.get_module("Bus")
+        upc = self.get_module("uPC")
+        supc = self.get_module("SuPC")
         pc = self.get_module("PC")
-        alu = self.get_module("ALU")
         ar = self.get_module("AR")
+        asr = self.get_module("ASR")
         hr = self.get_module("HR")
+        um = self.get_module("uM")
+        alu = self.get_module("ALU")
         grx = self.get_module("GRx")
+        ir = self.get_module("IR")
+        pm = self.get_module("PM")
+        k1 = self.get_module("K1")
+        k2 = self.get_module("K2")
         lc = self.get_module("LC")
-
-        bus_signal_pairs = [
-            (asr.signals["in_content"], None),
-            (ir.signals["in_input"], ir.signals["out_output"]),
-            (pm.signals["in_input"], pm.signals["out_content"]),
-            (None, None),
-            (pc.signals["in_input"], pc.signals["out_content"]),
-            (None, None),
-            (alu.signals["in_input_bus"], None),
-            (None, None),
-            (None, ar.signals["out_content"]),
-            (None, None),
-            (hr.signals["in_content"], hr.signals["out_content"]),
-            (None, None),
-            (grx.signals["in_input"], grx.signals["out_content"]),
-        ]
-
-        gui.add_module_graphics_item(
-            BusGraphicsItem(self.get_module("Bus"), bus_signal_pairs)
-        )
-        gui.add_module_graphics_item(uPcGraphicsItem(self.get_module("uPC")))
-        gui.add_module_graphics_item(SupcGraphicsItem(self.get_module("SuPC")))
-        gui.add_module_graphics_item(PcGraphicsItem(self.get_module("PC")))
-        gui.add_module_graphics_item(ArGraphicsItem(self.get_module("AR")))
-        gui.add_module_graphics_item(AsrGraphicsItem(self.get_module("ASR")))
-        gui.add_module_graphics_item(HrGraphicsItem(self.get_module("HR")))
-        gui.add_module_graphics_item(MicroMemoryGraphicsItem(self.get_module("uM")))
-        gui.add_module_graphics_item(AluGraphicsItem(self.get_module("ALU")))
-        gui.add_module_graphics_item(GrxGraphicsItem(self.get_module("GRx")))
-        gui.add_module_graphics_item(IrGraphicsItem(self.get_module("IR")))
-
-        flag_modules = ["Z-Flag", "N-Flag", "C-Flag", "O-Flag", "L-Flag", "LC"]
-        for name in flag_modules:
-            module = self.get_module(name)
-            widget = FlagGraphicsItem(module)
-            gui.add_module_graphics_item(widget)
+        z_flag = self.get_module("Z-Flag")
+        n_flag = self.get_module("N-Flag")
+        c_flag = self.get_module("C-Flag")
+        o_flag = self.get_module("O-Flag")
+
+        registers = [ar, asr, hr, supc, z_flag, n_flag, c_flag, o_flag]
+        for register in registers:
+            gui.add_module_widget(self._create_register_widget(register))
+
+        # bus_signal_pairs = [
+        #     (asr.signals["in_content"], None),
+        #     (ir.signals["in_input"], ir.signals["out_output"]),
+        #     (pm.signals["in_input"], pm.signals["out_content"]),
+        #     (None, None),
+        #     (pc.signals["in_input"], pc.signals["out_content"]),
+        #     (None, None),
+        #     (alu.signals["in_input_bus"], None),
+        #     (None, None),
+        #     (None, ar.signals["out_content"]),
+        #     (None, None),
+        #     (hr.signals["in_content"], hr.signals["out_content"]),
+        #     (None, None),
+        #     (grx.signals["in_input"], grx.signals["out_content"]),
+        # ]
 
         gui.add_signal_viewer(lc.signals["out_flag_l"], "L")
 
-        memory_modules = ["PM", "K1", "K2"]
-        for name in memory_modules:
-            module = self.get_module(name)
-            widget = MiaMemoryGraphicsItem(module)
-            gui.add_module_graphics_item(widget)
-
-        gui.add_all_signals()
+        # gui.add_all_signals()
 
         gui.show()
-        gui.load_layout("mia_layout")
+        # gui.load_layout("mia_layout")
         app.exec()
 
     def launch_cli(self):