From 4243fde9874d81d53aebfee4d8911ae68639eb3e Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <barracuda@macos-powerpc.org>
Date: Wed, 12 Aug 2026 18:24:26 +0000
Subject: [PATCH 3/4] Qt4: convert new-style connect() calls to SIGNAL/SLOT
 macros

Qt4's QObject::connect() only accepts the old string-based
SIGNAL()/SLOT() form; it cannot bind a pointer-to-member-function or a
functor/lambda slot (both Qt5+ additions). Converts every PMF-style
connect()/disconnect() across mainwindow, logdialog, FileLogger and
main.cpp to the old-style macros, which work unchanged under Qt5/6 too.

Lambda slots are replaced with named slots on MainWindow, since Qt4
cannot connect a signal directly to a functor:
- onActionQuitTriggered, onStateMachineStarted, onMinimizedWindowEntered/
  Exited, onServerProfileTriggered, onSingleInstanceModeToggled,
  onLogDialogFinished, onSingleAppMessageReceived (the last also needed
  by main.cpp, which is outside the class and so cannot see a lambda's
  captures either way).
- onStateMachineStarted uses a new m_profileName member instead of a
  lambda capture of the constructor's profileName argument.
- onServerProfileTriggered identifies which per-profile QAction fired
  via sender() instead of a per-action lambda capture.
- LogDialog gained a showAndActivate() slot combining show()/raise()/
  activateWindow(), since activateWindow() is not itself a registered
  Qt slot and so can't be named in a SLOT() macro directly.

Signal/slot signatures with a Qt type parameter (Logger::Message,
QString) are spelled with the exact const-reference form used in their
declarations, since the old-style macros match by literal normalized
signature text.

Part of Qt4 buildability work for the macOS PowerPC port.
---
 src/FileLogger.cpp        |   3 +-
 src/dialog/logdialog.cpp  |  19 ++-
 src/dialog/logdialog.h    |   4 +
 src/dialog/mainwindow.cpp | 267 +++++++++++++++++++++-----------------
 src/dialog/mainwindow.h   |  21 ++-
 src/main.cpp              |   6 +-
 6 files changed, 192 insertions(+), 128 deletions(-)

diff --git a/src/FileLogger.cpp b/src/FileLogger.cpp
index 8585454..c2063a1 100644
--- a/src/FileLogger.cpp
+++ b/src/FileLogger.cpp
@@ -35,7 +35,8 @@ FileLogger::FileLogger(QObject* parent, const QString& logPath, const size_t log
         throw;
     }
 
-    connect(&Logger::instance(), &Logger::newLogMessage, this, &FileLogger::addLogMessage);
+    connect(&Logger::instance(), SIGNAL(newLogMessage(const Logger::Message&)),
+        this, SLOT(addLogMessage(const Logger::Message&)));
 }
 
 FileLogger::~FileLogger()
diff --git a/src/dialog/logdialog.cpp b/src/dialog/logdialog.cpp
index b9406d1..759e294 100644
--- a/src/dialog/logdialog.cpp
+++ b/src/dialog/logdialog.cpp
@@ -44,23 +44,30 @@ LogDialog::LogDialog(QWidget* parent)
         ui->listWidget->scrollToBottom();
     }
 
-    connect(&Logger::instance(), &Logger::newLogMessage,
-        this, &LogDialog::append, Qt::QueuedConnection);
+    connect(&Logger::instance(), SIGNAL(newLogMessage(const Logger::Message&)),
+        this, SLOT(append(const Logger::Message&)), Qt::QueuedConnection);
 
     m_timer->setSingleShot(true);
     m_timer->setInterval(100);
-    connect(m_timer.get(), &QTimer::timeout,
-        ui->listWidget, &QListWidget::scrollToBottom);
+    connect(m_timer.get(), SIGNAL(timeout()),
+        ui->listWidget, SLOT(scrollToBottom()));
 }
 
 LogDialog::~LogDialog()
 {
-    disconnect(&Logger::instance(), &Logger::newLogMessage,
-        this, &LogDialog::append);
+    disconnect(&Logger::instance(), SIGNAL(newLogMessage(const Logger::Message&)),
+        this, SLOT(append(const Logger::Message&)));
 
     delete ui;
 }
 
