diff --git a/cpdctrl_gui/ui/main_window.py b/cpdctrl_gui/ui/main_window.py
index f367b33..ee10966 100644
--- a/cpdctrl_gui/ui/main_window.py
+++ b/cpdctrl_gui/ui/main_window.py
@@ -2,7 +2,7 @@
 from PyQt6.QtCore import Qt, QTimer
 from PyQt6.QtWidgets import QMainWindow, QWidget, QHBoxLayout, QLabel, QStatusBar, QFileDialog, \
     QVBoxLayout
-from PyQt6.QtWidgets import QToolBox, QTabWidget
+from PyQt6.QtWidgets import QTabWidget
 from PyQt6.QtGui import QIcon, QPixmap, QAction, QKeySequence
 from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QMessageBox
 
@@ -10,8 +10,7 @@ from ..resources import get_resource_path
 from .widgets.menubar import MenuBar
 from .widgets.toolbar import ToolBar
 from .widgets.metadata_input import MetadataInput
-from .widgets.measurement_settings import MeasurementSettings, ScriptSelection
-from .widgets.app_settings import AppSettings
+from cpdctrl_gui.ui.widgets.settings import MeasurementSettings, AppSettings
 from .widgets.plot import Plot
 from .widgets.device_select import ListChoice
 from .widgets.about import MarkdownView
@@ -47,7 +46,12 @@ class MainWindow(QMainWindow):
         super().__init__()
         # Window-Settings
         self.setWindowTitle(AppConfig.APP_NAME)
-        self.setGeometry(100, 100, 800, 600)
+        x = AppConfig.MAIN_CFG.get_or("geometry_x", 100)
+        y = AppConfig.MAIN_CFG.get_or("geometry_y", 100)
+        width = AppConfig.MAIN_CFG.get_or("geometry_width", 1000)
+        height = AppConfig.MAIN_CFG.get_or("geometry_height", 700)
+        self.setGeometry(x, y, width, height)
+
         central_widget = QWidget(self)
         self.setCentralWidget(central_widget)
 
@@ -69,18 +73,17 @@ class MainWindow(QMainWindow):
         central_widget.setLayout(layout)
 
         # Left: Toolbox
-        self.w_leftbox = QToolBox(self)
-        self.w_leftbox.setMinimumWidth(300)
-        layout.addWidget(self.w_leftbox)
+        self.w_lefttab = QTabWidget(self)
+        self.w_lefttab.setMinimumWidth(300)
+        layout.addWidget(self.w_lefttab)
 
         metadata_init_dict = AppConfig.MEAS_CFG.get_or("metadata", {})
         # Measurement settings
         self.w_measurement_settings = MeasurementSettings()
-        self.w_leftbox.addItem(self.w_measurement_settings, "Measurement settings")
+        self.w_lefttab.addTab(self.w_measurement_settings, "Measurement settings")
         # Measurement metadata
         self.w_metadata = MetadataInput(metadata_init_dict)
-        self.w_leftbox.addItem(self.w_metadata, "Measurement metadata")
-
+        self.w_lefttab.addTab(self.w_metadata, "Measurement metadata")
         # Right: Tabs: Script, Plot
         self.w_right_tab = QTabWidget()
         layout.addWidget(self.w_right_tab)
@@ -90,7 +93,7 @@ class MainWindow(QMainWindow):
 
         # LED SCRIPT
         self.w_led_script = LedScriptViewer(LedScript(0))
-        self.w_right_tab.addTab(self.w_led_script, "LED Script")
+        self.w_lefttab.addTab(self.w_led_script, "LED Script")
         self.w_measurement_settings.w_led_script.script_changed.connect(self.led_script_load)
 
         self.verbose = True
@@ -237,7 +240,7 @@ class MainWindow(QMainWindow):
         self.topbar.enable_button("meas_stop")
         self.w_plot.clear_data()
 
-        measurement_name = "guitest"
+        name = self.w_measurement_settings.get_value("name")
         script = self.w_measurement_settings.get_value("led_script")
         led_script = LedScript(script=script)
         flush_after = self.w_measurement_settings.get_value("flush_after")
@@ -248,15 +251,18 @@ class MainWindow(QMainWindow):
         auto_add_metadata = self.w_measurement_settings.get_value("auto_add_metadata")
 
         metadata = self.w_metadata.get_dict()
