diff --git a/README.md b/README.md
index 8d108438ee9bb92b2e85b01e6917344a5d76dc07..5841602bc890de1008bfda4da24e9e40ee060d3a 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
 [![PyPi](https://img.shields.io/pypi/v/cutelog.svg?style=flat-square)](https://pypi.python.org/pypi/cutelog)
 
 This is a graphical log viewer for Python's standard logging module.
-It can be targeted as a SocketHandler with no additional setup (see [Usage](#usage)).
+It can be targeted with a SocketHandler with no additional setup (see [Usage](#usage)).
 
 The program is in beta: it's lacking some features and may be unstable, but it works.
 cutelog is cross-platform, although it's mainly written and optimized for Linux.
@@ -45,14 +45,16 @@ $ pip install git+https://github.com/busimus/cutelog.git
 2. Put the following into your code:
 ```python
 import logging
-import logging.handlers
+from logging.handlers import SocketHandler
 
-log = logging.getLogger('MyLogger')
+log = logging.getLogger('Root logger')
 log.setLevel(1)  # to send all messages to cutelog
-socket_handler = logging.handlers.SocketHandler('127.0.0.1', 19996)  # default listening address
+socket_handler = SocketHandler('127.0.0.1', 19996)  # default listening address
 log.addHandler(socket_handler)
 log.info('Hello world!')
 ```
+Afterwards it's recommended to designate different loggers for different parts of your program with `log_2 = log.getChild("Child logger")`.
+This will create "log namespaces" which allow you to filter out messages from various subsystems of your program.
 
 ## Planned features
 * [ ] Indication that the connection has been closed
diff --git a/README.rst b/README.rst
index fafc8f0c7a01de9c91c07be90de63e387318c256..bba07ec006fbec8d818b8a6b4bcabb2beaa1f9e2 100644
--- a/README.rst
+++ b/README.rst
@@ -6,7 +6,7 @@ cutelog
 =======
 
 This is a graphical log viewer for Python's standard logging module.
-It can be targeted as a SocketHandler with no additional setup (see Usage_).
+It can be targeted with a SocketHandler with no additional setup (see Usage_).
 
 The program is in beta: it's lacking some features and may be unstable, but it works.
 cutelog is cross-platform, although it's mainly written and optimized for Linux.
@@ -52,12 +52,15 @@ Usage
     import logging
     from logging.handlers import SocketHandler
 
-    log = logging.getLogger('MyLogger')
+    log = logging.getLogger('Root logger')
     log.setLevel(1)  # to send all messages to cutelog
     socket_handler = SocketHandler('127.0.0.1', 19996)  # default listening address
     log.addHandler(socket_handler)
     log.info('Hello world!')
 
+Afterwards it's recommended to designate different loggers for different parts of your program with `log_2 = log.getChild("Child logger")`.
+This will create "log namespaces" which allow you to filter out messages from various subsystems of your program.
+
 Code, issues, changelog
 =======================
 Visit the project's `GitHub page <https://github.com/busimus/cutelog>`_.
diff --git a/cutelog/config.py b/cutelog/config.py
index 603d884d3d5b9e81147ae21cb4f5fffe8ce455bc..462aa1aa70428ee6f74c5c42d017634837d05f69 100644
--- a/cutelog/config.py
+++ b/cutelog/config.py
@@ -28,12 +28,12 @@ else:
 Option = namedtuple('Option', ['name', 'type', 'default'])
 OPTION_SPEC = (
     # Appearance
-    ('dark_theme_default',         bool, False),
-    ('logger_table_font',          str,  DEFAULT_FONT),
-    ('logger_table_font_size',     int,  9),
-    ('text_view_dialog_font',      str,  'Courier New'),
-    ('text_view_dialog_font_size', int,  12),
-    ('logger_row_height',          int,  20),
+    ('dark_theme_default',           bool, False),
+    ('logger_table_font',            str,  DEFAULT_FONT),
+    ('logger_table_font_size',       int,  9),
+    ('text_view_dialog_font',        str,  'Courier New'),
+    ('text_view_dialog_font_size',   int,  12),
+    ('logger_row_height',            int,  20),
 
     # Search
     ('search_open_default',          bool, False),
@@ -42,16 +42,16 @@ OPTION_SPEC = (
     ('search_wildcard_default',      bool, False),
 
     # Server
-    ('listen_host',  str,  '0.0.0.0'),
-    ('listen_port',  int,  19996),
-    ('one_tab_mode', bool, False),
+    ('listen_host',                  str,  '0.0.0.0'),
+    ('listen_port',                  int,  19996),
+    ('single_tab_mode_default',      bool, False),
 
     # Advanced
-    ('console_logging_level', int,   30),
-    ('loop_event_delay',      float, 0.005),
-    ('benchmark',             bool,  False),
-    ('benchmark_interval',    float, 0.0005),
-    ('light_theme_is_native', bool,  False),
+    ('console_logging_level',        int,   30),
+    ('loop_event_delay',             float, 0.005),
+    ('benchmark',                    bool,  False),
+    ('benchmark_interval',           float, 0.0005),
+    ('light_theme_is_native',        bool,  False),
 )
 
 
@@ -96,6 +96,15 @@ class Config(QObject):
         # self.log.debug('Returning "{}"'.format(value))
         return value
 
+    def __setitem__(self, name, value):
+        # self.log.debug('Setting "{}"'.format(name))
+        if name not in self.options:
+            raise Exception('No option with name "{}"'.format(name))
+        self.options[name] = value
+
+    def set_option(self, name, value):
+        self[name] = value
+
     @staticmethod
     def get_resource_path(name, directory='ui'):
         data_dir = resource_filename('cutelog', directory)
diff --git a/cutelog/listener.py b/cutelog/listener.py
index 4638ee702bad5101033f8e24f2ba990169df96c4..00ebb8d24777ccb1a307cff3c68d8c859cd61bdd 100644
--- a/cutelog/listener.py
+++ b/cutelog/listener.py
@@ -33,6 +33,8 @@ class LogServer(QTcpServer):
         if self.benchmark:
             self.log.debug('Starting a benchmark connection')
             new_conn = BenchmarkConnection(self, None, "benchmark", self.stop_signal, self.log)
+            new_conn.finished.connect(new_conn.deleteLater)
+            new_conn.connection_finished.connect(self.cleanup_connection)
             self.on_connection(new_conn, "benchmark")
             self.threads.append(new_conn)
             new_conn.start()
@@ -100,8 +102,9 @@ class LogConnection(QThread):
         self.tab_closed = False  # used to stop the connection from a "parent" logger
 
     def __repr__(self):
-        return "{}(name={}, socketDescriptor={})".format(self.__class__.__name__, self.name,
-                                                         self.socketDescriptor)
+        # return "{}(name={}, socketDescriptor={})".format(self.__class__.__name__, self.name,
+        #                                                  self.socketDescriptor)
+        return "{}(name={})".format(self.__class__.__name__, self.name)
 
     def run(self):
         self.log.debug('Connection "{}" is starting'.format(self.name))
@@ -188,3 +191,4 @@ class BenchmarkConnection(LogConnection):
             c += 1
             time.sleep(CONFIG.benchmark_interval)
         self.connection_finished.emit(self)
+        self.log.debug('Connection "{}" has stopped'.format(self.name))
diff --git a/cutelog/main_window.py b/cutelog/main_window.py
index 73646b80d36624b8c5261f01c765076bf0f9eaec..017136dc80134aab0dccb22b41aa430aee3cd6ef 100644
--- a/cutelog/main_window.py
+++ b/cutelog/main_window.py
@@ -1,4 +1,5 @@
 import asyncio
+from functools import partial
 
 from PyQt5 import uic
 from PyQt5.QtCore import Qt, QFile, QTextStream
@@ -30,6 +31,7 @@ class MainWindow(*MainWindowBase):
         self.stop_signal = asyncio.Event()
         self.finished = asyncio.Event()
         self.dark_theme = CONFIG['dark_theme_default']
+        self.single_tab_mode = CONFIG['single_tab_mode_default']
 
         self.loggers_by_name = {}  # name -> LoggerTab
 
@@ -44,34 +46,15 @@ class MainWindow(*MainWindowBase):
 
     def setupUi(self):
         super().setupUi(self)
+        self.setWindowTitle('cutelog')
+
         self.setup_menubar()
+        self.setup_action_triggers()
         self.setup_shortcuts()
 
         self.connectionTabWidget.tabCloseRequested.connect(self.close_tab)
 
-        self.setWindowTitle('cutelog')
-
-        self.actionQuit.triggered.connect(self.shutdown)
-
-        self.actionRenameTab.triggered.connect(self.rename_tab)
-        self.actionCloseTab.triggered.connect(self.close_current_tab)
-
-        self.actionPopOut.triggered.connect(self.pop_out_tab)
-        self.actionPopIn.triggered.connect(self.pop_in_tabs_dialog)
-        self.actionDarkTheme.toggled.connect(self.toggle_dark_theme)
-
-        # self.actionReloadStyle.triggered.connect(self.reload_stylesheet)
-        self.actionRestartServer.triggered.connect(self.restart_server)
-        self.actionStartStopServer.triggered.connect(self.start_or_stop_server)
-
-        self.actionAbout.triggered.connect(self.about_dialog)
-        self.actionSettings.triggered.connect(self.settings_dialog)
-        self.actionMergeTabs.triggered.connect(self.merge_tabs_dialog)
-        self.actionTrimTabRecords.triggered.connect(self.trim_records_dialog)
-        self.actionSetMaxCapacity.triggered.connect(self.max_capacity_dialog)
-
         self.reload_stylesheet()
-
         self.restore_geometry()
 
         self.show()
@@ -83,9 +66,12 @@ class MainWindow(*MainWindowBase):
 
         # File menu
         self.menuFile = self.menubar.addMenu("File")
-        self.actionDarkTheme = self.menuFile.addAction('Dark Theme')
+        self.actionDarkTheme = self.menuFile.addAction('Dark theme')
         self.actionDarkTheme.setCheckable(True)
         self.actionDarkTheme.setChecked(self.dark_theme)
+        self.actionSingleTab = self.menuFile.addAction('Single tab mode')
+        self.actionSingleTab.setCheckable(True)
+        self.actionSingleTab.setChecked(self.single_tab_mode)
         # self.actionReloadStyle = self.menuFile.addAction('Reload style')
         self.actionSettings = self.menuFile.addAction('Settings')
         self.menuFile.addSeparator()
@@ -113,6 +99,27 @@ class MainWindow(*MainWindowBase):
         self.menuHelp = self.menubar.addMenu("Help")
         self.actionAbout = self.menuHelp.addAction("About cutelog")
 
+    def setup_action_triggers(self):
+        self.actionQuit.triggered.connect(self.shutdown)
+        self.actionSingleTab.triggered.connect(partial(setattr, self, 'single_tab_mode'))
+
+        self.actionRenameTab.triggered.connect(self.rename_tab_dialog)
+        self.actionCloseTab.triggered.connect(self.close_current_tab)
+
+        self.actionPopOut.triggered.connect(self.pop_out_tab)
+        self.actionPopIn.triggered.connect(self.pop_in_tabs_dialog)
+        self.actionDarkTheme.toggled.connect(self.toggle_dark_theme)
+
+        # self.actionReloadStyle.triggered.connect(self.reload_stylesheet)
+        self.actionRestartServer.triggered.connect(self.restart_server)
+        self.actionStartStopServer.triggered.connect(self.start_or_stop_server)
+
+        self.actionAbout.triggered.connect(self.about_dialog)
+        self.actionSettings.triggered.connect(self.settings_dialog)
+        self.actionMergeTabs.triggered.connect(self.merge_tabs_dialog)
+        self.actionTrimTabRecords.triggered.connect(self.trim_records_dialog)
+        self.actionSetMaxCapacity.triggered.connect(self.max_capacity_dialog)
+
     def setup_shortcuts(self):
         self.actionQuit.setShortcut('Ctrl+Q')
         self.actionDarkTheme.setShortcut('Ctrl+S')
@@ -202,9 +209,11 @@ class MainWindow(*MainWindowBase):
 
     def on_connection(self, conn, name):
         self.log.debug('New connection: "{}"'.format(name))
-        one_tab_mode = CONFIG['one_tab_mode'] and len(self.loggers_by_name) > 0
 
-        if one_tab_mode:
+        # self.single_tab_mode is ignored if there are 0 tabs currently
+        single_tab_mode = self.single_tab_mode and len(self.loggers_by_name) > 0
+
+        if single_tab_mode:
             new_logger = list(self.loggers_by_name.values())[0]
             new_logger.add_connection(conn)
         else:
@@ -215,7 +224,7 @@ class MainWindow(*MainWindowBase):
         conn.new_record.connect(new_logger.on_record)
         conn.connection_finished.connect(new_logger.remove_connection)
 
-        if not one_tab_mode:
+        if not single_tab_mode:
             self.connectionTabWidget.addTab(new_logger, name)
             self.loggers_by_name[name] = new_logger
 
@@ -243,19 +252,6 @@ class MainWindow(*MainWindowBase):
         self.stop_reason = 'restart'
         self.stop_signal.set()
 
-    # async def wait_server_closed(self):
-    #     self.log.debug('Waiting for the server to close')
-    #     self.actionRestartServer.setText('Stopping the server...')
-    #     self.actionRestartServer.setEnabled(False)
-    #     try:
-    #         await asyncio.wait_for(self.server.wait_server_closed(), timeout=10)
-    #     except asyncio.TimeoutError as e:
-    #         self.log.error('Waiting for the server to close timed out after 10 seconds')
-    #     else:
-    #         self.log.debug('Waiting for server to close finished')
-    #         self.actionRestartServer.setText('Restart server')
-    #         self.actionRestartServer.setEnabled(True)
-
     def start_or_stop_server(self):
         if self.server_running:
             self.stop_reason = 'pause'
@@ -268,7 +264,7 @@ class MainWindow(*MainWindowBase):
     def set_status(self, string):
         self.statusBar().showMessage(string)
 
-    def rename_tab(self):
+    def rename_tab_dialog(self):
         logger, index = self.current_logger_and_index()
         if not logger:
             return
@@ -276,10 +272,10 @@ class MainWindow(*MainWindowBase):
         d = QInputDialog(self)
         d.setLabelText('Enter the new name for the "{}" tab:'.format(logger.name))
         d.setWindowTitle('Rename the "{}" tab'.format(logger.name))
-        d.textValueSelected.connect(self.change_current_tab_name)
+        d.textValueSelected.connect(self.rename_current_tab)
         d.open()
 
-    def change_current_tab_name(self, new_name):
+    def rename_current_tab(self, new_name):
         logger, index = self.current_logger_and_index()
         if new_name in self.loggers_by_name and new_name != logger.name:
             show_warning_dialog(self, "Rename error",
diff --git a/cutelog/resources/ui/settings_dialog.ui b/cutelog/resources/ui/settings_dialog.ui
index 5e230b9280d5f9505a9b29d86f6fcb5d869094b4..6fbd967de045e5d386b20a8dbcadf67e5f7f8f39 100644
--- a/cutelog/resources/ui/settings_dialog.ui
+++ b/cutelog/resources/ui/settings_dialog.ui
@@ -293,12 +293,12 @@
             </widget>
            </item>
            <item row="2" column="0">
-            <widget class="QLabel" name="oneTabLabel">
+            <widget class="QLabel" name="singleTabLabel">
              <property name="text">
-              <string>One &amp;tab for all connections</string>
+              <string>Single &amp;tab mode by default</string>
              </property>
              <property name="buddy">
-              <cstring>oneTabCheckBox</cstring>
+              <cstring>singleTabCheckBox</cstring>
              </property>
             </widget>
            </item>
@@ -316,7 +316,7 @@
             </spacer>
            </item>
            <item row="2" column="1">
-            <widget class="QCheckBox" name="oneTabCheckBox">
+            <widget class="QCheckBox" name="singleTabCheckBox">
              <property name="text">
               <string/>
              </property>
diff --git a/cutelog/settings_dialog.py b/cutelog/settings_dialog.py
index 5aa2aade34d19a7531c43703c71e722e3a4ead68..0c007638e88e56c24334393ae38a346cb4ee83ad 100644
--- a/cutelog/settings_dialog.py
+++ b/cutelog/settings_dialog.py
@@ -36,10 +36,10 @@ class SettingsDialog(*SettingsDialogBase):
         self.benchmarkCheckBox.setToolTip('Has effect after restarting the server, '
                                           '<b>for testing purposes only</b>.')
 
-        self.oneTabCheckBox.setToolTip("Forces all connections into one tab. "
+        self.singleTabCheckBox.setToolTip("Forces all connections into one tab. "
                                        "Useful for when you're restarting one "
                                        "program very often.")
-        self.oneTabLabel.setBuddy(self.oneTabCheckBox)  # @Hmmm: why doesn't this work?
+        self.singleTabLabel.setBuddy(self.singleTabCheckBox)  # @Hmmm: why doesn't this work?
 
     def load_from_config(self):
         # Appearance page
@@ -61,7 +61,7 @@ class SettingsDialog(*SettingsDialogBase):
         self.listenHostLine.setText(CONFIG['listen_host'])
         self.listenPortLine.setValidator(QIntValidator(0, 65535, self))
         self.listenPortLine.setText(str(CONFIG['listen_port']))
-        self.oneTabCheckBox.setChecked(CONFIG['one_tab_mode'])
+        self.singleTabCheckBox.setChecked(CONFIG['single_tab_mode_default'])
 
         # Advanced page
         self.logLevelLine.setValidator(QIntValidator(0, 1000, self))
@@ -99,7 +99,7 @@ class SettingsDialog(*SettingsDialogBase):
         o['listen_host'] = self.listenHostLine.text()
         o['listen_port'] = int(self.listenPortLine.text())
         o['console_logging_level'] = int(self.logLevelLine.text())
-        o['one_tab_mode'] = self.oneTabCheckBox.isChecked()
+        o['single_tab_mode_default'] = self.singleTabCheckBox.isChecked()
 
         # Advanced
         o['loop_event_delay'] = float(self.loopEventDelayLine.text())