Fix parents for all dialog windows
[quassel.git] / src / qtui / mainwin.cpp
index 7688512..b446130 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2005-2016 by the Quassel Project                        *
+ *   Copyright (C) 2005-2020 by the Quassel Project                        *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
 #include "mainwin.h"
 
 #include <QIcon>
+#include <QInputDialog>
 #include <QMenuBar>
 #include <QMessageBox>
 #include <QStatusBar>
 #include <QTableView>
 #include <QToolBar>
-#include <QInputDialog>
-
-#ifdef HAVE_KDE4
-#  include <KHelpMenu>
-#  include <KMenuBar>
-#  include <KShortcutsDialog>
-#  include <KStatusBar>
-#  include <KToggleFullScreenAction>
-#  include <KToolBar>
-#endif
 
 #ifdef HAVE_KF5
-#  include <KConfigWidgets/KStandardAction>
-#  include <KXmlGui/KHelpMenu>
-#  include <KXmlGui/KShortcutsDialog>
-#  include <KXmlGui/KToolBar>
-#  include <KWidgetsAddons/KToggleFullScreenAction>
+#    include <kconfigwidgets_version.h>
+
+#    include <KConfigWidgets/KStandardAction>
+#    include <KWidgetsAddons/KToggleFullScreenAction>
+#    include <KXmlGui/KHelpMenu>
+#    include <KXmlGui/KShortcutsDialog>
+#    include <KXmlGui/KToolBar>
 #endif
 
 #ifdef Q_WS_X11
-#  include <QX11Info>
+#    include <QX11Info>
 #endif
 
 #include "aboutdlg.h"
-#include "awaylogfilter.h"
-#include "awaylogview.h"
 #include "action.h"
 #include "actioncollection.h"
+#include "awaylogfilter.h"
+#include "awaylogview.h"
 #include "bufferhotlistfilter.h"
 #include "buffermodel.h"
 #include "bufferview.h"
 #include "clientignorelistmanager.h"
 #include "clienttransfer.h"
 #include "clienttransfermanager.h"
+#include "contextmenuactionprovider.h"
 #include "coreconfigwizard.h"
 #include "coreconnectdlg.h"
 #include "coreconnection.h"
 #include "coreconnectionstatuswidget.h"
 #include "coreinfodlg.h"
-#include "contextmenuactionprovider.h"
 #include "debugbufferviewoverlay.h"
-#include "debuglogwidget.h"
+#include "debuglogdlg.h"
 #include "debugmessagemodelfilter.h"
 #include "flatproxymodel.h"
+#include "icon.h"
 #include "inputwidget.h"
-#include "irclistmodel.h"
 #include "ircconnectionwizard.h"
+#include "irclistmodel.h"
 #include "legacysystemtray.h"
 #include "msgprocessorstatuswidget.h"
 #include "nicklistwidget.h"
 #include "qtuisettings.h"
 #include "qtuistyle.h"
 #include "receivefiledlg.h"
+#include "resourcetreedlg.h"
 #include "settingsdlg.h"
 #include "settingspagedlg.h"
+#include "sslinfodlg.h"
 #include "statusnotifieritem.h"
 #include "toolbaractionprovider.h"
 #include "topicwidget.h"
 #include "verticaldock.h"
 
 #ifndef HAVE_KDE
-#  ifdef HAVE_QTMULTIMEDIA
-#    include "qtmultimedianotificationbackend.h"
-#  endif
-#  ifdef HAVE_PHONON
-#    include "phononnotificationbackend.h"
-#  endif
-#  include "systraynotificationbackend.h"
-#  include "taskbarnotificationbackend.h"
+#    ifdef HAVE_QTMULTIMEDIA
+#        include "qtmultimedianotificationbackend.h"
+#    endif
+#    include "systraynotificationbackend.h"
+#    include "taskbarnotificationbackend.h"
 #else /* HAVE_KDE */
-#  include "knotificationbackend.h"
+#    include "knotificationbackend.h"
 #endif /* HAVE_KDE */
-
+#include "systrayanimationnotificationbackend.h"
 
 #ifdef HAVE_LIBSNORE
-#  include "snorenotificationbackend.h"
-#endif
-
-#ifdef HAVE_SSL
-#  include "sslinfodlg.h"
-#endif
-
-#ifdef HAVE_INDICATEQT
-  #include "indicatornotificationbackend.h"
+#    include "snorenotificationbackend.h"
 #endif
 
 #ifdef HAVE_NOTIFICATION_CENTER
-  #include "osxnotificationbackend.h"
+#    include "osxnotificationbackend.h"
 #endif
 
 #ifdef HAVE_DBUS
-  #include "dockmanagernotificationbackend.h"
+#    include "dockmanagernotificationbackend.h"
 #endif
 
 #include "settingspages/aliasessettingspage.h"
 #include "settingspages/backlogsettingspage.h"
 #include "settingspages/bufferviewsettingspage.h"
 #include "settingspages/chatmonitorsettingspage.h"
-#include "settingspages/chatviewsettingspage.h"
 #include "settingspages/chatviewcolorsettingspage.h"
+#include "settingspages/chatviewsettingspage.h"
 #include "settingspages/connectionsettingspage.h"
 #include "settingspages/coreaccountsettingspage.h"
 #include "settingspages/coreconnectionsettingspage.h"
+#include "settingspages/corehighlightsettingspage.h"
+#include "settingspages/dccsettingspage.h"
 #include "settingspages/highlightsettingspage.h"
 #include "settingspages/identitiessettingspage.h"
 #include "settingspages/ignorelistsettingspage.h"
 #include "settingspages/topicwidgetsettingspage.h"
 
 #ifndef HAVE_KDE
-#  include "settingspages/shortcutssettingspage.h"
+#    include "settingspages/shortcutssettingspage.h"
 #endif
 
 #ifdef HAVE_SONNET
-#  include "settingspages/sonnetsettingspage.h"
+#    include "settingspages/sonnetsettingspage.h"
 #endif
 
-
-MainWin::MainWin(QWidget *parent)
+MainWin::MainWin(QWidget* parent)
 #ifdef HAVE_KDE
-    : KMainWindow(parent), _kHelpMenu(new KHelpMenu(this)),
+    : KMainWindow(parent)
+    , _kHelpMenu(new KHelpMenu(this))
+    ,
 #else
-    : QMainWindow(parent),
+    : QMainWindow(parent)
+    ,
 #endif
-    _msgProcessorStatusWidget(new MsgProcessorStatusWidget(this)),
-    _coreConnectionStatusWidget(new CoreConnectionStatusWidget(Client::coreConnection(), this)),
-    _titleSetter(this),
-    _awayLog(0),
-    _layoutLoaded(false),
-    _activeBufferViewIndex(-1),
-    _aboutToQuit(false)
+    _msgProcessorStatusWidget(new MsgProcessorStatusWidget(this))
+    , _coreConnectionStatusWidget(new CoreConnectionStatusWidget(Client::coreConnection(), this))
+    , _titleSetter(this)
 {
-    setAttribute(Qt::WA_DeleteOnClose, false); // we delete the mainwin manually
+    setAttribute(Qt::WA_DeleteOnClose, false);  // we delete the mainwin manually
 
     QtUiSettings uiSettings;
     QString style = uiSettings.value("Style", QString()).toString();
@@ -190,27 +175,30 @@ MainWin::MainWin(QWidget *parent)
 
     setWindowTitle("Quassel IRC");
     setWindowIconText("Quassel IRC");
+    // Set the default icon for all windows
+    QApplication::setWindowIcon(icon::get("quassel"));
     updateIcon();
 }
 
-
 void MainWin::init()
 {
-    connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), SLOT(clientNetworkCreated(NetworkId)));
-    connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), SLOT(clientNetworkRemoved(NetworkId)));
-    connect(Client::messageModel(), SIGNAL(rowsInserted(const QModelIndex &, int, int)),
-        SLOT(messagesInserted(const QModelIndex &, int, int)));
-    connect(GraphicalUi::contextMenuActionProvider(), SIGNAL(showChannelList(NetworkId)), SLOT(showChannelList(NetworkId)));
-    connect(GraphicalUi::contextMenuActionProvider(), SIGNAL(showIgnoreList(QString)), SLOT(showIgnoreList(QString)));
-
-    connect(Client::coreConnection(), SIGNAL(startCoreSetup(QVariantList)), SLOT(showCoreConfigWizard(QVariantList)));
-    connect(Client::coreConnection(), SIGNAL(connectionErrorPopup(QString)), SLOT(handleCoreConnectionError(QString)));
-    connect(Client::coreConnection(), SIGNAL(userAuthenticationRequired(CoreAccount *, bool *, QString)), SLOT(userAuthenticationRequired(CoreAccount *, bool *, QString)));
-    connect(Client::coreConnection(), SIGNAL(handleNoSslInClient(bool *)), SLOT(handleNoSslInClient(bool *)));
-    connect(Client::coreConnection(), SIGNAL(handleNoSslInCore(bool *)), SLOT(handleNoSslInCore(bool *)));
-#ifdef HAVE_SSL
-    connect(Client::coreConnection(), SIGNAL(handleSslErrors(const QSslSocket *, bool *, bool *)), SLOT(handleSslErrors(const QSslSocket *, bool *, bool *)));
-#endif
+    connect(Client::instance(), &Client::networkCreated, this, &MainWin::clientNetworkCreated);
+    connect(Client::instance(), &Client::networkRemoved, this, &MainWin::clientNetworkRemoved);
+    connect(Client::messageModel(), &QAbstractItemModel::rowsInserted, this, &MainWin::messagesInserted);
+    connect(GraphicalUi::contextMenuActionProvider(), &NetworkModelController::showChannelList, this, &MainWin::showChannelList);
+    connect(Client::instance(), &Client::showChannelList, this, &MainWin::showChannelList);
+    connect(GraphicalUi::contextMenuActionProvider(), &NetworkModelController::showNetworkConfig, this, &MainWin::showNetworkConfig);
+    connect(GraphicalUi::contextMenuActionProvider(), &NetworkModelController::showIgnoreList, this, &MainWin::showIgnoreList);
+    connect(Client::instance(), &Client::showIgnoreList, this, &MainWin::showIgnoreList);
+    connect(Client::instance(), &Client::dbUpgradeInProgress, this, &MainWin::showMigrationWarning);
+    connect(Client::instance(), &Client::exitRequested, this, &MainWin::onExitRequested);
+
+    connect(Client::coreConnection(), &CoreConnection::startCoreSetup, this, &MainWin::showCoreConfigWizard);
+    connect(Client::coreConnection(), &CoreConnection::connectionErrorPopup, this, &MainWin::handleCoreConnectionError);
+    connect(Client::coreConnection(), &CoreConnection::userAuthenticationRequired, this, &MainWin::userAuthenticationRequired);
+    connect(Client::coreConnection(), &CoreConnection::handleNoSslInClient, this, &MainWin::handleNoSslInClient);
+    connect(Client::coreConnection(), &CoreConnection::handleNoSslInCore, this, &MainWin::handleNoSslInCore);
+    connect(Client::coreConnection(), &CoreConnection::handleSslErrors, this, &MainWin::handleSslErrors);
 
     // Setup Dock Areas
     setDockNestingEnabled(true);
@@ -223,7 +211,7 @@ void MainWin::init()
     setupActions();
     setupBufferWidget();
     setupMenus();
-    setupTransferWidget();
+    // setupTransferWidget(); not ready yet
     setupChatMonitor();
     setupTopicWidget();
     setupInputWidget();
@@ -239,28 +227,23 @@ void MainWin::init()
     _chatMonitorView->setFocusProxy(_inputWidget);
 
 #ifndef HAVE_KDE
-#  ifdef HAVE_QTMULTIMEDIA
+#    ifdef HAVE_QTMULTIMEDIA
     QtUi::registerNotificationBackend(new QtMultimediaNotificationBackend(this));
-#  endif
-#  ifdef HAVE_PHONON
-    QtUi::registerNotificationBackend(new PhononNotificationBackend(this));
-#  endif
+#    endif
     QtUi::registerNotificationBackend(new TaskbarNotificationBackend(this));
-#else /* HAVE_KDE */
+#else  /* HAVE_KDE */
     QtUi::registerNotificationBackend(new KNotificationBackend(this));
 #endif /* HAVE_KDE */
 
-
+#ifndef QT_NO_SYSTEMTRAYICON
+    QtUi::registerNotificationBackend(new SystrayAnimationNotificationBackend(this));
+#endif
 #ifdef HAVE_LIBSNORE
     QtUi::registerNotificationBackend(new SnoreNotificationBackend(this));
 #elif !defined(QT_NO_SYSTEMTRAYICON) && !defined(HAVE_KDE)
     QtUi::registerNotificationBackend(new SystrayNotificationBackend(this));
 #endif
 
-#ifdef HAVE_INDICATEQT
-    QtUi::registerNotificationBackend(new IndicatorNotificationBackend(this));
-#endif
-
 #ifdef HAVE_NOTIFICATION_CENTER
     QtUi::registerNotificationBackend(new OSXNotificationBackend(this));
 #endif