+void LogDialog::showAndActivate()
+{
+    show();
+    raise();
+    activateWindow();
+}
+
 void LogDialog::on_pushButtonSelectAll_clicked()
 {
     ui->listWidget->selectAll();
diff --git a/src/dialog/logdialog.h b/src/dialog/logdialog.h
index 1024a5d..e7110e4 100644
--- a/src/dialog/logdialog.h
+++ b/src/dialog/logdialog.h
@@ -40,6 +40,10 @@ signals:
 
 public slots:
     void append(const Logger::Message& message);
+    /* combines show()/raise()/activateWindow() behind a single real Qt
+     * slot, since QWidget::activateWindow() is not itself a registered
+     * slot and so cannot be named in a SIGNAL/SLOT-macro connect() */
+    void showAndActivate();
 
 private slots:
     void on_pushButtonClear_clicked();
diff --git a/src/dialog/mainwindow.cpp b/src/dialog/mainwindow.cpp
index 297a3bb..7c17e41 100644
--- a/src/dialog/mainwindow.cpp
+++ b/src/dialog/mainwindow.cpp
@@ -48,7 +48,9 @@ extern "C" {
 #include <QStateMachine>
 #include <QUrl>
 #include <QTimer>
-#include <QtConcurrent/QtConcurrentRun>
+/* Qt4's QtConcurrent module does not provide the "QtConcurrent/QtConcurrentRun"
+ * submodule-prefixed header; use the flat form that works on every Qt version. */
+#include <QtConcurrentRun>
 #include <QtNetwork/QNetworkProxy>
 #include <QtNetwork/QNetworkProxyFactory>
 #include <QtNetwork/QNetworkProxyQuery>
@@ -96,11 +98,12 @@ static int app_loglevel_rtab[] = {
 MainWindow::MainWindow(QWidget* parent, bool useTray, const QString profileName)
     : QMainWindow(parent)
     , ui(new Ui::MainWindow)
+    , m_profileName(profileName)
 {
     ui->setupUi(this);
 
-    connect(ui->viewLogButton, &QPushButton::clicked,
-        this, &MainWindow::createLogDialog);
+    connect(ui->viewLogButton, SIGNAL(clicked()),
+        this, SLOT(createLogDialog()));
 
     timer = new QTimer(this);
     blink_timer = new QTimer(this);
@@ -109,34 +112,26 @@ MainWindow::MainWindow(QWidget* parent, bool useTray, const QString profileName)
     downloadProgress = nullptr;
     manager = new QNetworkAccessManager();
 
-    connect(ui->actionQuit, &QAction::triggered,
-        [=]() {
-            if (m_trayIcon && m_disconnectAction->isEnabled()) {
-                connect(this, &MainWindow::readyToShutdown,
-                    qApp, &QApplication::quit);
-                on_disconnectClicked();
-            } else {
-                qApp->quit();
-            }
-        });
+    connect(ui->actionQuit, SIGNAL(triggered()),
+        this, SLOT(onActionQuitTriggered()));
 
-    connect(blink_timer, &QTimer::timeout,
-        this, &MainWindow::blink_ui,
+    connect(blink_timer, SIGNAL(timeout()),
+        this, SLOT(blink_ui()),
         Qt::QueuedConnection);
-    connect(timer, &QTimer::timeout,
-        this, &MainWindow::request_update_stats,
+    connect(timer, SIGNAL(timeout()),
+        this, SLOT(request_update_stats()),
         Qt::QueuedConnection);
-    connect(ui->serverList->lineEdit(), &QLineEdit::returnPressed,
-        this, &MainWindow::on_connectClicked,
+    connect(ui->serverList->lineEdit(), SIGNAL(returnPressed()),
+        this, SLOT(on_connectClicked()),
         Qt::QueuedConnection);
-    connect(this, &MainWindow::vpn_status_changed_sig,
-        this, &MainWindow::changeStatus,
+    connect(this, SIGNAL(vpn_status_changed_sig(int)),
+        this, SLOT(changeStatus(int)),
         Qt::QueuedConnection);
-    connect(ui->connectionButton, &QPushButton::clicked,
-        this, &MainWindow::on_connectClicked,
+    connect(ui->connectionButton, SIGNAL(clicked()),
+        this, SLOT(on_connectClicked()),
         Qt::QueuedConnection);
-    connect(this, &MainWindow::stats_changed_sig,
-        this, &MainWindow::statsChanged,
+    connect(this, SIGNAL(stats_changed_sig(QString, QString, QString)),
+        this, SLOT(statsChanged(QString, QString, QString)),
         Qt::QueuedConnection);
 
     ui->iconLabel->setPixmap(OFF_ICON);
@@ -146,8 +141,8 @@ MainWindow::MainWindow(QWidget* parent, bool useTray, const QString profileName)
     if (useTray) {
         createTrayIcon();
 
-        connect(m_trayIcon, &QSystemTrayIcon::activated,
-            this, &MainWindow::iconActivated);
+        connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
+            this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
 
         QFileSelector selector;
         QIcon icon(selector.select(QStringLiteral(":/images/network-disconnected.png")));
@@ -219,30 +214,8 @@ MainWindow::MainWindow(QWidget* parent, bool useTray, const QString profileName)
 
     machine->setInitialState(s1_noProfiles);
     machine->start();
-    connect(machine, &QStateMachine::started, [=]() {
-        // LCA: find better way to load/fill combobox...
-        this->reload_settings();
-
-        if (!profileName.isEmpty()) {
-            // TODO: better place when refactor SM...
-            const int profileIndex = ui->serverList->findText(profileName);
-            if (profileIndex != -1) {
-                ui->serverList->setCurrentIndex(profileIndex);
-                emit on_connectClicked();
-                return;
-            } else {
-                QMessageBox::warning(this,
-                    tr("Connection failed"),
-                    tr("Selected VPN profile '<b>%1</b>' does not exist.").arg(profileName));
-            }
-        }
-
-        OcSettings settings;
-        const int currentIndex = settings.value("Profiles/currentIndex", -1).toInt();
-        if (currentIndex != -1 && currentIndex < ui->serverList->count()) {
-            ui->serverList->setCurrentIndex(currentIndex);
-        }
-    });
+    connect(machine, SIGNAL(started()),
+        this, SLOT(onStateMachineStarted()));
 
     QMenu* serverProfilesMenu = new QMenu(this);
     serverProfilesMenu->addAction(ui->actionNewProfile);
@@ -262,20 +235,10 @@ MainWindow::MainWindow(QWidget* parent, bool useTray, const QString profileName)
 
     QState* s112_minimizedWindow = new QState();
     m_appWindowStateMachine->addState(s112_minimizedWindow);
-    connect(s112_minimizedWindow, &QState::entered, [=]() {
-        showMinimized();
-        if (ui->actionMinimizeToTheNotificationArea->isChecked()) {
-            QTimer::singleShot(10, this, SLOT(hide()));
-        }
-    });
-    connect(s112_minimizedWindow, &QState::exited, [=]() {
-        this->showNormal();
-        if (ui->actionMinimizeToTheNotificationArea->isChecked()) {
-            show();
-            raise();
-            activateWindow();
-        }
-    });
+    connect(s112_minimizedWindow, SIGNAL(entered()),
+        this, SLOT(onMinimizedWindowEntered()));
+    connect(s112_minimizedWindow, SIGNAL(exited()),
+        this, SLOT(onMinimizedWindowExited()));
     s112_minimizedWindow->assignProperty(ui->actionRestore, "enabled", true);
     s112_minimizedWindow->assignProperty(ui->actionMinimize, "enabled", false);
 
@@ -349,11 +312,97 @@ MainWindow::MainWindow(QWidget* parent, bool useTray, const QString profileName)
     s112_minimizedWindow->addTransition(restoreEvent);
 
     // start timer to check latest version
-    QTimer::singleShot(4000, this, &MainWindow::tryCheckLatestVersion);
+    QTimer::singleShot(4000, this, SLOT(tryCheckLatestVersion()));
 
     m_appWindowStateMachine->start();
 }
 
+void MainWindow::onActionQuitTriggered()
+{
+    if (m_trayIcon && m_disconnectAction->isEnabled()) {
+        connect(this, SIGNAL(readyToShutdown()),
+            qApp, SLOT(quit()));
+        on_disconnectClicked();
+    } else {
+        qApp->quit();
+    }
+}
+
+void MainWindow::onStateMachineStarted()
+{
+    // LCA: find better way to load/fill combobox...
+    this->reload_settings();
+
+    if (!m_profileName.isEmpty()) {
+        // TODO: better place when refactor SM...
+        const int profileIndex = ui->serverList->findText(m_profileName);
+        if (profileIndex != -1) {
+            ui->serverList->setCurrentIndex(profileIndex);
+            emit on_connectClicked();
+            return;
+        } else {
+            QMessageBox::warning(this,
+                tr("Connection failed"),
+                tr("Selected VPN profile '<b>%1</b>' does not exist.").arg(m_profileName));
+        }
+    }
+
+    OcSettings settings;
+    const int currentIndex = settings.value("Profiles/currentIndex", -1).toInt();
+    if (currentIndex != -1 && currentIndex < ui->serverList->count()) {
+        ui->serverList->setCurrentIndex(currentIndex);
+    }
+}
+
+void MainWindow::onMinimizedWindowEntered()
+{
+    showMinimized();
+    if (ui->actionMinimizeToTheNotificationArea->isChecked()) {
+        QTimer::singleShot(10, this, SLOT(hide()));
+    }
+}
+
+void MainWindow::onMinimizedWindowExited()
+{
+    this->showNormal();
+    if (ui->actionMinimizeToTheNotificationArea->isChecked()) {
+        show();
+        raise();
+        activateWindow();
+    }
+}
+
+void MainWindow::onServerProfileTriggered()
+{
+    QAction* act = qobject_cast<QAction*>(sender());
+    if (act == nullptr) {
+        return;
+    }
+
+    int idx = ui->serverList->findText(act->text());
+    if (idx != -1) {
+        ui->serverList->setCurrentIndex(idx);
+        on_connectClicked();
+    }
+}
+
+void MainWindow::onSingleInstanceModeToggled(bool checked)
+{
+    OcSettings settings;
+    settings.setValue("Settings/singleInstanceMode", checked);
+}
+
+void MainWindow::onLogDialogFinished()
+{
+    connect(ui->viewLogButton, SIGNAL(clicked()),
+        this, SLOT(createLogDialog()));
+}
+
+void MainWindow::onSingleAppMessageReceived(const QString& message)
+{
+    Logger::instance().addMessage(message);
+}
+
 static void term_thread(MainWindow* m, SOCKET* fd)
 {
     char cmd = OC_CMD_CANCEL;
@@ -400,8 +449,8 @@ void MainWindow::checkLatestVersion() const
 
     req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy);
 
-    connect(manager, &QNetworkAccessManager::finished,
-            this, &MainWindow::gotLatestVersion);
+    connect(manager, SIGNAL(finished(QNetworkReply*)),
+            this, SLOT(gotLatestVersion(QNetworkReply*)));
 
     Logger::instance().addMessage(QObject::tr("Checking for current version"));
     manager->get(req);
@@ -514,13 +563,8 @@ void MainWindow::reload_settings()
 
             if (m_trayIcon) {
                 QAction* act = m_trayIconMenuConnections->addAction(str);
-                connect(act, &QAction::triggered, [act, this]() {
-                    int idx = ui->serverList->findText(act->text());
-                    if (idx != -1) {
-                        ui->serverList->setCurrentIndex(idx);
-                        on_connectClicked();
-                    }
-                });
+                connect(act, SIGNAL(triggered()),
+                    this, SLOT(onServerProfileTriggered()));
             }
         }
     }
@@ -606,10 +650,10 @@ void MainWindow::changeStatus(int val)
         ui->connectionButton->setText(tr("Cancel"));
         blink_timer->start(1500);
 
-        disconnect(ui->connectionButton, &QPushButton::clicked,
-            this, &MainWindow::on_connectClicked);
-        connect(ui->connectionButton, &QPushButton::clicked,
-            this, &MainWindow::on_disconnectClicked,
+        disconnect(ui->connectionButton, SIGNAL(clicked()),
+            this, SLOT(on_connectClicked()));
+        connect(ui->connectionButton, SIGNAL(clicked()),
+            this, SLOT(on_disconnectClicked()),
             Qt::QueuedConnection);
     } else if (val == STATUS_DISCONNECTED) {
         blink_timer->stop();
@@ -652,10 +696,10 @@ void MainWindow::changeStatus(int val)
 
             m_trayIcon->setToolTip(QLatin1String("Disconnected"));
         }
-        disconnect(ui->connectionButton, &QPushButton::clicked,
-            this, &MainWindow::on_disconnectClicked);
-        connect(ui->connectionButton, &QPushButton::clicked,
-            this, &MainWindow::on_connectClicked,
+        disconnect(ui->connectionButton, SIGNAL(clicked()),
+            this, SLOT(on_disconnectClicked()));
+        connect(ui->connectionButton, SIGNAL(clicked()),
+            this, SLOT(on_connectClicked()),
             Qt::QueuedConnection);
 
         emit readyToShutdown();
@@ -892,8 +936,8 @@ void MainWindow::closeEvent(QCloseEvent* event)
         event->accept();
 
         if (m_trayIcon && m_disconnectAction->isEnabled()) {
-            connect(this, &MainWindow::readyToShutdown,
-                qApp, &QApplication::quit);
+            connect(this, SIGNAL(readyToShutdown()),
+                qApp, SLOT(quit()));
             on_disconnectClicked();
         } else {
             qApp->quit();
@@ -942,10 +986,8 @@ void MainWindow::readSettings()
     ui->actionStartMinimized->setChecked(settings.value("startMinimized", false).toBool());
 
     ui->actionSingleInstanceMode->setChecked(settings.value("singleInstanceMode", true).toBool());
-    connect(ui->actionSingleInstanceMode, &QAction::toggled, [](bool checked) {
-        OcSettings settings;
-        settings.setValue("Settings/singleInstanceMode", checked);
-    });
+    connect(ui->actionSingleInstanceMode, SIGNAL(toggled(bool)),
+        this, SLOT(onSingleInstanceModeToggled(bool)));
 
     int loglevel = settings.value("logLevel", PRG_INFO).toInt();
     int action_idx = app_loglevel_tab(loglevel);
@@ -982,23 +1024,16 @@ void MainWindow::createLogDialog()
 {
     auto dialog{ new LogDialog() };
 
-    disconnect(ui->viewLogButton, &QPushButton::clicked,
-        this, &MainWindow::createLogDialog);
+    disconnect(ui->viewLogButton, SIGNAL(clicked()),
+        this, SLOT(createLogDialog()));
 
-    connect(ui->viewLogButton, &QPushButton::clicked,
-        dialog, &QDialog::show);
-    connect(ui->viewLogButton, &QPushButton::clicked,
-        dialog, &QDialog::raise);
-    connect(ui->viewLogButton, &QPushButton::clicked,
-        dialog, &QDialog::activateWindow);
+    connect(ui->viewLogButton, SIGNAL(clicked()),
+        dialog, SLOT(showAndActivate()));
 
-    connect(dialog, &QDialog::finished,
-        [this]() {
-            connect(ui->viewLogButton, &QPushButton::clicked,
-                this, &MainWindow::createLogDialog);
-        });
-    connect(dialog, &QDialog::finished,
-        dialog, &QDialog::deleteLater);
+    connect(dialog, SIGNAL(finished(int)),
+        this, SLOT(onLogDialogFinished()));
+    connect(dialog, SIGNAL(finished(int)),
+        dialog, SLOT(deleteLater()));
 
     dialog->show();
     dialog->raise();
@@ -1013,8 +1048,8 @@ void MainWindow::createTrayIcon()
     m_trayIconMenu->addMenu(m_trayIconMenuConnections);
     m_disconnectAction = new QAction(tr("Disconnect"), this);
     m_trayIconMenu->addAction(m_disconnectAction);
-    connect(m_disconnectAction, &QAction::triggered,
-        this, &MainWindow::on_disconnectClicked);
+    connect(m_disconnectAction, SIGNAL(triggered()),
+        this, SLOT(on_disconnectClicked()));
 
     m_trayIconMenu->addSeparator();
     m_trayIconMenu->addAction(ui->actionLogWindow);
@@ -1051,8 +1086,8 @@ void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
 void MainWindow::on_actionNewProfile_triggered()
 {
     NewProfileDialog dialog(this);
-    connect(&dialog, &NewProfileDialog::connect,
-        this, &MainWindow::on_connectClicked,
+    connect(&dialog, SIGNAL(connect()),
+        this, SLOT(on_connectClicked()),
         Qt::QueuedConnection);
     if (dialog.exec() != QDialog::Accepted) {
         return;
@@ -1113,10 +1148,10 @@ void MainWindow::on_actionAbout_triggered()
     QString txt = QLatin1String("<h2>") + QLatin1String(PRODUCT_NAME_LONG) + QLatin1String("</h2>");
 
     if (QLatin1String(PROJECT_VERSION).contains(QLatin1String("-g"))) {
-        txt += tr("Development snapshot <i>%1</i> (%2 bit)<br>").arg(PROJECT_VERSION).arg(QSysInfo::buildCpuArchitecture() == QLatin1String("i386") ? 32 : 64);
+        txt += tr("Development snapshot <i>%1</i> (%2 bit)<br>").arg(PROJECT_VERSION).arg(sizeof(void*) == 4 ? 32 : 64);
         txt += tr("Built at <i>%1</i><br>").arg(QLatin1String(appBuildOn));
     } else {
-        txt += tr("Version <i>%1</i> (%2 bit)<br>").arg(PROJECT_VERSION).arg(QSysInfo::buildCpuArchitecture() == QLatin1String("i386") ? 32 : 64);
+        txt += tr("Version <i>%1</i> (%2 bit)<br>").arg(PROJECT_VERSION).arg(sizeof(void*) == 4 ? 32 : 64);
     }
 
     txt += tr("<br><i>%1</i> is free software developed by the OpenConnect GUI project community. See the license for more information.<br>").arg(APP_NAME);
@@ -1129,8 +1164,8 @@ void MainWindow::on_actionAbout_triggered()
 void MainWindow::checkForUpdatesDialog()
 {
     if (downloadProgress != nullptr) {
-        disconnect(this, &MainWindow::version_download_completed_sig,
-                   this, &MainWindow::checkForUpdatesDialog);
+        disconnect(this, SIGNAL(version_download_completed_sig()),
+                   this, SLOT(checkForUpdatesDialog()));
         this->downloadProgress->setValue(100);
         downloadProgress->done(0);
         delete downloadProgress;
@@ -1146,10 +1181,10 @@ void MainWindow::checkForUpdatesDialog()
 
     txt += tr("<h3>Current version</h3>");
     if (QLatin1String(PROJECT_VERSION).contains(QLatin1String("-g"))) {
-        txt += tr("Development snapshot <i>%1</i> (%2 bit)<br>").arg(PROJECT_VERSION).arg(QSysInfo::buildCpuArchitecture() == QLatin1String("i386") ? 32 : 64);
+        txt += tr("Development snapshot <i>%1</i> (%2 bit)<br>").arg(PROJECT_VERSION).arg(sizeof(void*) == 4 ? 32 : 64);
         txt += tr("Built at <i>%1</i><br>").arg(QLatin1String(appBuildOn));
     } else {
-        txt += tr("Version <i>%1</i> (%2 bit)<br>").arg(PROJECT_VERSION).arg(QSysInfo::buildCpuArchitecture() == QLatin1String("i386") ? 32 : 64);
+        txt += tr("Version <i>%1</i> (%2 bit)<br>").arg(PROJECT_VERSION).arg(sizeof(void*) == 4 ? 32 : 64);
     }
 
     txt += tr("<h3>Latest version</h3>");
@@ -1190,8 +1225,8 @@ void MainWindow::on_actionCheckForUpdates_triggered()
         downloadProgress = new QProgressDialog("Checking for latest version...", "Abort", 0, progress_max_value, this);
 
         // ensure that this is called when download is complete
-        connect(this, &MainWindow::version_download_completed_sig,
-                this, &MainWindow::checkForUpdatesDialog,
+        connect(this, SIGNAL(version_download_completed_sig()),
+                this, SLOT(checkForUpdatesDialog()),
                 Qt::QueuedConnection);
 
         downloadProgress->setValue(25);
diff --git a/src/dialog/mainwindow.h b/src/dialog/mainwindow.h
index 20d224e..7567b99 100644
--- a/src/dialog/mainwindow.h
+++ b/src/dialog/mainwindow.h
@@ -102,6 +102,9 @@ public slots:
     void on_actionReport_an_issue_triggered();
     void on_actionWebSite_triggered();
 
+    /* connected from main.cpp to QtSingleApplication::messageReceived */
+    void onSingleAppMessageReceived(const QString& message);
+
 signals:
     void stats_changed_sig(QString, QString, QString);
     void vpn_status_changed_sig(int);
@@ -114,8 +117,20 @@ private slots:
     void tryCheckLatestVersion();
     void checkForUpdatesDialog();
 
+    /* Named slots standing in for lambdas that used to be passed straight
+     * to connect(); Qt4's connect() cannot bind a functor/lambda slot. */
+    void onActionQuitTriggered();
+    void onStateMachineStarted();
+    void onMinimizedWindowEntered();
+    void onMinimizedWindowExited();
+    void onServerProfileTriggered();
+    void onSingleInstanceModeToggled(bool checked);
+    void onLogDialogFinished();
+
+    /* connected via old-style SIGNAL/SLOT macro, so must be a real slot */
+    void gotLatestVersion(QNetworkReply* reply);
+
 private:
-    void gotLatestVersion(QNetworkReply *reply);
     void checkLatestVersion() const;
 
     static QString normalize_byte_size(uint64_t bytes);
@@ -143,6 +158,10 @@ private:
     time_t last_check_time;
     QProgressDialog *downloadProgress;
 
+    /* copy of the ctor's profileName arg, needed by onStateMachineStarted()
+     * since Qt4's connect() cannot capture it via a lambda */
+    QString m_profileName;
+
     QNetworkAccessManager *manager;
 
     QStateMachine* m_appWindowStateMachine;
diff --git a/src/main.cpp b/src/main.cpp
index e18a76e..50c37b1 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -205,9 +205,7 @@ int main(int argc, char* argv[])
     mainWindow.show();
     mainWindow.setWindowTitle(APP_NAME);
 
-    QObject::connect(&app, &QtSingleApplication::messageReceived,
-        [&mainWindow](const QString& message) {
-            Logger::instance().addMessage(message);
-        });
+    QObject::connect(&app, SIGNAL(messageReceived(const QString&)),
+        &mainWindow, SLOT(onSingleAppMessageReceived(const QString&)));
     return app.exec();
 }
-- 
2.43.0

