From 97a63ea92c432cd862838530b0ab63fd845671d2 Mon Sep 17 00:00:00 2001 From: Karl Fleischmann Date: Tue, 10 Mar 2026 09:59:44 +0100 Subject: [PATCH] gui: Implement Daemon Warn Dialog Replace generic MessageBox with a manually programmed dialog, that allows copying the appropriate text into the clipboard. --- src/gui/CMakeLists.txt | 3 + src/gui/daemonwarndialog.cpp | 82 +++++++++++++ src/gui/daemonwarndialog.h | 26 ++++ src/gui/daemonwarndialog.ui | 222 +++++++++++++++++++++++++++++++++++ src/gui/mainwindow.cpp | 23 +--- 5 files changed, 336 insertions(+), 20 deletions(-) create mode 100644 src/gui/daemonwarndialog.cpp create mode 100644 src/gui/daemonwarndialog.h create mode 100644 src/gui/daemonwarndialog.ui diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index aeeae49e..4bfdd120 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -138,6 +138,7 @@ if (MACOS OR LINUX) clickeventpushbutton.cpp colorbutton.cpp colormap.cpp + daemonwarndialog.cpp extrasettingswidget.cpp fwupgradedialog.cpp gradientbutton.cpp @@ -195,6 +196,7 @@ if (MACOS OR LINUX) clickeventpushbutton.h colorbutton.h colormap.h + daemonwarndialog.h extrasettingswidget.h fwupgradedialog.h gradientbutton.h @@ -249,6 +251,7 @@ if (MACOS OR LINUX) animdetailsdialog.ui animsettingdialog.ui ckbupdaterwidget.ui + daemonwarndialog.ui extrasettingswidget.ui fwupgradedialog.ui gradientdialog.ui diff --git a/src/gui/daemonwarndialog.cpp b/src/gui/daemonwarndialog.cpp new file mode 100644 index 00000000..3e231ce4 --- /dev/null +++ b/src/gui/daemonwarndialog.cpp @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include + +#include "daemonwarndialog.h" +#include "ui_daemonwarndialog.h" + +DaemonWarnDialog::DaemonWarnDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::DaemonWarnDialog) +{ + ui->setupUi(this); + + // Release resources on exit. + this->setAttribute(Qt::WA_DeleteOnClose); + + // Display Critical Message Box icon. + QStyle *style = this->style(); + int imageSize = style->pixelMetric(QStyle::PM_MessageBoxIconSize, nullptr, this); + QIcon icon = style->standardIcon(QStyle::SP_MessageBoxCritical, nullptr, this); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + ui->iconLabel->setPixmap(icon.pixmap(QSize(imageSize, imageSize), this->devicePixelRatio())); +#else // QT_VERSION < 6.0.0 + ui->iconLabel->setPixmap(icon.pixmap(QSize(imageSize, imageSize))); +#endif + + // Display icon instead of name on copy buttons. + QIcon fallbackIcon = style->standardIcon(QStyle::SP_FileIcon, nullptr, this); +#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) + icon = QIcon::fromTheme(QIcon::ThemeIcon::EditCopy, fallbackIcon); +#else // QT_VERSION < 6.7.0 + icon = QIcon::fromTheme("edit-copy", fallbackIcon); +#endif + ui->pushButton->setIcon(icon); + ui->pushButton_2->setIcon(icon); + ui->pushButton_3->setIcon(icon); + +#ifdef Q_OS_MACOS + // On Mac only one command is displayed. Hide the remaining elements. + ui->label_4->hide(); + ui->label_5->hide(); + ui->label_6->hide(); + ui->label_7->hide(); + ui->pushButton_2->hide(); + ui->pushButton_3->hide(); + + ui->label_2->setText(tr("Start and enable it with:")); + ui->label_3->setText("sudo launchctl load -w /Library/LaunchDaemons/org.ckb-next.daemon.plist"); +#endif // Q_OS_MACOS + + // Call copyText() with the appropriate label, when the copy buttons are + // pressed. + QObject::connect(ui->pushButton, &QPushButton::clicked, this, [=] () { + this->copyText(ui->label_3); + }); + QObject::connect(ui->pushButton_2, &QPushButton::clicked, this, [=] () { + this->copyText(ui->label_5); + }); + QObject::connect(ui->pushButton_3, &QPushButton::clicked, this, [=] () { + this->copyText(ui->label_7); + }); + + ui->gridLayout->activate(); + this->setFixedSize(ui->gridLayoutWidget->geometry().size()); +} + +DaemonWarnDialog::~DaemonWarnDialog() { + delete ui; +} + +void +DaemonWarnDialog::copyText(QLabel *label) +{ + QClipboard *clipboard = QApplication::clipboard(); + + // Strip HTML tags when setting the clipboard content. + QTextDocument doc; + doc.setHtml(label->text()); + clipboard->setText(doc.toPlainText()); +} diff --git a/src/gui/daemonwarndialog.h b/src/gui/daemonwarndialog.h new file mode 100644 index 00000000..948f9522 --- /dev/null +++ b/src/gui/daemonwarndialog.h @@ -0,0 +1,26 @@ +#ifndef DAEMONWARNDIALOG_H +#define DAEMONWARNDIALOG_H + +#include +#include + +namespace Ui { +class DaemonWarnDialog; +} + +class DaemonWarnDialog : public QDialog +{ + Q_OBJECT + +public: + explicit DaemonWarnDialog(QWidget *parent); + ~DaemonWarnDialog(); + +private slots: + void copyText(QLabel *label); + +private: + Ui::DaemonWarnDialog *ui; +}; + +#endif // DAEMONWARNDIALOG_H diff --git a/src/gui/daemonwarndialog.ui b/src/gui/daemonwarndialog.ui new file mode 100644 index 00000000..b3437573 --- /dev/null +++ b/src/gui/daemonwarndialog.ui @@ -0,0 +1,222 @@ + + + DaemonWarnDialog + + + Qt::WindowModality::ApplicationModal + + + + 0 + 0 + 580 + 400 + + + + + 0 + 0 + + + + ckb-next-daemon not running + + + false + + + + + 0 + 0 + 581 + 400 + + + + + 16 + + + 16 + + + 16 + + + 16 + + + 8 + + + + + + + + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop + + + Qt::TextInteractionFlag::NoTextInteraction + + + + + + + Copy to clipboard + + + + + + false + + + + + + + Copy to clipboard + + + + + + false + + + false + + + + + + + Copy to clipboard + + + + + + false + + + + + + + <code>sudo systemctl unmask ckb-next-daemon</code> + + + Qt::TextFormat::RichText + + + true + + + Qt::TextInteractionFlag::LinksAccessibleByKeyboard|Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextBrowserInteraction|Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse + + + + + + + If "Unit ckb-next-daemon.service is masked", unmask it first and try again: + + + + + + + + 0 + 0 + + + + QDialogButtonBox::StandardButton::Ok + + + + + + + Start it once with: + + + + + + + The ckb-next daemon is not running. This program will <b>not</b> work without it! + + + + + + + <code>sudo systemctl start ckb-next-daemon</code> + + + Qt::TextFormat::RichText + + + true + + + Qt::TextInteractionFlag::LinksAccessibleByKeyboard|Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextBrowserInteraction|Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse + + + + + + + Enable it for every boot: + + + + + + + <code>sudo systemctl enable ckb-next-daemon</code> + + + Qt::TextFormat::RichText + + + true + + + Qt::TextInteractionFlag::LinksAccessibleByKeyboard|Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextBrowserInteraction|Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse + + + + + + + + + + buttonBox + accepted() + DaemonWarnDialog + accept() + + + 286 + 279 + + + 445 + 293 + + + + + + accept() + + diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 4adcbc86..9809dc5b 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -24,6 +24,7 @@ XWindowDetector* windowDetector = nullptr; #endif #include "ckbsystemtrayicon.h" +#include "daemonwarndialog.h" extern QSharedMemory appShare; @@ -163,25 +164,7 @@ MainWindow::MainWindow(const bool silent, QWidget *parent) : ui->tabWidget->addTab(settingsWidget = new SettingsWidget(this), QString(tr("Settings"))); settingsWidget->setVersion(KbManager::ckbGuiVersion()); - // create daemon dialog as a QMessageBox - // this will create a focussed dialog, that has to be interacted with, - // if the daemon is not running - // set the main and informative text to tell the user about the issue - QMessageBox dialog; - dialog.setText(tr("The ckb-next daemon is not running. This program will not work without it!")); -#ifndef Q_OS_MACOS - QString daemonDialogText = tr("Start it once with:") + - "
sudo systemctl start ckb-next-daemon
" + - tr("Enable it for every boot:") + - "
sudo systemctl enable ckb-next-daemon

" + - tr("If \"Unit ckb-next-daemon.service is masked.\", unmask it first and try again:") + - "
sudo systemctl unmask ckb-next-daemon
"; -#else - QString daemonDialogText = QString(tr("Start and enable it with:")) + - "
sudo launchctl load -w /Library/LaunchDaemons/org.ckb-next.daemon.plist
"; -#endif - dialog.setInformativeText(daemonDialogText); - dialog.setIcon(QMessageBox::Critical); + DaemonWarnDialog *warnDialog = new DaemonWarnDialog(mainWindow); // Set up signal handler socketpair(AF_UNIX, SOCK_STREAM, 0, MainWindow::signalHandlerFd); @@ -205,7 +188,7 @@ MainWindow::MainWindow(const bool silent, QWidget *parent) : // finally show the dialog settingsWidget->setStatus(tr("The ckb-next daemon is not running.")); showWindow(); - dialog.exec(); + warnDialog->open(); } #ifndef DISABLE_UPDATER if(!CkbSettings::get("Program/DisableAutoUpdCheck", false).toBool())