@@ -272,9 +255,9 @@ void MainWin::init()
     // we assume that at this point, all configurable actions are defined!
     QtUi::loadShortcuts();
 
-    connect(bufferWidget(), SIGNAL(currentChanged(BufferId)), SLOT(currentBufferChanged(BufferId)));
+    connect(bufferWidget(), selectOverload<BufferId>(&AbstractBufferContainer::currentChanged), this, &MainWin::currentBufferChanged);
 
-    setDisconnectedState(); // Disable menus and stuff
+    setDisconnectedState();  // Disable menus and stuff
 
 #ifdef HAVE_KDE
     setAutoSaveSettings();
@@ -287,29 +270,20 @@ void MainWin::init()
     // restore locked state of docks
     QtUi::actionCollection("General")->action("LockLayout")->setChecked(s.value("LockLayout", false).toBool());
 
-    CoreConnection *conn = Client::coreConnection();
-    if (!conn->connectToCore()) {
-        // No autoconnect selected (or no accounts)
-        showCoreConnectionDlg();
-    }
-}
-
-
-MainWin::~MainWin()
-{
-}
+    Quassel::registerQuitHandler([this]() {
+        QtUiSettings s;
+        saveStateToSettings(s);
+        saveLayout();
+        // Close all open dialogs and the MainWin, so we can safely kill the Client instance afterwards
+        // Note: This does not quit the application, as quitOnLastWindowClosed is set to false.
+        //       We rely on another quit handler to be registered that actually quits the application.
+        qApp->closeAllWindows();
+    });
 
-
-void MainWin::quit()
-{
-    QtUiSettings s;
-    saveStateToSettings(s);
-    saveLayout();
-    QApplication::quit();
+    QTimer::singleShot(0, this, &MainWin::doAutoConnect);
 }
 
-
-void MainWin::saveStateToSettings(UiSettings &s)
+void MainWin::saveStateToSettings(UiSettings& s)
 {
     s.setValue("MainWinSize", _normalSize);
     s.setValue("MainWinPos", _normalPos);
@@ -327,8 +301,7 @@ void MainWin::saveStateToSettings(UiSettings &s)
 #endif
 }
 
-
-void MainWin::restoreStateFromSettings(UiSettings &s)
+void MainWin::restoreStateFromSettings(UiSettings& s)
 {
     _normalSize = s.value("MainWinSize", size()).toSize();
     _normalPos = s.value("MainWinPos", pos()).toPoint();
@@ -349,9 +322,7 @@ void MainWin::restoreStateFromSettings(UiSettings &s)
     move(_normalPos);
 #endif
 
-    if ((Quassel::isOptionSet("hidewindow")
-            || s.value("MainWinHidden").toBool())
-            && _systemTray->isSystemTrayAvailable())
+    if ((Quassel::isOptionSet("hidewindow") || s.value("MainWinHidden").toBool()) && _systemTray->isSystemTrayAvailable())
         QtUi::hideMainWidget();
     else if (s.value("MainWinMinimized").toBool())
         showMinimized();
@@ -361,123 +332,157 @@ void MainWin::restoreStateFromSettings(UiSettings &s)
         show();
 }
 
-QMenu *MainWin::createPopupMenu()
+QMenuMainWin::createPopupMenu()
 {
-    QMenu *popupMenu = QMainWindow::createPopupMenu();
+    QMenupopupMenu = QMainWindow::createPopupMenu();
     popupMenu->addSeparator();
-    ActionCollection *coll = QtUi::actionCollection("General");
+    ActionCollectioncoll = QtUi::actionCollection("General");
     popupMenu->addAction(coll->action("ToggleMenuBar"));
     return popupMenu;
 }
 
-
 void MainWin::updateIcon()
 {
     QIcon icon;
     if (Client::isConnected())
-        icon = QIcon::fromTheme("quassel", QIcon(":/icons/quassel-128.png"));
+        icon = icon::get("quassel");
     else
-        icon = QIcon::fromTheme("quassel-inactive", QIcon(":/icons/quassel-128.png"));
+        icon = icon::get("inactive-quassel");
     setWindowIcon(icon);
-    qApp->setWindowIcon(icon);
 }
 
-
 void MainWin::setupActions()
 {
-    ActionCollection *coll = QtUi::actionCollection("General", tr("General"));
+    QAction* action{nullptr};
+    ActionCollection* coll = QtUi::actionCollection("General", tr("General"));
+
     // File
-    coll->addAction("ConnectCore", new Action(QIcon(":/icons/quassel-128.png"), tr("&Connect to Core..."), coll,
-            this, SLOT(showCoreConnectionDlg())));
-    coll->addAction("DisconnectCore", new Action(QIcon(":/icons/quassel-disconnect.png"), tr("&Disconnect from Core"), coll,
-            Client::instance(), SLOT(disconnectFromCore())));
-    coll->addAction("ChangePassword", new Action(QIcon::fromTheme("dialog-password"), tr("Change &Password..."), coll,
-            this, SLOT(showPasswordChangeDlg())));
-    coll->addAction("CoreInfo", new Action(QIcon::fromTheme("help-about"), tr("Core &Info..."), coll,
-            this, SLOT(showCoreInfoDlg())));
-    coll->addAction("ConfigureNetworks", new Action(QIcon::fromTheme("configure"), tr("Configure &Networks..."), coll,
-            this, SLOT(on_actionConfigureNetworks_triggered())));
-    // FIXME: use QKeySequence::Quit once we depend on Qt 4.6
-    coll->addAction("Quit", new Action(QIcon::fromTheme("application-exit"), tr("&Quit"), coll,
-            this, SLOT(quit()), Qt::CTRL + Qt::Key_Q));
+    coll->addActions(
+        {{"ConnectCore", new Action(icon::get("connect-quassel"), tr("&Connect to Core..."), coll, this, &MainWin::showCoreConnectionDlg)},
+         {"DisconnectCore",
+          new Action(icon::get("disconnect-quassel"), tr("&Disconnect from Core"), coll, Client::instance(), &Client::disconnectFromCore)},
+         {"ChangePassword", new Action(icon::get("dialog-password"), tr("Change &Password..."), coll, this, &MainWin::showPasswordChangeDlg)},
+         {"CoreInfo", new Action(icon::get("help-about"), tr("Core &Info..."), coll, this, &MainWin::showCoreInfoDlg)},
+         {"ConfigureNetworks",
+          new Action(icon::get("configure"), tr("Configure &Networks..."), coll, this, &MainWin::onConfigureNetworksTriggered)},
+         {"Quit", new Action(icon::get("application-exit"), tr("&Quit"), coll, Quassel::instance(), &Quassel::quit, Qt::CTRL + Qt::Key_Q)}});
 
     // View
-    coll->addAction("ConfigureBufferViews", new Action(tr("&Configure Chat Lists..."), coll,
-            this, SLOT(on_actionConfigureViews_triggered())));
+    coll->addAction("ConfigureBufferViews", new Action(tr("&Configure Chat Lists..."), coll, this, &MainWin::onConfigureViewsTriggered));
 
-    QAction *lockAct = coll->addAction("LockLayout", new Action(tr("&Lock Layout"), coll));
-    lockAct->setCheckable(true);
-    connect(lockAct, SIGNAL(toggled(bool)), SLOT(on_actionLockLayout_toggled(bool)));
+    coll->addAction("ToggleSearchBar", new Action(icon::get("edit-find"), tr("Show &Search Bar"), coll, QKeySequence::Find))->setCheckable(true);
+    coll->addAction("ShowAwayLog", new Action(tr("Show Away Log"), coll, this, &MainWin::showAwayLog));
+    coll->addAction("ToggleMenuBar", new Action(icon::get("show-menu"), tr("Show &Menubar"), coll))->setCheckable(true);
+    coll->addAction("ToggleStatusBar", new Action(tr("Show Status &Bar"), coll))->setCheckable(true);
 
-    coll->addAction("ToggleSearchBar", new Action(QIcon::fromTheme("edit-find"), tr("Show &Search Bar"), coll,
-            0, 0, QKeySequence::Find))->setCheckable(true);
-    coll->addAction("ShowAwayLog", new Action(tr("Show Away Log"), coll,
-            this, SLOT(showAwayLog())));
-    coll->addAction("ToggleMenuBar", new Action(QIcon::fromTheme("show-menu"), tr("Show &Menubar"), coll,
-            0, 0))->setCheckable(true);
-
-    coll->addAction("ToggleStatusBar", new Action(tr("Show Status &Bar"), coll,
-            0, 0))->setCheckable(true);
+    action = coll->addAction("LockLayout", new Action(tr("&Lock Layout"), coll));
+    action->setCheckable(true);
+    connect(action, &QAction::toggled, this, &MainWin::onLockLayoutToggled);
 
 #ifdef HAVE_KDE
+#    if KCONFIGWIDGETS_VERSION < QT_VERSION_CHECK(5, 23, 0)
     _fullScreenAction = KStandardAction::fullScreen(this, SLOT(onFullScreenToggled()), this, coll);
+#    else
+    _fullScreenAction = KStandardAction::fullScreen(this, &MainWin::onFullScreenToggled, this, coll);
+#    endif
 #else
-    _fullScreenAction = new Action(QIcon::fromTheme("view-fullscreen"), tr("&Full Screen Mode"), coll,
-        this, SLOT(onFullScreenToggled()), QKeySequence(Qt::Key_F11));
+    _fullScreenAction = new Action(icon::get("view-fullscreen"),
+                                   tr("&Full Screen Mode"),
+                                   coll,
+                                   this,
+                                   &MainWin::onFullScreenToggled,
+                                   QKeySequence::FullScreen);
     _fullScreenAction->setCheckable(true);
     coll->addAction("ToggleFullScreen", _fullScreenAction);
 #endif
 
     // Settings
-    QAction *configureShortcutsAct = new Action(QIcon::fromTheme("configure-shortcuts"), tr("Configure &Shortcuts..."), coll,
-        this, SLOT(showShortcutsDlg()));
-    configureShortcutsAct->setMenuRole(QAction::NoRole);
-    coll->addAction("ConfigureShortcuts", configureShortcutsAct);
-
-#ifdef Q_OS_MAC
-    QAction *configureQuasselAct = new Action(QIcon::fromTheme("configure"), tr("&Configure Quassel..."), coll,
-        this, SLOT(showSettingsDlg()));
-    configureQuasselAct->setMenuRole(QAction::PreferencesRole);
-#else
-    QAction *configureQuasselAct = new Action(QIcon::fromTheme("configure"), tr("&Configure Quassel..."), coll,
-        this, SLOT(showSettingsDlg()), QKeySequence(Qt::Key_F7));
-#endif
-    coll->addAction("ConfigureQuassel", configureQuasselAct);
+    coll->addAction("ConfigureShortcuts",
+                    new Action(icon::get("configure-shortcuts"), tr("Configure &Shortcuts..."), coll, this, &MainWin::showShortcutsDlg))
+        ->setMenuRole(QAction::NoRole);
+    coll->addAction("ConfigureQuassel",
+                    new Action(icon::get("configure"), tr("&Configure Quassel..."), coll, this, &MainWin::showSettingsDlg, QKeySequence(Qt::Key_F7)))
+        ->setMenuRole(QAction::PreferencesRole);
 
     // Help
-    QAction *aboutQuasselAct = new Action(QIcon(":/icons/quassel.png"), tr("&About Quassel"), coll,
-        this, SLOT(showAboutDlg()));
-    aboutQuasselAct->setMenuRole(QAction::AboutRole);
-    coll->addAction("AboutQuassel", aboutQuasselAct);
-
-    QAction *aboutQtAct = new Action(QIcon(":/pics/qt-logo.png"), tr("About &Qt"), coll,
-        qApp, SLOT(aboutQt()));
-    aboutQtAct->setMenuRole(QAction::AboutQtRole);
-    coll->addAction("AboutQt", aboutQtAct);
-    coll->addAction("DebugNetworkModel", new Action(QIcon::fromTheme("tools-report-bug"), tr("Debug &NetworkModel"), coll,
-            this, SLOT(on_actionDebugNetworkModel_triggered())));
-    coll->addAction("DebugBufferViewOverlay", new Action(QIcon::fromTheme("tools-report-bug"), tr("Debug &BufferViewOverlay"), coll,
-            this, SLOT(on_actionDebugBufferViewOverlay_triggered())));
-    coll->addAction("DebugMessageModel", new Action(QIcon::fromTheme("tools-report-bug"), tr("Debug &MessageModel"), coll,
-            this, SLOT(on_actionDebugMessageModel_triggered())));
-    coll->addAction("DebugHotList", new Action(QIcon::fromTheme("tools-report-bug"), tr("Debug &HotList"), coll,
-            this, SLOT(on_actionDebugHotList_triggered())));
-    coll->addAction("DebugLog", new Action(QIcon::fromTheme("tools-report-bug"), tr("Debug &Log"), coll,
-            this, SLOT(on_actionDebugLog_triggered())));
-    coll->addAction("ReloadStyle", new Action(QIcon::fromTheme("view-refresh"), tr("Reload Stylesheet"), coll,
-            QtUi::style(), SLOT(reload()), QKeySequence::Refresh));
-
-    coll->addAction("HideCurrentBuffer", new Action(tr("Hide Current Buffer"), coll,
-            this, SLOT(hideCurrentBuffer()), QKeySequence::Close));
+    coll->addAction("AboutQuassel", new Action(icon::get("quassel"), tr("&About Quassel"), coll, this, &MainWin::showAboutDlg))
+        ->setMenuRole(QAction::AboutRole);
+    coll->addAction("AboutQt", new Action(QIcon(":/pics/qt-logo-32.png"), tr("About &Qt"), coll, qApp, &QApplication::aboutQt))
+        ->setMenuRole(QAction::AboutQtRole);
+    coll->addActions(
+        {{"DebugNetworkModel",
+          new Action(icon::get("tools-report-bug"), tr("Debug &NetworkModel"), coll, this, &MainWin::onDebugNetworkModelTriggered)},
+         {"DebugBufferViewOverlay",
+          new Action(icon::get("tools-report-bug"), tr("Debug &BufferViewOverlay"), coll, this, &MainWin::onDebugBufferViewOverlayTriggered)},
+         {"DebugMessageModel",
+          new Action(icon::get("tools-report-bug"), tr("Debug &MessageModel"), coll, this, &MainWin::onDebugMessageModelTriggered)},
+         {"DebugHotList", new Action(icon::get("tools-report-bug"), tr("Debug &HotList"), coll, this, &MainWin::onDebugHotListTriggered)},
+         {"DebugLog", new Action(icon::get("tools-report-bug"), tr("Debug &Log"), coll, this, &MainWin::onDebugLogTriggered)},
+         {"ShowResourceTree",
+          new Action(icon::get("tools-report-bug"), tr("Show &Resource Tree"), coll, this, &MainWin::onShowResourceTreeTriggered)},
+         {"ReloadStyle",
+          new Action(icon::get("view-refresh"),
+                     tr("Reload Stylesheet"),
+                     coll,
+                     QtUi::style(),
+                     &UiStyle::reload,
+                     QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_R))}});
+
+    // Other
+    coll->addAction("HideCurrentBuffer", new Action(tr("Hide Current Buffer"), coll, this, &MainWin::hideCurrentBuffer, QKeySequence::Close));
+
+    // Text formatting
+    coll = QtUi::actionCollection("TextFormat", tr("Text formatting"));
+
+    coll->addActions(
+        {{"FormatApplyColor",
+          new Action(icon::get("format-text-color"),
+                     tr("Apply foreground color"),
+                     coll,
+                     this,
+                     &MainWin::onFormatApplyColorTriggered,
+                     QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_G))},
+         {"FormatApplyColorFill",
+          new Action(icon::get("format-fill-color"),
+                     tr("Apply background color"),
+                     coll,
+                     this,
+                     &MainWin::onFormatApplyColorFillTriggered,
+                     QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_B))},
+         {"FormatClear",
+          new Action(icon::get("edit-clear"),
+                     tr("Clear formatting"),
+                     coll,
+                     this,
+                     &MainWin::onFormatClearTriggered,
+                     QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C))},
+         {"FormatBold",
+          new Action(icon::get("format-text-bold"), tr("Toggle bold"), coll, this, &MainWin::onFormatBoldTriggered, QKeySequence::Bold)},
+         {"FormatItalic",
+          new Action(icon::get("format-text-italic"), tr("Toggle italics"), coll, this, &MainWin::onFormatItalicTriggered, QKeySequence::Italic)},
+         {"FormatUnderline",
+          new Action(icon::get("format-text-underline"),
+                     tr("Toggle underline"),
+                     coll,
+                     this,
+                     &MainWin::onFormatUnderlineTriggered,
+                     QKeySequence::Underline)},
+         {"FormatStrikethrough",
+          new Action(icon::get("format-text-strikethrough"),
+                     tr("Toggle strikethrough"),
+                     coll,
+                     this,
+                     &MainWin::onFormatStrikethroughTriggered,
+                     QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_S))}});
 
     // Navigation
     coll = QtUi::actionCollection("Navigation", tr("Navigation"));
 
