Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
embeddedoptionspage.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
8
9#include <deviceprofile_p.h>
10#include <iconloader_p.h>
11#include <shared_settings_p.h>
12#include <abstractdialoggui_p.h>
13#include <formwindowbase_p.h>
14
15
16// SDK
17#include <QtDesigner/abstractformeditor.h>
18#include <QtDesigner/abstractformwindowmanager.h>
19
20#include <QtWidgets/qlabel.h>
21#include <QtWidgets/qboxlayout.h>
22#include <QtWidgets/qapplication.h>
23#include <QtWidgets/qcombobox.h>
24#include <QtWidgets/qtoolbutton.h>
25#include <QtWidgets/qmessagebox.h>
26#include <QtWidgets/qlabel.h>
27#include <QtWidgets/qgroupbox.h>
28
29#include <QtCore/qset.h>
30#include <QtCore/qlist.h>
31
32#include <algorithm>
33
34QT_BEGIN_NAMESPACE
35
36using namespace Qt::StringLiterals;
37
38namespace qdesigner_internal {
39
40using DeviceProfileList = QList<DeviceProfile>;
41
43
44// Sort by name. Used by template, do not make it static!
45bool deviceProfileLessThan(const DeviceProfile &d1, const DeviceProfile &d2)
46{
47 return d1.name().toLower() < d2.name().toLower();
48}
49
50static bool ask(QWidget *parent,
51 QDesignerDialogGuiInterface *dlgui,
52 const QString &title,
53 const QString &what)
54{
55 return dlgui->message(parent, QDesignerDialogGuiInterface::OtherMessage,
56 QMessageBox::Question, title, what,
57 QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::Yes;
58}
59
60// ------------ EmbeddedOptionsControlPrivate
63public:
66
67 bool isDirty() const { return m_dirty; }
68
71 void slotAdd();
72 void slotEdit();
73 void slotDelete();
75
76private:
77 QStringList existingProfileNames() const;
78 void sortAndPopulateProfileCombo();
79 void updateState();
80 void updateDescriptionLabel();
81
82 QDesignerFormEditorInterface *m_core;
83 QComboBox *m_profileCombo;
84 QToolButton *m_addButton;
85 QToolButton *m_editButton;
86 QToolButton *m_deleteButton;
87 QLabel *m_descriptionLabel;
88
89 DeviceProfileList m_sortedProfiles;
90 EmbeddedOptionsControl *m_q = nullptr;
91 QSet<QString> m_usedProfiles;
92 bool m_dirty = false;
93};
94
95EmbeddedOptionsControlPrivate::EmbeddedOptionsControlPrivate(QDesignerFormEditorInterface *core) :
96 m_core(core),
97 m_profileCombo(new QComboBox),
98 m_addButton(new QToolButton),
99 m_editButton(new QToolButton),
100 m_deleteButton(new QToolButton),
101 m_descriptionLabel(new QLabel)
102{
103 m_descriptionLabel->setMinimumHeight(80);
104 // Determine used profiles to lock them
105 const QDesignerFormWindowManagerInterface *fwm = core->formWindowManager();
106 if (const int fwCount = fwm->formWindowCount()) {
107 for (int i = 0; i < fwCount; i++)
108 if (const FormWindowBase *fwb = qobject_cast<const FormWindowBase *>(fwm->formWindow(i))) {
109 const QString deviceProfileName = fwb->deviceProfileName();
110 if (!deviceProfileName.isEmpty())
111 m_usedProfiles.insert(deviceProfileName);
112 }
113 }
114}
115
116void EmbeddedOptionsControlPrivate::init(EmbeddedOptionsControl *q)
117{
118 m_q = q;
119 QVBoxLayout *vLayout = new QVBoxLayout;
120 QHBoxLayout *hLayout = new QHBoxLayout;
121 m_profileCombo->setMinimumWidth(200);
122 m_profileCombo->setEditable(false);
123 hLayout->addWidget(m_profileCombo);
124 m_profileCombo->addItem(EmbeddedOptionsControl::tr("None"));
125 EmbeddedOptionsControl::connect(m_profileCombo, &QComboBox::currentIndexChanged,
126 m_q, &EmbeddedOptionsControl::slotProfileIndexChanged);
127
128 m_addButton->setIcon(createIconSet("plus.png"_L1));
129 m_addButton->setToolTip(EmbeddedOptionsControl::tr("Add a profile"));
130 EmbeddedOptionsControl::connect(m_addButton, &QAbstractButton::clicked,
131 m_q, &EmbeddedOptionsControl::slotAdd);
132 hLayout->addWidget(m_addButton);
133
134 EmbeddedOptionsControl::connect(m_editButton, &QAbstractButton::clicked,
135 m_q, &EmbeddedOptionsControl::slotEdit);
136 m_editButton->setIcon(createIconSet("edit.png"_L1));
137 m_editButton->setToolTip(EmbeddedOptionsControl::tr("Edit the selected profile"));
138 hLayout->addWidget(m_editButton);
139
140 m_deleteButton->setIcon(createIconSet("minus.png"_L1));
141 m_deleteButton->setToolTip(EmbeddedOptionsControl::tr("Delete the selected profile"));
142 EmbeddedOptionsControl::connect(m_deleteButton, &QAbstractButton::clicked,
143 m_q, &EmbeddedOptionsControl::slotDelete);
144 hLayout->addWidget(m_deleteButton);
145
146 hLayout->addStretch();
147 vLayout->addLayout(hLayout);
148 vLayout->addWidget(m_descriptionLabel);
149 m_q->setLayout(vLayout);
150}
151
152QStringList EmbeddedOptionsControlPrivate::existingProfileNames() const
153{
154 QStringList rc;
155 for (const auto &dp : m_sortedProfiles)
156 rc.append(dp.name());
157 return rc;
158}
159
160void EmbeddedOptionsControlPrivate::slotAdd()
161{
162 DeviceProfileDialog dlg(m_core->dialogGui(), m_q);
163 dlg.setWindowTitle(EmbeddedOptionsControl::tr("Add Profile"));
164 // Create a new profile with a new, unique name
165 DeviceProfile settings;
166 settings.fromSystem();
167 dlg.setDeviceProfile(settings);
168
169 const QStringList names = existingProfileNames();
170 const QString newNamePrefix = EmbeddedOptionsControl::tr("New profile");
171 QString newName = newNamePrefix;
172 for (int i = 2; names.contains(newName); i++) {
173 newName = newNamePrefix;
174 newName += QString::number(i);
175 }
176
177 settings.setName(newName);
178 dlg.setDeviceProfile(settings);
179 if (dlg.showDialog(names)) {
180 const DeviceProfile newProfile = dlg.deviceProfile();
181 m_sortedProfiles.push_back(newProfile);
182 // Maintain sorted order
183 sortAndPopulateProfileCombo();
184 const int index = m_profileCombo->findText(newProfile.name());
185 m_profileCombo->setCurrentIndex(index);
186 m_dirty = true;
187 }
188}
189
190void EmbeddedOptionsControlPrivate::slotEdit()
191{
192 const int index = m_profileCombo->currentIndex() - profileComboIndexOffset;
193 if (index < 0)
194 return;
195
196 // Edit the profile, compile a list of existing names
197 // excluding current one. re-insert if changed,
198 // re-sort if name changed.
199 const DeviceProfile oldProfile = m_sortedProfiles.at(index);
200 const QString oldName = oldProfile.name();
201 QStringList names = existingProfileNames();
202 names.removeAll(oldName);
203
204 DeviceProfileDialog dlg(m_core->dialogGui(), m_q);
205 dlg.setWindowTitle(EmbeddedOptionsControl::tr("Edit Profile"));
206 dlg.setDeviceProfile(oldProfile);
207 if (dlg.showDialog(names)) {
208 const DeviceProfile newProfile = dlg.deviceProfile();
209 if (newProfile != oldProfile) {
210 m_dirty = true;
211 m_sortedProfiles[index] = newProfile;
212 if (newProfile.name() != oldName) {
213 sortAndPopulateProfileCombo();
214 const int index = m_profileCombo->findText(newProfile.name());
215 m_profileCombo->setCurrentIndex(index);
216 } else {
217 updateDescriptionLabel();
218 }
219
220 }
221 }
222}
223
224void EmbeddedOptionsControlPrivate::slotDelete()
225{
226 const int index = m_profileCombo->currentIndex() - profileComboIndexOffset;
227 if (index < 0)
228 return;
229 const QString name = m_sortedProfiles.at(index).name();
230 if (ask(m_q, m_core->dialogGui(),
231 EmbeddedOptionsControl::tr("Delete Profile"),
232 EmbeddedOptionsControl::tr("Would you like to delete the profile '%1'?").arg(name))) {
233 m_profileCombo->setCurrentIndex(0);
234 m_sortedProfiles.removeAt(index);
235 m_profileCombo->removeItem(index + profileComboIndexOffset);
236 m_dirty = true;
237 }
238}
239
240void EmbeddedOptionsControlPrivate::sortAndPopulateProfileCombo()
241{
242 // Clear items until only "None" is left
243 for (int i = m_profileCombo->count() - 1; i > 0; i--)
244 m_profileCombo->removeItem(i);
245 if (!m_sortedProfiles.isEmpty()) {
246 std::sort(m_sortedProfiles.begin(), m_sortedProfiles.end(), deviceProfileLessThan);
247 m_profileCombo->addItems(existingProfileNames());
248 }
249}
250
251void EmbeddedOptionsControlPrivate::loadSettings()
252{
253 const QDesignerSharedSettings settings(m_core);
254 m_sortedProfiles = settings.deviceProfiles();
255 sortAndPopulateProfileCombo();
256 // Index: 0 is "None"
257 const int settingsIndex = settings.currentDeviceProfileIndex();
258 const int profileIndex = settingsIndex >= 0 && settingsIndex < m_sortedProfiles.size() ? settingsIndex + profileComboIndexOffset : 0;
259 m_profileCombo->setCurrentIndex(profileIndex);
260 updateState();
261 m_dirty = false;
262}
263
264void EmbeddedOptionsControlPrivate::saveSettings()
265{
266 QDesignerSharedSettings settings(m_core);
267 settings.setDeviceProfiles(m_sortedProfiles);
268 // Index: 0 is "None"
269 settings.setCurrentDeviceProfileIndex(m_profileCombo->currentIndex() - profileComboIndexOffset);
270 m_dirty = false;
271}
272
273//: Format embedded device profile description
274static const char *descriptionFormat = QT_TRANSLATE_NOOP("EmbeddedOptionsControl",
275"<html>"
276"<table>"
277"<tr><td><b>Font</b></td><td>%1, %2</td></tr>"
278"<tr><td><b>Style</b></td><td>%3</td></tr>"
279"<tr><td><b>Resolution</b></td><td>%4 x %5</td></tr>"
280"</table>"
281"</html>");
282
283static inline QString description(const DeviceProfile& p)
284{
285 QString styleName = p.style();
286 if (styleName.isEmpty())
287 styleName = EmbeddedOptionsControl::tr("Default");
288 return EmbeddedOptionsControl::tr(descriptionFormat).
289 arg(p.fontFamily()).arg(p.fontPointSize()).arg(styleName).arg(p.dpiX()).arg(p.dpiY());
290}
291
292void EmbeddedOptionsControlPrivate::updateDescriptionLabel()
293{
294 const int profileIndex = m_profileCombo->currentIndex() - profileComboIndexOffset;
295 if (profileIndex >= 0) {
296 m_descriptionLabel->setText(description(m_sortedProfiles.at(profileIndex)));
297 } else {
298 m_descriptionLabel->clear();
299 }
300}
301
302void EmbeddedOptionsControlPrivate::updateState()
303{
304 const int profileIndex = m_profileCombo->currentIndex() - profileComboIndexOffset;
305 // Allow for changing/deleting only if it is not in use
306 bool modifyEnabled = false;
307 if (profileIndex >= 0)
308 modifyEnabled = !m_usedProfiles.contains(m_sortedProfiles.at(profileIndex).name());
309 m_editButton->setEnabled(modifyEnabled);
310 m_deleteButton->setEnabled(modifyEnabled);
311 updateDescriptionLabel();
312}
313
314void EmbeddedOptionsControlPrivate::slotProfileIndexChanged(int)
315{
316 updateState();
317 m_dirty = true;
318}
319
320// ------------- EmbeddedOptionsControl
321EmbeddedOptionsControl::EmbeddedOptionsControl(QDesignerFormEditorInterface *core, QWidget *parent) :
322 QWidget(parent),
323 m_d(new EmbeddedOptionsControlPrivate(core))
324{
325 m_d->init(this);
326}
327
328EmbeddedOptionsControl::~EmbeddedOptionsControl()
329{
330 delete m_d;
331}
332
333void EmbeddedOptionsControl::slotAdd()
334{
335 m_d->slotAdd();
336}
337
338void EmbeddedOptionsControl::slotEdit()
339{
340 m_d->slotEdit();
341}
342
343void EmbeddedOptionsControl::slotDelete()
344{
345 m_d->slotDelete();
346}
347
348void EmbeddedOptionsControl::loadSettings()
349{
350 m_d->loadSettings();
351}
352
353void EmbeddedOptionsControl::saveSettings()
354{
355 m_d->saveSettings();
356}
357
358void EmbeddedOptionsControl::slotProfileIndexChanged(int i)
359{
360 m_d->slotProfileIndexChanged(i);
361}
362
363bool EmbeddedOptionsControl::isDirty() const
364{
365 return m_d->isDirty();
366}
367
368// EmbeddedOptionsPage:
369EmbeddedOptionsPage::EmbeddedOptionsPage(QDesignerFormEditorInterface *core) :
370 m_core(core)
371{
372}
373
374QString EmbeddedOptionsPage::name() const
375{
376 //: Tab in preferences dialog
377 return QCoreApplication::translate("EmbeddedOptionsPage", "Embedded Design");
378}
379
380QWidget *EmbeddedOptionsPage::createPage(QWidget *parent)
381{
382 QWidget *optionsWidget = new QWidget(parent);
383
384 QVBoxLayout *optionsVLayout = new QVBoxLayout();
385
386 //: EmbeddedOptionsControl group box"
387 QGroupBox *gb = new QGroupBox(QCoreApplication::translate("EmbeddedOptionsPage", "Device Profiles"));
388 QVBoxLayout *gbVLayout = new QVBoxLayout();
389 m_embeddedOptionsControl = new EmbeddedOptionsControl(m_core);
390 m_embeddedOptionsControl->loadSettings();
391 gbVLayout->addWidget(m_embeddedOptionsControl);
392 gb->setLayout(gbVLayout);
393 optionsVLayout->addWidget(gb);
394
395 optionsVLayout->addStretch(1);
396
397 // Outer layout to give it horizontal stretch
398 QHBoxLayout *optionsHLayout = new QHBoxLayout();
399 optionsHLayout->addLayout(optionsVLayout);
400 optionsHLayout->addStretch(1);
401 optionsWidget->setLayout(optionsHLayout);
402 return optionsWidget;
403}
404
405void EmbeddedOptionsPage::apply()
406{
407 if (!m_embeddedOptionsControl || !m_embeddedOptionsControl->isDirty())
408 return;
409
410 m_embeddedOptionsControl->saveSettings();
411 if (FormWindowManager *fw = qobject_cast<qdesigner_internal::FormWindowManager *>(m_core->formWindowManager()))
412 fw->deviceProfilesChanged();
413}
414
415void EmbeddedOptionsPage::finish()
416{
417}
418}
419
420QT_END_NAMESPACE
friend class QWidget
Definition qpainter.h:421
bool deviceProfileLessThan(const DeviceProfile &d1, const DeviceProfile &d2)
static bool ask(QWidget *parent, QDesignerDialogGuiInterface *dlgui, const QString &title, const QString &what)