-        metadata["name"] = measurement_name
+        metadata["name"] = name
         metadata["led_script"] = str(script)
 
         log.info(f"Starting measurement with:\n\tinterval = {interval}\n\tflush_after = {flush_after}\n\tuse_buffer = {use_buffer}\n\tmax_measurements = {max_measurements}\n\tstop_on_script_end = {stop_on_script_end}")
 
-        self.w_led_script.w_time_left.set_end_time(time.time() + led_script.script["dtsum"][-1])
+        # the time left estimation might be a little to short, since the actual measurement is started a few lines of
+        # code later
+        t_now = time.time()
+        self.w_led_script.w_time_left.set_start_end_time(t_now, t_now + led_script.script["dtsum"][-1])
 
         self.led_script = LedScript(script=script, auto_update=True, verbose=True)
-        self.data_collector = DataCollector(metadata=metadata, data_path=AppConfig.MAIN_CFG.get("datadir"), data_name=measurement_name)
+        self.data_collector = DataCollector(metadata=metadata, data_path=AppConfig.MAIN_CFG.get("dir_cache"), data_name=measurement_name)
         # data_collector.clear()
         self.data_queue = mp.Queue()
         self.command_queue = mp.Queue()
@@ -353,6 +359,7 @@ class MainWindow(QMainWindow):
 
     def app_open_about(self) -> None:
         dialog = QDialog()
+        dialog.setWindowTitle("About cpdctrl-gui")
         buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok)
         buttons.accepted.connect(dialog.accept)
         dialog.setLayout(QVBoxLayout())
@@ -372,6 +379,7 @@ class MainWindow(QMainWindow):
 
     def app_open_help(self) -> None:
         dialog = QDialog()
+        dialog.setWindowTitle("Help")
         buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok)
         buttons.accepted.connect(dialog.accept)
         dialog.setLayout(QVBoxLayout())
@@ -385,9 +393,13 @@ class MainWindow(QMainWindow):
 
     def app_open_settings(self) -> None:
         dialog = QDialog()
-        w_settings = AppSettings()
+        dialog.setWindowTitle("Settings")
         layout = QVBoxLayout()
-        layout.addWidget(w_settings)
+        w_app_settings = AppSettings()
+        layout.addWidget(w_app_settings)
+        buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok)
+        buttons.accepted.connect(dialog.accept)
+        layout.addWidget(buttons)
         dialog.setLayout(layout)
         dialog.exec()
 
@@ -397,4 +409,10 @@ class MainWindow(QMainWindow):
         # save the metadata
         metadata = self.w_metadata.get_dict()
         AppConfig.MEAS_CFG.set("metadata", metadata)