-    coll->addAction("JumpHotBuffer", new Action(tr("Jump to hot chat"), coll,
-            this, SLOT(on_jumpHotBuffer_triggered()), QKeySequence(Qt::META + Qt::Key_A)));
-
-    coll->addAction("ActivateBufferFilter", new Action(tr("Activate the buffer search"), coll,
-            this, SLOT(on_bufferSearch_triggered()), QKeySequence(Qt::CTRL + Qt::Key_S)));
+    coll->addActions(
+        {{"JumpHotBuffer",
+          new Action(tr("Jump to hot chat"), coll, this, &MainWin::onJumpHotBufferTriggered, QKeySequence(Qt::META + Qt::Key_A))},
+         {"ActivateBufferFilter",
+          new Action(tr("Activate the buffer search"), coll, this, &MainWin::onBufferSearchTriggered, QKeySequence(Qt::CTRL + Qt::Key_S))}});
 
     // Jump keys
 #ifdef Q_OS_MAC
@@ -488,71 +493,102 @@ void MainWin::setupActions()
     const int jumpModifier = Qt::AltModifier;
 #endif
 
-    coll->addAction("BindJumpKey0", new Action(tr("Set Quick Access #0"), coll, this, SLOT(bindJumpKey()),
-            QKeySequence(bindModifier + Qt::Key_0)))->setProperty("Index", 0);
-    coll->addAction("BindJumpKey1", new Action(tr("Set Quick Access #1"), coll, this, SLOT(bindJumpKey()),
-            QKeySequence(bindModifier + Qt::Key_1)))->setProperty("Index", 1);
-    coll->addAction("BindJumpKey2", new Action(tr("Set Quick Access #2"), coll, this, SLOT(bindJumpKey()),
-            QKeySequence(bindModifier + Qt::Key_2)))->setProperty("Index", 2);
-    coll->addAction("BindJumpKey3", new Action(tr("Set Quick Access #3"), coll, this, SLOT(bindJumpKey()),
-            QKeySequence(bindModifier + Qt::Key_3)))->setProperty("Index", 3);
-    coll->addAction("BindJumpKey4", new Action(tr("Set Quick Access #4"), coll, this, SLOT(bindJumpKey()),
-            QKeySequence(bindModifier + Qt::Key_4)))->setProperty("Index", 4);
-    coll->addAction("BindJumpKey5", new Action(tr("Set Quick Access #5"), coll, this, SLOT(bindJumpKey()),
-            QKeySequence(bindModifier + Qt::Key_5)))->setProperty("Index", 5);
-    coll->addAction("BindJumpKey6", new Action(tr("Set Quick Access #6"), coll, this, SLOT(bindJumpKey()),
-            QKeySequence(bindModifier + Qt::Key_6)))->setProperty("Index", 6);
-    coll->addAction("BindJumpKey7", new Action(tr("Set Quick Access #7"), coll, this, SLOT(bindJumpKey()),
-            QKeySequence(bindModifier + Qt::Key_7)))->setProperty("Index", 7);
-    coll->addAction("BindJumpKey8", new Action(tr("Set Quick Access #8"), coll, this, SLOT(bindJumpKey()),
-            QKeySequence(bindModifier + Qt::Key_8)))->setProperty("Index", 8);
-    coll->addAction("BindJumpKey9", new Action(tr("Set Quick Access #9"), coll, this, SLOT(bindJumpKey()),
-            QKeySequence(bindModifier + Qt::Key_9)))->setProperty("Index", 9);
-
-    coll->addAction("JumpKey0", new Action(tr("Quick Access #0"), coll, this, SLOT(onJumpKey()),
-            QKeySequence(jumpModifier + Qt::Key_0)))->setProperty("Index", 0);
-    coll->addAction("JumpKey1", new Action(tr("Quick Access #1"), coll, this, SLOT(onJumpKey()),
-            QKeySequence(jumpModifier + Qt::Key_1)))->setProperty("Index", 1);
-    coll->addAction("JumpKey2", new Action(tr("Quick Access #2"), coll, this, SLOT(onJumpKey()),
-            QKeySequence(jumpModifier + Qt::Key_2)))->setProperty("Index", 2);
-    coll->addAction("JumpKey3", new Action(tr("Quick Access #3"), coll, this, SLOT(onJumpKey()),
-            QKeySequence(jumpModifier + Qt::Key_3)))->setProperty("Index", 3);
-    coll->addAction("JumpKey4", new Action(tr("Quick Access #4"), coll, this, SLOT(onJumpKey()),
-            QKeySequence(jumpModifier + Qt::Key_4)))->setProperty("Index", 4);
-    coll->addAction("JumpKey5", new Action(tr("Quick Access #5"), coll, this, SLOT(onJumpKey()),
-            QKeySequence(jumpModifier + Qt::Key_5)))->setProperty("Index", 5);
-    coll->addAction("JumpKey6", new Action(tr("Quick Access #6"), coll, this, SLOT(onJumpKey()),
-            QKeySequence(jumpModifier + Qt::Key_6)))->setProperty("Index", 6);
-    coll->addAction("JumpKey7", new Action(tr("Quick Access #7"), coll, this, SLOT(onJumpKey()),
-            QKeySequence(jumpModifier + Qt::Key_7)))->setProperty("Index", 7);
-    coll->addAction("JumpKey8", new Action(tr("Quick Access #8"), coll, this, SLOT(onJumpKey()),
-            QKeySequence(jumpModifier + Qt::Key_8)))->setProperty("Index", 8);
-    coll->addAction("JumpKey9", new Action(tr("Quick Access #9"), coll, this, SLOT(onJumpKey()),
-            QKeySequence(jumpModifier + Qt::Key_9)))->setProperty("Index", 9);
+    coll->addAction("BindJumpKey0",
+                    new Action(tr("Set Quick Access #0"), coll, this, &MainWin::bindJumpKey, QKeySequence(bindModifier + Qt::Key_0)))
+        ->setProperty("Index", 0);
+    coll->addAction("BindJumpKey1",
+                    new Action(tr("Set Quick Access #1"), coll, this, &MainWin::bindJumpKey, QKeySequence(bindModifier + Qt::Key_1)))
+        ->setProperty("Index", 1);
+    coll->addAction("BindJumpKey2",
+                    new Action(tr("Set Quick Access #2"), coll, this, &MainWin::bindJumpKey, QKeySequence(bindModifier + Qt::Key_2)))
+        ->setProperty("Index", 2);
+    coll->addAction("BindJumpKey3",
+                    new Action(tr("Set Quick Access #3"), coll, this, &MainWin::bindJumpKey, QKeySequence(bindModifier + Qt::Key_3)))
+        ->setProperty("Index", 3);
+    coll->addAction("BindJumpKey4",
+                    new Action(tr("Set Quick Access #4"), coll, this, &MainWin::bindJumpKey, QKeySequence(bindModifier + Qt::Key_4)))
+        ->setProperty("Index", 4);
+    coll->addAction("BindJumpKey5",
+                    new Action(tr("Set Quick Access #5"), coll, this, &MainWin::bindJumpKey, QKeySequence(bindModifier + Qt::Key_5)))
+        ->setProperty("Index", 5);
+    coll->addAction("BindJumpKey6",
+                    new Action(tr("Set Quick Access #6"), coll, this, &MainWin::bindJumpKey, QKeySequence(bindModifier + Qt::Key_6)))
+        ->setProperty("Index", 6);
+    coll->addAction("BindJumpKey7",
+                    new Action(tr("Set Quick Access #7"), coll, this, &MainWin::bindJumpKey, QKeySequence(bindModifier + Qt::Key_7)))
+        ->setProperty("Index", 7);
+    coll->addAction("BindJumpKey8",
+                    new Action(tr("Set Quick Access #8"), coll, this, &MainWin::bindJumpKey, QKeySequence(bindModifier + Qt::Key_8)))
+        ->setProperty("Index", 8);
+    coll->addAction("BindJumpKey9",
+                    new Action(tr("Set Quick Access #9"), coll, this, &MainWin::bindJumpKey, QKeySequence(bindModifier + Qt::Key_9)))
+        ->setProperty("Index", 9);
+
+    coll->addAction("JumpKey0", new Action(tr("Quick Access #0"), coll, this, &MainWin::onJumpKey, QKeySequence(jumpModifier + Qt::Key_0)))
+        ->setProperty("Index", 0);
+    coll->addAction("JumpKey1", new Action(tr("Quick Access #1"), coll, this, &MainWin::onJumpKey, QKeySequence(jumpModifier + Qt::Key_1)))
+        ->setProperty("Index", 1);
+    coll->addAction("JumpKey2", new Action(tr("Quick Access #2"), coll, this, &MainWin::onJumpKey, QKeySequence(jumpModifier + Qt::Key_2)))
+        ->setProperty("Index", 2);
+    coll->addAction("JumpKey3", new Action(tr("Quick Access #3"), coll, this, &MainWin::onJumpKey, QKeySequence(jumpModifier + Qt::Key_3)))
+        ->setProperty("Index", 3);
+    coll->addAction("JumpKey4", new Action(tr("Quick Access #4"), coll, this, &MainWin::onJumpKey, QKeySequence(jumpModifier + Qt::Key_4)))
+        ->setProperty("Index", 4);
+    coll->addAction("JumpKey5", new Action(tr("Quick Access #5"), coll, this, &MainWin::onJumpKey, QKeySequence(jumpModifier + Qt::Key_5)))
+        ->setProperty("Index", 5);
+    coll->addAction("JumpKey6", new Action(tr("Quick Access #6"), coll, this, &MainWin::onJumpKey, QKeySequence(jumpModifier + Qt::Key_6)))
+        ->setProperty("Index", 6);
+    coll->addAction("JumpKey7", new Action(tr("Quick Access #7"), coll, this, &MainWin::onJumpKey, QKeySequence(jumpModifier + Qt::Key_7)))
+        ->setProperty("Index", 7);
+    coll->addAction("JumpKey8", new Action(tr("Quick Access #8"), coll, this, &MainWin::onJumpKey, QKeySequence(jumpModifier + Qt::Key_8)))
+        ->setProperty("Index", 8);
+    coll->addAction("JumpKey9", new Action(tr("Quick Access #9"), coll, this, &MainWin::onJumpKey, QKeySequence(jumpModifier + Qt::Key_9)))
+        ->setProperty("Index", 9);
 
     // Buffer navigation
