diff --git a/src/lib/common/Settings.cpp b/src/lib/common/Settings.cpp index fb1b66970..cb2c97eca 100644 --- a/src/lib/common/Settings.cpp +++ b/src/lib/common/Settings.cpp @@ -174,11 +174,15 @@ QString Settings::cleanComputerName(const QString &name) return cleanName; } -void Settings::checkIfSettingsWritableChange() const +void Settings::checkIfSettingsWritableChange() { - bool writable = m_settings->isWritable(); + if (!instance()->m_settingsWatcher->files().contains(Settings::settingsFile())) + m_settingsWatcher->addPath(Settings::settingsFile()); + + bool writable = Settings::isWritable(); if (writable == m_settingsWritable) return; + qDebug() << QString("Setting are now %1").arg(writable ? "writable" : "readonly"); instance()->m_settingsWritable = writable; Q_EMIT instance()->settingsWritableChanged(writable); } diff --git a/src/lib/common/Settings.h b/src/lib/common/Settings.h index 7aad23cf4..ede0e1648 100644 --- a/src/lib/common/Settings.h +++ b/src/lib/common/Settings.h @@ -233,7 +233,7 @@ private: * @brief checkIfSettingsWritableChange * Checks if the changed settings is now read only */ - void checkIfSettingsWritableChange() const; + void checkIfSettingsWritableChange(); QSettings *m_settings = nullptr; QSettings *m_stateSettings = nullptr; diff --git a/src/lib/gui/CMakeLists.txt b/src/lib/gui/CMakeLists.txt index 5dd9cafe6..b0e096dcb 100644 --- a/src/lib/gui/CMakeLists.txt +++ b/src/lib/gui/CMakeLists.txt @@ -120,6 +120,8 @@ add_library(${target} STATIC widgets/StatusBar.h widgets/TrashScreenWidget.cpp widgets/TrashScreenWidget.h + widgets/SettingsDialogButtonBox.cpp + widgets/SettingsDialogButtonBox.h ) target_link_libraries(${target} diff --git a/src/lib/gui/dialogs/SettingsDialog.cpp b/src/lib/gui/dialogs/SettingsDialog.cpp index eb655837f..cfc15087c 100644 --- a/src/lib/gui/dialogs/SettingsDialog.cpp +++ b/src/lib/gui/dialogs/SettingsDialog.cpp @@ -15,6 +15,7 @@ #include "common/Settings.h" #include "gui/TlsUtility.h" #include "gui/core/NetworkMonitor.h" +#include "gui/widgets/SettingsDialogButtonBox.h" #include #include @@ -26,10 +27,12 @@ using namespace deskflow::gui; SettingsDialog::SettingsDialog(QWidget *parent, const ServerConfig &serverConfig) : QDialog(parent), ui{std::make_unique()}, - m_serverConfig(serverConfig) + m_serverConfig(serverConfig), + m_buttonBox{new SettingsDialogButtonBox(this)} { ui->setupUi(this); + layout()->addWidget(m_buttonBox); ui->tabWidget->setCurrentIndex(0); // these are enabled by the control next to them @@ -93,15 +96,10 @@ void SettingsDialog::changeEvent(QEvent *e) void SettingsDialog::initConnections() const { - connect(this, &SettingsDialog::shown, this, &SettingsDialog::showReadOnlyMessage, Qt::QueuedConnection); - - connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &SettingsDialog::accept); - connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); - connect(ui->buttonBox->button(QDialogButtonBox::Reset), &QPushButton::clicked, this, &SettingsDialog::loadFromConfig); - connect( - ui->buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, this, - &SettingsDialog::resetToDefault - ); + connect(m_buttonBox, &SettingsDialogButtonBox::accepted, this, &SettingsDialog::accept); + connect(m_buttonBox, &SettingsDialogButtonBox::rejected, this, &QDialog::reject); + connect(m_buttonBox, &SettingsDialogButtonBox::reset, this, &SettingsDialog::loadFromConfig); + connect(m_buttonBox, &SettingsDialogButtonBox::restoreDefault, this, &SettingsDialog::resetToDefault); connect(ui->cbRunEnterCommand, &QCheckBox::toggled, ui->lineCommandEnter, &QLineEdit::setEnabled); connect(ui->cbRunExitCommand, &QCheckBox::toggled, ui->lineCommandExit, &QLineEdit::setEnabled); @@ -144,6 +142,7 @@ void SettingsDialog::initConnections() const connect(ui->cbRunExitCommand, &QCheckBox::toggled, this, &SettingsDialog::setButtonBoxEnabledButtons); connect(ui->lineCommandEnter, &QLineEdit::textChanged, this, &SettingsDialog::setButtonBoxEnabledButtons); connect(ui->lineCommandExit, &QLineEdit::textChanged, this, &SettingsDialog::setButtonBoxEnabledButtons); + connect(Settings::instance(), &Settings::settingsWritableChanged, this, &SettingsDialog::updateControls); } void SettingsDialog::regenCertificates() @@ -194,17 +193,6 @@ void SettingsDialog::showEvent(QShowEvent *event) Q_EMIT shown(); } -void SettingsDialog::showReadOnlyMessage() -{ - if (Settings::isWritable()) - return; - QMessageBox::information( - this, tr("%1 Read-only settings").arg(kAppName), - tr("

Settings are read-only because you only have read access to the file:

%1

") - .arg(QDir::toNativeSeparators(Settings::settingsFile())) - ); -} - void SettingsDialog::resetAllSettings() { auto result = QMessageBox::question( @@ -234,10 +222,6 @@ void SettingsDialog::updateText() ui->comboLogLevel->setItemData(i, toolTips.at(i), Qt::ToolTipRole); } } - ui->buttonBox->button(QDialogButtonBox::Save)->setToolTip(tr("Close and save changes")); - ui->buttonBox->button(QDialogButtonBox::Cancel)->setToolTip(tr("Close and forget changes")); - ui->buttonBox->button(QDialogButtonBox::Reset)->setToolTip(tr("Reset to stored values")); - ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setToolTip(tr("Reset to default values")); } void SettingsDialog::accept() @@ -390,8 +374,6 @@ void SettingsDialog::updateControls() const bool serviceChecked = ui->groupService->isChecked(); const bool logToFile = ui->groupLogToFile->isChecked(); - ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(writable); - ui->sbPort->setEnabled(writable); ui->comboInterface->setEnabled(writable); ui->comboLogLevel->setEnabled(writable); @@ -551,9 +533,9 @@ void SettingsDialog::resetToDefault() void SettingsDialog::setButtonBoxEnabledButtons() const { const bool modified = isModified(); - ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(modified); - ui->buttonBox->button(QDialogButtonBox::Reset)->setEnabled(modified); - ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setEnabled(!isDefault()); + m_buttonBox->enableSave(modified); + m_buttonBox->enableReset(modified); + m_buttonBox->enableRestoreDefaults(!isDefault()); } SettingsDialog::~SettingsDialog() = default; diff --git a/src/lib/gui/dialogs/SettingsDialog.h b/src/lib/gui/dialogs/SettingsDialog.h index b6a8e6a55..354e71e86 100644 --- a/src/lib/gui/dialogs/SettingsDialog.h +++ b/src/lib/gui/dialogs/SettingsDialog.h @@ -1,6 +1,6 @@ /* * Deskflow -- mouse and keyboard sharing utility - * SPDX-FileCopyrightText: (C) 2025 Deskflow Developers + * SPDX-FileCopyrightText: (C) 2025 - 2026 Deskflow Developers * SPDX-FileCopyrightText: (C) 2012 Synergy App Ltd * SPDX-FileCopyrightText: (C) 2008 Volker Lanz * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception @@ -11,6 +11,8 @@ #include "gui/config/ServerConfig.h" +class SettingsDialogButtonBox; + namespace Ui { class SettingsDialog; } @@ -42,7 +44,6 @@ private: bool isClientMode() const; void updateTlsControls(); void updateTlsControlsEnabled(); - void showReadOnlyMessage(); void resetAllSettings(); void updateText(); @@ -87,4 +88,5 @@ private: bool m_interfaceSetOnLoad = false; std::unique_ptr ui; const ServerConfig &m_serverConfig; + SettingsDialogButtonBox *m_buttonBox = nullptr; }; diff --git a/src/lib/gui/dialogs/SettingsDialog.ui b/src/lib/gui/dialogs/SettingsDialog.ui index 051a81096..3c177bb95 100644 --- a/src/lib/gui/dialogs/SettingsDialog.ui +++ b/src/lib/gui/dialogs/SettingsDialog.ui @@ -7,7 +7,7 @@ 0 0 490 - 366 + 326 @@ -864,16 +864,6 @@ - - - - Qt::Orientation::Horizontal - - - QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Reset|QDialogButtonBox::StandardButton::RestoreDefaults|QDialogButtonBox::StandardButton::Save - - - diff --git a/src/lib/gui/widgets/SettingsDialogButtonBox.cpp b/src/lib/gui/widgets/SettingsDialogButtonBox.cpp new file mode 100644 index 000000000..cc9eb099e --- /dev/null +++ b/src/lib/gui/widgets/SettingsDialogButtonBox.cpp @@ -0,0 +1,97 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2026 Deskflow Developers + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ + +#include "SettingsDialogButtonBox.h" +#include "common/Settings.h" + +#include +#include +#include +#include +#include +#include + +SettingsDialogButtonBox::SettingsDialogButtonBox(QWidget *parent) + : QWidget{parent}, + m_buttonBox{new QDialogButtonBox(this)}, + m_lblText{new QLabel(this)}, + m_lblIcon{new QLabel(this)} +{ + m_lblIcon->setPixmap(QIcon::fromTheme(QIcon::ThemeIcon::DialogWarning).pixmap(24, 24)); + m_buttonBox->addButton(QDialogButtonBox::Save); + m_buttonBox->addButton(QDialogButtonBox::Cancel); + m_buttonBox->addButton(QDialogButtonBox::Reset); + m_buttonBox->addButton(QDialogButtonBox::RestoreDefaults); + settingsWritableChanged(Settings::isWritable()); + + auto layout = new QHBoxLayout(this); + layout->addWidget(m_lblIcon); + layout->addWidget(m_lblText); + layout->addWidget(m_buttonBox); + setLayout(layout); + + updateText(); + + connect(m_buttonBox, &QDialogButtonBox::accepted, this, &SettingsDialogButtonBox::accepted); + connect(m_buttonBox, &QDialogButtonBox::rejected, this, &SettingsDialogButtonBox::rejected); + connect(m_buttonBox->button(QDialogButtonBox::Reset), &QPushButton::clicked, this, &SettingsDialogButtonBox::reset); + connect( + m_buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, this, + &SettingsDialogButtonBox::restoreDefault + ); + connect( + Settings::instance(), &Settings::settingsWritableChanged, this, &SettingsDialogButtonBox::settingsWritableChanged + ); +} + +void SettingsDialogButtonBox::enableSave(bool enable) const +{ + m_buttonBox->button(QDialogButtonBox::Save)->setEnabled(enable); +} + +void SettingsDialogButtonBox::enableReset(bool enable) const +{ + m_buttonBox->button(QDialogButtonBox::Reset)->setEnabled(enable); +} + +void SettingsDialogButtonBox::enableRestoreDefaults(bool enable) const +{ + m_buttonBox->button(QDialogButtonBox::RestoreDefaults)->setEnabled(enable); +} + +void SettingsDialogButtonBox::changeEvent(QEvent *e) +{ + QWidget::changeEvent(e); + if (e->type() == QEvent::LanguageChange) + updateText(); +} + +void SettingsDialogButtonBox::updateText() +{ + m_lblText->setText(tr("Settings are read only")); + m_lblText->setToolTip(tr("%1 is not writable").arg(Settings::settingsFile())); + + m_buttonBox->button(QDialogButtonBox::Save)->setToolTip(tr("Close and save changes")); + m_buttonBox->button(QDialogButtonBox::Cancel)->setToolTip(tr("Close and forget changes")); + m_buttonBox->button(QDialogButtonBox::Reset)->setToolTip(tr("Reset to stored values")); + m_buttonBox->button(QDialogButtonBox::RestoreDefaults)->setToolTip(tr("Reset to default values")); +} + +void SettingsDialogButtonBox::settingsWritableChanged(bool writable) +{ + // Hide all first to prevent any change in overall width + m_lblIcon->setVisible(false); + m_lblText->setVisible(false); + m_buttonBox->button(QDialogButtonBox::Save)->setVisible(false); + m_buttonBox->button(QDialogButtonBox::Reset)->setVisible(false); + m_buttonBox->button(QDialogButtonBox::RestoreDefaults)->setVisible(false); + + m_lblIcon->setVisible(!writable); + m_lblText->setVisible(!writable); + m_buttonBox->button(QDialogButtonBox::Save)->setVisible(writable); + m_buttonBox->button(QDialogButtonBox::Reset)->setVisible(writable); + m_buttonBox->button(QDialogButtonBox::RestoreDefaults)->setVisible(writable); +} diff --git a/src/lib/gui/widgets/SettingsDialogButtonBox.h b/src/lib/gui/widgets/SettingsDialogButtonBox.h new file mode 100644 index 000000000..23266f31f --- /dev/null +++ b/src/lib/gui/widgets/SettingsDialogButtonBox.h @@ -0,0 +1,37 @@ +/* + * Deskflow -- mouse and keyboard sharing utility + * SPDX-FileCopyrightText: (C) 2026 Deskflow Developers + * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception + */ + +#pragma once + +#include + +class QLabel; +class QDialogButtonBox; + +class SettingsDialogButtonBox : public QWidget +{ + Q_OBJECT +public: + explicit SettingsDialogButtonBox(QWidget *parent = nullptr); + void enableSave(bool enable) const; + void enableReset(bool enable) const; + void enableRestoreDefaults(bool enable) const; +Q_SIGNALS: + void accepted(); + void rejected(); + void reset(); + void restoreDefault(); + +protected: + void changeEvent(QEvent *e) override; + +private: + void updateText(); + void settingsWritableChanged(bool writable); + QDialogButtonBox *m_buttonBox = nullptr; + QLabel *m_lblText = nullptr; + QLabel *m_lblIcon = nullptr; +}; diff --git a/translations/deskflow_es.ts b/translations/deskflow_es.ts index 6a9334a22..093c87e22 100644 --- a/translations/deskflow_es.ts +++ b/translations/deskflow_es.ts @@ -1159,14 +1159,6 @@ Al habilitar esta opción, se deshabilitará la interfaz gráfica de usuario (GU <p>Are you sure you want to clear all settings and restart %1?</p> <p>This action cannot be undone.</p> - - %1 Read-only settings - %1 Configuración de solo lectura - - - <p>Settings are read-only because you only have read access to the file:</p><p>%1</p> - <p>Las configuraciones son de solo lectura porque solo tiene acceso de lectura al archivo:</p><p>%1</p> - Required messages Mensajes obligatorios @@ -1191,22 +1183,6 @@ Al habilitar esta opción, se deshabilitará la interfaz gráfica de usuario (GU Verbose debug output Salida de depuración detallada - - Close and save changes - Cerrar y guardar los cambios - - - Close and forget changes - Cerrar y olvidar los cambios - - - Reset to stored values - Restablecer los valores almacenados - - - Reset to default values - Restablecer valores predeterminados - TLS Certificate Regenerated Certificado TLS regenerado @@ -1296,6 +1272,33 @@ Al habilitar esta opción, se deshabilitará la interfaz gráfica de usuario (GU Eliminar todas las configuraciones + + SettingsDialogButtonBox + + Settings are read only + La configuración es de solo lectura + + + %1 is not writable + %1 no tiene permisos de escritura + + + Close and save changes + Cerrar y guardar los cambios + + + Close and forget changes + Cerrar y olvidar los cambios + + + Reset to stored values + Restablecer los valores almacenados + + + Reset to default values + Restablecer valores predeterminados + + StatusBar diff --git a/translations/deskflow_it.ts b/translations/deskflow_it.ts index 46ae2f298..509784fe4 100644 --- a/translations/deskflow_it.ts +++ b/translations/deskflow_it.ts @@ -1159,14 +1159,6 @@ L'abilitazione di questa impostazione disabiliterà l'interfaccia graf <p>Are you sure you want to clear all settings and restart %1?</p> <p>This action cannot be undone.</p> - - %1 Read-only settings - %1 Impostazioni di sola lettura - - - <p>Settings are read-only because you only have read access to the file:</p><p>%1</p> - <p>Le impostazioni sono di sola lettura perché hai solo accesso in lettura al file:</p><p>%1</p> - Required messages Messaggi richiesti @@ -1191,22 +1183,6 @@ L'abilitazione di questa impostazione disabiliterà l'interfaccia graf Verbose debug output Output di debug dettagliato - - Close and save changes - Chiudi e salva le modifiche - - - Close and forget changes - Chiudi e dimentica le modifiche - - - Reset to stored values - Ripristina i valori memorizzati - - - Reset to default values - Ripristina i valori predefiniti - TLS Certificate Regenerated Certificato TLS rigenerato @@ -1296,6 +1272,33 @@ L'abilitazione di questa impostazione disabiliterà l'interfaccia graf Rimuovi tutte le impostazioni + + SettingsDialogButtonBox + + Settings are read only + Le impostazioni sono di sola lettura + + + %1 is not writable + %1 non è scrivibile + + + Close and save changes + Chiudi e salva le modifiche + + + Close and forget changes + Chiudi e dimentica le modifiche + + + Reset to stored values + Ripristina i valori memorizzati + + + Reset to default values + Ripristina i valori predefiniti + + StatusBar diff --git a/translations/deskflow_ja.ts b/translations/deskflow_ja.ts index a637d5000..c11e8b9b7 100644 --- a/translations/deskflow_ja.ts +++ b/translations/deskflow_ja.ts @@ -1185,14 +1185,6 @@ Enabling this setting will disable the server config GUI. <p>Are you sure you want to clear all settings and restart %1?</p> <p>This action cannot be undone.</p> - - %1 Read-only settings - %1 読み取り専用設定 - - - <p>Settings are read-only because you only have read access to the file:</p><p>%1</p> - <p>以下のファイルへの書き込み権限がないため、設定は読み取り専用です:</p><p>%1</p> - Required messages 必須のメッセージ @@ -1217,22 +1209,6 @@ Enabling this setting will disable the server config GUI. Verbose debug output 詳細なデバッグ出力 - - Close and save changes - 変更を保存して閉じる - - - Close and forget changes - 変更を破棄して閉じる - - - Reset to stored values - 変更前の値にリセットする - - - Reset to default values - デフォルト値にリセットする - Automatic 自動 @@ -1298,6 +1274,33 @@ Enabling this setting will disable the server config GUI. すべての設定を削除する + + SettingsDialogButtonBox + + Settings are read only + 設定は読み取り専用です + + + %1 is not writable + %1 は書き込み可能ではありません + + + Close and save changes + 変更を保存して閉じる + + + Close and forget changes + 変更を破棄して閉じる + + + Reset to stored values + 変更前の値にリセットする + + + Reset to default values + デフォルト値にリセットする + + StatusBar diff --git a/translations/deskflow_ko.ts b/translations/deskflow_ko.ts index e434b92b3..c46dad56a 100644 --- a/translations/deskflow_ko.ts +++ b/translations/deskflow_ko.ts @@ -1183,14 +1183,6 @@ Enabling this setting will disable the server config GUI. <p>Are you sure you want to clear all settings and restart %1?</p> <p>This action cannot be undone.</p> - - %1 Read-only settings - %1 읽기 전용 설정 - - - <p>Settings are read-only because you only have read access to the file:</p><p>%1</p> - <p>다음 파일에 대한 쓰기 권한이 없어 설정이 읽기 전용입니다:</p><p>%1</p> - Required messages 필수 메시지 @@ -1215,22 +1207,6 @@ Enabling this setting will disable the server config GUI. Verbose debug output 상세 디버그 출력 - - Close and save changes - 변경 사항 저장 후 닫기 - - - Close and forget changes - 저장하지 않고 닫기 - - - Reset to stored values - 저장된 값으로 재설정 - - - Reset to default values - 기본값으로 재설정 - Automatic 자동 @@ -1296,6 +1272,33 @@ Enabling this setting will disable the server config GUI. 모든 설정 제거 + + SettingsDialogButtonBox + + Settings are read only + 설정은 읽기 전용입니다 + + + %1 is not writable + %1은(는) 쓰기 가능하지 않습니다 + + + Close and save changes + 변경 사항 저장 후 닫기 + + + Close and forget changes + 저장하지 않고 닫기 + + + Reset to stored values + 저장된 값으로 재설정 + + + Reset to default values + 기본값으로 재설정 + + StatusBar diff --git a/translations/deskflow_ru.ts b/translations/deskflow_ru.ts index 180f1a374..e39cf17ad 100644 --- a/translations/deskflow_ru.ts +++ b/translations/deskflow_ru.ts @@ -1181,14 +1181,6 @@ Enabling this setting will disable the server config GUI. <p>Are you sure you want to clear all settings and restart %1?</p> <p>This action cannot be undone.</p> - - %1 Read-only settings - %1 Настройки только для чтения - - - <p>Settings are read-only because you only have read access to the file:</p><p>%1</p> - <p>Настройки доступны только для чтения, так как у вас есть доступ только на чтение к файлу:</p><p>%1</p> - Required messages Обязательные сообщения @@ -1213,22 +1205,6 @@ Enabling this setting will disable the server config GUI. Verbose debug output Подробный вывод отладки - - Close and save changes - Закрыть и сохранить изменения - - - Close and forget changes - Закройте изменения и забудьте о них - - - Reset to stored values - Сбросить до сохраненных значений - - - Reset to default values - Сбросить до значений по умолчанию - Automatic Автоматически @@ -1294,6 +1270,33 @@ Enabling this setting will disable the server config GUI. Удалить все настройки + + SettingsDialogButtonBox + + Settings are read only + Настройки доступны только для чтения + + + %1 is not writable + %1 недоступен для записи + + + Close and save changes + Закрыть и сохранить изменения + + + Close and forget changes + Закройте изменения и забудьте о них + + + Reset to stored values + Сбросить до сохраненных значений + + + Reset to default values + Сбросить до значений по умолчанию + + StatusBar diff --git a/translations/deskflow_zh_CN.ts b/translations/deskflow_zh_CN.ts index bc026fe9d..fb9a4387d 100644 --- a/translations/deskflow_zh_CN.ts +++ b/translations/deskflow_zh_CN.ts @@ -1185,14 +1185,6 @@ Enabling this setting will disable the server config GUI. <p>Are you sure you want to clear all settings and restart %1?</p> <p>This action cannot be undone.</p> - - %1 Read-only settings - %1 只读设置 - - - <p>Settings are read-only because you only have read access to the file:</p><p>%1</p> - <p>设置是只读的,因为您对该文件只有读取权限:</p><p>%1</p> - Required messages 必要消息 @@ -1217,22 +1209,6 @@ Enabling this setting will disable the server config GUI. Verbose debug output 详细调试输出 - - Close and save changes - 关闭并保存更改 - - - Close and forget changes - 关闭并放弃修改 - - - Reset to stored values - 重置为存储值 - - - Reset to default values - 重置为默认值 - Automatic 自动的 @@ -1298,6 +1274,33 @@ Enabling this setting will disable the server config GUI. 移除所有设置 + + SettingsDialogButtonBox + + Settings are read only + 设置仅为只读 + + + %1 is not writable + %1 不可写入 + + + Close and save changes + 关闭并保存更改 + + + Close and forget changes + 关闭并放弃修改 + + + Reset to stored values + 重置为存储值 + + + Reset to default values + 重置为默认值 + + StatusBar