-        event.accept()
+        # store the geometry as text values in config
+        geo = self.geometry()
+        AppConfig.MAIN_CFG.set("geometry_x", geo.x())
+        AppConfig.MAIN_CFG.set("geometry_y", geo.y())
+        AppConfig.MAIN_CFG.set("geometry_width", geo.width())
+        AppConfig.MAIN_CFG.set("geometry_height", geo.height())
+
diff --git a/cpdctrl_gui/ui/widgets/app_settings.py b/cpdctrl_gui/ui/widgets/app_settings.py
deleted file mode 100644
index d120b66..0000000
--- a/cpdctrl_gui/ui/widgets/app_settings.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from PyQt6.QtWidgets import QWidget, QVBoxLayout, QFormLayout
-
-from ...utility.config import AppConfig
-
-class AppSettings(QWidget):
-    def __init__(self):
-        super().__init__()
-        self.setLayout(QVBoxLayout())
-        self.l_form = QFormLayout()
diff --git a/cpdctrl_gui/ui/widgets/settings/__init__.py b/cpdctrl_gui/ui/widgets/settings/__init__.py
new file mode 100644
index 0000000..8f69751
--- /dev/null
+++ b/cpdctrl_gui/ui/widgets/settings/__init__.py
@@ -0,0 +1,2 @@
+from .app_settings import AppSettings
+from .measurement_settings import MeasurementSettings
\ No newline at end of file
diff --git a/cpdctrl_gui/ui/widgets/settings/app_settings.py b/cpdctrl_gui/ui/widgets/settings/app_settings.py
new file mode 100644
index 0000000..b503d96
--- /dev/null
+++ b/cpdctrl_gui/ui/widgets/settings/app_settings.py
@@ -0,0 +1,22 @@
+from PyQt6.QtWidgets import QWidget, QVBoxLayout, QFormLayout, QFileDialog, QCheckBox, QSpinBox
+
+from cpdctrl_gui.utility.config import AppConfig
+from .base import FileSelection, SettingsForm
+
+class AppSettings(QWidget):
+    def __init__(self):
+        super().__init__()
+        self.setLayout(QVBoxLayout())
+        self.w_form = SettingsForm(AppConfig.MAIN_CFG)
+        self.layout().addWidget(self.w_form)
+
+        w_cache_dir = FileSelection(filemode=QFileDialog.FileMode.Directory)
+        self.w_form.add_form_row("dir_cache", "Cache Directory", "~/.cache/cpdctrl", w_cache_dir, "Directory to store temporary data")
+        self.w_form.add_form_row("led_device_auto_reconnect", "Autoconnect to last LED Controller", True, QCheckBox(), "Automatically connect to the last used LED Controller")
+        self.w_form.add_form_row("voltage_measurement_device_auto_reconnect", "Autoconnect to last Voltage Measurement Device", True, QCheckBox(), "Automatically connect to the last used Voltage Measurement Device")
+        w_plot_n = QSpinBox()
+        w_plot_n.setMinimum(1000)
+        w_plot_n.setMaximum(200000)
+        w_plot_n.setSingleStep(1000)
+        self.w_form.add_form_row("plot_max_data_points", "Max datapoints in the plot", 20000, w_plot_n, "Maximum number of datapoints in the live plot.\nThis value is limited to ensure performance is not degraded in long measurements")
+
diff --git a/cpdctrl_gui/ui/widgets/settings/base.py b/cpdctrl_gui/ui/widgets/settings/base.py
new file mode 100644
index 0000000..8cdabd3
--- /dev/null
+++ b/cpdctrl_gui/ui/widgets/settings/base.py
@@ -0,0 +1,144 @@
+from PyQt6.QtGui import QIcon
+from PyQt6.QtWidgets import QWidget, QLabel, QFormLayout, QSpinBox, QDoubleSpinBox, QLineEdit, QHBoxLayout, QPushButton, QFileDialog, QCheckBox
+from PyQt6.QtCore import pyqtSignal
+from cpdctrl.utility.config_file import ConfigFile
+
+
+class FileSelection(QWidget):
+    """
+    Widget allowing the user to select a file or directory.
+    """
+    value_changed = pyqtSignal(str)
+    def __init__(self, init_file="", filemode=QFileDialog.FileMode.AnyFile, parent=None):
+        super().__init__(parent)
+        self.setLayout(QHBoxLayout())
+        self.w_edit = QLineEdit()
+        self.w_edit.setText(init_file)
+        self.w_btn = QPushButton()
+        self.w_btn.setIcon(QIcon.fromTheme(QIcon.ThemeIcon.FolderOpen))
+        self.layout().addWidget(self.w_edit)
+        self.layout().addWidget(self.w_btn)
+        # open file dialog when button is clicked
+        self.w_btn.clicked.connect(self._open_file_dialog)
+        # emit value_changed on self when w_edit emits value_changed
+        self.w_edit.textChanged.connect(self.value_changed)
+
+        self.file_mode = filemode
+        # remove all spacing and padding from the layout
+        self.layout().setContentsMargins(0, 0, 0, 0)
+
+    def setValue(self, value: str):
+        self.w_edit.setText(value)
+
+    def _open_file_dialog(self):
+        dialog = QFileDialog(self)
+        # only directories
+        dialog.setFileMode(self.file_mode)
+        if dialog.exec():
+            dirname = dialog.selectedFiles()[0]
+            self.w_edit.setText(dirname)
+
+class SettingsForm(QWidget):
+    """
+    Form that is connected to a config file instance
+    """
+    def __init__(self, config_file: ConfigFile, parent=None):
+        super().__init__(parent)
+        self.setLayout(QFormLayout())
+        self.ws_form = {}
+        self.config_file = config_file
+
+    def __contains__(self, item):
+        return item in self.ws_form
+
+    def add_form_row(self, key: str, label: str, default_value, widget: QWidget, tooltip: str = None):
+        """
+        Add a row to the form. Uses the value from the config file corresponding to <key> or the default value.
+        Parameters
+        ----------
+        key
+        label: str
+            Label for the form widget
+        default_value
+        widget
+            Widget to add to the form
+        tooltip
+
+        Returns
+        -------
+
+        """
+        if tooltip: widget.setToolTip(tooltip)
+        value = self.config_file.get_or(key, default_value)
+        # set the value depending on the type of the widget
+        if isinstance(widget, QSpinBox) or isinstance(widget, QDoubleSpinBox):
+            widget.setValue(value)
+            widget.valueChanged.connect(lambda v: self.value_updated(key, v))
+        elif isinstance(widget, QCheckBox):
+            widget.setChecked(value)
+            widget.stateChanged.connect(lambda v: self.value_updated(key, v))
+        elif isinstance(widget, FileSelection):
+            widget.setValue(value)
+            widget.value_changed.connect(lambda v: self.value_updated(key, v))
+        else:
+            raise ValueError(f"Unknown widget type: {type(widget)}")
+        self.layout().addRow(QLabel(label), widget)
+        self.ws_form[key] = widget
+
+
+    def value_updated(self, key, value):
+        """
+        Update the value in the config file when it is updated in the widget
+        Parameters
+        ----------
+        key
+        value
+        """
+        self.config_file.set(key, value)
+
+    def set_value(self, key, value):
+        """
+        Set the value of the widget with the given key.
+        ""
+        Parameters
+        ----------
+        key
+        value
+
+        Returns
+        -------
+        """
+        if key in self.ws_form:
+            # set depending on widget type
+            if isinstance(self.ws_form[key], QSpinBox) or isinstance(self.ws_form[key], QDoubleSpinBox):
+                self.ws_form[key].setValue(value)
+            elif isinstance(self.ws_form[key], QCheckBox):
+                self.ws_form[key].setChecked(value)
+            elif isinstance(self.ws_form[key], FileSelection):
+                self.ws_form[key].setValue(value)
+            else:
+                raise ValueError(f"Unknown widget type: {type(self.ws_form[key])}")
+        else:
+            raise ValueError(f"Unknown key: {key}")
+
+    def get_value(self, key):
+        """
+        Get the value of the widget with the given key.
+        Parameters
+        ----------
+        key
+
+        Returns
+        -------
+
+        """
+        if key in self.ws_form:
+            # get depending on widget type
+            if isinstance(self.ws_form[key], QSpinBox) or isinstance(self.ws_form[key], QDoubleSpinBox):
+                return self.ws_form[key].value()
+            elif isinstance(self.ws_form[key], QCheckBox):
+                return self.ws_form[key].isChecked()
+            else:
+                raise ValueError(f"Unknown widget type: {type(self.ws_form[key])}")
+        else:
+            raise ValueError(f"Unknown key: {key}")
diff --git a/cpdctrl_gui/ui/widgets/measurement_settings.py b/cpdctrl_gui/ui/widgets/settings/measurement_settings.py
similarity index 64%
rename from cpdctrl_gui/ui/widgets/measurement_settings.py
rename to cpdctrl_gui/ui/widgets/settings/measurement_settings.py
index 540b6da..fdb1af1 100644
--- a/cpdctrl_gui/ui/widgets/measurement_settings.py
+++ b/cpdctrl_gui/ui/widgets/settings/measurement_settings.py
@@ -4,7 +4,8 @@ from PyQt6.QtWidgets import QFormLayout, QDoubleSpinBox, QCheckBox, QLineEdit, Q
 
 from os import path
 
