gui: Implement Daemon Warn Dialog

Replace generic MessageBox with a manually programmed dialog, that
allows copying the appropriate text into the clipboard.
This commit is contained in:
Karl Fleischmann
2026-05-26 21:18:11 +03:00
committed by Tasos Sahanidis
parent 389af0b63c
commit 97a63ea92c
5 changed files with 336 additions and 20 deletions
+3
View File
@@ -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
+82
View File
@@ -0,0 +1,82 @@
#include <QClipboard>
#include <QLabel>
#include <QScreen>
#include <QStyle>
#include <QTextDocument>
#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("<code>sudo launchctl load -w /Library/LaunchDaemons/org.ckb-next.daemon.plist</code>");
#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());
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef DAEMONWARNDIALOG_H
#define DAEMONWARNDIALOG_H
#include <QDialog>
#include <QLabel>
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
+222
View File
@@ -0,0 +1,222 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DaemonWarnDialog</class>
<widget class="QDialog" name="DaemonWarnDialog">
<property name="windowModality">
<enum>Qt::WindowModality::ApplicationModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>580</width>
<height>400</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>ckb-next-daemon not running</string>
</property>
<property name="modal">
<bool>false</bool>
</property>
<widget class="QWidget" name="gridLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>581</width>
<height>400</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="2,1,10,1">
<property name="leftMargin">
<number>16</number>
</property>
<property name="topMargin">
<number>16</number>
</property>
<property name="rightMargin">
<number>16</number>
</property>
<property name="bottomMargin">
<number>16</number>
</property>
<property name="spacing">
<number>8</number>
</property>
<item row="0" column="0" rowspan="8">
<widget class="QLabel" name="iconLabel">
<property name="text">
<string notr="true"/>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
</property>
<property name="textInteractionFlags">
<set>Qt::TextInteractionFlag::NoTextInteraction</set>
</property>
</widget>
</item>
<item row="6" column="3">
<widget class="QPushButton" name="pushButton_3">
<property name="toolTip">
<string>Copy to clipboard</string>
</property>
<property name="text">
<string/>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QPushButton" name="pushButton">
<property name="toolTip">
<string>Copy to clipboard</string>
</property>
<property name="text">
<string/>
</property>
<property name="default">
<bool>false</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QPushButton" name="pushButton_2">
<property name="toolTip">
<string>Copy to clipboard</string>
</property>
<property name="text">
<string/>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QLabel" name="label_7">
<property name="text">
<string notr="true">&lt;code&gt;sudo systemctl unmask ckb-next-daemon&lt;/code&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::TextFormat::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextInteractionFlag::LinksAccessibleByKeyboard|Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextBrowserInteraction|Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="5" column="1" colspan="3">
<widget class="QLabel" name="label_6">
<property name="text">
<string>If &quot;Unit ckb-next-daemon.service is masked&quot;, unmask it first and try again:</string>
</property>
</widget>
</item>
<item row="7" column="1" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Ok</set>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Start it once with:</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QLabel" name="label">
<property name="text">
<string>The ckb-next daemon is not running. This program will &lt;b&gt;not&lt;/b&gt; work without it!</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string notr="true">&lt;code&gt;sudo systemctl start ckb-next-daemon&lt;/code&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::TextFormat::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextInteractionFlag::LinksAccessibleByKeyboard|Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextBrowserInteraction|Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="1" colspan="3">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Enable it for every boot:</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QLabel" name="label_5">
<property name="text">
<string notr="true">&lt;code&gt;sudo systemctl enable ckb-next-daemon&lt;/code&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::TextFormat::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextInteractionFlag::LinksAccessibleByKeyboard|Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextBrowserInteraction|Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DaemonWarnDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>286</x>
<y>279</y>
</hint>
<hint type="destinationlabel">
<x>445</x>
<y>293</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>accept()</slot>
</slots>
</ui>
+3 -20
View File
@@ -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 <b>not</b> work without it!"));
#ifndef Q_OS_MACOS
QString daemonDialogText = tr("Start it once with:") +
"<blockquote><code>sudo systemctl start ckb-next-daemon</code></blockquote>" +
tr("Enable it for every boot:") +
"<blockquote><code>sudo systemctl enable ckb-next-daemon</code></blockquote><br>" +
tr("If \"Unit ckb-next-daemon.service is masked.\", unmask it first and try again:") +
"<blockquote><code>sudo systemctl unmask ckb-next-daemon</code></blockquote>";
#else
QString daemonDialogText = QString(tr("Start and enable it with:")) +
"<blockquote><code>sudo launchctl load -w /Library/LaunchDaemons/org.ckb-next.daemon.plist</code></blockquote>";
#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())