-    coll->addAction("NextBufferView", new Action(QIcon::fromTheme("go-next-view"), tr("Activate Next Chat List"), coll,
-            this, SLOT(nextBufferView()), QKeySequence(QKeySequence::Forward)));
-    coll->addAction("PreviousBufferView", new Action(QIcon::fromTheme("go-previous-view"), tr("Activate Previous Chat List"), coll,
-            this, SLOT(previousBufferView()), QKeySequence::Back));
-    coll->addAction("NextBuffer", new Action(QIcon::fromTheme("go-down"), tr("Go to Next Chat"), coll,
-            this, SLOT(nextBuffer()), QKeySequence(Qt::ALT + Qt::Key_Down)));
-    coll->addAction("PreviousBuffer", new Action(QIcon::fromTheme("go-up"), tr("Go to Previous Chat"), coll,
-            this, SLOT(previousBuffer()), QKeySequence(Qt::ALT + Qt::Key_Up)));
+    coll->addAction("NextBufferView",
+                    new Action(icon::get("go-next-view"),
+                               tr("Activate Next Chat List"),
+                               coll,
+                               this,
+                               &MainWin::nextBufferView,
+                               QKeySequence(QKeySequence::Forward)));
+    coll->addAction("PreviousBufferView",
+                    new Action(icon::get("go-previous-view"),
+                               tr("Activate Previous Chat List"),
+                               coll,
+                               this,
+                               &MainWin::previousBufferView,
+                               QKeySequence::Back));
+    coll->addAction("NextBuffer",
+                    new Action(icon::get("go-down"),
+                               tr("Go to Next Chat"),
+                               coll,
+                               this,
+                               &MainWin::nextBuffer,
+                               QKeySequence(Qt::ALT + Qt::Key_Down)));
+    coll->addAction("PreviousBuffer",
+                    new Action(icon::get("go-up"),
+                               tr("Go to Previous Chat"),
+                               coll,
+                               this,
+                               &MainWin::previousBuffer,
+                               QKeySequence(Qt::ALT + Qt::Key_Up)));
 }
 