-from ...utility.config import AppConfig
+from cpdctrl_gui.utility.config import AppConfig
+from .base import SettingsForm
 
 
 class DeviceSelection(QGroupBox):
@@ -126,68 +127,40 @@ class MeasurementSettings(QWidget):
         self.w_led_script = ScriptSelection()
         self.l_vbox.addWidget(self.w_led_script)
         # key-value stuff in a form
-        self.l_form = QFormLayout()
-        self.l_vbox.addLayout(self.l_form)
-        self.ws_form = {}
+        self.w_form = SettingsForm(AppConfig.MEAS_CFG)
+        self.l_vbox.addWidget(self.w_form)
+        self.w_form.add_form_row("name", "Name", "", QLineEdit(self), "Name of the measurement")
         w_box_interval = QDoubleSpinBox(self)
         w_box_interval.setDecimals(2)
         w_box_interval.setMinimum(0.01)
         w_box_interval.setSingleStep(0.1)
-        self._add_form_field("interval", "Interval [s]", 1.0, w_box_interval, "Amount of seconds to wait between voltage measurements and LED device updates")
+        self.w_form.add_form_row("interval", "Interval [s]", 1.0, w_box_interval, "Amount of seconds to wait between voltage measurements and LED device updates")
         w_box_max_measurements = QSpinBox(self)
         w_box_max_measurements.setMaximum(2147483647)   # max int32
         w_box_max_measurements.setMinimum(0)            # 0 for infinite measurements
