10#include <QAbstractButton>
11#include <QDialogButtonBox>
16#include <QStackedWidget>
27const int kListMinimumWidth = 120;
28const int kListMaximumWidth = 240;
30const int kIconSize = 24;
34QxSettingsDialogPrivate::QxSettingsDialogPrivate() =
default;
36void QxSettingsDialogPrivate::init()
40 QVBoxLayout *outer =
new QVBoxLayout(q);
42 QHBoxLayout *body =
new QHBoxLayout();
43 outer->addLayout(body, 1);
45 m_list =
new QListWidget(q);
46 m_list->setIconSize(QSize(kIconSize, kIconSize));
47 m_list->setUniformItemSizes(
true);
48 m_list->setMinimumWidth(kListMinimumWidth);
49 m_list->setMaximumWidth(kListMaximumWidth);
52 m_list->setFocusPolicy(Qt::NoFocus);
53 body->addWidget(m_list);
55 m_stack =
new QStackedWidget(q);
56 body->addWidget(m_stack, 1);
58 QObject::connect(m_list, &QListWidget::currentRowChanged, q, [
this, q](
int row) {
59 if (row < 0 || row >= m_pages.count()) {
62 m_stack->setCurrentIndex(row);
63 Q_EMIT q->currentPageChanged(m_pages.at(row).id);
66 m_buttons =
new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply |
67 QDialogButtonBox::RestoreDefaults,
69 outer->addWidget(m_buttons);
73 QObject::connect(m_buttons, &QDialogButtonBox::accepted, q, [q]() {
76 QObject::connect(m_buttons, &QDialogButtonBox::rejected, q, [q]() {
81 QObject::connect(m_buttons->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, q, [q]() {
84 QObject::connect(m_buttons->button(QDialogButtonBox::RestoreDefaults), &QAbstractButton::clicked, q, [q]() {
91int QxSettingsDialogPrivate::indexOf(
const QString &
id)
const
93 for (
int i = 0; i < m_pages.count(); ++i) {
94 if (m_pages.at(i).id ==
id) {
101void QxSettingsDialogPrivate::loadPage(
const Page &page)
103 if (!page.
editor || !m_settings) {
107 QHash<QString, QVariant> values;
111 values.insert(property.key, m_settings->value(property.key, property.defaultValue));
116void QxSettingsDialogPrivate::load()
118 for (
const Page &page : m_pages) {
123void QxSettingsDialogPrivate::write()
const
129 for (
const Page &page : m_pages) {
133 const QHash<QString, QVariant> values = page.editor->allValues();
134 for (
auto it = values.constBegin(); it != values.constEnd(); ++it) {
135 m_settings->setValue(it.key(), it.value());
141bool QxSettingsDialogPrivate::isModified()
const
143 for (
const Page &page : m_pages) {
144 if (page.editor && page.editor->isModified()) {
151void QxSettingsDialogPrivate::updateButtons()
156 if (QAbstractButton *apply = m_buttons->button(QDialogButtonBox::Apply)) {
157 apply->setEnabled(isModified());
161QxSettingsDialog::QxSettingsDialog(
QxSettings *settings, QWidget *parent)
179 return d->m_settings;
183 const QList<QxProperty> &properties)
188 qWarning(
"QxSettingsDialog: a page needs a non-empty id");
191 if (d->indexOf(
id) >= 0) {
192 qWarning(
"QxSettingsDialog: a page with id '%s' already exists", qPrintable(
id));
197 d->m_stack->addWidget(
editor);
198 for (
const QxProperty &property : properties) {
204 new QListWidgetItem(icon, title, d->m_list);
211 d->m_pages.append(page);
217 d->loadPage(d->m_pages.last());
218 if (d->m_pages.count() == 1) {
220 d->m_list->setCurrentRow(0);
221 d->m_stack->setCurrentIndex(0);
230 const int index = d->indexOf(pageId);
232 qWarning(
"QxSettingsDialog: there is no page with id '%s'", qPrintable(pageId));
238 d->m_pages[index].properties.append(properties);
241 d->loadPage(d->m_pages.at(index));
258 const int index = d->indexOf(pageId);
259 return index < 0 ?
Q_NULLPTR : d->m_pages.at(index).editor;
265 const int index = d->m_stack->currentIndex();
266 if (index < 0 || index >= d->m_pages.count()) {
269 return d->m_pages.at(index).id;
275 return d->isModified();
290 page.editor->reset();
300 if (!d->m_settings) {
301 qWarning(
"QxSettingsDialog: there is no settings object to apply to");
311 page.editor->setAllValues(page.editor->allValues());
321 const int index = d->indexOf(
id);
326 d->m_list->setCurrentRow(index);
342 page.editor->resetToInitial();
357 QDialog::showEvent(event);
A form built from a list of QxProperty descriptors.
void setAllValues(const QHash< QString, QVariant > &values)
Sets every key of values that this editor knows and takes the result as the new baseline,...
void addGroup(const QString &title, const QList< QxProperty > &properties)
Opens a section titled title and adds properties to it.
void addProperty(const QxProperty &property)
Adds property to the section the last addGroup() opened, or to the plain form when there is none yet.
void modifiedChanged(bool modified)
isModified() changed.
The state behind QxSettingsDialog: the pages, the settings object they are read from and written to,...
A settings dialog: a list of pages on the left, a key/value form on the right and the three things a ...
void applied()
The values have been written and synced.
QString currentPageId() const
void reject() override
Discards the edits and closes.
void addGroup(const QString &pageId, const QString &title, const QList< QxProperty > &properties)
Opens a group inside the page pageId and adds properties to it.
void accept() override
Applies and closes.
void reload()
Reads every page back out of the settings object; the dialog does this itself whenever it is shown.
void showEvent(QShowEvent *event) override
void reset()
Sets every property of every page back to the default its descriptor declares.
QxPropertyEditor * editor(const QString &pageId) const
The form of the page pageId, or null when there is no such page.
bool isModified() const
Whether anything on any page differs from what it was loaded as.
void apply()
Writes every value to the settings object and syncs it.
void setCurrentPage(const QString &id)
~QxSettingsDialog() override
QStringList pageIds() const
void addPage(const QString &id, const QIcon &icon, const QString &title, const QList< QxProperty > &properties)
Adds a page: an entry in the list on the left and a form on the right holding properties.
QxCore::QxSettings * settings() const
Thin wrapper around QSettings that keeps call sites free of the usual boilerplate: typed accessors wi...
#define QX_APP_END_NAMESPACE
#define Q_NULLPTR
Copyleft (C) 2025 maminjie canpool@163.com SPDX-License-Identifier: MulanPSL-2.0
#define QX_APP_BEGIN_NAMESPACE
#define QX_FINI_PRIVATE()
#define QX_CORE_USE_NAMESPACE
One setting, described well enough to be edited.
QxPropertyEditor * editor
QList< QxProperty > properties