-
 void MainWin::setupMenus()
 {
-    ActionCollection *coll = QtUi::actionCollection("General");
+    ActionCollectioncoll = QtUi::actionCollection("General");
 
     _fileMenu = menuBar()->addMenu(tr("&File"));
 
-    static const QStringList coreActions = QStringList()
-        << "ConnectCore" << "DisconnectCore" << "ChangePassword" << "CoreInfo";
+    static const QStringList coreActions = QStringList() << "ConnectCore"
+                                                         << "DisconnectCore"
+                                                         << "ChangePassword"
+                                                         << "CoreInfo";
 
-    QAction *coreAction;
-    foreach(QString actionName, coreActions) {
+    QActioncoreAction;
+    foreach (QString actionName, coreActions) {
         coreAction = coll->action(actionName);
         _fileMenu->addAction(coreAction);
         flagRemoteCoreOnly(coreAction);
@@ -584,45 +620,53 @@ void MainWin::setupMenus()
 
     _settingsMenu = menuBar()->addMenu(tr("&Settings"));
 #ifdef HAVE_KDE
+#    if KCONFIGWIDGETS_VERSION < QT_VERSION_CHECK(5, 23, 0)
     _settingsMenu->addAction(KStandardAction::configureNotifications(this, SLOT(showNotificationsDlg()), this));
     _settingsMenu->addAction(KStandardAction::keyBindings(this, SLOT(showShortcutsDlg()), this));
+#    else
+    _settingsMenu->addAction(KStandardAction::configureNotifications(this, &MainWin::showNotificationsDlg, this));
+    _settingsMenu->addAction(KStandardAction::keyBindings(this, &MainWin::showShortcutsDlg, this));
+#    endif
 #else
     _settingsMenu->addAction(coll->action("ConfigureShortcuts"));
 #endif
     _settingsMenu->addAction(coll->action("ConfigureQuassel"));
 
-
     _helpMenu = menuBar()->addMenu(tr("&Help"));
 
     _helpMenu->addAction(coll->action("AboutQuassel"));
 #ifndef HAVE_KDE
     _helpMenu->addAction(coll->action("AboutQt"));
 #else
+#    if KCONFIGWIDGETS_VERSION < QT_VERSION_CHECK(5, 23, 0)
     _helpMenu->addAction(KStandardAction::aboutKDE(_kHelpMenu, SLOT(aboutKDE()), this));
+#    else
+    _helpMenu->addAction(KStandardAction::aboutKDE(_kHelpMenu, &KHelpMenu::aboutKDE, this));
+#    endif
 #endif
     _helpMenu->addSeparator();
-    _helpDebugMenu = _helpMenu->addMenu(QIcon::fromTheme("tools-report-bug"), tr("Debug"));
+    _helpDebugMenu = _helpMenu->addMenu(icon::get("tools-report-bug"), tr("Debug"));
     _helpDebugMenu->addAction(coll->action("DebugNetworkModel"));
     _helpDebugMenu->addAction(coll->action("DebugBufferViewOverlay"));
     _helpDebugMenu->addAction(coll->action("DebugMessageModel"));
     _helpDebugMenu->addAction(coll->action("DebugHotList"));
     _helpDebugMenu->addAction(coll->action("DebugLog"));
+    _helpDebugMenu->addAction(coll->action("ShowResourceTree"));
     _helpDebugMenu->addSeparator();
     _helpDebugMenu->addAction(coll->action("ReloadStyle"));
 
     // Toggle visibility
-    QAction *showMenuBar = QtUi::actionCollection("General")->action("ToggleMenuBar");
+    QActionshowMenuBar = QtUi::actionCollection("General")->action("ToggleMenuBar");
 
     QtUiSettings uiSettings;
     bool enabled = uiSettings.value("ShowMenuBar", QVariant(true)).toBool();
     showMenuBar->setChecked(enabled);
     enabled ? menuBar()->show() : menuBar()->hide();
 
-    connect(showMenuBar, SIGNAL(toggled(bool)), menuBar(), SLOT(setVisible(bool)));
-    connect(showMenuBar, SIGNAL(toggled(bool)), this, SLOT(saveMenuBarStatus(bool)));
+    connect(showMenuBar, &QAction::toggled, menuBar(), &QMenuBar::setVisible);
+    connect(showMenuBar, &QAction::toggled, this, &MainWin::saveMenuBarStatus);
 }
 
-
 void MainWin::setupBufferWidget()
 {
     _bufferWidget = new BufferWidget(this);
@@ -631,53 +675,52 @@ void MainWin::setupBufferWidget()
     setCentralWidget(_bufferWidget);
 }
 
-
 void MainWin::addBufferView(int bufferViewConfigId)
 {
     addBufferView(Client::bufferViewManager()->clientBufferViewConfig(bufferViewConfigId));
 }
 
-
-void MainWin::addBufferView(ClientBufferViewConfig *config)
+void MainWin::addBufferView(ClientBufferViewConfig* config)
 {
     if (!config)
         return;
 
     config->setLocked(QtUiSettings().value("LockLayout", false).toBool());
-    BufferViewDock *dock = new BufferViewDock(config, this);
+    auto* dock = new BufferViewDock(config, this);
 
-    //create the view and initialize it's filter
-    BufferView *view = new BufferView(dock);
+    // create the view and initialize it's filter
+    auto* view = new BufferView(dock);
     view->setFilteredModel(Client::bufferModel(), config);
-    view->installEventFilter(_inputWidget); // for key presses
+    view->installEventFilter(_inputWidget);  // for key presses
 
     Client::bufferModel()->synchronizeView(view);
 
+    dock->setLocked(QtUiSettings().value("LockLayout", false).toBool());
+
     dock->setWidget(view);
-    dock->setVisible(_layoutLoaded); // don't show before state has been restored
+    dock->setVisible(_layoutLoaded);  // don't show before state has been restored
 
     addDockWidget(Qt::LeftDockWidgetArea, dock);
     _bufferViewsMenu->addAction(dock->toggleViewAction());
 
-    connect(dock->toggleViewAction(), SIGNAL(toggled(bool)), this, SLOT(bufferViewToggled(bool)));
-    connect(dock, SIGNAL(visibilityChanged(bool)), SLOT(bufferViewVisibilityChanged(bool)));
+    connect(dock->toggleViewAction(), &QAction::toggled, this, &MainWin::bufferViewToggled);
+    connect(dock, &QDockWidget::visibilityChanged, this, &MainWin::bufferViewVisibilityChanged);
     _bufferViews.append(dock);
 
     if (!activeBufferView())
         nextBufferView();
 }
 
-
 void MainWin::removeBufferView(int bufferViewConfigId)
 {
     QVariant actionData;
-    BufferViewDock *dock;
-    foreach(QAction *action, _bufferViewsMenu->actions()) {
+    BufferViewDockdock;
+    foreach (QAction* action, _bufferViewsMenu->actions()) {
         actionData = action->data();
         if (!actionData.isValid())
             continue;
 
-        dock = qobject_cast<BufferViewDock *>(action->parent());
+        dock = qobject_cast<BufferViewDock*>(action->parent());
         if (dock && actionData.toInt() == bufferViewConfigId) {
             removeAction(action);
             Client::bufferViewOverlay()->removeView(dock->bufferViewId());
@@ -694,7 +737,6 @@ void MainWin::removeBufferView(int bufferViewConfigId)
     }
 }
 
-
 void MainWin::bufferViewToggled(bool enabled)
 {
     if (!enabled && !isMinimized()) {
@@ -702,9 +744,9 @@ void MainWin::bufferViewToggled(bool enabled)
         // since this isn't our fault and we can't do anything about it, we suppress the resulting calls
         return;
     }
-    QAction *action = qobject_cast<QAction *>(sender());
+    auto* action = qobject_cast<QAction*>(sender());
     Q_ASSERT(action);
-    BufferViewDock *dock = qobject_cast<BufferViewDock *>(action->parent());
+    auto* dock = qobject_cast<BufferViewDock*>(action->parent());
     Q_ASSERT(dock);
 
     // Make sure we don't toggle backlog fetch for a view we've already removed
@@ -717,35 +759,31 @@ void MainWin::bufferViewToggled(bool enabled)
         Client::bufferViewOverlay()->removeView(dock->bufferViewId());
 }
 
-
 void MainWin::bufferViewVisibilityChanged(bool visible)
 {
     Q_UNUSED(visible);
-    BufferViewDock *dock = qobject_cast<BufferViewDock *>(sender());
+    auto* dock = qobject_cast<BufferViewDock*>(sender());
     Q_ASSERT(dock);
     if ((!dock->isHidden() && !activeBufferView()) || (dock->isHidden() && dock->isActive()))
         nextBufferView();
 }
 
-
-BufferView *MainWin::allBuffersView() const
+BufferView* MainWin::allBuffersView() const
 {
     // "All Buffers" is always the first dock created
     if (_bufferViews.count() > 0)
         return _bufferViews[0]->bufferView();
-    return 0;
+    return nullptr;
 }
 
-
-BufferView *MainWin::activeBufferView() const
+BufferView* MainWin::activeBufferView() const
 {
     if (_activeBufferViewIndex < 0 || _activeBufferViewIndex >= _bufferViews.count())
-        return 0;
-    BufferViewDock *dock = _bufferViews.at(_activeBufferViewIndex);
-    return dock->isActive() ? dock->bufferView() : 0;
+        return nullptr;
+    BufferViewDockdock = _bufferViews.at(_activeBufferViewIndex);
+    return dock->isActive() ? dock->bufferView() : nullptr;
 }
 
-
 void MainWin::changeActiveBufferView(int bufferViewId)
 {
     if (bufferViewId < 0)
@@ -757,7 +795,7 @@ void MainWin::changeActiveBufferView(int bufferViewId)
     }
 
     for (int i = 0; i < _bufferViews.count(); i++) {
-        BufferViewDock *dock = _bufferViews.at(i);
+        BufferViewDockdock = _bufferViews.at(i);
         if (dock->bufferViewId() == bufferViewId && !dock->isHidden()) {
             _activeBufferViewIndex = i;
             dock->setActive(true);
@@ -765,25 +803,56 @@ void MainWin::changeActiveBufferView(int bufferViewId)
         }
     }
 
-    nextBufferView(); // fallback
+    nextBufferView();  // fallback
 }
 
-
 void MainWin::showPasswordChangeDlg()
 {
-    if((Client::coreFeatures() & Quassel::PasswordChange)) {
-        PasswordChangeDlg dlg(this);
-        dlg.exec();
+    if (Client::isCoreFeatureEnabled(Quassel::Feature::PasswordChange)) {
+        PasswordChangeDlg{this}.exec();
     }
     else {
-        QMessageBox box(QMessageBox::Warning, tr("Feature Not Supported"),
+        QMessageBox box(QMessageBox::Warning,
+                        tr("Feature Not Supported"),
                         tr("<b>Your Quassel Core does not support this feature</b>"),
-                        QMessageBox::Ok, this);
+                        QMessageBox::Ok);
         box.setInformativeText(tr("You need a Quassel Core v0.12.0 or newer in order to be able to remotely change your password."));
         box.exec();
     }
 }
 
+void MainWin::showMigrationWarning(bool show)
+{
+    if (show && !_migrationWarning) {
+        _migrationWarning = new QMessageBox(QMessageBox::Information,
+                                            tr("Upgrading..."),
+                                            "<b>" + tr("Your database is being upgraded") + "</b>",
+                                            QMessageBox::NoButton,
+                                            this);
+        _migrationWarning->setInformativeText(
+            "<p>" + tr("In order to support new features, we need to make changes to your backlog database. This may take a long while.")
+            + "</p><p>" + tr("Do not exit Quassel until the upgrade is complete!") + "</p>");
+        _migrationWarning->setStandardButtons(QMessageBox::NoButton);
+        _migrationWarning->show();
+    }
+    else if (!show && _migrationWarning) {
+        _migrationWarning->close();
+        _migrationWarning->deleteLater();
+        _migrationWarning = nullptr;
+    }
+}
+
+void MainWin::onExitRequested(const QString& reason)
+{
+    if (!reason.isEmpty()) {
+        QMessageBox box(QMessageBox::Critical,
+                        tr("Fatal error"),
+                        "<b>" + tr("Quassel encountered a fatal error and is terminated.") + "</b>",
+                        QMessageBox::Ok);
+        box.setInformativeText("<p>" + tr("Reason:<em>") + " " + reason + "</em>");
+        box.exec();
+    }
+}
 
 void MainWin::changeActiveBufferView(bool backwards)
 {
@@ -795,17 +864,17 @@ void MainWin::changeActiveBufferView(bool backwards)
         return;
 
     int c = _bufferViews.count();
-    while (c--) { // yes, this will reactivate the current active one if all others fail
+    while (c--) {  // yes, this will reactivate the current active one if all others fail
         if (backwards) {
             if (--_activeBufferViewIndex < 0)
-                _activeBufferViewIndex = _bufferViews.count()-1;
+                _activeBufferViewIndex = _bufferViews.count() - 1;
         }
         else {
             if (++_activeBufferViewIndex >= _bufferViews.count())
                 _activeBufferViewIndex = 0;
         }
 
-        BufferViewDock *dock = _bufferViews.at(_activeBufferViewIndex);
+        BufferViewDockdock = _bufferViews.at(_activeBufferViewIndex);
         if (dock->isHidden())
             continue;
 
@@ -816,85 +885,88 @@ void MainWin::changeActiveBufferView(bool backwards)
     _activeBufferViewIndex = -1;
 }
 
-
 void MainWin::nextBufferView()
 {
     changeActiveBufferView(false);
 }
 
-
 void MainWin::previousBufferView()
 {
     changeActiveBufferView(true);
 }
 
-
 void MainWin::nextBuffer()
 {
-    BufferView *view = activeBufferView();
+    BufferViewview = activeBufferView();
     if (view)
         view->nextBuffer();
 }
 
-
 void MainWin::previousBuffer()
 {
-    BufferView *view = activeBufferView();
+    BufferViewview = activeBufferView();
     if (view)
         view->previousBuffer();
 }
 
-
 void MainWin::hideCurrentBuffer()
 {
-    BufferView *view = activeBufferView();
+    BufferViewview = activeBufferView();
     if (view)
         view->hideCurrentBuffer();
 }
 
-
 void MainWin::showNotificationsDlg()
 {
-    SettingsPageDlg dlg(new NotificationsSettingsPage(this), this);
-    dlg.exec();
+    SettingsPageDlg{new NotificationsSettingsPage{}, this}.exec();
 }
 
-
-void MainWin::on_actionConfigureNetworks_triggered()
+void MainWin::onConfigureNetworksTriggered()
 {
-    SettingsPageDlg dlg(new NetworksSettingsPage(this), this);
-    dlg.exec();
+    SettingsPageDlg{new NetworksSettingsPage{}, this}.exec();
 }
 
-
-void MainWin::on_actionConfigureViews_triggered()
+void MainWin::onConfigureViewsTriggered()
 {
-    SettingsPageDlg dlg(new BufferViewSettingsPage(this), this);
-    dlg.exec();
+    SettingsPageDlg{new BufferViewSettingsPage{}, this}.exec();
 }
 
-
-void MainWin::on_actionLockLayout_toggled(bool lock)
+void MainWin::onLockLayoutToggled(bool lock)
 {
-    QList<VerticalDock *> docks = findChildren<VerticalDock *>();
-    foreach(VerticalDock *dock, docks) {
+    QList<VerticalDock*> docks = findChildren<VerticalDock*>();
+    foreach (VerticalDock* dock, docks) {
         dock->showTitle(!lock);
     }
+
+    QList<NickListDock*> nickdocks = findChildren<NickListDock*>();
+    foreach (NickListDock* nickdock, nickdocks) {
+        nickdock->setLocked(lock);
+    }
+
+    QList<BufferViewDock*> bufferdocks = findChildren<BufferViewDock*>();
+    foreach (BufferViewDock* bufferdock, bufferdocks) {
+        bufferdock->setLocked(lock);
+    }
+
     if (Client::bufferViewManager()) {
-        foreach(ClientBufferViewConfig *config, Client::bufferViewManager()->clientBufferViewConfigs()) {
+        foreach (ClientBufferViewConfig* config, Client::bufferViewManager()->clientBufferViewConfigs()) {
             config->setLocked(lock);
         }
     }
+
+    _mainToolBar->setMovable(!lock);
+    _nickToolBar->setMovable(!lock);
+
     QtUiSettings().setValue("LockLayout", lock);
 }
 
-
 void MainWin::setupNickWidget()
 {
     // create nick dock
-    NickListDock *nickDock = new NickListDock(tr("Nicks"), this);
+    NickListDocknickDock = new NickListDock(tr("Nicks"), this);
     nickDock->setObjectName("NickDock");
     nickDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
+    nickDock->setLocked(QtUiSettings().value("LockLayout", false).toBool());
 
     _nickListWidget = new NickListWidget(nickDock);
     nickDock->setWidget(_nickListWidget);
@@ -904,7 +976,7 @@ void MainWin::setupNickWidget()
     nickDock->toggleViewAction()->setText(tr("Show Nick List"));
 
     // See NickListDock::NickListDock();
-    // connect(nickDock->toggleViewAction(), SIGNAL(triggered(bool)), nickListWidget, SLOT(showWidget(bool)));
+    // connect(nickDock->toggleViewAction(), &NickListDock::triggered, nickListWidget, &QWidget::showWidget);
 
     // attach the NickListWidget to the BufferModel and the default selection
     _nickListWidget->setModel(Client::bufferModel());
@@ -913,13 +985,12 @@ void MainWin::setupNickWidget()
     _nickListWidget->setVisible(false);
 }
 
-
 void MainWin::setupChatMonitor()
 {
-    VerticalDock *dock = new VerticalDock(tr("Chat Monitor"), this);
+    VerticalDockdock = new VerticalDock(tr("Chat Monitor"), this);
     dock->setObjectName("ChatMonitorDock");
 
-    ChatMonitorFilter *filter = new ChatMonitorFilter(Client::messageModel(), this);
+    auto* filter = new ChatMonitorFilter(Client::messageModel(), this);
     _chatMonitorView = new ChatMonitorView(filter, this);
     _chatMonitorView->show();
     dock->setWidget(_chatMonitorView);
@@ -930,10 +1001,9 @@ void MainWin::setupChatMonitor()
     dock->toggleViewAction()->setText(tr("Show Chat Monitor"));
 }
 
-
 void MainWin::setupInputWidget()
 {
-    VerticalDock *dock = new VerticalDock(tr("Inputline"), this);
+    VerticalDockdock = new VerticalDock(tr("Inputline"), this);
     dock->setObjectName("InputDock");
 
     _inputWidget = new InputWidget(dock);
@@ -948,14 +1018,11 @@ void MainWin::setupInputWidget()
     _inputWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel());
 
     _inputWidget->inputLine()->installEventFilter(_bufferWidget);
-
-    connect(_topicWidget, SIGNAL(switchedPlain()), _bufferWidget, SLOT(setFocus()));
 }
 
-
 void MainWin::setupTopicWidget()
 {
-    VerticalDock *dock = new VerticalDock(tr("Topic"), this);
+    VerticalDockdock = new VerticalDock(tr("Topic"), this);
     dock->setObjectName("TopicDock");
     _topicWidget = new TopicWidget(dock);
 
@@ -964,48 +1031,46 @@ void MainWin::setupTopicWidget()
     _topicWidget->setModel(Client::bufferModel());
     _topicWidget->setSelectionModel(Client::bufferModel()->standardSelectionModel());
 
+    connect(_topicWidget, &TopicWidget::switchedPlain, _bufferWidget, selectOverload<>(&QWidget::setFocus));
+
     addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical);
 
     _viewMenu->addAction(dock->toggleViewAction());
     dock->toggleViewAction()->setText(tr("Show Topic Line"));
 }
 
-
 void MainWin::setupTransferWidget()
 {
     auto dock = new QDockWidget(tr("Transfers"), this);
     dock->setObjectName("TransferDock");
-    dock->setAllowedAreas(Qt::TopDockWidgetArea|Qt::BottomDockWidgetArea);
+    dock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
 
-    auto view = new QTableView(dock); // to be replaced by the real thing
+    auto view = new QTableView(dock);  // to be replaced by the real thing
     view->setModel(Client::transferModel());
     dock->setWidget(view);
-    dock->hide(); // hidden by default
+    dock->hide();  // hidden by default
     addDockWidget(Qt::TopDockWidgetArea, dock, Qt::Vertical);
 
     auto action = dock->toggleViewAction();
     action->setText(tr("Show File Transfers"));
-    action->setIcon(QIcon::fromTheme("download"));
+    action->setIcon(icon::get("download"));
     action->setShortcut(QKeySequence(Qt::Key_F6));
     QtUi::actionCollection("General")->addAction("ShowTransferWidget", action);
     _viewMenu->addAction(action);
 }
 
-
 void MainWin::setupViewMenuTail()
 {
     _viewMenu->addSeparator();
     _viewMenu->addAction(_fullScreenAction);
 }
 
-
 void MainWin::setupTitleSetter()
 {
     _titleSetter.setModel(Client::bufferModel());
     _titleSetter.setSelectionModel(Client::bufferModel()->standardSelectionModel());
 }
 
-
 void MainWin::setupStatusBar()
 {
     // MessageProcessor progress
@@ -1015,7 +1080,7 @@ void MainWin::setupStatusBar()
     _coreConnectionStatusWidget->update();
     statusBar()->addPermanentWidget(_coreConnectionStatusWidget);
 
-    QAction *showStatusbar = QtUi::actionCollection("General")->action("ToggleStatusBar");
+    QActionshowStatusbar = QtUi::actionCollection("General")->action("ToggleStatusBar");
 
     QtUiSettings uiSettings;
 
@@ -1023,35 +1088,33 @@ void MainWin::setupStatusBar()
     showStatusbar->setChecked(enabled);
     enabled ? statusBar()->show() : statusBar()->hide();
 
-    connect(showStatusbar, SIGNAL(toggled(bool)), statusBar(), SLOT(setVisible(bool)));
-    connect(showStatusbar, SIGNAL(toggled(bool)), this, SLOT(saveStatusBarStatus(bool)));
+    connect(showStatusbar, &QAction::toggled, statusBar(), &QWidget::setVisible);
+    connect(showStatusbar, &QAction::toggled, this, &MainWin::saveStatusBarStatus);
 
-    connect(Client::coreConnection(), SIGNAL(connectionMsg(QString)), statusBar(), SLOT(showMessage(QString)));
+    connect(Client::coreConnection(), &CoreConnection::connectionMsg, statusBar(), [statusBar = statusBar()](auto&& message) {
+        statusBar->showMessage(message);
+    });
 }
 
-
 void MainWin::setupHotList()
 {
-    FlatProxyModel *flatProxy = new FlatProxyModel(this);
+    auto* flatProxy = new FlatProxyModel(this);
     flatProxy->setSourceModel(Client::bufferModel());
     _bufferHotList = new BufferHotListFilter(flatProxy);
 }
 
-
 void MainWin::saveMenuBarStatus(bool enabled)
 {
     QtUiSettings uiSettings;
     uiSettings.setValue("ShowMenuBar", enabled);
 }
 
-
 void MainWin::saveStatusBarStatus(bool enabled)
 {
     QtUiSettings uiSettings;
     uiSettings.setValue("ShowStatusBar", enabled);
 }
 
-
 void MainWin::setupSystray()
 {
 #ifdef HAVE_DBUS
@@ -1059,18 +1122,20 @@ void MainWin::setupSystray()
 #elif !defined QT_NO_SYSTEMTRAYICON
     _systemTray = new LegacySystemTray(this);
 #else
-    _systemTray = new SystemTray(this); // dummy
+    _systemTray = new SystemTray(this);  // dummy
 #endif
-    _systemTray->init();
 }
 
-
 void MainWin::setupToolBars()
 {
-    connect(_bufferWidget, SIGNAL(currentChanged(QModelIndex)),
-        QtUi::toolBarActionProvider(), SLOT(currentBufferChanged(QModelIndex)));
-    connect(_nickListWidget, SIGNAL(nickSelectionChanged(QModelIndexList)),
-        QtUi::toolBarActionProvider(), SLOT(nickSelectionChanged(QModelIndexList)));
+    connect(_bufferWidget,
+            selectOverload<const QModelIndex&>(&AbstractBufferContainer::currentChanged),
+            QtUi::toolBarActionProvider(),
+            &ToolBarActionProvider::onCurrentBufferChanged);
+    connect(_nickListWidget,
+            &NickListWidget::nickSelectionChanged,
+            QtUi::toolBarActionProvider(),
+            &ToolBarActionProvider::onNickSelectionChanged);
 
 #ifdef Q_OS_MAC
     setUnifiedTitleAndToolBarOnMac(true);
@@ -1086,11 +1151,13 @@ void MainWin::setupToolBars()
     addToolBar(_mainToolBar);
 
     if (Quassel::runMode() != Quassel::Monolithic) {
-        ActionCollection *coll = QtUi::actionCollection("General");
+        ActionCollectioncoll = QtUi::actionCollection("General");
         _mainToolBar->addAction(coll->action("ConnectCore"));
         _mainToolBar->addAction(coll->action("DisconnectCore"));
     }
 
+    _mainToolBar->setMovable(!QtUiSettings().value("LockLayout", false).toBool());
+
     QtUi::toolBarActionProvider()->addActions(_mainToolBar, ToolBarActionProvider::MainToolBar);
     _toolbarMenu->addAction(_mainToolBar->toggleViewAction());
 
@@ -1101,8 +1168,9 @@ void MainWin::setupToolBars()
     _nickToolBar->setObjectName("NickToolBar");
 #endif
     _nickToolBar->setWindowTitle(tr("Nick Toolbar"));
-    _nickToolBar->setVisible(false); //default: not visible
+    _nickToolBar->setVisible(false);  // default: not visible
     addToolBar(_nickToolBar);
+    _nickToolBar->setMovable(!QtUiSettings().value("LockLayout", false).toBool());
 
     QtUi::toolBarActionProvider()->addActions(_nickToolBar, ToolBarActionProvider::NickToolBar);
     _toolbarMenu->addAction(_nickToolBar->toggleViewAction());
@@ -1112,7 +1180,7 @@ void MainWin::setupToolBars()
 
     bool visible = uiSettings.value("ShowMainToolBar", QVariant(true)).toBool();
     _mainToolBar->setVisible(visible);
-    connect(_mainToolBar, SIGNAL(visibilityChanged(bool)), this, SLOT(saveMainToolBarStatus(bool)));
+    connect(_mainToolBar, &QToolBar::visibilityChanged, this, &MainWin::saveMainToolBarStatus);
 #endif
 }
 
@@ -1126,43 +1194,56 @@ void MainWin::saveMainToolBarStatus(bool enabled)
 #endif
 }
 
+void MainWin::doAutoConnect()
+{
+    int accountId = Quassel::optionValue("account").toInt();
+    if (!Client::coreConnection()->connectToCore(accountId)) {
+        // No autoconnect selected (or no accounts)
+        showCoreConnectionDlg();
+    }
+}
 
 void MainWin::connectedToCore()
 {
     Q_CHECK_PTR(Client::bufferViewManager());
-    connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigAdded(int)), this, SLOT(addBufferView(int)));
-    connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigDeleted(int)), this, SLOT(removeBufferView(int)));
-    connect(Client::bufferViewManager(), SIGNAL(initDone()), this, SLOT(loadLayout()));
+    connect(Client::bufferViewManager(), &BufferViewManager::bufferViewConfigAdded, this, selectOverload<int>(&MainWin::addBufferView));
+    connect(Client::bufferViewManager(), &BufferViewManager::bufferViewConfigDeleted, this, &MainWin::removeBufferView);
+    connect(Client::bufferViewManager(), &SyncableObject::initDone, this, &MainWin::loadLayout);
 
     if (Client::transferManager()) {
-        connect(Client::transferManager(), SIGNAL(transferAdded(QUuid)), SLOT(showNewTransferDlg(QUuid)));
+        connect(Client::transferManager(), &TransferManager::transferAdded, this, &MainWin::showNewTransferDlg);
     }
 
     setConnectedState();
 }
 
-
 void MainWin::setConnectedState()
 {
-    ActionCollection *coll = QtUi::actionCollection("General");
+    ActionCollectioncoll = QtUi::actionCollection("General");
 
     coll->action("ConnectCore")->setEnabled(false);
     coll->action("DisconnectCore")->setEnabled(true);
     coll->action("ChangePassword")->setEnabled(true);
     coll->action("CoreInfo")->setEnabled(true);
 
-    foreach(QAction *action, _fileMenu->actions()) {
+    foreach (QAction* action, _fileMenu->actions()) {
         if (isRemoteCoreOnly(action))
             action->setVisible(!Client::internalCore());
     }
 
-    disconnect(Client::backlogManager(), SIGNAL(updateProgress(int, int)), _msgProcessorStatusWidget, SLOT(setProgress(int, int)));
-    disconnect(Client::backlogManager(), SIGNAL(messagesRequested(const QString &)), this, SLOT(showStatusBarMessage(const QString &)));
-    disconnect(Client::backlogManager(), SIGNAL(messagesProcessed(const QString &)), this, SLOT(showStatusBarMessage(const QString &)));
+    disconnect(Client::backlogManager(),
+               &ClientBacklogManager::updateProgress,
+               _msgProcessorStatusWidget,
+               &MsgProcessorStatusWidget::setProgress);
+    disconnect(Client::backlogManager(), &ClientBacklogManager::messagesRequested, this, &MainWin::showStatusBarMessage);
+    disconnect(Client::backlogManager(), &ClientBacklogManager::messagesProcessed, this, &MainWin::showStatusBarMessage);
     if (!Client::internalCore()) {
-        connect(Client::backlogManager(), SIGNAL(updateProgress(int, int)), _msgProcessorStatusWidget, SLOT(setProgress(int, int)));
-        connect(Client::backlogManager(), SIGNAL(messagesRequested(const QString &)), this, SLOT(showStatusBarMessage(const QString &)));
-        connect(Client::backlogManager(), SIGNAL(messagesProcessed(const QString &)), this, SLOT(showStatusBarMessage(const QString &)));
+        connect(Client::backlogManager(),
+                &ClientBacklogManager::updateProgress,
+                _msgProcessorStatusWidget,
+                &MsgProcessorStatusWidget::setProgress);
+        connect(Client::backlogManager(), &ClientBacklogManager::messagesRequested, this, &MainWin::showStatusBarMessage);
+        connect(Client::backlogManager(), &ClientBacklogManager::messagesProcessed, this, &MainWin::showStatusBarMessage);
     }
 
     // _viewMenu->setEnabled(true);
@@ -1176,7 +1257,7 @@ void MainWin::setConnectedState()
     systemTray()->setState(SystemTray::Active);
 
     if (Client::networkIds().isEmpty()) {
-        IrcConnectionWizard *wizard = new IrcConnectionWizard(this, Qt::Sheet);
+        IrcConnectionWizardwizard = new IrcConnectionWizard(this, Qt::Sheet);
         wizard->show();
     }
     else {
@@ -1190,19 +1271,18 @@ void MainWin::setConnectedState()
     }
 }
 
-
 void MainWin::loadLayout()
 {
     QtUiSettings s;
     int accountId = Client::currentCoreAccount().accountId().toInt();
     QByteArray state = s.value(QString("MainWinState-%1").arg(accountId)).toByteArray();
+    _nickListWidget->setVisible(true);
     if (state.isEmpty()) {
-        foreach(BufferViewDock *view, _bufferViews)
-        view->show();
+        foreach (BufferViewDock* view, _bufferViews)
+            view->show();
         _layoutLoaded = true;
         return;
     }
-    _nickListWidget->setVisible(true);
     restoreState(state, accountId);
     int bufferViewId = s.value(QString("ActiveBufferView-%1").arg(accountId), -1).toInt();
     if (bufferViewId >= 0)
@@ -1211,19 +1291,17 @@ void MainWin::loadLayout()
     _layoutLoaded = true;
 }
 
-
 void MainWin::saveLayout()
 {
     QtUiSettings s;
-    int accountId = _bufferViews.count() ? Client::currentCoreAccount().accountId().toInt() : 0; // only save if we still have a layout!
+    int accountId = _bufferViews.count() ? Client::currentCoreAccount().accountId().toInt() : 0;  // only save if we still have a layout!
     if (accountId > 0) {
         s.setValue(QString("MainWinState-%1").arg(accountId), saveState(accountId));
-        BufferView *view = activeBufferView();
+        BufferViewview = activeBufferView();
         s.setValue(QString("ActiveBufferView-%1").arg(accountId), view ? view->config()->bufferViewId() : -1);
     }
 }
 
-
 void MainWin::disconnectedFromCore()
 {
     // save core specific layout and remove bufferviews;
@@ -1231,13 +1309,13 @@ void MainWin::disconnectedFromCore()
     _layoutLoaded = false;
 
     QVariant actionData;
-    BufferViewDock *dock;
-    foreach(QAction *action, _bufferViewsMenu->actions()) {
+    BufferViewDockdock;
+    foreach (QAction* action, _bufferViewsMenu->actions()) {
         actionData = action->data();
         if (!actionData.isValid())
             continue;
 
-        dock = qobject_cast<BufferViewDock *>(action->parent());
+        dock = qobject_cast<BufferViewDock*>(action->parent());
         if (dock && actionData.toInt() != -1) {
             removeAction(action);
             _bufferViews.removeAll(dock);
@@ -1257,11 +1335,10 @@ void MainWin::disconnectedFromCore()
     setDisconnectedState();
 }
 
-
 void MainWin::setDisconnectedState()
 {
-    ActionCollection *coll = QtUi::actionCollection("General");
-    //ui.menuCore->setEnabled(false);
+    ActionCollectioncoll = QtUi::actionCollection("General");
+    // ui.menuCore->setEnabled(false);
     coll->action("ConnectCore")->setEnabled(true);
     coll->action("DisconnectCore")->setEnabled(false);
     coll->action("CoreInfo")->setEnabled(false);
@@ -1275,48 +1352,52 @@ void MainWin::setDisconnectedState()
     _nickListWidget->setVisible(false);
 }
 
-
-void MainWin::userAuthenticationRequired(CoreAccount *account, bool *valid, const QString &errorMessage)
+void MainWin::userAuthenticationRequired(CoreAccount* account, bool* valid, const QString& errorMessage)
 {
     Q_UNUSED(errorMessage)
     CoreConnectAuthDlg dlg(account, this);
     *valid = (dlg.exec() == QDialog::Accepted);
 }
 
-
-void MainWin::handleNoSslInClient(bool *accepted)
+void MainWin::handleNoSslInClient(bool* accepted)
 {
-    QMessageBox box(QMessageBox::Warning, tr("Unencrypted Connection"), tr("<b>Your client does not support SSL encryption</b>"),
-        QMessageBox::Ignore|QMessageBox::Cancel, this);
+    QMessageBox box(QMessageBox::Warning,
+                    tr("Unencrypted Connection"),
+                    tr("<b>Your client does not support SSL encryption</b>"),
+                    QMessageBox::Ignore | QMessageBox::Cancel);
     box.setInformativeText(tr("Sensitive data, like passwords, will be transmitted unencrypted to your Quassel core."));
     box.setDefaultButton(QMessageBox::Ignore);
-    *accepted = box.exec() == QMessageBox::Ignore;
+    *accepted = (box.exec() == QMessageBox::Ignore);
 }
 
-
-void MainWin::handleNoSslInCore(bool *accepted)
+void MainWin::handleNoSslInCore(bool* accepted)
 {
-    QMessageBox box(QMessageBox::Warning, tr("Unencrypted Connection"), tr("<b>Your core does not support SSL encryption</b>"),
-        QMessageBox::Ignore|QMessageBox::Cancel, this);
+    QMessageBox box(QMessageBox::Warning,
+                    tr("Unencrypted Connection"),
+                    tr("<b>Your core does not support SSL encryption</b>"),
+                    QMessageBox::Ignore | QMessageBox::Cancel);
     box.setInformativeText(tr("Sensitive data, like passwords, will be transmitted unencrypted to your Quassel core."));
     box.setDefaultButton(QMessageBox::Ignore);
-    *accepted = box.exec() == QMessageBox::Ignore;
+    *accepted = (box.exec() == QMessageBox::Ignore);
 }
 
-
-#ifdef HAVE_SSL
-
-void MainWin::handleSslErrors(const QSslSocket *socket, bool *accepted, bool *permanently)
+void MainWin::handleSslErrors(const QSslSocket* socket, bool* accepted, bool* permanently)
 {
     QString errorString = "<ul>";
-    foreach(const QSslError error, socket->sslErrors())
-    errorString += QString("<li>%1</li>").arg(error.errorString());
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
+    for (const auto& error : socket->sslErrors()) {
+#else
+    for (const auto& error : socket->sslHandshakeErrors()) {
+#endif
+        errorString += QString("<li>%1</li>").arg(error.errorString());
+    }
     errorString += "</ul>";
 
     QMessageBox box(QMessageBox::Warning,
-        tr("Untrusted Security Certificate"),
-        tr("<b>The SSL certificate provided by the core at %1 is untrusted for the following reasons:</b>").arg(socket->peerName()),
-        QMessageBox::Cancel, this);
+                    tr("Untrusted Security Certificate"),
+                    tr("<b>The SSL certificate provided by the core at %1 is untrusted for the following reasons:</b>").arg(socket->peerName()),
+                    QMessageBox::Cancel);
     box.setInformativeText(errorString);
     box.addButton(tr("Continue"), QMessageBox::AcceptRole);
     box.setDefaultButton(box.addButton(tr("Show Certificate"), QMessageBox::HelpRole));
@@ -1329,34 +1410,29 @@ void MainWin::handleSslErrors(const QSslSocket *socket, bool *accepted, bool *pe
             SslInfoDlg dlg(socket, this);
             dlg.exec();
         }
-    }
-    while (role == QMessageBox::HelpRole);
+    } while (role == QMessageBox::HelpRole);
 
     *accepted = role == QMessageBox::AcceptRole;
     if (*accepted) {
         QMessageBox box2(QMessageBox::Warning,
-            tr("Untrusted Security Certificate"),
-            tr("Would you like to accept this certificate forever without being prompted?"),
-            0, this);
+                         tr("Untrusted Security Certificate"),
+                         tr("Would you like to accept this certificate forever without being prompted?"),
+                         QMessageBox::NoButton);
         box2.setDefaultButton(box2.addButton(tr("Current Session Only"), QMessageBox::NoRole));
         box2.addButton(tr("Forever"), QMessageBox::YesRole);
         box2.exec();
-        *permanently =  box2.buttonRole(box2.clickedButton()) == QMessageBox::YesRole;
+        *permanently = (box2.buttonRole(box2.clickedButton()) == QMessageBox::YesRole);
     }
 }
 
-
-#endif /* HAVE_SSL */
-
-void MainWin::handleCoreConnectionError(const QString &error)
+void MainWin::handleCoreConnectionError(const QString& error)
 {
     QMessageBox::critical(this, tr("Core Connection Error"), error, QMessageBox::Ok);
 }
 
-
 void MainWin::showCoreConnectionDlg()
 {
-    CoreConnectDlg dlg(this);
+    CoreConnectDlg dlg{this};
     if (dlg.exec() == QDialog::Accepted) {
         AccountId accId = dlg.selectedAccount();
         if (accId.isValid())
@@ -1364,71 +1440,88 @@ void MainWin::showCoreConnectionDlg()
     }
 }
 
-
-void MainWin::showCoreConfigWizard(const QVariantList &backends)
+void MainWin::showCoreConfigWizard(const QVariantList& backends, const QVariantList& authenticators)
 {
-    CoreConfigWizard *wizard = new CoreConfigWizard(Client::coreConnection(), backends, this);
+    auto* wizard = new CoreConfigWizard(Client::coreConnection(), backends, authenticators, this);
 
     wizard->show();
 }
 
-
-void MainWin::showChannelList(NetworkId netId)
+void MainWin::showChannelList(NetworkId netId, const QString& channelFilters, bool listImmediately)
 {
-    ChannelListDlg *channelListDlg = new ChannelListDlg();
-
     if (!netId.isValid()) {
-        QAction *action = qobject_cast<QAction *>(sender());
+        auto* action = qobject_cast<QAction*>(sender());
         if (action)
             netId = action->data().value<NetworkId>();
+        if (!netId.isValid()) {
+            // We still haven't found a valid network, probably no network selected, e.g. "/list"
+            // on the client homescreen when no networks are connected.
+            QMessageBox box(QMessageBox::Information,
+                            tr("No network selected"),
+                            QString("<b>%1</b>").arg(tr("No network selected")),
+                            QMessageBox::Ok);
+            box.setInformativeText(tr("Select a network before trying to view the channel list."));
+            box.exec();
+            return;
+        }
     }
 
+    auto* channelListDlg = new ChannelListDlg(this);
     channelListDlg->setAttribute(Qt::WA_DeleteOnClose);
     channelListDlg->setNetwork(netId);
+    if (!channelFilters.isEmpty()) {
+        channelListDlg->setChannelFilters(channelFilters);
+    }
+    if (listImmediately) {
+        channelListDlg->requestSearch();
+    }
     channelListDlg->show();
 }
 
+void MainWin::showNetworkConfig(NetworkId netId)
+{
+    SettingsPageDlg dlg{new NetworksSettingsPage{}, this};
+    if (netId.isValid())
+        qobject_cast<NetworksSettingsPage*>(dlg.currentPage())->bufferList_Open(netId);
+    dlg.exec();
+}
 
 void MainWin::showIgnoreList(QString newRule)
 {
-    SettingsPageDlg dlg(new IgnoreListSettingsPage(this), this);
+    SettingsPageDlg dlg{new IgnoreListSettingsPage{}, this};
     // prepare config dialog for new rule
     if (!newRule.isEmpty())
-        qobject_cast<IgnoreListSettingsPage *>(dlg.currentPage())->editIgnoreRule(newRule);
+        qobject_cast<IgnoreListSettingsPage*>(dlg.currentPage())->editIgnoreRule(newRule);
     dlg.exec();
 }
 
-
 void MainWin::showCoreInfoDlg()
 {
-    CoreInfoDlg(this).exec();
+    CoreInfoDlg{this}.exec();
 }
 
-
 void MainWin::showAwayLog()
 {
     if (_awayLog)
         return;
-    AwayLogFilter *filter = new AwayLogFilter(Client::messageModel());
-    _awayLog = new AwayLogView(filter, 0);
+    auto* filter = new AwayLogFilter(Client::messageModel());
+    _awayLog = new AwayLogView(filter, nullptr);
     filter->setParent(_awayLog);
-    connect(_awayLog, SIGNAL(destroyed()), this, SLOT(awayLogDestroyed()));
+    connect(_awayLog, &QObject::destroyed, this, &MainWin::awayLogDestroyed);
     _awayLog->setAttribute(Qt::WA_DeleteOnClose);
     _awayLog->show();
 }
 
-
 void MainWin::awayLogDestroyed()
 {
-    _awayLog = 0;
+    _awayLog = nullptr;
 }
 
-
 void MainWin::showSettingsDlg()
 {
-    SettingsDlg *dlg = new SettingsDlg();
+    auto dlg = new SettingsDlg(this);
 
-    //Category: Interface
+    // Category: Interface
     dlg->registerSettingsPage(new AppearanceSettingsPage(dlg));
     dlg->registerSettingsPage(new ChatViewSettingsPage(dlg));
     dlg->registerSettingsPage(new ChatViewColorSettingsPage(dlg));
@@ -1440,16 +1533,25 @@ void MainWin::showSettingsDlg()
 #ifdef HAVE_SONNET
     dlg->registerSettingsPage(new SonnetSettingsPage(dlg));
 #endif
-    dlg->registerSettingsPage(new HighlightSettingsPage(dlg));
+    auto coreHighlightsPage = new CoreHighlightSettingsPage(dlg);
+    auto localHighlightsPage = new HighlightSettingsPage(dlg);
+    // Let CoreHighlightSettingsPage reload HighlightSettingsPage after doing an import with
+    // cleaning up.  Otherwise, HighlightSettingsPage won't show that the local rules were deleted.
+    connect(coreHighlightsPage, &CoreHighlightSettingsPage::localHighlightsChanged,
+            localHighlightsPage, &HighlightSettingsPage::load);
+    // Put core-side highlights before local/legacy highlights
+    dlg->registerSettingsPage(coreHighlightsPage);
+    dlg->registerSettingsPage(localHighlightsPage);
     dlg->registerSettingsPage(new NotificationsSettingsPage(dlg));
     dlg->registerSettingsPage(new BacklogSettingsPage(dlg));
 
-    //Category: IRC
+    // Category: IRC
     dlg->registerSettingsPage(new ConnectionSettingsPage(dlg));
     dlg->registerSettingsPage(new IdentitiesSettingsPage(dlg));
     dlg->registerSettingsPage(new NetworksSettingsPage(dlg));
     dlg->registerSettingsPage(new AliasesSettingsPage(dlg));
     dlg->registerSettingsPage(new IgnoreListSettingsPage(dlg));
+    // dlg->registerSettingsPage(new DccSettingsPage(dlg)); not ready yet
 
     // Category: Remote Cores
     if (Quassel::runMode() != Quassel::Monolithic) {
@@ -1460,40 +1562,38 @@ void MainWin::showSettingsDlg()
     dlg->show();
 }
 
-
 void MainWin::showAboutDlg()
 {
-    AboutDlg(this).exec();
+    AboutDlg{this}.exec();
 }
 
-
 void MainWin::showShortcutsDlg()
 {
 #ifdef HAVE_KDE
-    KShortcutsDialog dlg(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsDisallowed, this);
-    foreach(KActionCollection *coll, QtUi::actionCollections())
-    dlg.addCollection(coll, coll->property("Category").toString());
+    KShortcutsDialog dlg(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsDisallowed);
+    foreach (KActionCollection* coll, QtUi::actionCollections()) {
+        dlg.addCollection(coll, coll->property("Category").toString());
+    }
     dlg.configure(true);
 #else
-    SettingsPageDlg dlg(new ShortcutsSettingsPage(QtUi::actionCollections(), this), this);
-    dlg.exec();
+    SettingsPageDlg{new ShortcutsSettingsPage{QtUi::actionCollections()}, this}.exec();
 #endif
 }
 
-
-void MainWin::showNewTransferDlg(const QUuid &transferId)
+void MainWin::showNewTransferDlg(const QUuid& transferId)
 {
     auto transfer = Client::transferManager()->transfer(transferId);
     if (transfer) {
-        ReceiveFileDlg *dlg = new ReceiveFileDlg(transfer, this);
-        dlg->show();
+        if (transfer->status() == Transfer::Status::New) {
+            auto* dlg = new ReceiveFileDlg(transfer, this);
+            dlg->show();
+        }
     }
     else {
         qWarning() << "Unknown transfer ID" << transferId;
     }
 }
 
-
 void MainWin::onFullScreenToggled()
 {
     // Relying on QWidget::isFullScreen is discouraged, see the KToggleFullScreenAction docs
@@ -1509,12 +1609,11 @@ void MainWin::onFullScreenToggled()
 #endif
 }
 
-
 /********************************************************************************************************/
 
-bool MainWin::event(QEvent *event)
+bool MainWin::event(QEventevent)
 {
-    switch(event->type()) {
+    switch (event->type()) {
     case QEvent::WindowActivate: {
         BufferId bufferId = Client::bufferModel()->currentBuffer();
         if (bufferId.isValid())
@@ -1531,8 +1630,7 @@ bool MainWin::event(QEvent *event)
     return QMainWindow::event(event);
 }
 
-
-void MainWin::moveEvent(QMoveEvent *event)
+void MainWin::moveEvent(QMoveEvent* event)
 {
     if (!(windowState() & Qt::WindowMaximized))
         _normalPos = event->pos();
@@ -1540,8 +1638,7 @@ void MainWin::moveEvent(QMoveEvent *event)
     QMainWindow::moveEvent(event);
 }
 
-
-void MainWin::resizeEvent(QResizeEvent *event)
+void MainWin::resizeEvent(QResizeEvent* event)
 {
     if (!(windowState() & Qt::WindowMaximized))
         _normalSize = event->size();
@@ -1549,11 +1646,10 @@ void MainWin::resizeEvent(QResizeEvent *event)
     QMainWindow::resizeEvent(event);
 }
 
-
-void MainWin::closeEvent(QCloseEvent *event)
+void MainWin::closeEvent(QCloseEvent* event)
 {
     QtUiSettings s;
-    QtUiApplication *app = qobject_cast<QtUiApplication *> qApp;
+    auto* app = qobject_cast<QtUiApplication*> qApp;
     Q_ASSERT(app);
     // On OSX it can happen that the closeEvent occurs twice. (Especially if packaged with Frameworks)
     // This messes up MainWinState/MainWinHidden save/restore.
@@ -1562,22 +1658,21 @@ void MainWin::closeEvent(QCloseEvent *event)
         QtUi::hideMainWidget();
         event->ignore();
     }
-    else if(!_aboutToQuit) {
+    else if (!_aboutToQuit) {
         _aboutToQuit = true;
         event->accept();
-        quit();
+        Quassel::instance()->quit();
     }
     else {
         event->ignore();
     }
 }
 
-
-void MainWin::messagesInserted(const QModelIndex &parent, int start, int end)
+void MainWin::messagesInserted(const QModelIndex& parent, int start, int end)
 {
     Q_UNUSED(parent);
 
-    bool hasFocus = QApplication::activeWindow() != 0;
+    bool hasFocus = QApplication::activeWindow() != nullptr;
 
     for (int i = start; i <= end; i++) {
         QModelIndex idx = Client::messageModel()->index(i, ChatLineModel::ContentsColumn);
@@ -1593,8 +1688,7 @@ void MainWin::messagesInserted(const QModelIndex &parent, int start, int end)
         BufferInfo::Type bufType = Client::networkModel()->bufferType(bufId);
 
         // check if bufferId belongs to the shown chatlists
-        if (!(Client::bufferViewOverlay()->bufferIds().contains(bufId) ||
-              Client::bufferViewOverlay()->tempRemovedBufferIds().contains(bufId)))
+        if (!(Client::bufferViewOverlay()->bufferIds().contains(bufId) || Client::bufferViewOverlay()->tempRemovedBufferIds().contains(bufId)))
             continue;
 
         // check if it's the buffer currently displayed
@@ -1606,7 +1700,9 @@ void MainWin::messagesInserted(const QModelIndex &parent, int start, int end)
             continue;
 
         // and of course: don't notify for ignored messages
-        if (Client::ignoreListManager() && Client::ignoreListManager()->match(idx.data(MessageModel::MessageRole).value<Message>(), Client::networkModel()->networkName(bufId)))
+        if (Client::ignoreListManager()
+            && Client::ignoreListManager()->match(idx.data(MessageModel::MessageRole).value<Message>(),
+                                                  Client::networkModel()->networkName(bufId)))
             continue;
 
         // seems like we have a legit notification candidate!
@@ -1628,26 +1724,24 @@ void MainWin::messagesInserted(const QModelIndex &parent, int start, int end)
     }
 }
 
-
 void MainWin::currentBufferChanged(BufferId buffer)
 {
     if (buffer.isValid())
         Client::instance()->markBufferAsRead(buffer);
 }
 
-
 void MainWin::clientNetworkCreated(NetworkId id)
 {
-    const Network *net = Client::network(id);
-    QAction *act = new QAction(net->networkName(), this);
+    const Networknet = Client::network(id);
+    auto* act = new QAction(net->networkName(), this);
     act->setObjectName(QString("NetworkAction-%1").arg(id.toInt()));
-    act->setData(QVariant::fromValue<NetworkId>(id));
-    connect(net, SIGNAL(updatedRemotely()), this, SLOT(clientNetworkUpdated()));
-    connect(act, SIGNAL(triggered()), this, SLOT(connectOrDisconnectFromNet()));
+    act->setData(QVariant::fromValue(id));
+    connect(net, &SyncableObject::updatedRemotely, this, &MainWin::clientNetworkUpdated);
+    connect(act, &QAction::triggered, this, &MainWin::connectOrDisconnectFromNet);
 
-    QAction *beforeAction = 0;
-    foreach(QAction *action, _networksMenu->actions()) {
-        if (!action->data().isValid()) // ignore stock actions
+    QAction* beforeAction = nullptr;
+    foreach (QAction* action, _networksMenu->actions()) {
+        if (!action->data().isValid())  // ignore stock actions
             continue;
         if (net->networkName().localeAwareCompare(action->text()) < 0) {
             beforeAction = action;
@@ -1657,14 +1751,13 @@ void MainWin::clientNetworkCreated(NetworkId id)
     _networksMenu->insertAction(beforeAction, act);
 }
 
-
 void MainWin::clientNetworkUpdated()
 {
-    const Network *net = qobject_cast<const Network *>(sender());
+    const auto* net = qobject_cast<const Network*>(sender());
     if (!net)
         return;
 
-    QAction *action = findChild<QAction *>(QString("NetworkAction-%1").arg(net->networkId().toInt()));
+    auto* action = findChild<QAction*>(QString("NetworkAction-%1").arg(net->networkId().toInt()));
     if (!action)
         return;
 
@@ -1672,7 +1765,7 @@ void MainWin::clientNetworkUpdated()
 
     switch (net->connectionState()) {
     case Network::Initialized:
-        action->setIcon(QIcon::fromTheme("network-connect"));
+        action->setIcon(icon::get("network-connect"));
         // if we have no currently selected buffer, jump to the first connecting statusbuffer
         if (!bufferWidget()->currentBuffer().isValid()) {
             QModelIndex idx = Client::networkModel()->networkIndex(net->networkId());
@@ -1683,36 +1776,94 @@ void MainWin::clientNetworkUpdated()
         }
         break;
     case Network::Disconnected:
-        action->setIcon(QIcon::fromTheme("network-disconnect"));
+        action->setIcon(icon::get("network-disconnect"));
         break;
     default:
-        action->setIcon(QIcon::fromTheme("network-wired"));
+        action->setIcon(icon::get("network-wired"));
     }
 }
 
-
 void MainWin::clientNetworkRemoved(NetworkId id)
 {
-    QAction *action = findChild<QAction *>(QString("NetworkAction-%1").arg(id.toInt()));
+    auto* action = findChild<QAction*>(QString("NetworkAction-%1").arg(id.toInt()));
     if (!action)
         return;
 
     action->deleteLater();
 }
 
-
 void MainWin::connectOrDisconnectFromNet()
 {
-    QAction *act = qobject_cast<QAction *>(sender());
-    if (!act) return;
-    const Network *net = Client::network(act->data().value<NetworkId>());
-    if (!net) return;
-    if (net->connectionState() == Network::Disconnected) net->requestConnect();
-    else net->requestDisconnect();
+    auto* act = qobject_cast<QAction*>(sender());
+    if (!act)
+        return;
+    const Network* net = Client::network(act->data().value<NetworkId>());
+    if (!net)
+        return;
+    if (net->connectionState() == Network::Disconnected)
+        net->requestConnect();
+    else
+        net->requestDisconnect();
+}
+
+void MainWin::onFormatApplyColorTriggered()
+{
+    if (!_inputWidget)
+        return;
+
+    _inputWidget->applyFormatActiveColor();
+}
+
+void MainWin::onFormatApplyColorFillTriggered()
+{
+    if (!_inputWidget)
+        return;
+
+    _inputWidget->applyFormatActiveColorFill();
+}
+
+void MainWin::onFormatClearTriggered()
+{
+    if (!_inputWidget)
+        return;
+
+    _inputWidget->clearFormat();
+}
+
+void MainWin::onFormatBoldTriggered()
+{
+    if (!_inputWidget)
+        return;
+
+    _inputWidget->toggleFormatBold();
+}
+
+void MainWin::onFormatItalicTriggered()
+{
+    if (!_inputWidget)
+        return;
+
+    _inputWidget->toggleFormatItalic();
 }
 
+void MainWin::onFormatUnderlineTriggered()
+{
+    if (!_inputWidget)
+        return;
+
+    _inputWidget->toggleFormatUnderline();
+}
 
-void MainWin::on_jumpHotBuffer_triggered()
+void MainWin::onFormatStrikethroughTriggered()
+{
+    if (!_inputWidget)
+        return;
+
+    _inputWidget->toggleFormatStrikethrough();
+}
+
+
+void MainWin::onJumpHotBufferTriggered()
 {
     if (!_bufferHotList->rowCount())
         return;
@@ -1720,7 +1871,7 @@ void MainWin::on_jumpHotBuffer_triggered()
     Client::bufferModel()->switchToBuffer(_bufferHotList->hottestBuffer());
 }
 
-void MainWin::on_bufferSearch_triggered()
+void MainWin::onBufferSearchTriggered()
 {
     if (_activeBufferViewIndex < 0 || _activeBufferViewIndex >= _bufferViews.count()) {
         qWarning() << "Tried to activate filter on invalid bufferview:" << _activeBufferViewIndex;
@@ -1730,10 +1881,9 @@ void MainWin::on_bufferSearch_triggered()
     _bufferViews[_activeBufferViewIndex]->activateFilter();
 }
 
-
 void MainWin::onJumpKey()
 {
-    QAction *action = qobject_cast<QAction *>(sender());
+    auto* action = qobject_cast<QAction*>(sender());
     if (!action || !Client::bufferModel())
         return;
     int idx = action->property("Index").toInt();
@@ -1749,10 +1899,9 @@ void MainWin::onJumpKey()
         Client::bufferModel()->switchToBuffer(buffer);
 }
 
-
 void MainWin::bindJumpKey()
 {
-    QAction *action = qobject_cast<QAction *>(sender());
+    auto* action = qobject_cast<QAction*>(sender());
     if (!action || !Client::bufferModel())
         return;
     int idx = action->property("Index").toInt();
@@ -1761,10 +1910,9 @@ void MainWin::bindJumpKey()
     CoreAccountSettings().setJumpKeyMap(_jumpKeyMap);
 }
 
-
-void MainWin::on_actionDebugNetworkModel_triggered()
+void MainWin::onDebugNetworkModelTriggered()
 {
-    QTreeView *view = new QTreeView;
+    auto* view = new QTreeView;
     view->setAttribute(Qt::WA_DeleteOnClose);
     view->setWindowTitle("Debug NetworkModel View");
     view->setModel(Client::networkModel());
@@ -1775,31 +1923,28 @@ void MainWin::on_actionDebugNetworkModel_triggered()
     view->show();
 }
 
-
-void MainWin::on_actionDebugHotList_triggered()
+void MainWin::onDebugHotListTriggered()
 {
     _bufferHotList->invalidate();
     _bufferHotList->sort(0, Qt::DescendingOrder);
 
-    QTreeView *view = new QTreeView;
+    auto* view = new QTreeView;
     view->setAttribute(Qt::WA_DeleteOnClose);
     view->setModel(_bufferHotList);
     view->show();
 }
 
-
-void MainWin::on_actionDebugBufferViewOverlay_triggered()
+void MainWin::onDebugBufferViewOverlayTriggered()
 {
-    DebugBufferViewOverlay *overlay = new DebugBufferViewOverlay(0);
+    auto* overlay = new DebugBufferViewOverlay(nullptr);
     overlay->setAttribute(Qt::WA_DeleteOnClose);
     overlay->show();
 }
 
-
-void MainWin::on_actionDebugMessageModel_triggered()
+void MainWin::onDebugMessageModelTriggered()
 {
-    QTableView *view = new QTableView(0);
-    DebugMessageModelFilter *filter = new DebugMessageModelFilter(view);
+    auto* view = new QTableView(nullptr);
+    auto* filter = new DebugMessageModelFilter(view);
     filter->setSourceModel(Client::messageModel());
     view->setModel(filter);
     view->setAttribute(Qt::WA_DeleteOnClose, true);
@@ -1808,15 +1953,19 @@ void MainWin::on_actionDebugMessageModel_triggered()
     view->show();
 }
 
-
-void MainWin::on_actionDebugLog_triggered()
+void MainWin::onDebugLogTriggered()
 {
-    DebugLogWidget *logWidget = new DebugLogWidget(0);
-    logWidget->show();
+    auto dlg = new DebugLogDlg(this);  // will be deleted on close
+    dlg->show();
 }
 
+void MainWin::onShowResourceTreeTriggered()
+{
+    auto dlg = new ResourceTreeDlg(this);  // will be deleted on close
+    dlg->show();
+}
 
-void MainWin::showStatusBarMessage(const QString &message)
+void MainWin::showStatusBarMessage(const QStringmessage)
 {
     statusBar()->showMessage(message, 10000);
 }