-        self._add_form_field("max_measurements", "Max Measurements", 0, w_box_max_measurements, "Number of measurements to take. Set to 0 for infinite measurements")
-        self._add_form_field("stop_on_script_end", "Stop on Script End", False, QCheckBox(self), "Stop measurement when LED script ends")
-        self._add_form_field("use_buffer", "Use Buffer", False, QCheckBox(self), "If available, use the voltage device buffer for more accurate measurement timings.\nLeads to a lower accuracy of LED update timings, up to 1*interval")
+        self.w_form.add_form_row("max_measurements", "Max Measurements", 0, w_box_max_measurements, "Number of measurements to take. Set to 0 for infinite measurements")
+        self.w_form.add_form_row("stop_on_script_end", "Stop on Script End", False, QCheckBox(self), "Stop measurement when LED script ends")
+        self.w_form.add_form_row("use_buffer", "Use Buffer", False, QCheckBox(self), "If available, use the voltage device buffer for more accurate measurement timings.\nLeads to a lower accuracy of LED update timings, up to 1*interval")
         w_box_flush_after = QSpinBox(self)
         w_box_flush_after.setMaximum(2147483647)  # max int32
         w_box_flush_after.setSingleStep(500)
-        self._add_form_field("flush_after", "Flush-Data Interval", 0, w_box_flush_after, "Number of measurements to take before writing the data to an intermediate file")
+        self.w_form.add_form_row("flush_after", "Flush-Data Interval", 0, w_box_flush_after, "Number of measurements to take before writing the data to an intermediate file")
+        self.w_form.add_form_row("auto_add_metadata", "Auto-add Metadata", True,  QCheckBox(self), "Automatically add measurement metadata to the data file.\nThis includes: device names, measurement mode, measurement interval, start and stop times, led script")
+
         self.l_vbox.addStretch(1)
-        self._add_form_field("auto_add_metadata", "Auto-add Metadata", True,  QCheckBox(self), "Automatically add measurement metadata to the data file.\nThis includes: device names, measurement mode, measurement interval, start and stop times, led script")
 
-    def _add_form_field(self, key: str, label: str, default_value, widget: QWidget, tooltip: str = None):
-        if tooltip: widget.setToolTip(tooltip)
-        value = AppConfig.MEAS_CFG.get_or(key, default_value)
-        # set the value depending on the type of the widget
-        if isinstance(widget, QSpinBox) or isinstance(widget, QDoubleSpinBox):
-            widget.setValue(value)
-            widget.valueChanged.connect(lambda value: self.value_updated(key, value))
-        elif isinstance(widget, QCheckBox):
-            widget.setChecked(value)
-            widget.stateChanged.connect(lambda value: self.value_updated(key, value))
-        else:
-            raise ValueError(f"Unknown widget type: {type(widget)}")
-        self.l_form.addRow(QLabel(label), widget)
-        self.ws_form[key] = widget
-
-    def value_updated(self, key, value):
-        AppConfig.MEAS_CFG.set(key, value)
 
     def set_value(self, key, value):
-        if key in self.ws_form:
-            # set depending on widget type
-            if isinstance(self.ws_form[key], QSpinBox) or isinstance(self.ws_form[key], QDoubleSpinBox):
-                self.ws_form[key].setValue(value)
-            elif isinstance(self.ws_form[key], QCheckBox):
-                self.ws_form[key].setChecked(value)
-            else:
-                raise ValueError(f"Unknown widget type: {type(self.ws_form[key])}")
+        if key in self.w_form:
+            self.w_form.set_value(key, value)
         elif key.startswith("device_"):
             self.w_device_selection.set_value(key, value)
         else:
             raise ValueError(f"Unknown key: {key}")
 
     def get_value(self, key):
-        if key in self.ws_form:
-            # get depending on widget type
-            if isinstance(self.ws_form[key], QSpinBox) or isinstance(self.ws_form[key], QDoubleSpinBox):
-                return self.ws_form[key].value()
-            elif isinstance(self.ws_form[key], QCheckBox):
-               return self.ws_form[key].isChecked()
-            else:
-                raise ValueError(f"Unknown widget type: {type(self.ws_form[key])}")
+        if key in self.w_form:
+            return self.w_form.get_value(key)
         elif key == "led_script":
             return self.w_led_script.get_script()
         else: