├── README.md
├── setting_tools.ico
├── de_skycoder42_qtmvvm_settings_widgets.qrc
├── de_skycoder42_qtmvvm_settings_widgets.pri
├── .gitignore
├── qtmvvm_settings_widgets_de.ts
├── qtmvvm_settings_widgets_template.ts
├── qpm.json
├── qpmx.json
├── LICENSE
├── settingsdialog.h
├── settingsdialog.ui
└── settingsdialog.cpp
/README.md:
--------------------------------------------------------------------------------
1 | # QtMvvmSettingsWidgets
2 |
3 | Has been replaced by https://github.com/Skycoder42/QtMvvm
4 |
--------------------------------------------------------------------------------
/setting_tools.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Skycoder42/QtMvvmSettingsWidgets/master/setting_tools.ico
--------------------------------------------------------------------------------
/de_skycoder42_qtmvvm_settings_widgets.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | setting_tools.ico
4 |
5 |
6 |
--------------------------------------------------------------------------------
/de_skycoder42_qtmvvm_settings_widgets.pri:
--------------------------------------------------------------------------------
1 | HEADERS += $$PWD/settingsdialog.h
2 |
3 | SOURCES += $$PWD/settingsdialog.cpp
4 |
5 | FORMS += $$PWD/settingsdialog.ui
6 |
7 | RESOURCES += $$PWD/de_skycoder42_qtmvvm_settings_widgets.qrc
8 |
9 | TRANSLATIONS += $$PWD/qtmvvm_settings_widgets_de.ts \
10 | $$PWD/qtmvvm_settings_widgets_template.ts
11 |
12 | INCLUDEPATH += $$PWD
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # C++ objects and libs
2 |
3 | *.slo
4 | *.lo
5 | *.o
6 | *.a
7 | *.la
8 | *.lai
9 | *.so
10 | *.dll
11 | *.dylib
12 |
13 | # Qt-es
14 |
15 | /.qmake.cache
16 | /.qmake.stash
17 | *.pro.user
18 | *.pro.user.*
19 | *.qbs.user
20 | *.qbs.user.*
21 | *.moc
22 | moc_*.cpp
23 | qrc_*.cpp
24 | ui_*.h
25 | Makefile*
26 | *build-*
27 |
28 | # QtCreator
29 |
30 | *.autosave
31 |
32 | # QtCtreator Qml
33 | *.qmlproject.user
34 | *.qmlproject.user.*
35 |
36 | # QtCtreator CMake
37 | CMakeLists.txt.user
38 |
39 | #qpm
40 | vendor
--------------------------------------------------------------------------------
/qtmvvm_settings_widgets_de.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SettingsDialog
6 |
7 |
8 | Settings
9 | Einstellungen
10 |
11 |
12 |
13 | Search in settings…
14 | In Einstellungen suchen…
15 |
16 |
17 |
18 | :
19 | :
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/qtmvvm_settings_widgets_template.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SettingsDialog
6 |
7 |
8 | Settings
9 |
10 |
11 |
12 |
13 | Search in settings…
14 |
15 |
16 |
17 |
18 | :
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/qpm.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": {
3 | "email": "skycoder42.de@gmx.de",
4 | "name": "Skycoder"
5 | },
6 | "dependencies": [
7 | "de.skycoder42.qtmvvm.settings.core@1.1.2",
8 | "de.skycoder42.qtmvvm.widgets@1.1.2"
9 | ],
10 | "description": "The widgets frontend of QtMvvm settings module",
11 | "license": "BSD_3_CLAUSE",
12 | "name": "de.skycoder42.qtmvvm.settings.widgets",
13 | "pri_filename": "de_skycoder42_qtmvvm_settings_widgets.pri",
14 | "repository": {
15 | "type": "GITHUB",
16 | "url": "https://github.com/Skycoder42/QtMvvmSettingsWidgets.git"
17 | },
18 | "version": {
19 | "fingerprint": "",
20 | "label": "1.1.3",
21 | "revision": ""
22 | },
23 | "webpage": "https://github.com/Skycoder42/QtMvvm"
24 | }
25 |
--------------------------------------------------------------------------------
/qpmx.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": [
3 | {
4 | "package": "de.skycoder42.qtmvvm.settings.core",
5 | "provider": "qpm",
6 | "version": "1.1.2"
7 | },
8 | {
9 | "package": "de.skycoder42.qtmvvm.widgets",
10 | "provider": "qpm",
11 | "version": "1.1.2"
12 | }
13 | ],
14 | "license": {
15 | "file": "LICENSE",
16 | "name": "BSD_3_CLAUSE"
17 | },
18 | "prcFile": "",
19 | "priFile": "de_skycoder42_qtmvvm_settings_widgets.pri",
20 | "priIncludes": [
21 | ],
22 | "publishers": {
23 | "qpm": {
24 | "author": {
25 | "email": "skycoder42.de@gmx.de",
26 | "name": "Skycoder"
27 | },
28 | "description": "The widgets frontend of QtMvvm settings module",
29 | "name": "de.skycoder42.qtmvvm.settings.widgets",
30 | "repository": {
31 | "type": "GITHUB",
32 | "url": "https://github.com/Skycoder42/QtMvvmSettingsWidgets.git"
33 | },
34 | "webpage": "https://github.com/Skycoder42/QtMvvm"
35 | }
36 | },
37 | "source": false
38 | }
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2017, Felix Barz
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/settingsdialog.h:
--------------------------------------------------------------------------------
1 | #ifndef SETTINGSDIALOG_H
2 | #define SETTINGSDIALOG_H
3 |
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | namespace Ui {
18 | class SettingsDialog;
19 | }
20 |
21 | class CategoryItemDelegate : public QStyledItemDelegate
22 | {
23 | public:
24 | CategoryItemDelegate(std::function _updateFunc,
25 | const QSize &_iconSize,
26 | int layoutSpacing,
27 | QObject *parent = nullptr);
28 |
29 | QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
30 |
31 | private:
32 | QSize _iconSize;
33 | std::function _updateFunc;
34 | };
35 |
36 | class SettingsDialog : public QDialog
37 | {
38 | Q_OBJECT
39 |
40 | public:
41 | Q_INVOKABLE SettingsDialog(Control *mControl, QWidget *parent = nullptr);
42 | ~SettingsDialog();
43 |
44 | private slots:
45 | void resetListSize();
46 | void updateWidth(int width);
47 |
48 | void propertyChanged();
49 | void saveValues();
50 | void restoreValues();
51 |
52 | void on_buttonBox_clicked(QAbstractButton *button);
53 | void on_filterLineEdit_textChanged(const QString &searchText);
54 |
55 | private:
56 | SettingsControl *_control;
57 | Ui::SettingsDialog *_ui;
58 | CategoryItemDelegate *_delegate;
59 | int _maxWidthBase;
60 |
61 | typedef QPair EntryInfo;
62 | QHash _entryMap;
63 | QSet _changedEntries;
64 |
65 | int calcSpacing(Qt::Orientation orientation);
66 |
67 | void createUi(const SettingsSetup &setup);
68 | void createCategory(const SettingsCategory &category);
69 | void createSection(const SettingsSection §ion, QTabWidget *tabWidget);
70 | void createGroup(const SettingsGroup &group, QWidget *contentWidget, QFormLayout *layout);
71 | void createEntry(const SettingsEntry &entry, QWidget *sectionWidget, QFormLayout *layout);
72 |
73 | void searchInDialog(const QRegularExpression ®ex);
74 | bool searchInCategory(const QRegularExpression ®ex, QTabWidget *tab);
75 | bool searchInSection(const QRegularExpression ®ex, QWidget *contentWidget);
76 | bool searchInGroup(const QRegularExpression ®ex, QGroupBox *groupWidget);
77 | bool searchInEntry(const QRegularExpression ®ex, QLabel *label, QWidget *content);
78 |
79 | QIcon loadIcon(const QUrl &icon);
80 | };
81 |
82 | #endif // SETTINGSDIALOG_H
83 |
--------------------------------------------------------------------------------
/settingsdialog.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | SettingsDialog
4 |
5 |
6 |
7 | 0
8 | 0
9 | 850
10 | 500
11 |
12 |
13 |
14 | Settings
15 |
16 |
17 | true
18 |
19 |
20 | true
21 |
22 |
23 |
24 | 0
25 |
26 | -
27 |
28 |
29 |
30 | 0
31 |
32 |
33 | 0
34 |
35 |
36 | 0
37 |
38 |
39 | 0
40 |
41 |
42 | 0
43 |
44 |
-
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | 255
53 | 255
54 | 255
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | 255
64 | 255
65 | 255
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | 240
75 | 240
76 | 240
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | QFrame::NoFrame
85 |
86 |
87 | Qt::ScrollBarAsNeeded
88 |
89 |
90 | Qt::ScrollBarAlwaysOff
91 |
92 |
93 | QAbstractItemView::NoEditTriggers
94 |
95 |
96 |
97 | 32
98 | 32
99 |
100 |
101 |
102 | QListView::Adjust
103 |
104 |
105 | 1
106 |
107 |
108 |
109 | -
110 |
111 |
112 | Qt::Vertical
113 |
114 |
115 |
116 | -
117 |
118 |
119 | Qt::Horizontal
120 |
121 |
122 |
123 | 6
124 | 0
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | -
133 |
134 |
-
135 |
136 |
137 | 2
138 |
139 |
-
140 |
141 |
142 |
143 | 10
144 | 75
145 | true
146 |
147 |
148 |
149 | Qt::PlainText
150 |
151 |
152 | 4
153 |
154 |
155 |
156 | -
157 |
158 |
159 |
160 | 0
161 | 0
162 |
163 |
164 |
165 |
166 | 200
167 | 0
168 |
169 |
170 |
171 | Search in settings…
172 |
173 |
174 | true
175 |
176 |
177 |
178 |
179 |
180 | -
181 |
182 |
183 | -
184 |
185 |
186 | Qt::Horizontal
187 |
188 |
189 | QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 | categoryListWidget
201 | currentRowChanged(int)
202 | contentStackWidget
203 | setCurrentIndex(int)
204 |
205 |
206 | 123
207 | 172
208 |
209 |
210 | 488
211 | 189
212 |
213 |
214 |
215 |
216 | categoryListWidget
217 | currentTextChanged(QString)
218 | titleLabel
219 | setText(QString)
220 |
221 |
222 | 156
223 | 42
224 |
225 |
226 | 466
227 | 16
228 |
229 |
230 |
231 |
232 |
233 |
--------------------------------------------------------------------------------
/settingsdialog.cpp:
--------------------------------------------------------------------------------
1 | #include "settingsdialog.h"
2 | #include "ui_settingsdialog.h"
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | static void settingsInit();
13 | Q_COREAPP_STARTUP_FUNCTION(settingsInit)
14 |
15 | #define TAB_CONTENT_NAME QStringLiteral("tabContent_371342666")
16 |
17 | SettingsDialog::SettingsDialog(Control *mControl, QWidget *parent) :
18 | QDialog(parent),
19 | _control(static_cast(mControl)),
20 | _ui(new Ui::SettingsDialog),
21 | _delegate(nullptr),
22 | _maxWidthBase(0),
23 | _entryMap(),
24 | _changedEntries()
25 | {
26 | _ui->setupUi(this);
27 | _ui->buttonBox->button(QDialogButtonBox::Ok)->setAutoDefault(false);
28 | _ui->buttonBox->button(QDialogButtonBox::Cancel)->setAutoDefault(false);
29 | _ui->buttonBox->button(QDialogButtonBox::Apply)->setAutoDefault(false);
30 | _ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setAutoDefault(false);
31 | _ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
32 |
33 | if(parentWidget()) {
34 | setWindowModality(Qt::WindowModal);
35 | setWindowFlags(Qt::Sheet | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint);
36 | } else {
37 | setWindowModality(Qt::ApplicationModal);
38 | setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint);
39 | }
40 |
41 | #ifdef Q_OS_OSX
42 | auto font = _ui->titleLabel->font();
43 | font.setPointSize(16);
44 | _ui->titleLabel->setFont(font);
45 | #endif
46 |
47 | int listSpacing = calcSpacing(Qt::Vertical);
48 | _delegate = new CategoryItemDelegate(std::bind(&SettingsDialog::updateWidth, this, std::placeholders::_1),
49 | _ui->categoryListWidget->iconSize(),
50 | qMax(qRound(listSpacing * (2./3.)), 1),
51 | this);
52 | _ui->categoryListWidget->setItemDelegate(_delegate);
53 | _ui->categoryListWidget->setSpacing(qMax(qRound(listSpacing / 3.), 1) - 1);
54 |
55 | int spacing = calcSpacing(Qt::Horizontal);
56 | _ui->contentLayout->setSpacing(spacing);
57 | _ui->categoryLineSpacer->changeSize(spacing,
58 | 0,
59 | QSizePolicy::Fixed,
60 | QSizePolicy::Fixed);
61 |
62 | createUi(_control->loadSetup("widgets"));
63 | }
64 |
65 | SettingsDialog::~SettingsDialog()
66 | {
67 | delete _ui;
68 | }
69 |
70 | void SettingsDialog::resetListSize()
71 | {
72 | int max = _ui->categoryListWidget->count();
73 | if(max <= 1) {
74 | _ui->categoryContentWidget->hide();
75 | resize(width() - _ui->categoryContentWidget->sizeHint().width(), height());
76 | } else {
77 | auto width = _ui->categoryListWidget->sizeHint().width();
78 | _ui->categoryListWidget->setFixedWidth(width);
79 | _maxWidthBase = width;
80 | }
81 | }
82 |
83 | void SettingsDialog::updateWidth(int width)
84 | {
85 | if(width > _maxWidthBase) {
86 | _maxWidthBase = width;
87 | QStyle *style = _ui->categoryListWidget->style();
88 | width += style->pixelMetric(QStyle::PM_ScrollBarExtent);
89 | width += style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
90 | _ui->categoryListWidget->setFixedWidth(width);
91 | }
92 | }
93 |
94 | void SettingsDialog::propertyChanged()
95 | {
96 | auto widget = qobject_cast(sender());
97 | if(widget)
98 | _changedEntries.insert(widget);
99 | }
100 |
101 | void SettingsDialog::saveValues()
102 | {
103 | for(auto it = _changedEntries.begin(); it != _changedEntries.end();) {
104 | auto widget = *it;
105 | auto info = _entryMap.value(widget);
106 | _control->saveValue(info.first.key, info.second.read(widget));
107 | if(info.second.hasNotifySignal())
108 | it = _changedEntries.erase(it);
109 | else
110 | it++;
111 | }
112 | }
113 |
114 | void SettingsDialog::restoreValues()
115 | {
116 | foreach(auto info, _entryMap)
117 | _control->resetValue(info.first.key);
118 | }
119 |
120 | void SettingsDialog::on_buttonBox_clicked(QAbstractButton *button)
121 | {
122 | switch(_ui->buttonBox->standardButton(button)) {
123 | case QDialogButtonBox::Ok:
124 | saveValues();
125 | accept();
126 | break;
127 | case QDialogButtonBox::Cancel:
128 | reject();
129 | break;
130 | case QDialogButtonBox::Apply:
131 | saveValues();
132 | break;
133 | case QDialogButtonBox::RestoreDefaults:
134 | if(_control->canRestoreDefaults()) {
135 | auto result = CoreMessage::message(_control->restoreConfig());
136 | connect(result, &MessageResult::positiveAction, this, [=](){
137 | restoreValues();
138 | accept();
139 | });
140 | }
141 | break;
142 | default:
143 | Q_UNREACHABLE();
144 | }
145 | }
146 |
147 | void SettingsDialog::on_filterLineEdit_textChanged(const QString &searchText)
148 | {
149 | auto regex = QRegularExpression::escape(searchText);
150 | regex.replace(QStringLiteral("\\*"), QStringLiteral(".*"));
151 | regex.replace(QStringLiteral("\\?"), QStringLiteral("."));
152 | searchInDialog(QRegularExpression(regex, QRegularExpression::CaseInsensitiveOption));
153 | }
154 |
155 | int SettingsDialog::calcSpacing(Qt::Orientation orientation)
156 | {
157 | auto baseSize = style()->pixelMetric(orientation == Qt::Horizontal ?
158 | QStyle::PM_LayoutHorizontalSpacing :
159 | QStyle::PM_LayoutVerticalSpacing);
160 | if(baseSize < 0)
161 | baseSize = style()->layoutSpacing(QSizePolicy::DefaultType, QSizePolicy::DefaultType, orientation);
162 | if(baseSize < 0)
163 | baseSize = style()->layoutSpacing(QSizePolicy::LineEdit, QSizePolicy::LineEdit, orientation);
164 | if(baseSize < 0) {
165 | #ifdef Q_OS_OSX
166 | baseSize = 10;
167 | #else
168 | baseSize = 6;
169 | #endif
170 | }
171 |
172 | return baseSize;
173 | }
174 |
175 | void SettingsDialog::createUi(const SettingsSetup &setup)
176 | {
177 | _ui->filterLineEdit->setVisible(setup.allowSearch);
178 | _ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setVisible(setup.allowRestore && _control->canRestoreDefaults());
179 |
180 | foreach(auto category, setup.categories)
181 | createCategory(category);
182 |
183 | resetListSize();
184 | _ui->categoryListWidget->setCurrentRow(0);
185 | }
186 |
187 | void SettingsDialog::createCategory(const SettingsCategory &category)
188 | {
189 | auto item = new QListWidgetItem();
190 | item->setText(category.title);
191 | item->setIcon(loadIcon(category.icon));
192 | item->setToolTip(category.tooltip.isNull() ? category.title : category.tooltip);
193 | item->setWhatsThis(item->toolTip());
194 | auto tab = new QTabWidget();
195 | tab->setTabBarAutoHide(true);
196 |
197 | _ui->contentStackWidget->addWidget(tab);
198 | _ui->categoryListWidget->addItem(item);
199 |
200 | foreach(auto section, category.sections)
201 | createSection(section, tab);
202 | }
203 |
204 | void SettingsDialog::createSection(const SettingsSection §ion, QTabWidget *tabWidget)
205 | {
206 | auto scrollArea = new QScrollArea();
207 | scrollArea->setWidgetResizable(true);
208 | scrollArea->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
209 | scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
210 | scrollArea->setAutoFillBackground(true);
211 | auto pal = scrollArea->palette();
212 | pal.setColor(QPalette::Window, tabWidget->palette().color(QPalette::Base));
213 | scrollArea->setPalette(pal);
214 | scrollArea->setFrameShape(QFrame::NoFrame);
215 |
216 | auto scrollContent = new QWidget(scrollArea);
217 | scrollContent->setObjectName(TAB_CONTENT_NAME);
218 | auto layout = new QFormLayout(scrollContent);
219 | scrollContent->setLayout(layout);
220 | scrollArea->setWidget(scrollContent);
221 |
222 | auto index = tabWidget->addTab(scrollArea, loadIcon(section.icon), section.title);
223 | auto tooltip = section.tooltip.isNull() ? section.title : section.tooltip;
224 | tabWidget->tabBar()->setTabToolTip(index, tooltip);
225 | tabWidget->tabBar()->setTabWhatsThis(index, tooltip);
226 |
227 | foreach(auto group, section.groups)
228 | createGroup(group, scrollContent, layout);
229 | }
230 |
231 | void SettingsDialog::createGroup(const SettingsGroup &group, QWidget *contentWidget, QFormLayout *layout)
232 | {
233 | QWidget *sectionWidget = nullptr;
234 | QFormLayout *sectionLayout = nullptr;
235 | if(group.title.isNull()) {
236 | sectionWidget = contentWidget;
237 | sectionLayout = layout;
238 | } else {
239 | auto groupBox = new QGroupBox(group.title, contentWidget);
240 | layout->addRow(groupBox);
241 | sectionWidget = groupBox;
242 | sectionLayout = new QFormLayout(groupBox);
243 | groupBox->setLayout(sectionLayout);
244 | }
245 |
246 | foreach(auto entry, group.entries)
247 | createEntry(entry, sectionWidget, sectionLayout);
248 | }
249 |
250 | void SettingsDialog::createEntry(const SettingsEntry &entry, QWidget *sectionWidget, QFormLayout *layout)
251 | {
252 | auto widgetFactory = WidgetPresenter::inputWidgetFactory();
253 | QWidget *content = widgetFactory->createWidget(entry.type, sectionWidget, entry.properties);
254 | if(!content) {
255 | qWarning() << "Failed to create settings widget for type" << entry.type;
256 | return;
257 | }
258 | auto property = widgetFactory->userProperty(content);
259 | if(!property.isValid()) {
260 | qWarning() << "Failed to get user property for type" << entry.type;
261 | return;
262 | }
263 |
264 | property.write(content, _control->loadValue(entry.key, entry.defaultValue));
265 | if(property.hasNotifySignal()) {
266 | auto changedSlot = metaObject()->method(metaObject()->indexOfSlot("propertyChanged()"));
267 | connect(content, property.notifySignal(),
268 | this, changedSlot);
269 | } else
270 | _changedEntries.insert(content);
271 |
272 | auto label = new QLabel(entry.title + tr(":"), sectionWidget);
273 | label->setBuddy(content);
274 | label->setToolTip(entry.tooltip.isNull() ? entry.title : entry.tooltip);
275 | label->setWhatsThis(label->toolTip());
276 | if(content->toolTip().isNull())
277 | content->setToolTip(label->toolTip());
278 | if(content->whatsThis().isNull())
279 | content->setWhatsThis(label->toolTip());
280 |
281 | layout->addRow(label, content);
282 | _entryMap.insert(content, {entry, property});
283 | }
284 |
285 | void SettingsDialog::searchInDialog(const QRegularExpression ®ex)
286 | {
287 | for(int i = 0, max = _ui->categoryListWidget->count(); i < max; ++i) {
288 | auto item = _ui->categoryListWidget->item(i);
289 | auto tab = static_cast(_ui->contentStackWidget->widget(i));
290 |
291 | if(searchInCategory(regex, tab) ||
292 | regex.match(item->text()).hasMatch()) {
293 | item->setHidden(false);
294 |
295 | if(_ui->categoryListWidget->currentRow() == -1)
296 | _ui->categoryListWidget->setCurrentRow(i);
297 | } else {
298 | item->setHidden(true);
299 |
300 | if(_ui->categoryListWidget->currentRow() == i) {
301 | auto found = false;
302 | for(int j = 0; j < max; j++) {
303 | if(!_ui->categoryListWidget->item(j)->isHidden()){
304 | _ui->categoryListWidget->setCurrentRow(j);
305 | found = true;
306 | break;
307 | }
308 | }
309 | if(!found) {
310 | _ui->categoryListWidget->setCurrentRow(-1);
311 | _ui->contentStackWidget->setCurrentIndex(max);
312 | }
313 | }
314 | }
315 | }
316 | }
317 |
318 | bool SettingsDialog::searchInCategory(const QRegularExpression ®ex, QTabWidget *tab)
319 | {
320 | auto someFound = false;
321 |
322 | for(int i = 0, max = tab->count(); i < max; ++i) {
323 | if(searchInSection(regex, tab->widget(i)->findChild(TAB_CONTENT_NAME)) ||
324 | regex.match(tab->tabText(i)).hasMatch()){
325 | tab->setTabEnabled(i, true);
326 | someFound = true;
327 | } else
328 | tab->setTabEnabled(i, false);
329 | }
330 |
331 | return someFound;
332 | }
333 |
334 | bool SettingsDialog::searchInSection(const QRegularExpression ®ex, QWidget *contentWidget)
335 | {
336 | auto someFound = false;
337 |
338 | auto layout = static_cast(contentWidget->layout());
339 | for(int i = 0, max = layout->rowCount(); i < max; ++i) {
340 | auto spanItem = layout->itemAt(i, QFormLayout::SpanningRole);
341 | if(spanItem) {
342 | auto group = static_cast(spanItem->widget());
343 | someFound |= searchInGroup(regex, group) ||
344 | regex.match(group->title()).hasMatch();
345 | } else {
346 | auto label = static_cast(layout->itemAt(i, QFormLayout::LabelRole)->widget());
347 | auto content = layout->itemAt(i, QFormLayout::FieldRole)->widget();
348 | someFound |= searchInEntry(regex, label, content);
349 | }
350 | }
351 |
352 | return someFound;
353 | }
354 |
355 | bool SettingsDialog::searchInGroup(const QRegularExpression ®ex, QGroupBox *groupWidget)
356 | {
357 | auto someFound = false;
358 |
359 | auto layout = static_cast(groupWidget->layout());
360 | for(int i = 0, max = layout->rowCount(); i < max; ++i) {
361 | auto label = static_cast(layout->itemAt(i, QFormLayout::LabelRole)->widget());
362 | auto content = layout->itemAt(i, QFormLayout::FieldRole)->widget();
363 | someFound |= searchInEntry(regex, label, content);
364 | }
365 |
366 | return someFound;
367 | }
368 |
369 | bool SettingsDialog::searchInEntry(const QRegularExpression ®ex, QLabel *label, QWidget *content)
370 | {
371 | if(regex.pattern().isEmpty()) {
372 | label->setStyleSheet(QString());
373 | return false;
374 | }
375 | auto keys = _entryMap.value(content).first.searchKeys;
376 | keys.append(label->text());
377 | foreach(auto key, keys) {
378 | if(regex.match(key).hasMatch()) {
379 | label->setStyleSheet(QStringLiteral("QLabel {"
380 | " background-color: rgba(19,232,51,0.4);"
381 | " border: 1px solid rgba(19,196,45,0.8);"
382 | " border-radius: 4px;"
383 | "}"));
384 | return true;
385 | }
386 | }
387 | label->setStyleSheet(QString());
388 | return false;
389 | }
390 |
391 | QIcon SettingsDialog::loadIcon(const QUrl &icon)
392 | {
393 | if(icon.scheme() == QStringLiteral("qrc"))
394 | return QIcon(QLatin1Char(':') + icon.path());
395 | else
396 | return QIcon(icon.toLocalFile());
397 | }
398 |
399 |
400 |
401 | CategoryItemDelegate::CategoryItemDelegate(std::function updateFunc, const QSize &iconSize, int layoutSpacing, QObject *parent) :
402 | QStyledItemDelegate(parent),
403 | _iconSize(),
404 | _updateFunc(updateFunc)
405 | {
406 | this->_iconSize = iconSize + QSize(0, layoutSpacing);
407 | }
408 |
409 | QSize CategoryItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
410 | {
411 | QSize size = QStyledItemDelegate::sizeHint(option, index);
412 | _updateFunc(size.width());
413 | return size.expandedTo(_iconSize);
414 | }
415 |
416 | static void settingsInit()
417 | {
418 | XmlSettingsSetupLoader::overwriteDefaultIcon(QStringLiteral("qrc:/qtmvvm/icons/settings.ico"));
419 | }
420 |
--------------------------------------------------------------------------------