1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Designer of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "designerpropertymanager.h"
30#include "qtpropertymanager.h"
31#include "paletteeditorbutton.h"
32#include "qlonglongvalidator.h"
33#include "stringlisteditorbutton.h"
34#include "qtresourceview_p.h"
35#include "qtpropertybrowserutils_p.h"
36
37#include <formwindowbase_p.h>
38#include <formwindowmanager.h>
39#include <formwindow.h>
40#include <propertysheet.h>
41#include <qextensionmanager.h>
42#include <formwindowcursor.h>
43#include <textpropertyeditor_p.h>
44#include <stylesheeteditor_p.h>
45#include <richtexteditor_p.h>
46#include <plaintexteditor_p.h>
47#include <iconloader_p.h>
48#include <iconselector_p.h>
49#include <abstractdialoggui_p.h>
50
51#include <QtWidgets/qlabel.h>
52#include <QtWidgets/qtoolbutton.h>
53#include <QtWidgets/qboxlayout.h>
54#include <QtCore/qfileinfo.h>
55#if QT_CONFIG(clipboard)
56#include <QtGui/qclipboard.h>
57#endif
58#include <QtWidgets/qlineedit.h>
59#include <QtWidgets/qdialogbuttonbox.h>
60#include <QtWidgets/qpushbutton.h>
61#include <QtWidgets/qfiledialog.h>
62#include <QtWidgets/qaction.h>
63#include <QtWidgets/qmenu.h>
64#include <QtWidgets/qkeysequenceedit.h>
65#include <QtGui/qevent.h>
66#include <QtWidgets/qapplication.h>
67#include <QtCore/qurl.h>
68
69#include <QtCore/qdebug.h>
70
71QT_BEGIN_NAMESPACE
72
73static const char *resettableAttributeC = "resettable";
74static const char *flagsAttributeC = "flags";
75static const char *validationModesAttributeC = "validationMode";
76static const char *superPaletteAttributeC = "superPalette";
77static const char *defaultResourceAttributeC = "defaultResource";
78static const char *fontAttributeC = "font";
79static const char *themeAttributeC = "theme";
80
81class DesignerFlagPropertyType
82{
83};
84
85
86class DesignerAlignmentPropertyType
87{
88};
89
90QT_END_NAMESPACE
91
92Q_DECLARE_METATYPE(DesignerFlagPropertyType)
93Q_DECLARE_METATYPE(DesignerAlignmentPropertyType)
94
95QT_BEGIN_NAMESPACE
96
97namespace qdesigner_internal {
98
99template <class PropertySheetValue>
100void TranslatablePropertyManager<PropertySheetValue>::initialize(QtVariantPropertyManager *m,
101 QtProperty *property,
102 const PropertySheetValue &value)
103{
104 m_values.insert(property, value);
105
106 QtVariantProperty *translatable = m->addProperty(propertyType: QVariant::Bool, name: DesignerPropertyManager::tr(s: "translatable"));
107 translatable->setValue(value.translatable());
108 m_valueToTranslatable.insert(key: property, value: translatable);
109 m_translatableToValue.insert(key: translatable, value: property);
110 property->addSubProperty(property: translatable);
111
112 if (!DesignerPropertyManager::useIdBasedTranslations()) {
113 QtVariantProperty *disambiguation = m->addProperty(propertyType: QVariant::String, name: DesignerPropertyManager::tr(s: "disambiguation"));
114 disambiguation->setValue(value.disambiguation());
115 m_valueToDisambiguation.insert(key: property, value: disambiguation);
116 m_disambiguationToValue.insert(key: disambiguation, value: property);
117 property->addSubProperty(property: disambiguation);
118 }
119
120 QtVariantProperty *comment = m->addProperty(propertyType: QVariant::String, name: DesignerPropertyManager::tr(s: "comment"));
121 comment->setValue(value.comment());
122 m_valueToComment.insert(key: property, value: comment);
123 m_commentToValue.insert(key: comment, value: property);
124 property->addSubProperty(property: comment);
125
126 if (DesignerPropertyManager::useIdBasedTranslations()) {
127 QtVariantProperty *id = m->addProperty(propertyType: QVariant::String, name: DesignerPropertyManager::tr(s: "id"));
128 id->setValue(value.id());
129 m_valueToId.insert(key: property, value: id);
130 m_idToValue.insert(key: id, value: property);
131 property->addSubProperty(property: id);
132 }
133}
134
135template <class PropertySheetValue>
136bool TranslatablePropertyManager<PropertySheetValue>::uninitialize(QtProperty *property)
137{
138 if (QtProperty *comment = m_valueToComment.value(key: property)) {
139 delete comment;
140 m_commentToValue.remove(key: comment);
141 } else {
142 return false;
143 }
144 if (QtProperty *translatable = m_valueToTranslatable.value(key: property)) {
145 delete translatable;
146 m_translatableToValue.remove(key: translatable);
147 }
148 if (QtProperty *disambiguation = m_valueToDisambiguation.value(key: property)) {
149 delete disambiguation;
150 m_disambiguationToValue.remove(key: disambiguation);
151 }
152 if (QtProperty *id = m_valueToId.value(key: property)) {
153 delete id;
154 m_idToValue.remove(key: id);
155 }
156
157 m_values.remove(property);
158 m_valueToComment.remove(key: property);
159 m_valueToTranslatable.remove(key: property);
160 m_valueToDisambiguation.remove(key: property);
161 m_valueToId.remove(key: property);
162 return true;
163}
164
165template <class PropertySheetValue>
166bool TranslatablePropertyManager<PropertySheetValue>::destroy(QtProperty *subProperty)
167{
168 const auto commentToValueIt = m_commentToValue.find(key: subProperty);
169 if (commentToValueIt != m_commentToValue.end()) {
170 m_valueToComment.remove(key: commentToValueIt.value());
171 m_commentToValue.erase(it: commentToValueIt);
172 return true;
173 }
174 const auto translatableToValueIt = m_translatableToValue.find(key: subProperty);
175 if (translatableToValueIt != m_translatableToValue.end()) {
176 m_valueToTranslatable.remove(key: translatableToValueIt.value());
177 m_translatableToValue.erase(it: translatableToValueIt);
178 return true;
179 }
180 const auto disambiguationToValueIt = m_disambiguationToValue.find(key: subProperty);
181 if (disambiguationToValueIt != m_disambiguationToValue.end()) {
182 m_valueToDisambiguation.remove(key: disambiguationToValueIt.value());
183 m_disambiguationToValue.erase(it: disambiguationToValueIt);
184 return true;
185 }
186 const auto idToValueIt = m_idToValue.find(key: subProperty);
187 if (idToValueIt != m_idToValue.end()) {
188 m_valueToId.remove(key: idToValueIt.value());
189 m_idToValue.erase(it: idToValueIt);
190 return true;
191 }
192 return false;
193}
194
195template <class PropertySheetValue>
196int TranslatablePropertyManager<PropertySheetValue>::valueChanged(QtVariantPropertyManager *m,
197 QtProperty *propertyIn,
198 const QVariant &value)
199{
200 if (QtProperty *property = m_translatableToValue.value(key: propertyIn, defaultValue: 0)) {
201 const PropertySheetValue oldValue = m_values.value(property);
202 PropertySheetValue newValue = oldValue;
203 newValue.setTranslatable(value.toBool());
204 if (newValue != oldValue) {
205 m->variantProperty(property)->setValue(QVariant::fromValue(newValue));
206 return DesignerPropertyManager::Changed;
207 }
208 return DesignerPropertyManager::Unchanged;
209 }
210 if (QtProperty *property = m_commentToValue.value(key: propertyIn)) {
211 const PropertySheetValue oldValue = m_values.value(property);
212 PropertySheetValue newValue = oldValue;
213 newValue.setComment(value.toString());
214 if (newValue != oldValue) {
215 m->variantProperty(property)->setValue(QVariant::fromValue(newValue));
216 return DesignerPropertyManager::Changed;
217 }
218 return DesignerPropertyManager::Unchanged;
219 }
220 if (QtProperty *property = m_disambiguationToValue.value(key: propertyIn, defaultValue: 0)) {
221 const PropertySheetValue oldValue = m_values.value(property);
222 PropertySheetValue newValue = oldValue;
223 newValue.setDisambiguation(value.toString());
224 if (newValue != oldValue) {
225 m->variantProperty(property)->setValue(QVariant::fromValue(newValue));
226 return DesignerPropertyManager::Changed;
227 }
228 return DesignerPropertyManager::Unchanged;
229 }
230 if (QtProperty *property = m_idToValue.value(key: propertyIn)) {
231 const PropertySheetValue oldValue = m_values.value(property);
232 PropertySheetValue newValue = oldValue;
233 newValue.setId(value.toString());
234 if (newValue != oldValue) {
235 m->variantProperty(property)->setValue(QVariant::fromValue(newValue));
236 return DesignerPropertyManager::Changed;
237 }
238 return DesignerPropertyManager::Unchanged;
239 }
240 return DesignerPropertyManager::NoMatch;
241}
242
243template <class PropertySheetValue>
244int TranslatablePropertyManager<PropertySheetValue>::setValue(QtVariantPropertyManager *m,
245 QtProperty *property,
246 int expectedTypeId,
247 const QVariant &variantValue)
248{
249 const auto it = m_values.find(property);
250 if (it == m_values.end())
251 return DesignerPropertyManager::NoMatch;
252 if (variantValue.userType() != expectedTypeId)
253 return DesignerPropertyManager::NoMatch;
254 const PropertySheetValue value = qvariant_cast<PropertySheetValue>(variantValue);
255 if (value == it.value())
256 return DesignerPropertyManager::Unchanged;
257 if (QtVariantProperty *comment = m->variantProperty(property: m_valueToComment.value(key: property)))
258 comment->setValue(value.comment());
259 if (QtVariantProperty *translatable = m->variantProperty(property: m_valueToTranslatable.value(key: property)))
260 translatable->setValue(value.translatable());
261 if (QtVariantProperty *disambiguation = m->variantProperty(property: m_valueToDisambiguation.value(key: property)))
262 disambiguation->setValue(value.disambiguation());
263 if (QtVariantProperty *id = m->variantProperty(property: m_valueToId.value(key: property)))
264 id->setValue(value.id());
265 it.value() = value;
266 return DesignerPropertyManager::Changed;
267}
268
269template <class PropertySheetValue>
270bool TranslatablePropertyManager<PropertySheetValue>::value(const QtProperty *property, QVariant *rc) const
271{
272 const auto it = m_values.constFind(const_cast<QtProperty *>(property));
273 if (it == m_values.constEnd())
274 return false;
275 *rc = QVariant::fromValue(it.value());
276 return true;
277}
278
279// ------------ TextEditor
280class TextEditor : public QWidget
281{
282 Q_OBJECT
283public:
284 TextEditor(QDesignerFormEditorInterface *core, QWidget *parent);
285
286 TextPropertyValidationMode textPropertyValidationMode() const;
287 void setTextPropertyValidationMode(TextPropertyValidationMode vm);
288
289 void setRichTextDefaultFont(const QFont &font) { m_richTextDefaultFont = font; }
290 QFont richTextDefaultFont() const { return m_richTextDefaultFont; }
291
292 void setSpacing(int spacing);
293
294 TextPropertyEditor::UpdateMode updateMode() const { return m_editor->updateMode(); }
295 void setUpdateMode(TextPropertyEditor::UpdateMode um) { m_editor->setUpdateMode(um); }
296
297 void setIconThemeModeEnabled(bool enable);
298
299public slots:
300 void setText(const QString &text);
301
302signals:
303 void textChanged(const QString &text);
304
305private slots:
306 void buttonClicked();
307 void resourceActionActivated();
308 void fileActionActivated();
309private:
310 TextPropertyEditor *m_editor;
311 IconThemeEditor *m_themeEditor;
312 bool m_iconThemeModeEnabled;
313 QFont m_richTextDefaultFont;
314 QToolButton *m_button;
315 QMenu *m_menu;
316 QAction *m_resourceAction;
317 QAction *m_fileAction;
318 QHBoxLayout *m_layout;
319 QDesignerFormEditorInterface *m_core;
320};
321
322TextEditor::TextEditor(QDesignerFormEditorInterface *core, QWidget *parent) :
323 QWidget(parent),
324 m_editor(new TextPropertyEditor(this)),
325 m_themeEditor(new IconThemeEditor(this, false)),
326 m_iconThemeModeEnabled(false),
327 m_richTextDefaultFont(QApplication::font()),
328 m_button(new QToolButton(this)),
329 m_menu(new QMenu(this)),
330 m_resourceAction(new QAction(tr(s: "Choose Resource..."), this)),
331 m_fileAction(new QAction(tr(s: "Choose File..."), this)),
332 m_layout(new QHBoxLayout(this)),
333 m_core(core)
334{
335 m_themeEditor->setVisible(false);
336 m_button->setVisible(false);
337
338 m_layout->addWidget(m_editor);
339 m_layout->addWidget(m_themeEditor);
340 m_button->setText(tr(s: "..."));
341 m_button->setSizePolicy(hor: QSizePolicy::Fixed, ver: QSizePolicy::Ignored);
342 m_button->setFixedWidth(20);
343 m_layout->addWidget(m_button);
344 m_layout->setContentsMargins(QMargins());
345 m_layout->setSpacing(0);
346
347 connect(sender: m_resourceAction, signal: &QAction::triggered, receiver: this, slot: &TextEditor::resourceActionActivated);
348 connect(sender: m_fileAction, signal: &QAction::triggered, receiver: this, slot: &TextEditor::fileActionActivated);
349 connect(sender: m_editor, signal: &TextPropertyEditor::textChanged, receiver: this, slot: &TextEditor::textChanged);
350 connect(sender: m_themeEditor, signal: &IconThemeEditor::edited, receiver: this, slot: &TextEditor::textChanged);
351 connect(sender: m_button, signal: &QAbstractButton::clicked, receiver: this, slot: &TextEditor::buttonClicked);
352
353 setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
354 setFocusProxy(m_editor);
355
356 m_menu->addAction(action: m_resourceAction);
357 m_menu->addAction(action: m_fileAction);
358}
359
360void TextEditor::setSpacing(int spacing)
361{
362 m_layout->setSpacing(spacing);
363}
364
365void TextEditor::setIconThemeModeEnabled(bool enable)
366{
367 if (m_iconThemeModeEnabled == enable)
368 return; // nothing changes
369 m_iconThemeModeEnabled = enable;
370 m_editor->setVisible(!enable);
371 m_themeEditor->setVisible(enable);
372 if (enable) {
373 m_themeEditor->setTheme(m_editor->text());
374 setFocusProxy(m_themeEditor);
375 } else {
376 m_editor->setText(m_themeEditor->theme());
377 setFocusProxy(m_editor);
378 }
379}
380
381TextPropertyValidationMode TextEditor::textPropertyValidationMode() const
382{
383 return m_editor->textPropertyValidationMode();
384}
385
386void TextEditor::setTextPropertyValidationMode(TextPropertyValidationMode vm)
387{
388 m_editor->setTextPropertyValidationMode(vm);
389 if (vm == ValidationURL) {
390 m_button->setMenu(m_menu);
391 m_button->setFixedWidth(30);
392 m_button->setPopupMode(QToolButton::MenuButtonPopup);
393 } else {
394 m_button->setMenu(nullptr);
395 m_button->setFixedWidth(20);
396 m_button->setPopupMode(QToolButton::DelayedPopup);
397 }
398 m_button->setVisible(vm == ValidationStyleSheet || vm == ValidationRichText || vm == ValidationMultiLine || vm == ValidationURL);
399}
400
401void TextEditor::setText(const QString &text)
402{
403 if (m_iconThemeModeEnabled)
404 m_themeEditor->setTheme(text);
405 else
406 m_editor->setText(text);
407}
408
409void TextEditor::buttonClicked()
410{
411 const QString oldText = m_editor->text();
412 QString newText;
413 switch (textPropertyValidationMode()) {
414 case ValidationStyleSheet: {
415 StyleSheetEditorDialog dlg(m_core, this);
416 dlg.setText(oldText);
417 if (dlg.exec() != QDialog::Accepted)
418 return;
419 newText = dlg.text();
420 }
421 break;
422 case ValidationRichText: {
423 RichTextEditorDialog dlg(m_core, this);
424 dlg.setDefaultFont(m_richTextDefaultFont);
425 dlg.setText(oldText);
426 if (dlg.showDialog() != QDialog::Accepted)
427 return;
428 newText = dlg.text(format: Qt::AutoText);
429 }
430 break;
431 case ValidationMultiLine: {
432 PlainTextEditorDialog dlg(m_core, this);
433 dlg.setDefaultFont(m_richTextDefaultFont);
434 dlg.setText(oldText);
435 if (dlg.showDialog() != QDialog::Accepted)
436 return;
437 newText = dlg.text();
438 }
439 break;
440 case ValidationURL:
441 if (oldText.isEmpty() || oldText.startsWith(QStringLiteral("qrc:")))
442 resourceActionActivated();
443 else
444 fileActionActivated();
445 return;
446 default:
447 return;
448 }
449 if (newText != oldText) {
450 m_editor->setText(newText);
451 emit textChanged(text: newText);
452 }
453}
454
455void TextEditor::resourceActionActivated()
456{
457 QString oldPath = m_editor->text();
458 if (oldPath.startsWith(QStringLiteral("qrc:")))
459 oldPath.remove(i: 0, len: 4);
460 // returns ':/file'
461 QString newPath = IconSelector::choosePixmapResource(core: m_core, resourceModel: m_core->resourceModel(), oldPath, parent: this);
462 if (newPath.startsWith(c: QLatin1Char(':')))
463 newPath.remove(i: 0, len: 1);
464 if (newPath.isEmpty() || newPath == oldPath)
465 return;
466 const QString newText = QStringLiteral("qrc:") + newPath;
467 m_editor->setText(newText);
468 emit textChanged(text: newText);
469}
470
471void TextEditor::fileActionActivated()
472{
473 QString oldPath = m_editor->text();
474 if (oldPath.startsWith(QStringLiteral("file:")))
475 oldPath = oldPath.mid(position: 5);
476 const QString newPath = m_core->dialogGui()->getOpenFileName(parent: this, caption: tr(s: "Choose a File"), dir: oldPath);
477 if (newPath.isEmpty() || newPath == oldPath)
478 return;
479 const QString newText = QUrl::fromLocalFile(localfile: newPath).toString();
480 m_editor->setText(newText);
481 emit textChanged(text: newText);
482}
483
484// ------------ ThemeInputDialog
485
486class IconThemeDialog : public QDialog
487{
488 Q_OBJECT
489public:
490 static QString getTheme(QWidget *parent, const QString &theme, bool *ok);
491private:
492 IconThemeDialog(QWidget *parent);
493 IconThemeEditor *m_editor;
494};
495
496IconThemeDialog::IconThemeDialog(QWidget *parent)
497 : QDialog(parent)
498{
499 setWindowTitle(tr(s: "Set Icon From Theme"));
500
501 QVBoxLayout *layout = new QVBoxLayout(this);
502 QLabel *label = new QLabel(tr(s: "Input icon name from the current theme:"), this);
503 m_editor = new IconThemeEditor(this);
504 QDialogButtonBox *buttons = new QDialogButtonBox(this);
505 buttons->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
506
507 layout->addWidget(label);
508 layout->addWidget(m_editor);
509 layout->addWidget(buttons);
510
511 connect(sender: buttons, signal: &QDialogButtonBox::accepted, receiver: this, slot: &QDialog::accept);
512 connect(sender: buttons, signal: &QDialogButtonBox::rejected, receiver: this, slot: &QDialog::reject);
513}
514
515QString IconThemeDialog::getTheme(QWidget *parent, const QString &theme, bool *ok)
516{
517 IconThemeDialog dlg(parent);
518 dlg.m_editor->setTheme(theme);
519 if (dlg.exec() == QDialog::Accepted) {
520 *ok = true;
521 return dlg.m_editor->theme();
522 }
523 *ok = false;
524 return QString();
525}
526
527// ------------ PixmapEditor
528class PixmapEditor : public QWidget
529{
530 Q_OBJECT
531public:
532 PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent);
533
534 void setSpacing(int spacing);
535 void setPixmapCache(DesignerPixmapCache *cache);
536 void setIconThemeModeEnabled(bool enabled);
537public slots:
538 void setPath(const QString &path);
539 void setTheme(const QString &theme);
540 void setDefaultPixmap(const QPixmap &pixmap);
541
542signals:
543 void pathChanged(const QString &path);
544 void themeChanged(const QString &theme);
545
546protected:
547 void contextMenuEvent(QContextMenuEvent *event) override;
548
549private slots:
550 void defaultActionActivated();
551 void resourceActionActivated();
552 void fileActionActivated();
553 void themeActionActivated();
554#if QT_CONFIG(clipboard)
555 void copyActionActivated();
556 void pasteActionActivated();
557 void clipboardDataChanged();
558#endif
559private:
560 void updateLabels();
561 bool m_iconThemeModeEnabled;
562 QDesignerFormEditorInterface *m_core;
563 QLabel *m_pixmapLabel;
564 QLabel *m_pathLabel;
565 QToolButton *m_button;
566 QAction *m_resourceAction;
567 QAction *m_fileAction;
568 QAction *m_themeAction;
569 QAction *m_copyAction;
570 QAction *m_pasteAction;
571 QHBoxLayout *m_layout;
572 QPixmap m_defaultPixmap;
573 QString m_path;
574 QString m_theme;
575 DesignerPixmapCache *m_pixmapCache;
576};
577
578PixmapEditor::PixmapEditor(QDesignerFormEditorInterface *core, QWidget *parent) :
579 QWidget(parent),
580 m_iconThemeModeEnabled(false),
581 m_core(core),
582 m_pixmapLabel(new QLabel(this)),
583 m_pathLabel(new QLabel(this)),
584 m_button(new QToolButton(this)),
585 m_resourceAction(new QAction(tr(s: "Choose Resource..."), this)),
586 m_fileAction(new QAction(tr(s: "Choose File..."), this)),
587 m_themeAction(new QAction(tr(s: "Set Icon From Theme..."), this)),
588 m_copyAction(new QAction(createIconSet(QStringLiteral("editcopy.png")), tr(s: "Copy Path"), this)),
589 m_pasteAction(new QAction(createIconSet(QStringLiteral("editpaste.png")), tr(s: "Paste Path"), this)),
590 m_layout(new QHBoxLayout(this)),
591 m_pixmapCache(nullptr)
592{
593 m_layout->addWidget(m_pixmapLabel);
594 m_layout->addWidget(m_pathLabel);
595 m_button->setText(tr(s: "..."));
596 m_button->setSizePolicy(hor: QSizePolicy::Fixed, ver: QSizePolicy::Ignored);
597 m_button->setFixedWidth(30);
598 m_button->setPopupMode(QToolButton::MenuButtonPopup);
599 m_layout->addWidget(m_button);
600 m_layout->setContentsMargins(QMargins());
601 m_layout->setSpacing(0);
602 m_pixmapLabel->setFixedWidth(16);
603 m_pixmapLabel->setAlignment(Qt::AlignCenter);
604 m_pathLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed));
605 m_themeAction->setVisible(false);
606
607 QMenu *menu = new QMenu(this);
608 menu->addAction(action: m_resourceAction);
609 menu->addAction(action: m_fileAction);
610 menu->addAction(action: m_themeAction);
611
612 m_button->setMenu(menu);
613 m_button->setText(tr(s: "..."));
614
615 connect(sender: m_button, signal: &QAbstractButton::clicked, receiver: this, slot: &PixmapEditor::defaultActionActivated);
616 connect(sender: m_resourceAction, signal: &QAction::triggered, receiver: this, slot: &PixmapEditor::resourceActionActivated);
617 connect(sender: m_fileAction, signal: &QAction::triggered, receiver: this, slot: &PixmapEditor::fileActionActivated);
618 connect(sender: m_themeAction, signal: &QAction::triggered, receiver: this, slot: &PixmapEditor::themeActionActivated);
619#if QT_CONFIG(clipboard)
620 connect(sender: m_copyAction, signal: &QAction::triggered, receiver: this, slot: &PixmapEditor::copyActionActivated);
621 connect(sender: m_pasteAction, signal: &QAction::triggered, receiver: this, slot: &PixmapEditor::pasteActionActivated);
622#endif
623 setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Ignored));
624 setFocusProxy(m_button);
625
626#if QT_CONFIG(clipboard)
627 connect(sender: QApplication::clipboard(), signal: &QClipboard::dataChanged,
628 receiver: this, slot: &PixmapEditor::clipboardDataChanged);
629 clipboardDataChanged();
630#endif
631}
632
633void PixmapEditor::setPixmapCache(DesignerPixmapCache *cache)
634{
635 m_pixmapCache = cache;
636}
637
638void PixmapEditor::setIconThemeModeEnabled(bool enabled)
639{
640 if (m_iconThemeModeEnabled == enabled)
641 return;
642 m_iconThemeModeEnabled = enabled;
643 m_themeAction->setVisible(enabled);
644}
645
646void PixmapEditor::setSpacing(int spacing)
647{
648 m_layout->setSpacing(spacing);
649}
650
651void PixmapEditor::setPath(const QString &path)
652{
653 m_path = path;
654 updateLabels();
655}
656
657void PixmapEditor::setTheme(const QString &theme)
658{
659 m_theme = theme;
660 updateLabels();
661}
662
663void PixmapEditor::updateLabels()
664{
665 if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(name: m_theme)) {
666 m_pixmapLabel->setPixmap(QIcon::fromTheme(name: m_theme).pixmap(w: 16, h: 16));
667 m_pathLabel->setText(tr(s: "[Theme] %1").arg(a: m_theme));
668 m_copyAction->setEnabled(true);
669 } else {
670 if (m_path.isEmpty()) {
671 m_pathLabel->setText(m_path);
672 m_pixmapLabel->setPixmap(m_defaultPixmap);
673 m_copyAction->setEnabled(false);
674 } else {
675 m_pathLabel->setText(QFileInfo(m_path).fileName());
676 if (m_pixmapCache)
677 m_pixmapLabel->setPixmap(QIcon(m_pixmapCache->pixmap(value: PropertySheetPixmapValue(m_path))).pixmap(w: 16, h: 16));
678 m_copyAction->setEnabled(true);
679 }
680 }
681}
682
683void PixmapEditor::setDefaultPixmap(const QPixmap &pixmap)
684{
685 m_defaultPixmap = QIcon(pixmap).pixmap(w: 16, h: 16);
686 const bool hasThemeIcon = m_iconThemeModeEnabled && QIcon::hasThemeIcon(name: m_theme);
687 if (!hasThemeIcon && m_path.isEmpty())
688 m_pixmapLabel->setPixmap(m_defaultPixmap);
689}
690
691void PixmapEditor::contextMenuEvent(QContextMenuEvent *event)
692{
693 QMenu menu(this);
694 menu.addAction(action: m_copyAction);
695 menu.addAction(action: m_pasteAction);
696 menu.exec(pos: event->globalPos());
697 event->accept();
698}
699
700void PixmapEditor::defaultActionActivated()
701{
702 if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(name: m_theme)) {
703 themeActionActivated();
704 return;
705 }
706 // Default to resource
707 const PropertySheetPixmapValue::PixmapSource ps = m_path.isEmpty() ? PropertySheetPixmapValue::ResourcePixmap : PropertySheetPixmapValue::getPixmapSource(core: m_core, path: m_path);
708 switch (ps) {
709 case PropertySheetPixmapValue::LanguageResourcePixmap:
710 case PropertySheetPixmapValue::ResourcePixmap:
711 resourceActionActivated();
712 break;
713 case PropertySheetPixmapValue::FilePixmap:
714 fileActionActivated();
715 break;
716 }
717}
718
719void PixmapEditor::resourceActionActivated()
720{
721 const QString oldPath = m_path;
722 const QString newPath = IconSelector::choosePixmapResource(core: m_core, resourceModel: m_core->resourceModel(), oldPath, parent: this);
723 if (!newPath.isEmpty() && newPath != oldPath) {
724 setTheme(QString());
725 setPath(newPath);
726 emit pathChanged(path: newPath);
727 }
728}
729
730void PixmapEditor::fileActionActivated()
731{
732 const QString newPath = IconSelector::choosePixmapFile(directory: m_path, dlgGui: m_core->dialogGui(), parent: this);
733 if (!newPath.isEmpty() && newPath != m_path) {
734 setTheme(QString());
735 setPath(newPath);
736 emit pathChanged(path: newPath);
737 }
738}
739
740void PixmapEditor::themeActionActivated()
741{
742 bool ok;
743 const QString newTheme = IconThemeDialog::getTheme(parent: this, theme: m_theme, ok: &ok);
744 if (ok && newTheme != m_theme) {
745 setTheme(newTheme);
746 setPath(QString());
747 emit themeChanged(theme: newTheme);
748 }
749}
750
751#if QT_CONFIG(clipboard)
752void PixmapEditor::copyActionActivated()
753{
754 QClipboard *clipboard = QApplication::clipboard();
755 if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(name: m_theme))
756 clipboard->setText(m_theme);
757 else
758 clipboard->setText(m_path);
759}
760
761void PixmapEditor::pasteActionActivated()
762{
763 QClipboard *clipboard = QApplication::clipboard();
764 QString subtype = QStringLiteral("plain");
765 QString text = clipboard->text(subtype);
766 if (!text.isNull()) {
767 QStringList list = text.split(sep: QLatin1Char('\n'));
768 if (!list.isEmpty()) {
769 text = list.at(i: 0);
770 if (m_iconThemeModeEnabled && QIcon::hasThemeIcon(name: text)) {
771 setTheme(text);
772 setPath(QString());
773 emit themeChanged(theme: text);
774 } else {
775 setPath(text);
776 setTheme(QString());
777 emit pathChanged(path: text);
778 }
779 }
780 }
781}
782
783void PixmapEditor::clipboardDataChanged()
784{
785 QClipboard *clipboard = QApplication::clipboard();
786 QString subtype = QStringLiteral("plain");
787 const QString text = clipboard->text(subtype);
788 m_pasteAction->setEnabled(!text.isNull());
789}
790#endif
791
792// --------------- ResetWidget
793class ResetWidget : public QWidget
794{
795 Q_OBJECT
796public:
797 ResetWidget(QtProperty *property, QWidget *parent = nullptr);
798
799 void setWidget(QWidget *widget);
800 void setResetEnabled(bool enabled);
801 void setValueText(const QString &text);
802 void setValueIcon(const QIcon &icon);
803 void setSpacing(int spacing);
804signals:
805 void resetProperty(QtProperty *property);
806private slots:
807 void slotClicked();
808private:
809 QtProperty *m_property;
810 QLabel *m_textLabel;
811 QLabel *m_iconLabel;
812 QToolButton *m_button;
813 int m_spacing;
814};
815
816ResetWidget::ResetWidget(QtProperty *property, QWidget *parent) :
817 QWidget(parent),
818 m_property(property),
819 m_textLabel(new QLabel(this)),
820 m_iconLabel(new QLabel(this)),
821 m_button(new QToolButton(this)),
822 m_spacing(-1)
823{
824 m_textLabel->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed));
825 m_iconLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
826 m_button->setToolButtonStyle(Qt::ToolButtonIconOnly);
827 m_button->setIcon(createIconSet(QStringLiteral("resetproperty.png")));
828 m_button->setIconSize(QSize(8,8));
829 m_button->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding));
830 connect(sender: m_button, signal: &QAbstractButton::clicked, receiver: this, slot: &ResetWidget::slotClicked);
831 QLayout *layout = new QHBoxLayout(this);
832 layout->setContentsMargins(QMargins());
833 layout->setSpacing(m_spacing);
834 layout->addWidget(w: m_iconLabel);
835 layout->addWidget(w: m_textLabel);
836 layout->addWidget(w: m_button);
837 setFocusProxy(m_textLabel);
838 setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
839}
840
841void ResetWidget::setSpacing(int spacing)
842{
843 m_spacing = spacing;
844 layout()->setSpacing(m_spacing);
845}
846
847void ResetWidget::setWidget(QWidget *widget)
848{
849 if (m_textLabel) {
850 delete m_textLabel;
851 m_textLabel = nullptr;
852 }
853 if (m_iconLabel) {
854 delete m_iconLabel;
855 m_iconLabel = nullptr;
856 }
857 delete layout();
858 QLayout *layout = new QHBoxLayout(this);
859 layout->setContentsMargins(QMargins());
860 layout->setSpacing(m_spacing);
861 layout->addWidget(w: widget);
862 layout->addWidget(w: m_button);
863 setFocusProxy(widget);
864}
865
866void ResetWidget::setResetEnabled(bool enabled)
867{
868 m_button->setEnabled(enabled);
869}
870
871void ResetWidget::setValueText(const QString &text)
872{
873 if (m_textLabel)
874 m_textLabel->setText(text);
875}
876
877void ResetWidget::setValueIcon(const QIcon &icon)
878{
879 QPixmap pix = icon.pixmap(size: QSize(16, 16));
880 if (m_iconLabel) {
881 m_iconLabel->setVisible(!pix.isNull());
882 m_iconLabel->setPixmap(pix);
883 }
884}
885
886void ResetWidget::slotClicked()
887{
888 emit resetProperty(property: m_property);
889}
890
891
892// ------------ DesignerPropertyManager:
893
894DesignerPropertyManager::DesignerPropertyManager(QDesignerFormEditorInterface *core, QObject *parent) :
895 QtVariantPropertyManager(parent),
896 m_changingSubValue(false),
897 m_core(core),
898 m_object(nullptr),
899 m_sourceOfChange(nullptr)
900{
901 connect(sender: this, signal: &QtVariantPropertyManager::valueChanged,
902 receiver: this, slot: &DesignerPropertyManager::slotValueChanged);
903 connect(sender: this, signal: & QtAbstractPropertyManager::propertyDestroyed,
904 receiver: this, slot: &DesignerPropertyManager::slotPropertyDestroyed);
905}
906
907DesignerPropertyManager::~DesignerPropertyManager()
908{
909 clear();
910}
911
912bool DesignerPropertyManager::m_IdBasedTranslations = false;
913
914int DesignerPropertyManager::bitCount(int mask) const
915{
916 int count = 0;
917 for (; mask; count++)
918 mask &= mask - 1; // clear the least significant bit set
919 return count;
920}
921
922int DesignerPropertyManager::alignToIndexH(uint align) const
923{
924 if (align & Qt::AlignLeft)
925 return 0;
926 if (align & Qt::AlignHCenter)
927 return 1;
928 if (align & Qt::AlignRight)
929 return 2;
930 if (align & Qt::AlignJustify)
931 return 3;
932 return 0;
933}
934
935int DesignerPropertyManager::alignToIndexV(uint align) const
936{
937 if (align & Qt::AlignTop)
938 return 0;
939 if (align & Qt::AlignVCenter)
940 return 1;
941 if (align & Qt::AlignBottom)
942 return 2;
943 return 1;
944}
945
946uint DesignerPropertyManager::indexHToAlign(int idx) const
947{
948 switch (idx) {
949 case 0: return Qt::AlignLeft;
950 case 1: return Qt::AlignHCenter;
951 case 2: return Qt::AlignRight;
952 case 3: return Qt::AlignJustify;
953 default: break;
954 }
955 return Qt::AlignLeft;
956}
957
958uint DesignerPropertyManager::indexVToAlign(int idx) const
959{
960 switch (idx) {
961 case 0: return Qt::AlignTop;
962 case 1: return Qt::AlignVCenter;
963 case 2: return Qt::AlignBottom;
964 default: break;
965 }
966 return Qt::AlignVCenter;
967}
968
969QString DesignerPropertyManager::indexHToString(int idx) const
970{
971 switch (idx) {
972 case 0: return tr(s: "AlignLeft");
973 case 1: return tr(s: "AlignHCenter");
974 case 2: return tr(s: "AlignRight");
975 case 3: return tr(s: "AlignJustify");
976 default: break;
977 }
978 return tr(s: "AlignLeft");
979}
980
981QString DesignerPropertyManager::indexVToString(int idx) const
982{
983 switch (idx) {
984 case 0: return tr(s: "AlignTop");
985 case 1: return tr(s: "AlignVCenter");
986 case 2: return tr(s: "AlignBottom");
987 default: break;
988 }
989 return tr(s: "AlignVCenter");
990}
991
992void DesignerPropertyManager::slotValueChanged(QtProperty *property, const QVariant &value)
993{
994 if (m_changingSubValue)
995 return;
996 bool enableSubPropertyHandling = true;
997
998 // Find a matching manager
999 int subResult = m_stringManager.valueChanged(m: this, property, value);
1000 if (subResult == NoMatch)
1001 subResult = m_keySequenceManager.valueChanged(m: this, property, value);
1002 if (subResult == NoMatch)
1003 subResult = m_stringListManager.valueChanged(m: this, property, value);
1004 if (subResult == NoMatch)
1005 subResult = m_brushManager.valueChanged(vm: this, property, value);
1006 if (subResult == NoMatch)
1007 subResult = m_fontManager.valueChanged(vm: this, property, value);
1008 if (subResult != NoMatch) {
1009 if (subResult == Changed)
1010 emit valueChanged(property, value, enableSubPropertyHandling);
1011 return;
1012 }
1013
1014 if (QtProperty *flagProperty = m_flagToProperty.value(akey: property, adefaultValue: 0)) {
1015 const auto subFlags = m_propertyToFlags.value(akey: flagProperty);
1016 const int subFlagCount = subFlags.count();
1017 // flag changed
1018 const bool subValue = variantProperty(property)->value().toBool();
1019 const int subIndex = subFlags.indexOf(t: property);
1020 if (subIndex < 0)
1021 return;
1022
1023 uint newValue = 0;
1024
1025 m_changingSubValue = true;
1026
1027 FlagData data = m_flagValues.value(akey: flagProperty);
1028 const auto values = data.values;
1029 // Compute new value, without including (additional) supermasks
1030 if (values.at(i: subIndex) == 0) {
1031 for (int i = 0; i < subFlagCount; ++i) {
1032 QtVariantProperty *subFlag = variantProperty(property: subFlags.at(i));
1033 subFlag->setValue(i == subIndex);
1034 }
1035 } else {
1036 if (subValue)
1037 newValue = values.at(i: subIndex); // value mask of subValue
1038 for (int i = 0; i < subFlagCount; ++i) {
1039 QtVariantProperty *subFlag = variantProperty(property: subFlags.at(i));
1040 if (subFlag->value().toBool() && bitCount(mask: values.at(i)) == 1)
1041 newValue |= values.at(i);
1042 }
1043 if (newValue == 0) {
1044 // Uncheck all items except 0-mask
1045 for (int i = 0; i < subFlagCount; ++i) {
1046 QtVariantProperty *subFlag = variantProperty(property: subFlags.at(i));
1047 subFlag->setValue(values.at(i) == 0);
1048 }
1049 } else if (newValue == data.val) {
1050 if (!subValue && bitCount(mask: values.at(i: subIndex)) > 1) {
1051 // We unchecked something, but the original value still holds
1052 variantProperty(property)->setValue(true);
1053 }
1054 } else {
1055 // Make sure 0-mask is not selected
1056 for (int i = 0; i < subFlagCount; ++i) {
1057 QtVariantProperty *subFlag = variantProperty(property: subFlags.at(i));
1058 if (values.at(i) == 0)
1059 subFlag->setValue(false);
1060 }
1061 // Check/uncheck proper masks
1062 if (subValue) {
1063 // Make sure submasks and supermasks are selected
1064 for (int i = 0; i < subFlagCount; ++i) {
1065 QtVariantProperty *subFlag = variantProperty(property: subFlags.at(i));
1066 const uint vi = values.at(i);
1067 if ((vi != 0) && ((vi & newValue) == vi) && !subFlag->value().toBool())
1068 subFlag->setValue(true);
1069 }
1070 } else {
1071 // Make sure supermasks are not selected if they're no longer valid
1072 for (int i = 0; i < subFlagCount; ++i) {
1073 QtVariantProperty *subFlag = variantProperty(property: subFlags.at(i));
1074 const uint vi = values.at(i);
1075 if (subFlag->value().toBool() && ((vi & newValue) != vi))
1076 subFlag->setValue(false);
1077 }
1078 }
1079 }
1080 }
1081 m_changingSubValue = false;
1082 data.val = newValue;
1083 QVariant v;
1084 v.setValue(data.val);
1085 variantProperty(property: flagProperty)->setValue(v);
1086 } else if (QtProperty *alignProperty = m_alignHToProperty.value(akey: property, adefaultValue: 0)) {
1087 const uint v = m_alignValues.value(akey: alignProperty);
1088 const uint newValue = indexHToAlign(idx: value.toInt()) | indexVToAlign(idx: alignToIndexV(align: v));
1089 if (v == newValue)
1090 return;
1091
1092 variantProperty(property: alignProperty)->setValue(newValue);
1093 } else if (QtProperty *alignProperty = m_alignVToProperty.value(akey: property, adefaultValue: 0)) {
1094 const uint v = m_alignValues.value(akey: alignProperty);
1095 const uint newValue = indexVToAlign(idx: value.toInt()) | indexHToAlign(idx: alignToIndexH(align: v));
1096 if (v == newValue)
1097 return;
1098
1099 variantProperty(property: alignProperty)->setValue(newValue);
1100 } else if (QtProperty *iProperty = m_iconSubPropertyToProperty.value(akey: property, adefaultValue: 0)) {
1101 QtVariantProperty *iconProperty = variantProperty(property: iProperty);
1102 PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(v: iconProperty->value());
1103 QMap<QtProperty *, QPair<QIcon::Mode, QIcon::State> >::ConstIterator itState = m_iconSubPropertyToState.constFind(key: property);
1104 if (itState != m_iconSubPropertyToState.constEnd()) {
1105 QPair<QIcon::Mode, QIcon::State> pair = m_iconSubPropertyToState.value(akey: property);
1106 icon.setPixmap(mode: pair.first, state: pair.second, path: qvariant_cast<PropertySheetPixmapValue>(v: value));
1107 } else { // must be theme property
1108 icon.setTheme(value.toString());
1109 }
1110 QtProperty *origSourceOfChange = m_sourceOfChange;
1111 if (!origSourceOfChange)
1112 m_sourceOfChange = property;
1113 iconProperty->setValue(QVariant::fromValue(value: icon));
1114 if (!origSourceOfChange)
1115 m_sourceOfChange = origSourceOfChange;
1116 } else if (m_iconValues.contains(key: property)) {
1117 enableSubPropertyHandling = m_sourceOfChange;
1118 }
1119 emit valueChanged(property, value, enableSubPropertyHandling);
1120}
1121
1122void DesignerPropertyManager::slotPropertyDestroyed(QtProperty *property)
1123{
1124 if (QtProperty *flagProperty = m_flagToProperty.value(akey: property, adefaultValue: 0)) {
1125 PropertyToPropertyListMap::iterator it = m_propertyToFlags.find(key: flagProperty);
1126 auto &propertyList = it.value();
1127 propertyList.replace(i: propertyList.indexOf(t: property), t: 0);
1128 m_flagToProperty.remove(key: property);
1129 } else if (QtProperty *alignProperty = m_alignHToProperty.value(akey: property, adefaultValue: 0)) {
1130 m_propertyToAlignH.remove(key: alignProperty);
1131 m_alignHToProperty.remove(key: property);
1132 } else if (QtProperty *alignProperty = m_alignVToProperty.value(akey: property, adefaultValue: 0)) {
1133 m_propertyToAlignV.remove(key: alignProperty);
1134 m_alignVToProperty.remove(key: property);
1135 } else if (m_stringManager.destroy(subProperty: property)
1136 || m_stringListManager.destroy(subProperty: property)
1137 || m_keySequenceManager.destroy(subProperty: property)) {
1138 } else if (QtProperty *iconProperty = m_iconSubPropertyToProperty.value(akey: property, adefaultValue: 0)) {
1139 if (m_propertyToTheme.value(akey: iconProperty) == property) {
1140 m_propertyToTheme.remove(key: iconProperty);
1141 } else {
1142 QMap<QtProperty *, QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> >::iterator it =
1143 m_propertyToIconSubProperties.find(key: iconProperty);
1144 QPair<QIcon::Mode, QIcon::State> state = m_iconSubPropertyToState.value(akey: property);
1145 QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> &propertyList = it.value();
1146 propertyList.remove(key: state);
1147 m_iconSubPropertyToState.remove(key: property);
1148 }
1149 m_iconSubPropertyToProperty.remove(key: property);
1150 } else {
1151 m_fontManager.slotPropertyDestroyed(property);
1152 m_brushManager.slotPropertyDestroyed(property);
1153 }
1154 m_alignDefault.remove(key: property);
1155}
1156
1157QStringList DesignerPropertyManager::attributes(int propertyType) const
1158{
1159 if (!isPropertyTypeSupported(propertyType))
1160 return QStringList();
1161
1162 QStringList list = QtVariantPropertyManager::attributes(propertyType);
1163 if (propertyType == designerFlagTypeId()) {
1164 list.append(t: QLatin1String(flagsAttributeC));
1165 } else if (propertyType == designerPixmapTypeId()) {
1166 list.append(t: QLatin1String(defaultResourceAttributeC));
1167 } else if (propertyType == designerIconTypeId()) {
1168 list.append(t: QLatin1String(defaultResourceAttributeC));
1169 } else if (propertyType == designerStringTypeId() || propertyType == QVariant::String) {
1170 list.append(t: QLatin1String(validationModesAttributeC));
1171 list.append(t: QLatin1String(fontAttributeC));
1172 list.append(t: QLatin1String(themeAttributeC));
1173 } else if (propertyType == QVariant::Palette) {
1174 list.append(t: QLatin1String(superPaletteAttributeC));
1175 }
1176 list.append(t: QLatin1String(resettableAttributeC));
1177 return list;
1178}
1179
1180int DesignerPropertyManager::attributeType(int propertyType, const QString &attribute) const
1181{
1182 if (!isPropertyTypeSupported(propertyType))
1183 return 0;
1184
1185 if (propertyType == designerFlagTypeId() && attribute == QLatin1String(flagsAttributeC))
1186 return designerFlagListTypeId();
1187 if (propertyType == designerPixmapTypeId() && attribute == QLatin1String(defaultResourceAttributeC))
1188 return QVariant::Pixmap;
1189 if (propertyType == designerIconTypeId() && attribute == QLatin1String(defaultResourceAttributeC))
1190 return QVariant::Icon;
1191 if (attribute == QLatin1String(resettableAttributeC))
1192 return QVariant::Bool;
1193 if (propertyType == designerStringTypeId() || propertyType == QVariant::String) {
1194 if (attribute == QLatin1String(validationModesAttributeC))
1195 return QVariant::Int;
1196 if (attribute == QLatin1String(fontAttributeC))
1197 return QVariant::Font;
1198 if (attribute == QLatin1String(themeAttributeC))
1199 return QVariant::Bool;
1200 }
1201 if (propertyType == QVariant::Palette && attribute == QLatin1String(superPaletteAttributeC))
1202 return QVariant::Palette;
1203
1204 return QtVariantPropertyManager::attributeType(propertyType, attribute);
1205}
1206
1207QVariant DesignerPropertyManager::attributeValue(const QtProperty *property, const QString &attribute) const
1208{
1209 QtProperty *prop = const_cast<QtProperty *>(property);
1210
1211 if (attribute == QLatin1String(resettableAttributeC)) {
1212 const PropertyBoolMap::const_iterator it = m_resetMap.constFind(key: prop);
1213 if (it != m_resetMap.constEnd())
1214 return it.value();
1215 }
1216
1217 if (attribute == QLatin1String(flagsAttributeC)) {
1218 PropertyFlagDataMap::const_iterator it = m_flagValues.constFind(key: prop);
1219 if (it != m_flagValues.constEnd()) {
1220 QVariant v;
1221 v.setValue(it.value().flags);
1222 return v;
1223 }
1224 }
1225 if (attribute == QLatin1String(validationModesAttributeC)) {
1226 const PropertyIntMap::const_iterator it = m_stringAttributes.constFind(key: prop);
1227 if (it != m_stringAttributes.constEnd())
1228 return it.value();
1229 }
1230
1231 if (attribute == QLatin1String(fontAttributeC)) {
1232 const PropertyFontMap::const_iterator it = m_stringFontAttributes.constFind(key: prop);
1233 if (it != m_stringFontAttributes.constEnd())
1234 return it.value();
1235 }
1236
1237 if (attribute == QLatin1String(themeAttributeC)) {
1238 const PropertyBoolMap::const_iterator it = m_stringThemeAttributes.constFind(key: prop);
1239 if (it != m_stringThemeAttributes.constEnd())
1240 return it.value();
1241 }
1242
1243 if (attribute == QLatin1String(superPaletteAttributeC)) {
1244 PropertyPaletteDataMap::const_iterator it = m_paletteValues.constFind(key: prop);
1245 if (it != m_paletteValues.constEnd())
1246 return it.value().superPalette;
1247 }
1248
1249 if (attribute == QLatin1String(defaultResourceAttributeC)) {
1250 QMap<QtProperty *, QPixmap>::const_iterator itPix = m_defaultPixmaps.constFind(key: prop);
1251 if (itPix != m_defaultPixmaps.constEnd())
1252 return itPix.value();
1253
1254 QMap<QtProperty *, QIcon>::const_iterator itIcon = m_defaultIcons.constFind(key: prop);
1255 if (itIcon != m_defaultIcons.constEnd())
1256 return itIcon.value();
1257 }
1258
1259 if (attribute == alignDefaultAttribute()) {
1260 Qt::Alignment v = m_alignDefault.value(key: property,
1261 defaultValue: Qt::Alignment(Qt::AlignLeading | Qt::AlignHCenter));
1262 return QVariant(uint(v));
1263 }
1264
1265 return QtVariantPropertyManager::attributeValue(property, attribute);
1266}
1267
1268void DesignerPropertyManager::setAttribute(QtProperty *property,
1269 const QString &attribute, const QVariant &value)
1270{
1271 if (attribute == QLatin1String(resettableAttributeC) && m_resetMap.contains(key: property)) {
1272 if (value.userType() != QVariant::Bool)
1273 return;
1274 const bool val = value.toBool();
1275 const PropertyBoolMap::iterator it = m_resetMap.find(key: property);
1276 if (it.value() == val)
1277 return;
1278 it.value() = val;
1279 emit attributeChanged(property: variantProperty(property), attribute, val: value);
1280 return;
1281 }
1282 if (attribute == QLatin1String(flagsAttributeC) && m_flagValues.contains(key: property)) {
1283 if (value.userType() != designerFlagListTypeId())
1284 return;
1285
1286 const DesignerFlagList flags = qvariant_cast<DesignerFlagList>(v: value);
1287 PropertyFlagDataMap::iterator fit = m_flagValues.find(key: property);
1288 FlagData data = fit.value();
1289 if (data.flags == flags)
1290 return;
1291
1292 PropertyToPropertyListMap::iterator pfit = m_propertyToFlags.find(key: property);
1293 for (QtProperty *prop : qAsConst(t&: pfit.value())) {
1294 if (prop) {
1295 delete prop;
1296 m_flagToProperty.remove(key: prop);
1297 }
1298 }
1299 pfit.value().clear();
1300
1301 QList<uint> values;
1302
1303 for (const QPair<QString, uint> &pair : flags) {
1304 const QString flagName = pair.first;
1305 QtProperty *prop = addProperty(propertyType: QVariant::Bool);
1306 prop->setPropertyName(flagName);
1307 property->addSubProperty(property: prop);
1308 m_propertyToFlags[property].append(t: prop);
1309 m_flagToProperty[prop] = property;
1310 values.append(t: pair.second);
1311 }
1312
1313 data.val = 0;
1314 data.flags = flags;
1315 data.values = values;
1316
1317 fit.value() = data;
1318
1319 QVariant v;
1320 v.setValue(flags);
1321 emit attributeChanged(property, attribute, val: v);
1322
1323 emit propertyChanged(property);
1324 emit QtVariantPropertyManager::valueChanged(property, val: data.val);
1325 } else if (attribute == QLatin1String(validationModesAttributeC) && m_stringAttributes.contains(key: property)) {
1326 if (value.userType() != QVariant::Int)
1327 return;
1328
1329 const PropertyIntMap::iterator it = m_stringAttributes.find(key: property);
1330 const int oldValue = it.value();
1331
1332 const int newValue = value.toInt();
1333
1334 if (oldValue == newValue)
1335 return;
1336
1337 it.value() = newValue;
1338
1339 emit attributeChanged(property, attribute, val: newValue);
1340 } else if (attribute == QLatin1String(fontAttributeC) && m_stringFontAttributes.contains(key: property)) {
1341 if (value.userType() != QVariant::Font)
1342 return;
1343
1344 const PropertyFontMap::iterator it = m_stringFontAttributes.find(key: property);
1345 const QFont oldValue = it.value();
1346
1347 const QFont newValue = qvariant_cast<QFont>(v: value);
1348
1349 if (oldValue == newValue)
1350 return;
1351
1352 it.value() = newValue;
1353
1354 emit attributeChanged(property, attribute, val: newValue);
1355 } else if (attribute == QLatin1String(themeAttributeC) && m_stringThemeAttributes.contains(key: property)) {
1356 if (value.userType() != QVariant::Bool)
1357 return;
1358
1359 const PropertyBoolMap::iterator it = m_stringThemeAttributes.find(key: property);
1360 const bool oldValue = it.value();
1361
1362 const bool newValue = value.toBool();
1363
1364 if (oldValue == newValue)
1365 return;
1366
1367 it.value() = newValue;
1368
1369 emit attributeChanged(property, attribute, val: newValue);
1370 } else if (attribute == QLatin1String(superPaletteAttributeC) && m_paletteValues.contains(key: property)) {
1371 if (value.userType() != QVariant::Palette)
1372 return;
1373
1374 QPalette superPalette = qvariant_cast<QPalette>(v: value);
1375
1376 const PropertyPaletteDataMap::iterator it = m_paletteValues.find(key: property);
1377 PaletteData data = it.value();
1378 if (data.superPalette == superPalette)
1379 return;
1380
1381 data.superPalette = superPalette;
1382 // resolve here
1383 const uint mask = data.val.resolve();
1384 data.val = data.val.resolve(superPalette);
1385 data.val.resolve(mask);
1386
1387 it.value() = data;
1388
1389 QVariant v;
1390 v.setValue(superPalette);
1391 emit attributeChanged(property, attribute, val: v);
1392
1393 emit propertyChanged(property);
1394 emit QtVariantPropertyManager::valueChanged(property, val: data.val); // if resolve was done, this is also for consistency
1395 } else if (attribute == QLatin1String(defaultResourceAttributeC) && m_defaultPixmaps.contains(key: property)) {
1396 if (value.userType() != QVariant::Pixmap)
1397 return;
1398
1399 QPixmap defaultPixmap = qvariant_cast<QPixmap>(v: value);
1400
1401 const QMap<QtProperty *, QPixmap>::iterator it = m_defaultPixmaps.find(key: property);
1402 QPixmap oldDefaultPixmap = it.value();
1403 if (defaultPixmap.cacheKey() == oldDefaultPixmap.cacheKey())
1404 return;
1405
1406 it.value() = defaultPixmap;
1407
1408 QVariant v = QVariant::fromValue(value: defaultPixmap);
1409 emit attributeChanged(property, attribute, val: v);
1410
1411 emit propertyChanged(property);
1412 } else if (attribute == QLatin1String(defaultResourceAttributeC) && m_defaultIcons.contains(key: property)) {
1413 if (value.userType() != QVariant::Icon)
1414 return;
1415
1416 QIcon defaultIcon = qvariant_cast<QIcon>(v: value);
1417
1418 const QMap<QtProperty *, QIcon>::iterator it = m_defaultIcons.find(key: property);
1419 QIcon oldDefaultIcon = it.value();
1420 if (defaultIcon.cacheKey() == oldDefaultIcon.cacheKey())
1421 return;
1422
1423 it.value() = defaultIcon;
1424
1425 qdesigner_internal::PropertySheetIconValue icon = m_iconValues.value(akey: property);
1426 if (icon.paths().isEmpty()) {
1427 QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> subIconProperties = m_propertyToIconSubProperties.value(akey: property);
1428 for (auto itSub = subIconProperties.cbegin(), end = subIconProperties.cend(); itSub != end; ++itSub) {
1429 QPair<QIcon::Mode, QIcon::State> pair = itSub.key();
1430 QtProperty *subProp = itSub.value();
1431 setAttribute(property: subProp, attribute: QLatin1String(defaultResourceAttributeC),
1432 value: defaultIcon.pixmap(w: 16, h: 16, mode: pair.first, state: pair.second));
1433 }
1434 }
1435
1436 QVariant v = QVariant::fromValue(value: defaultIcon);
1437 emit attributeChanged(property, attribute, val: v);
1438
1439 emit propertyChanged(property);
1440 } else if (attribute == alignDefaultAttribute()) {
1441 m_alignDefault[property] = Qt::Alignment(value.toUInt());
1442 }
1443 QtVariantPropertyManager::setAttribute(property, attribute, value);
1444}
1445
1446int DesignerPropertyManager::designerFlagTypeId()
1447{
1448 static const int rc = qMetaTypeId<DesignerFlagPropertyType>();
1449 return rc;
1450}
1451
1452int DesignerPropertyManager::designerFlagListTypeId()
1453{
1454 static const int rc = qMetaTypeId<DesignerFlagList>();
1455 return rc;
1456}
1457
1458int DesignerPropertyManager::designerAlignmentTypeId()
1459{
1460 static const int rc = qMetaTypeId<DesignerAlignmentPropertyType>();
1461 return rc;
1462}
1463
1464int DesignerPropertyManager::designerPixmapTypeId()
1465{
1466 return qMetaTypeId<PropertySheetPixmapValue>();
1467}
1468
1469int DesignerPropertyManager::designerIconTypeId()
1470{
1471 return qMetaTypeId<PropertySheetIconValue>();
1472}
1473
1474int DesignerPropertyManager::designerStringTypeId()
1475{
1476 return qMetaTypeId<PropertySheetStringValue>();
1477}
1478
1479int DesignerPropertyManager::designerStringListTypeId()
1480{
1481 return qMetaTypeId<PropertySheetStringListValue>();
1482}
1483
1484int DesignerPropertyManager::designerKeySequenceTypeId()
1485{
1486 return qMetaTypeId<PropertySheetKeySequenceValue>();
1487}
1488
1489QString DesignerPropertyManager::alignDefaultAttribute()
1490{
1491 return QStringLiteral("alignDefault");
1492}
1493
1494uint DesignerPropertyManager::alignDefault(const QtVariantProperty *prop)
1495{
1496 return prop->attributeValue(attribute: DesignerPropertyManager::alignDefaultAttribute()).toUInt();
1497}
1498
1499bool DesignerPropertyManager::isPropertyTypeSupported(int propertyType) const
1500{
1501 switch (propertyType) {
1502 case QVariant::Palette:
1503 case QVariant::UInt:
1504 case QVariant::LongLong:
1505 case QVariant::ULongLong:
1506 case QVariant::Url:
1507 case QVariant::ByteArray:
1508 case QVariant::StringList:
1509 case QVariant::Brush:
1510 return true;
1511 default:
1512 break;
1513 }
1514
1515 if (propertyType == designerFlagTypeId())
1516 return true;
1517 if (propertyType == designerAlignmentTypeId())
1518 return true;
1519 if (propertyType == designerPixmapTypeId())
1520 return true;
1521 if (propertyType == designerIconTypeId())
1522 return true;
1523 if (propertyType == designerStringTypeId() || propertyType == designerStringListTypeId())
1524 return true;
1525 if (propertyType == designerKeySequenceTypeId())
1526 return true;
1527
1528 return QtVariantPropertyManager::isPropertyTypeSupported(propertyType);
1529}
1530
1531QString DesignerPropertyManager::valueText(const QtProperty *property) const
1532{
1533 if (m_flagValues.contains(key: const_cast<QtProperty *>(property))) {
1534 const FlagData data = m_flagValues.value(akey: const_cast<QtProperty *>(property));
1535 const uint v = data.val;
1536 const QChar bar = QLatin1Char('|');
1537 QString valueStr;
1538 for (const DesignerIntPair &p : data.flags) {
1539 const uint val = p.second;
1540 const bool checked = (val == 0) ? (v == 0) : ((val & v) == val);
1541 if (checked) {
1542 if (!valueStr.isEmpty())
1543 valueStr += bar;
1544 valueStr += p.first;
1545 }
1546 }
1547 return valueStr;
1548 }
1549 if (m_alignValues.contains(key: const_cast<QtProperty *>(property))) {
1550 const uint v = m_alignValues.value(akey: const_cast<QtProperty *>(property));
1551 return tr(s: "%1, %2").arg(args: indexHToString(idx: alignToIndexH(align: v)),
1552 args: indexVToString(idx: alignToIndexV(align: v)));
1553 }
1554 if (m_paletteValues.contains(key: const_cast<QtProperty *>(property))) {
1555 const PaletteData data = m_paletteValues.value(akey: const_cast<QtProperty *>(property));
1556 const uint mask = data.val.resolve();
1557 if (mask)
1558 return tr(s: "Customized (%n roles)", c: nullptr, n: bitCount(mask));
1559 static const QString inherited = tr(s: "Inherited");
1560 return inherited;
1561 }
1562 if (m_iconValues.contains(key: const_cast<QtProperty *>(property))) {
1563 const PropertySheetIconValue icon = m_iconValues.value(akey: const_cast<QtProperty *>(property));
1564 const QString theme = icon.theme();
1565 if (!theme.isEmpty() && QIcon::hasThemeIcon(name: theme))
1566 return tr(s: "[Theme] %1").arg(a: theme);
1567 const auto &paths = icon.paths();
1568 const PropertySheetIconValue::ModeStateToPixmapMap::const_iterator it = paths.constFind(key: qMakePair(x: QIcon::Normal, y: QIcon::Off));
1569 if (it == paths.constEnd())
1570 return QString();
1571 return QFileInfo(it.value().path()).fileName();
1572 }
1573 if (m_pixmapValues.contains(key: const_cast<QtProperty *>(property))) {
1574 const QString path = m_pixmapValues.value(akey: const_cast<QtProperty *>(property)).path();
1575 if (path.isEmpty())
1576 return QString();
1577 return QFileInfo(path).fileName();
1578 }
1579 if (m_uintValues.contains(key: const_cast<QtProperty *>(property))) {
1580 return QString::number(m_uintValues.value(akey: const_cast<QtProperty *>(property)));
1581 }
1582 if (m_longLongValues.contains(key: const_cast<QtProperty *>(property))) {
1583 return QString::number(m_longLongValues.value(akey: const_cast<QtProperty *>(property)));
1584 }
1585 if (m_uLongLongValues.contains(key: const_cast<QtProperty *>(property))) {
1586 return QString::number(m_uLongLongValues.value(akey: const_cast<QtProperty *>(property)));
1587 }
1588 if (m_urlValues.contains(key: const_cast<QtProperty *>(property))) {
1589 return m_urlValues.value(akey: const_cast<QtProperty *>(property)).toString();
1590 }
1591 if (m_byteArrayValues.contains(key: const_cast<QtProperty *>(property))) {
1592 return QString::fromUtf8(str: m_byteArrayValues.value(akey: const_cast<QtProperty *>(property)));
1593 }
1594 const int vType = QtVariantPropertyManager::valueType(property);
1595 if (vType == QVariant::String || vType == designerStringTypeId()) {
1596 const QString str = (QtVariantPropertyManager::valueType(property) == QVariant::String) ? value(property).toString() : qvariant_cast<PropertySheetStringValue>(v: value(property)).value();
1597 const int validationMode = attributeValue(property, attribute: QLatin1String(validationModesAttributeC)).toInt();
1598 return TextPropertyEditor::stringToEditorString(s: str, validationMode: static_cast<TextPropertyValidationMode>(validationMode));
1599 }
1600 if (vType == QVariant::StringList || vType == designerStringListTypeId()) {
1601 QVariant v = value(property);
1602 const QStringList list = v.type() == QVariant::StringList ? v.toStringList() : qvariant_cast<PropertySheetStringListValue>(v).value();
1603 return list.join(sep: QLatin1String("; "));
1604 }
1605 if (vType == designerKeySequenceTypeId()) {
1606 return qvariant_cast<PropertySheetKeySequenceValue>(v: value(property)).value().toString(format: QKeySequence::NativeText);
1607 }
1608 if (vType == QVariant::Bool) {
1609 return QString();
1610 }
1611
1612 QString rc;
1613 if (m_brushManager.valueText(property, text: &rc))
1614 return rc;
1615 return QtVariantPropertyManager::valueText(property);
1616}
1617
1618void DesignerPropertyManager::reloadResourceProperties()
1619{
1620 DesignerIconCache *iconCache = nullptr;
1621 for (auto itIcon = m_iconValues.cbegin(), end = m_iconValues.cend(); itIcon!= end; ++itIcon) {
1622 QtProperty *property = itIcon.key();
1623 const PropertySheetIconValue &icon = itIcon.value();
1624
1625 QIcon defaultIcon = m_defaultIcons.value(akey: property);
1626 if (!icon.paths().isEmpty()) {
1627 if (!iconCache) {
1628 QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(obj: m_object);
1629 qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(object: formWindow);
1630 iconCache = fwb->iconCache();
1631 }
1632 if (iconCache)
1633 defaultIcon = iconCache->icon(value: icon);
1634 }
1635
1636 QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> subProperties = m_propertyToIconSubProperties.value(akey: property);
1637 for (auto itSub = subProperties.cbegin(), end = subProperties.cend(); itSub != end; ++itSub) {
1638 const QPair<QIcon::Mode, QIcon::State> pair = itSub.key();
1639 QtVariantProperty *subProperty = variantProperty(property: itSub.value());
1640 subProperty->setAttribute(attribute: QLatin1String(defaultResourceAttributeC),
1641 value: defaultIcon.pixmap(w: 16, h: 16, mode: pair.first, state: pair.second));
1642 }
1643
1644 emit propertyChanged(property);
1645 emit QtVariantPropertyManager::valueChanged(property, val: QVariant::fromValue(value: itIcon.value()));
1646 }
1647 for (auto itPix = m_pixmapValues.cbegin(), end = m_pixmapValues.cend(); itPix != end; ++itPix) {
1648 QtProperty *property = itPix.key();
1649 emit propertyChanged(property);
1650 emit QtVariantPropertyManager::valueChanged(property, val: QVariant::fromValue(value: itPix.value()));
1651 }
1652}
1653
1654QIcon DesignerPropertyManager::valueIcon(const QtProperty *property) const
1655{
1656 if (m_iconValues.contains(key: const_cast<QtProperty *>(property))) {
1657 if (!property->isModified())
1658 return m_defaultIcons.value(akey: const_cast<QtProperty *>(property)).pixmap(w: 16, h: 16);
1659 QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(obj: m_object);
1660 qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(object: formWindow);
1661 if (fwb)
1662 return fwb->iconCache()->icon(value: m_iconValues.value(akey: const_cast<QtProperty *>(property))).pixmap(w: 16, h: 16);
1663 } else if (m_pixmapValues.contains(key: const_cast<QtProperty *>(property))) {
1664 if (!property->isModified())
1665 return m_defaultPixmaps.value(akey: const_cast<QtProperty *>(property));
1666 QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(obj: m_object);
1667 qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(object: formWindow);
1668 if (fwb)
1669 return fwb->pixmapCache()->pixmap(value: m_pixmapValues.value(akey: const_cast<QtProperty *>(property)));
1670 } else if (m_stringThemeAttributes.value(key: const_cast<QtProperty *>(property), defaultValue: false)) {
1671 return QIcon::fromTheme(name: value(property).toString());
1672 } else {
1673 QIcon rc;
1674 if (m_brushManager.valueIcon(property, icon: &rc))
1675 return rc;
1676 }
1677
1678 return QtVariantPropertyManager::valueIcon(property);
1679}
1680
1681QVariant DesignerPropertyManager::value(const QtProperty *property) const
1682{
1683 if (m_flagValues.contains(key: const_cast<QtProperty *>(property)))
1684 return m_flagValues.value(akey: const_cast<QtProperty *>(property)).val;
1685 if (m_alignValues.contains(key: const_cast<QtProperty *>(property)))
1686 return m_alignValues.value(akey: const_cast<QtProperty *>(property));
1687 if (m_paletteValues.contains(key: const_cast<QtProperty *>(property)))
1688 return m_paletteValues.value(akey: const_cast<QtProperty *>(property)).val;
1689 if (m_iconValues.contains(key: const_cast<QtProperty *>(property)))
1690 return QVariant::fromValue(value: m_iconValues.value(akey: const_cast<QtProperty *>(property)));
1691 if (m_pixmapValues.contains(key: const_cast<QtProperty *>(property)))
1692 return QVariant::fromValue(value: m_pixmapValues.value(akey: const_cast<QtProperty *>(property)));
1693 QVariant rc;
1694 if (m_stringManager.value(property, rc: &rc)
1695 || m_keySequenceManager.value(property, rc: &rc)
1696 || m_stringListManager.value(property, rc: &rc)
1697 || m_brushManager.value(property, v: &rc))
1698 return rc;
1699 if (m_uintValues.contains(key: const_cast<QtProperty *>(property)))
1700 return m_uintValues.value(akey: const_cast<QtProperty *>(property));
1701 if (m_longLongValues.contains(key: const_cast<QtProperty *>(property)))
1702 return m_longLongValues.value(akey: const_cast<QtProperty *>(property));
1703 if (m_uLongLongValues.contains(key: const_cast<QtProperty *>(property)))
1704 return m_uLongLongValues.value(akey: const_cast<QtProperty *>(property));
1705 if (m_urlValues.contains(key: const_cast<QtProperty *>(property)))
1706 return m_urlValues.value(akey: const_cast<QtProperty *>(property));
1707 if (m_byteArrayValues.contains(key: const_cast<QtProperty *>(property)))
1708 return m_byteArrayValues.value(akey: const_cast<QtProperty *>(property));
1709
1710 return QtVariantPropertyManager::value(property);
1711}
1712
1713int DesignerPropertyManager::valueType(int propertyType) const
1714{
1715 switch (propertyType) {
1716 case QVariant::Palette:
1717 case QVariant::UInt:
1718 case QVariant::LongLong:
1719 case QVariant::ULongLong:
1720 case QVariant::Url:
1721 case QVariant::ByteArray:
1722 case QVariant::StringList:
1723 case QVariant::Brush:
1724 return propertyType;
1725 default:
1726 break;
1727 }
1728 if (propertyType == designerFlagTypeId())
1729 return QVariant::UInt;
1730 if (propertyType == designerAlignmentTypeId())
1731 return QVariant::UInt;
1732 if (propertyType == designerPixmapTypeId())
1733 return propertyType;
1734 if (propertyType == designerIconTypeId())
1735 return propertyType;
1736 if (propertyType == designerStringTypeId() || propertyType == designerStringListTypeId())
1737 return propertyType;
1738 if (propertyType == designerKeySequenceTypeId())
1739 return propertyType;
1740 return QtVariantPropertyManager::valueType(propertyType);
1741}
1742
1743void DesignerPropertyManager::setValue(QtProperty *property, const QVariant &value)
1744{
1745 int subResult = m_stringManager.setValue(m: this, property, expectedTypeId: designerStringTypeId(), value);
1746 if (subResult == NoMatch)
1747 subResult = m_stringListManager.setValue(m: this, property, expectedTypeId: designerStringListTypeId(), value);
1748 if (subResult == NoMatch)
1749 subResult = m_keySequenceManager.setValue(m: this, property, expectedTypeId: designerKeySequenceTypeId(), value);
1750 if (subResult == NoMatch)
1751 subResult = m_brushManager.setValue(vm: this, property, value);
1752 if (subResult != NoMatch) {
1753 if (subResult == Changed) {
1754 emit QtVariantPropertyManager::valueChanged(property, val: value);
1755 emit propertyChanged(property);
1756 }
1757 return;
1758 }
1759
1760 const PropertyFlagDataMap::iterator fit = m_flagValues.find(key: property);
1761
1762 if (fit != m_flagValues.end()) {
1763 if (value.type() != QVariant::UInt && !value.canConvert(targetTypeId: QVariant::UInt))
1764 return;
1765
1766 const uint v = value.toUInt();
1767
1768 FlagData data = fit.value();
1769 if (data.val == v)
1770 return;
1771
1772 // set Value
1773
1774 const auto values = data.values;
1775 const auto subFlags = m_propertyToFlags.value(akey: property);
1776 const int subFlagCount = subFlags.count();
1777 for (int i = 0; i < subFlagCount; ++i) {
1778 QtVariantProperty *subFlag = variantProperty(property: subFlags.at(i));
1779 const uint val = values.at(i);
1780 const bool checked = (val == 0) ? (v == 0) : ((val & v) == val);
1781 subFlag->setValue(checked);
1782 }
1783
1784 for (int i = 0; i < subFlagCount; ++i) {
1785 QtVariantProperty *subFlag = variantProperty(property: subFlags.at(i));
1786 const uint val = values.at(i);
1787 const bool checked = (val == 0) ? (v == 0) : ((val & v) == val);
1788 bool enabled = true;
1789 if (val == 0) {
1790 if (checked)
1791 enabled = false;
1792 } else if (bitCount(mask: val) > 1) {
1793 // Disabled if all flags contained in the mask are checked
1794 uint currentMask = 0;
1795 for (int j = 0; j < subFlagCount; ++j) {
1796 QtVariantProperty *subFlag = variantProperty(property: subFlags.at(i: j));
1797 if (bitCount(mask: values.at(i: j)) == 1)
1798 currentMask |= subFlag->value().toBool() ? values.at(i: j) : 0;
1799 }
1800 if ((currentMask & values.at(i)) == values.at(i))
1801 enabled = false;
1802 }
1803 subFlag->setEnabled(enabled);
1804 }
1805
1806 data.val = v;
1807 fit.value() = data;
1808
1809 emit QtVariantPropertyManager::valueChanged(property, val: data.val);
1810 emit propertyChanged(property);
1811
1812 return;
1813 }
1814 if (m_alignValues.contains(key: property)) {
1815 if (value.type() != QVariant::UInt && !value.canConvert(targetTypeId: QVariant::UInt))
1816 return;
1817
1818 const uint v = value.toUInt();
1819
1820 uint val = m_alignValues.value(akey: property);
1821
1822 if (val == v)
1823 return;
1824
1825 QtVariantProperty *alignH = variantProperty(property: m_propertyToAlignH.value(akey: property));
1826 QtVariantProperty *alignV = variantProperty(property: m_propertyToAlignV.value(akey: property));
1827
1828 if (alignH)
1829 alignH->setValue(alignToIndexH(align: v));
1830 if (alignV)
1831 alignV->setValue(alignToIndexV(align: v));
1832
1833 m_alignValues[property] = v;
1834
1835 emit QtVariantPropertyManager::valueChanged(property, val: v);
1836 emit propertyChanged(property);
1837
1838 return;
1839 }
1840 if (m_paletteValues.contains(key: property)) {
1841 if (value.type() != QVariant::Palette && !value.canConvert(targetTypeId: QVariant::Palette))
1842 return;
1843
1844 QPalette p = qvariant_cast<QPalette>(v: value);
1845
1846 PaletteData data = m_paletteValues.value(akey: property);
1847
1848 const uint mask = p.resolve();
1849 p = p.resolve(data.superPalette);
1850 p.resolve(mask);
1851
1852 if (data.val == p && data.val.resolve() == p.resolve())
1853 return;
1854
1855 data.val = p;
1856 m_paletteValues[property] = data;
1857
1858 emit QtVariantPropertyManager::valueChanged(property, val: data.val);
1859 emit propertyChanged(property);
1860
1861 return;
1862 }
1863 if (m_iconValues.contains(key: property)) {
1864 if (value.userType() != designerIconTypeId())
1865 return;
1866
1867 const PropertySheetIconValue icon = qvariant_cast<PropertySheetIconValue>(v: value);
1868
1869 const PropertySheetIconValue oldIcon = m_iconValues.value(akey: property);
1870 if (icon == oldIcon)
1871 return;
1872
1873 m_iconValues[property] = icon;
1874
1875 QIcon defaultIcon = m_defaultIcons.value(akey: property);
1876 if (!icon.paths().isEmpty()) {
1877 QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(obj: m_object);
1878 qdesigner_internal::FormWindowBase *fwb = qobject_cast<qdesigner_internal::FormWindowBase *>(object: formWindow);
1879 if (fwb)
1880 defaultIcon = fwb->iconCache()->icon(value: icon);
1881 }
1882
1883 const auto &iconPaths = icon.paths();
1884
1885 QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> subProperties = m_propertyToIconSubProperties.value(akey: property);
1886 for (auto itSub = subProperties.cbegin(), end = subProperties.cend(); itSub != end; ++itSub) {
1887 const QPair<QIcon::Mode, QIcon::State> pair = itSub.key();
1888 QtVariantProperty *subProperty = variantProperty(property: itSub.value());
1889 bool hasPath = iconPaths.contains(key: pair);
1890 subProperty->setModified(hasPath);
1891 subProperty->setValue(QVariant::fromValue(value: iconPaths.value(akey: pair)));
1892 subProperty->setAttribute(attribute: QLatin1String(defaultResourceAttributeC),
1893 value: defaultIcon.pixmap(w: 16, h: 16, mode: pair.first, state: pair.second));
1894 }
1895 QtVariantProperty *themeSubProperty = variantProperty(property: m_propertyToTheme.value(akey: property));
1896 if (themeSubProperty) {
1897 const QString theme = icon.theme();
1898 themeSubProperty->setModified(!theme.isEmpty());
1899 themeSubProperty->setValue(theme);
1900 }
1901
1902 emit QtVariantPropertyManager::valueChanged(property, val: QVariant::fromValue(value: icon));
1903 emit propertyChanged(property);
1904
1905 QString toolTip;
1906 const QMap<QPair<QIcon::Mode, QIcon::State>, PropertySheetPixmapValue>::ConstIterator itNormalOff =
1907 iconPaths.constFind(key: qMakePair(x: QIcon::Normal, y: QIcon::Off));
1908 if (itNormalOff != iconPaths.constEnd())
1909 toolTip = itNormalOff.value().path();
1910 // valueText() only show the file name; show full path as ToolTip.
1911 property->setToolTip(QDir::toNativeSeparators(pathName: toolTip));
1912
1913 return;
1914 }
1915 if (m_pixmapValues.contains(key: property)) {
1916 if (value.userType() != designerPixmapTypeId())
1917 return;
1918
1919 const PropertySheetPixmapValue pixmap = qvariant_cast<PropertySheetPixmapValue>(v: value);
1920
1921 const PropertySheetPixmapValue oldPixmap = m_pixmapValues.value(akey: property);
1922 if (pixmap == oldPixmap)
1923 return;
1924
1925 m_pixmapValues[property] = pixmap;
1926
1927 emit QtVariantPropertyManager::valueChanged(property, val: QVariant::fromValue(value: pixmap));
1928 emit propertyChanged(property);
1929
1930 // valueText() only show the file name; show full path as ToolTip.
1931 property->setToolTip(QDir::toNativeSeparators(pathName: pixmap.path()));
1932
1933 return;
1934 }
1935 if (m_uintValues.contains(key: property)) {
1936 if (value.type() != QVariant::UInt && !value.canConvert(targetTypeId: QVariant::UInt))
1937 return;
1938
1939 const uint v = value.toUInt(ok: nullptr);
1940
1941 const uint oldValue = m_uintValues.value(akey: property);
1942 if (v == oldValue)
1943 return;
1944
1945 m_uintValues[property] = v;
1946
1947 emit QtVariantPropertyManager::valueChanged(property, val: v);
1948 emit propertyChanged(property);
1949
1950 return;
1951 }
1952 if (m_longLongValues.contains(key: property)) {
1953 if (value.type() != QVariant::LongLong && !value.canConvert(targetTypeId: QVariant::LongLong))
1954 return;
1955
1956 const qlonglong v = value.toLongLong(ok: nullptr);
1957
1958 const qlonglong oldValue = m_longLongValues.value(akey: property);
1959 if (v == oldValue)
1960 return;
1961
1962 m_longLongValues[property] = v;
1963
1964 emit QtVariantPropertyManager::valueChanged(property, val: v);
1965 emit propertyChanged(property);
1966
1967 return;
1968 }
1969 if (m_uLongLongValues.contains(key: property)) {
1970 if (value.type() != QVariant::ULongLong && !value.canConvert(targetTypeId: QVariant::ULongLong))
1971 return;
1972
1973 qulonglong v = value.toULongLong(ok: nullptr);
1974
1975 qulonglong oldValue = m_uLongLongValues.value(akey: property);
1976 if (v == oldValue)
1977 return;
1978
1979 m_uLongLongValues[property] = v;
1980
1981 emit QtVariantPropertyManager::valueChanged(property, val: v);
1982 emit propertyChanged(property);
1983
1984 return;
1985 }
1986 if (m_urlValues.contains(key: property)) {
1987 if (value.type() != QVariant::Url && !value.canConvert(targetTypeId: QVariant::Url))
1988 return;
1989
1990 const QUrl v = value.toUrl();
1991
1992 const QUrl oldValue = m_urlValues.value(akey: property);
1993 if (v == oldValue)
1994 return;
1995
1996 m_urlValues[property] = v;
1997
1998 emit QtVariantPropertyManager::valueChanged(property, val: v);
1999 emit propertyChanged(property);
2000
2001 return;
2002 }
2003 if (m_byteArrayValues.contains(key: property)) {
2004 if (value.type() != QVariant::ByteArray && !value.canConvert(targetTypeId: QVariant::ByteArray))
2005 return;
2006
2007 const QByteArray v = value.toByteArray();
2008
2009 const QByteArray oldValue = m_byteArrayValues.value(akey: property);
2010 if (v == oldValue)
2011 return;
2012
2013 m_byteArrayValues[property] = v;
2014
2015 emit QtVariantPropertyManager::valueChanged(property, val: v);
2016 emit propertyChanged(property);
2017
2018 return;
2019 }
2020 m_fontManager.setValue(vm: this, property, value);
2021 QtVariantPropertyManager::setValue(property, val: value);
2022 if (QtVariantPropertyManager::valueType(property) == QVariant::Bool)
2023 property->setToolTip(QtVariantPropertyManager::valueText(property));
2024}
2025
2026void DesignerPropertyManager::initializeProperty(QtProperty *property)
2027{
2028 m_resetMap[property] = false;
2029
2030 const int type = propertyType(property);
2031 m_fontManager.preInitializeProperty(property, type, resetMap&: m_resetMap);
2032 switch (type) {
2033 case QVariant::Palette:
2034 m_paletteValues[property] = PaletteData();
2035 break;
2036 case QVariant::String:
2037 m_stringAttributes[property] = ValidationSingleLine;
2038 m_stringFontAttributes[property] = QApplication::font();
2039 m_stringThemeAttributes[property] = false;
2040 break;
2041 case QVariant::UInt:
2042 m_uintValues[property] = 0;
2043 break;
2044 case QVariant::LongLong:
2045 m_longLongValues[property] = 0;
2046 break;
2047 case QVariant::ULongLong:
2048 m_uLongLongValues[property] = 0;
2049 break;
2050 case QVariant::Url:
2051 m_urlValues[property] = QUrl();
2052 break;
2053 case QVariant::ByteArray:
2054 m_byteArrayValues[property] = nullptr;
2055 break;
2056 case QVariant::Brush:
2057 m_brushManager.initializeProperty(vm: this, property, enumTypeId: enumTypeId());
2058 break;
2059 default:
2060 if (type == designerFlagTypeId()) {
2061 m_flagValues[property] = FlagData();
2062 m_propertyToFlags[property] = QList<QtProperty *>();
2063 } else if (type == designerAlignmentTypeId()) {
2064 const uint align = Qt::AlignLeft | Qt::AlignVCenter;
2065 m_alignValues[property] = align;
2066
2067 QtVariantProperty *alignH = addProperty(propertyType: enumTypeId(), name: tr(s: "Horizontal"));
2068 QStringList namesH;
2069 namesH << indexHToString(idx: 0) << indexHToString(idx: 1) << indexHToString(idx: 2) << indexHToString(idx: 3);
2070 alignH->setAttribute(QStringLiteral("enumNames"), value: namesH);
2071 alignH->setValue(alignToIndexH(align));
2072 m_propertyToAlignH[property] = alignH;
2073 m_alignHToProperty[alignH] = property;
2074 property->addSubProperty(property: alignH);
2075
2076 QtVariantProperty *alignV = addProperty(propertyType: enumTypeId(), name: tr(s: "Vertical"));
2077 QStringList namesV;
2078 namesV << indexVToString(idx: 0) << indexVToString(idx: 1) << indexVToString(idx: 2);
2079 alignV->setAttribute(QStringLiteral("enumNames"), value: namesV);
2080 alignV->setValue(alignToIndexV(align));
2081 m_propertyToAlignV[property] = alignV;
2082 m_alignVToProperty[alignV] = property;
2083 property->addSubProperty(property: alignV);
2084 } else if (type == designerPixmapTypeId()) {
2085 m_pixmapValues[property] = PropertySheetPixmapValue();
2086 m_defaultPixmaps[property] = QPixmap();
2087 } else if (type == designerIconTypeId()) {
2088 m_iconValues[property] = PropertySheetIconValue();
2089 m_defaultIcons[property] = QIcon();
2090
2091 QtVariantProperty *themeProp = addProperty(propertyType: QVariant::String, name: tr(s: "Theme"));
2092 themeProp->setAttribute(attribute: QLatin1String(themeAttributeC), value: true);
2093 m_iconSubPropertyToProperty[themeProp] = property;
2094 m_propertyToTheme[property] = themeProp;
2095 m_resetMap[themeProp] = true;
2096 property->addSubProperty(property: themeProp);
2097
2098 createIconSubProperty(iconProperty: property, mode: QIcon::Normal, state: QIcon::Off, subName: tr(s: "Normal Off"));
2099 createIconSubProperty(iconProperty: property, mode: QIcon::Normal, state: QIcon::On, subName: tr(s: "Normal On"));
2100 createIconSubProperty(iconProperty: property, mode: QIcon::Disabled, state: QIcon::Off, subName: tr(s: "Disabled Off"));
2101 createIconSubProperty(iconProperty: property, mode: QIcon::Disabled, state: QIcon::On, subName: tr(s: "Disabled On"));
2102 createIconSubProperty(iconProperty: property, mode: QIcon::Active, state: QIcon::Off, subName: tr(s: "Active Off"));
2103 createIconSubProperty(iconProperty: property, mode: QIcon::Active, state: QIcon::On, subName: tr(s: "Active On"));
2104 createIconSubProperty(iconProperty: property, mode: QIcon::Selected, state: QIcon::Off, subName: tr(s: "Selected Off"));
2105 createIconSubProperty(iconProperty: property, mode: QIcon::Selected, state: QIcon::On, subName: tr(s: "Selected On"));
2106 } else if (type == designerStringTypeId()) {
2107 m_stringManager.initialize(m: this, property, value: PropertySheetStringValue());
2108 m_stringAttributes.insert(key: property, value: ValidationMultiLine);
2109 m_stringFontAttributes.insert(key: property, value: QApplication::font());
2110 m_stringThemeAttributes.insert(key: property, value: false);
2111 } else if (type == designerStringListTypeId()) {
2112 m_stringListManager.initialize(m: this, property, value: PropertySheetStringListValue());
2113 } else if (type == designerKeySequenceTypeId()) {
2114 m_keySequenceManager.initialize(m: this, property, value: PropertySheetKeySequenceValue());
2115 }
2116 }
2117
2118 QtVariantPropertyManager::initializeProperty(property);
2119 m_fontManager.postInitializeProperty(vm: this, property, type, enumTypeId: DesignerPropertyManager::enumTypeId());
2120 if (type == QVariant::Double)
2121 setAttribute(property, QStringLiteral("decimals"), value: 6);
2122}
2123
2124void DesignerPropertyManager::createIconSubProperty(QtProperty *iconProperty, QIcon::Mode mode, QIcon::State state, const QString &subName)
2125{
2126 QPair<QIcon::Mode, QIcon::State> pair = qMakePair(x: mode, y: state);
2127 QtVariantProperty *subProp = addProperty(propertyType: DesignerPropertyManager::designerPixmapTypeId(), name: subName);
2128 m_propertyToIconSubProperties[iconProperty][pair] = subProp;
2129 m_iconSubPropertyToState[subProp] = pair;
2130 m_iconSubPropertyToProperty[subProp] = iconProperty;
2131 m_resetMap[subProp] = true;
2132 iconProperty->addSubProperty(property: subProp);
2133}
2134
2135void DesignerPropertyManager::uninitializeProperty(QtProperty *property)
2136{
2137 m_resetMap.remove(key: property);
2138
2139 const auto propList = m_propertyToFlags.value(akey: property);
2140 for (QtProperty *prop : propList) {
2141 if (prop) {
2142 delete prop;
2143 m_flagToProperty.remove(key: prop);
2144 }
2145 }
2146 m_propertyToFlags.remove(key: property);
2147 m_flagValues.remove(key: property);
2148
2149 QtProperty *alignH = m_propertyToAlignH.value(akey: property);
2150 if (alignH) {
2151 delete alignH;
2152 m_alignHToProperty.remove(key: alignH);
2153 }
2154 QtProperty *alignV = m_propertyToAlignV.value(akey: property);
2155 if (alignV) {
2156 delete alignV;
2157 m_alignVToProperty.remove(key: alignV);
2158 }
2159
2160 m_stringManager.uninitialize(property);
2161 m_stringListManager.uninitialize(property);
2162 m_keySequenceManager.uninitialize(property);
2163
2164 if (QtProperty *iconTheme = m_propertyToTheme.value(akey: property)) {
2165 delete iconTheme;
2166 m_iconSubPropertyToProperty.remove(key: iconTheme);
2167 }
2168
2169 m_propertyToAlignH.remove(key: property);
2170 m_propertyToAlignV.remove(key: property);
2171
2172 m_stringAttributes.remove(key: property);
2173 m_stringFontAttributes.remove(key: property);
2174
2175 m_paletteValues.remove(key: property);
2176
2177 m_iconValues.remove(key: property);
2178 m_defaultIcons.remove(key: property);
2179
2180 m_pixmapValues.remove(key: property);
2181 m_defaultPixmaps.remove(key: property);
2182
2183 QMap<QPair<QIcon::Mode, QIcon::State>, QtProperty *> iconSubProperties = m_propertyToIconSubProperties.value(akey: property);
2184 for (auto itIcon = iconSubProperties.cbegin(), end = iconSubProperties.cend(); itIcon != end; ++itIcon) {
2185 QtProperty *subIcon = itIcon.value();
2186 delete subIcon;
2187 m_iconSubPropertyToState.remove(key: subIcon);
2188 m_iconSubPropertyToProperty.remove(key: subIcon);
2189 }
2190 m_propertyToIconSubProperties.remove(key: property);
2191 m_iconSubPropertyToState.remove(key: property);
2192 m_iconSubPropertyToProperty.remove(key: property);
2193
2194 m_uintValues.remove(key: property);
2195 m_longLongValues.remove(key: property);
2196 m_uLongLongValues.remove(key: property);
2197 m_urlValues.remove(key: property);
2198 m_byteArrayValues.remove(key: property);
2199
2200 m_fontManager.uninitializeProperty(property);
2201 m_brushManager.uninitializeProperty(property);
2202
2203 QtVariantPropertyManager::uninitializeProperty(property);
2204}
2205
2206bool DesignerPropertyManager::resetTextAlignmentProperty(QtProperty *property)
2207{
2208 const auto it = m_alignDefault.constFind(key: property);
2209 if (it == m_alignDefault.cend())
2210 return false;
2211 QtVariantProperty *alignProperty = variantProperty(property);
2212 alignProperty->setValue(DesignerPropertyManager::alignDefault(prop: alignProperty));
2213 alignProperty->setModified(false);
2214 return true;
2215}
2216
2217bool DesignerPropertyManager::resetFontSubProperty(QtProperty *property)
2218{
2219 return m_fontManager.resetFontSubProperty(vm: this, subProperty: property);
2220}
2221
2222bool DesignerPropertyManager::resetIconSubProperty(QtProperty *property)
2223{
2224 QtProperty *iconProperty = m_iconSubPropertyToProperty.value(akey: property);
2225 if (!iconProperty)
2226 return false;
2227
2228 if (m_pixmapValues.contains(key: property)) {
2229 QtVariantProperty *pixmapProperty = variantProperty(property);
2230 pixmapProperty->setValue(QVariant::fromValue(value: PropertySheetPixmapValue()));
2231 return true;
2232 }
2233 if (m_propertyToTheme.contains(key: iconProperty)) {
2234 QtVariantProperty *themeProperty = variantProperty(property);
2235 themeProperty->setValue(QString());
2236 return true;
2237 }
2238 return false;
2239}
2240
2241// -------- DesignerEditorFactory
2242DesignerEditorFactory::DesignerEditorFactory(QDesignerFormEditorInterface *core, QObject *parent) :
2243 QtVariantEditorFactory(parent),
2244 m_resetDecorator(new ResetDecorator(core, this)),
2245 m_changingPropertyValue(false),
2246 m_core(core),
2247 m_spacing(-1)
2248{
2249 connect(sender: m_resetDecorator, signal: &ResetDecorator::resetProperty,
2250 receiver: this, slot: &DesignerEditorFactory::resetProperty);
2251}
2252
2253DesignerEditorFactory::~DesignerEditorFactory() = default;
2254
2255void DesignerEditorFactory::setSpacing(int spacing)
2256{
2257 m_spacing = spacing;
2258 m_resetDecorator->setSpacing(spacing);
2259}
2260
2261void DesignerEditorFactory::setFormWindowBase(qdesigner_internal::FormWindowBase *fwb)
2262{
2263 m_fwb = fwb;
2264 DesignerPixmapCache *cache = nullptr;
2265 if (fwb)
2266 cache = fwb->pixmapCache();
2267 for (auto it = m_editorToPixmapProperty.cbegin(), end = m_editorToPixmapProperty.cend(); it != end; ++it)
2268 it.key()->setPixmapCache(cache);
2269 for (auto it = m_editorToIconProperty.cbegin(), end = m_editorToIconProperty.cend(); it != end; ++it)
2270 it.key()->setPixmapCache(cache);
2271}
2272
2273void DesignerEditorFactory::connectPropertyManager(QtVariantPropertyManager *manager)
2274{
2275 m_resetDecorator->connectPropertyManager(manager);
2276 connect(sender: manager, signal: &QtVariantPropertyManager::attributeChanged,
2277 receiver: this, slot: &DesignerEditorFactory::slotAttributeChanged);
2278 connect(sender: manager, signal: &QtVariantPropertyManager::valueChanged,
2279 receiver: this, slot: &DesignerEditorFactory::slotValueChanged);
2280 connect(sender: manager, signal: &QtVariantPropertyManager::propertyChanged,
2281 receiver: this, slot: &DesignerEditorFactory::slotPropertyChanged);
2282 QtVariantEditorFactory::connectPropertyManager(manager);
2283}
2284
2285void DesignerEditorFactory::disconnectPropertyManager(QtVariantPropertyManager *manager)
2286{
2287 m_resetDecorator->disconnectPropertyManager(manager);
2288 disconnect(sender: manager, signal: &QtVariantPropertyManager::attributeChanged,
2289 receiver: this, slot: &DesignerEditorFactory::slotAttributeChanged);
2290 disconnect(sender: manager, signal: &QtVariantPropertyManager::valueChanged,
2291 receiver: this, slot: &DesignerEditorFactory::slotValueChanged);
2292 disconnect(sender: manager, signal: &QtVariantPropertyManager::propertyChanged,
2293 receiver: this, slot: &DesignerEditorFactory::slotPropertyChanged);
2294 QtVariantEditorFactory::disconnectPropertyManager(manager);
2295}
2296
2297// A helper that calls a setter with a value on a pointer list of editor objects.
2298// Could use QList<Editor*> instead of EditorContainer/Editor, but that crashes VS 6.
2299template <class EditorContainer, class Editor, class SetterParameter, class Value>
2300static inline void applyToEditors(const EditorContainer &list, void (Editor::*setter)(SetterParameter), const Value &value)
2301{
2302 if (list.isEmpty()) {
2303 return;
2304 }
2305 for (auto it = list.constBegin(), end = list.constEnd(); it != end; ++it) {
2306 Editor &editor = *(*it);
2307 (editor.*setter)(value);
2308 }
2309}
2310
2311void DesignerEditorFactory::slotAttributeChanged(QtProperty *property, const QString &attribute, const QVariant &value)
2312{
2313 QtVariantPropertyManager *manager = propertyManager(property);
2314 const int type = manager->propertyType(property);
2315 if (type == DesignerPropertyManager::designerPixmapTypeId() && attribute == QLatin1String(defaultResourceAttributeC)) {
2316 const QPixmap pixmap = qvariant_cast<QPixmap>(v: value);
2317 applyToEditors(list: m_pixmapPropertyToEditors.value(akey: property), setter: &PixmapEditor::setDefaultPixmap, value: pixmap);
2318 } else if (type == DesignerPropertyManager::designerStringTypeId() || type == QVariant::String) {
2319 if (attribute == QLatin1String(validationModesAttributeC)) {
2320 const TextPropertyValidationMode validationMode = static_cast<TextPropertyValidationMode>(value.toInt());
2321 applyToEditors(list: m_stringPropertyToEditors.value(akey: property), setter: &TextEditor::setTextPropertyValidationMode, value: validationMode);
2322 }
2323 if (attribute == QLatin1String(fontAttributeC)) {
2324 const QFont font = qvariant_cast<QFont>(v: value);
2325 applyToEditors(list: m_stringPropertyToEditors.value(akey: property), setter: &TextEditor::setRichTextDefaultFont, value: font);
2326 }
2327 if (attribute == QLatin1String(themeAttributeC)) {
2328 const bool themeEnabled = value.toBool();
2329 applyToEditors(list: m_stringPropertyToEditors.value(akey: property), setter: &TextEditor::setIconThemeModeEnabled, value: themeEnabled);
2330 }
2331 } else if (type == QVariant::Palette && attribute == QLatin1String(superPaletteAttributeC)) {
2332 const QPalette palette = qvariant_cast<QPalette>(v: value);
2333 applyToEditors(list: m_palettePropertyToEditors.value(akey: property), setter: &PaletteEditorButton::setSuperPalette, value: palette);
2334 }
2335}
2336
2337void DesignerEditorFactory::slotPropertyChanged(QtProperty *property)
2338{
2339 QtVariantPropertyManager *manager = propertyManager(property);
2340 const int type = manager->propertyType(property);
2341 if (type == DesignerPropertyManager::designerIconTypeId()) {
2342 QPixmap defaultPixmap;
2343 if (!property->isModified())
2344 defaultPixmap = qvariant_cast<QIcon>(v: manager->attributeValue(property, attribute: QLatin1String(defaultResourceAttributeC))).pixmap(w: 16, h: 16);
2345 else if (m_fwb)
2346 defaultPixmap = m_fwb->iconCache()->icon(value: qvariant_cast<PropertySheetIconValue>(v: manager->value(property))).pixmap(w: 16, h: 16);
2347 const auto editors = m_iconPropertyToEditors.value(akey: property);
2348 for (PixmapEditor *editor : editors)
2349 editor->setDefaultPixmap(defaultPixmap);
2350 }
2351}
2352
2353void DesignerEditorFactory::slotValueChanged(QtProperty *property, const QVariant &value)
2354{
2355 if (m_changingPropertyValue)
2356 return;
2357
2358 QtVariantPropertyManager *manager = propertyManager(property);
2359 const int type = manager->propertyType(property);
2360 switch (type) {
2361 case QVariant::String:
2362 applyToEditors(list: m_stringPropertyToEditors.value(akey: property), setter: &TextEditor::setText, value: value.toString());
2363 break;
2364 case QVariant::Palette:
2365 applyToEditors(list: m_palettePropertyToEditors.value(akey: property), setter: &PaletteEditorButton::setPalette, value: qvariant_cast<QPalette>(v: value));
2366 break;
2367 case QVariant::UInt:
2368 applyToEditors(list: m_uintPropertyToEditors.value(akey: property), setter: &QLineEdit::setText, value: QString::number(value.toUInt()));
2369 break;
2370 case QVariant::LongLong:
2371 applyToEditors(list: m_longLongPropertyToEditors.value(akey: property), setter: &QLineEdit::setText, value: QString::number(value.toLongLong()));
2372 break;
2373 case QVariant::ULongLong:
2374 applyToEditors(list: m_uLongLongPropertyToEditors.value(akey: property), setter: &QLineEdit::setText, value: QString::number(value.toULongLong()));
2375 break;
2376 case QVariant::Url:
2377 applyToEditors(list: m_urlPropertyToEditors.value(akey: property), setter: &TextEditor::setText, value: value.toUrl().toString());
2378 break;
2379 case QVariant::ByteArray:
2380 applyToEditors(list: m_byteArrayPropertyToEditors.value(akey: property), setter: &TextEditor::setText, value: QString::fromUtf8(str: value.toByteArray()));
2381 break;
2382 case QVariant::StringList:
2383 applyToEditors(list: m_stringListPropertyToEditors.value(akey: property), setter: &StringListEditorButton::setStringList, value: value.toStringList());
2384 break;
2385 default:
2386 if (type == DesignerPropertyManager::designerIconTypeId()) {
2387 PropertySheetIconValue iconValue = qvariant_cast<PropertySheetIconValue>(v: value);
2388 applyToEditors(list: m_iconPropertyToEditors.value(akey: property), setter: &PixmapEditor::setTheme, value: iconValue.theme());
2389 applyToEditors(list: m_iconPropertyToEditors.value(akey: property), setter: &PixmapEditor::setPath, value: iconValue.pixmap(mode: QIcon::Normal, state: QIcon::Off).path());
2390 } else if (type == DesignerPropertyManager::designerPixmapTypeId()) {
2391 applyToEditors(list: m_pixmapPropertyToEditors.value(akey: property), setter: &PixmapEditor::setPath, value: qvariant_cast<PropertySheetPixmapValue>(v: value).path());
2392 } else if (type == DesignerPropertyManager::designerStringTypeId()) {
2393 applyToEditors(list: m_stringPropertyToEditors.value(akey: property), setter: &TextEditor::setText, value: qvariant_cast<PropertySheetStringValue>(v: value).value());
2394 } else if (type == DesignerPropertyManager::designerStringListTypeId()) {
2395 applyToEditors(list: m_stringListPropertyToEditors.value(akey: property), setter: &StringListEditorButton::setStringList, value: qvariant_cast<PropertySheetStringListValue>(v: value).value());
2396 } else if (type == DesignerPropertyManager::designerKeySequenceTypeId()) {
2397 applyToEditors(list: m_keySequencePropertyToEditors.value(akey: property), setter: &QKeySequenceEdit::setKeySequence, value: qvariant_cast<PropertySheetKeySequenceValue>(v: value).value());
2398 }
2399 break;
2400 }
2401}
2402
2403TextEditor *DesignerEditorFactory::createTextEditor(QWidget *parent, TextPropertyValidationMode vm, const QString &value)
2404{
2405 TextEditor *rc = new TextEditor(m_core, parent);
2406 rc->setText(value);
2407 rc->setSpacing(m_spacing);
2408 rc->setTextPropertyValidationMode(vm);
2409 connect(sender: rc, signal: &QObject::destroyed, receiver: this, slot: &DesignerEditorFactory::slotEditorDestroyed);
2410 return rc;
2411}
2412
2413QWidget *DesignerEditorFactory::createEditor(QtVariantPropertyManager *manager, QtProperty *property,
2414 QWidget *parent)
2415{
2416 QWidget *editor = nullptr;
2417 const int type = manager->propertyType(property);
2418 switch (type) {
2419 case QVariant::Bool: {
2420 editor = QtVariantEditorFactory::createEditor(manager, property, parent);
2421 QtBoolEdit *boolEdit = qobject_cast<QtBoolEdit *>(object: editor);
2422 if (boolEdit)
2423 boolEdit->setTextVisible(false);
2424 }
2425 break;
2426 case QVariant::String: {
2427 const TextPropertyValidationMode tvm = static_cast<TextPropertyValidationMode>(manager->attributeValue(property, attribute: QLatin1String(validationModesAttributeC)).toInt());
2428 TextEditor *ed = createTextEditor(parent, vm: tvm, value: manager->value(property).toString());
2429 const QVariant richTextDefaultFont = manager->attributeValue(property, attribute: QLatin1String(fontAttributeC));
2430 if (richTextDefaultFont.type() == QVariant::Font)
2431 ed->setRichTextDefaultFont(qvariant_cast<QFont>(v: richTextDefaultFont));
2432 const bool themeEnabled = manager->attributeValue(property, attribute: QLatin1String(themeAttributeC)).toBool();
2433 ed->setIconThemeModeEnabled(themeEnabled);
2434 m_stringPropertyToEditors[property].append(t: ed);
2435 m_editorToStringProperty[ed] = property;
2436 connect(sender: ed, signal: &QObject::destroyed, receiver: this, slot: &DesignerEditorFactory::slotEditorDestroyed);
2437 connect(sender: ed, signal: &TextEditor::textChanged, receiver: this, slot: &DesignerEditorFactory::slotStringTextChanged);
2438 editor = ed;
2439 }
2440 break;
2441 case QVariant::Palette: {
2442 PaletteEditorButton *ed = new PaletteEditorButton(m_core, qvariant_cast<QPalette>(v: manager->value(property)), parent);
2443 ed->setSuperPalette(qvariant_cast<QPalette>(v: manager->attributeValue(property, attribute: QLatin1String(superPaletteAttributeC))));
2444 m_palettePropertyToEditors[property].append(t: ed);
2445 m_editorToPaletteProperty[ed] = property;
2446 connect(sender: ed, signal: &QObject::destroyed, receiver: this, slot: &DesignerEditorFactory::slotEditorDestroyed);
2447 connect(sender: ed, signal: &PaletteEditorButton::paletteChanged, receiver: this, slot: &DesignerEditorFactory::slotPaletteChanged);
2448 editor = ed;
2449 }
2450 break;
2451 case QVariant::UInt: {
2452 QLineEdit *ed = new QLineEdit(parent);
2453 ed->setValidator(new QULongLongValidator(0, UINT_MAX, ed));
2454 ed->setText(QString::number(manager->value(property).toUInt()));
2455 m_uintPropertyToEditors[property].append(t: ed);
2456 m_editorToUintProperty[ed] = property;
2457 connect(sender: ed, signal: &QObject::destroyed, receiver: this, slot: &DesignerEditorFactory::slotEditorDestroyed);
2458 connect(sender: ed, signal: &QLineEdit::textChanged, receiver: this, slot: &DesignerEditorFactory::slotUintChanged);
2459 editor = ed;
2460 }
2461 break;
2462 case QVariant::LongLong: {
2463 QLineEdit *ed = new QLineEdit(parent);
2464 ed->setValidator(new QLongLongValidator(ed));
2465 ed->setText(QString::number(manager->value(property).toLongLong()));
2466 m_longLongPropertyToEditors[property].append(t: ed);
2467 m_editorToLongLongProperty[ed] = property;
2468 connect(sender: ed, signal: &QObject::destroyed, receiver: this, slot: &DesignerEditorFactory::slotEditorDestroyed);
2469 connect(sender: ed, signal: &QLineEdit::textChanged, receiver: this, slot: &DesignerEditorFactory::slotLongLongChanged);
2470 editor = ed;
2471 }
2472 break;
2473 case QVariant::ULongLong: {
2474 QLineEdit *ed = new QLineEdit(parent);
2475 ed->setValidator(new QULongLongValidator(ed));
2476 ed->setText(QString::number(manager->value(property).toULongLong()));
2477 m_uLongLongPropertyToEditors[property].append(t: ed);
2478 m_editorToULongLongProperty[ed] = property;
2479 connect(sender: ed, signal: &QObject::destroyed, receiver: this, slot: &DesignerEditorFactory::slotEditorDestroyed);
2480 connect(sender: ed, signal: &QLineEdit::textChanged, receiver: this, slot: &DesignerEditorFactory::slotULongLongChanged);
2481 editor = ed;
2482 }
2483 break;
2484 case QVariant::Url: {
2485 TextEditor *ed = createTextEditor(parent, vm: ValidationURL, value: manager->value(property).toUrl().toString());
2486 ed->setUpdateMode(TextPropertyEditor::UpdateOnFinished);
2487 m_urlPropertyToEditors[property].append(t: ed);
2488 m_editorToUrlProperty[ed] = property;
2489 connect(sender: ed, signal: &QObject::destroyed, receiver: this, slot: &DesignerEditorFactory::slotEditorDestroyed);
2490 connect(sender: ed, signal: &TextEditor::textChanged, receiver: this, slot: &DesignerEditorFactory::slotUrlChanged);
2491 editor = ed;
2492 }
2493 break;
2494 case QVariant::ByteArray: {
2495 TextEditor *ed = createTextEditor(parent, vm: ValidationMultiLine, value: QString::fromUtf8(str: manager->value(property).toByteArray()));
2496 m_byteArrayPropertyToEditors[property].append(t: ed);
2497 m_editorToByteArrayProperty[ed] = property;
2498 connect(sender: ed, signal: &QObject::destroyed, receiver: this, slot: &DesignerEditorFactory::slotEditorDestroyed);
2499 connect(sender: ed, signal: &TextEditor::textChanged, receiver: this, slot: &DesignerEditorFactory::slotByteArrayChanged);
2500 editor = ed;
2501 }
2502 break;
2503 default:
2504 if (type == DesignerPropertyManager::designerPixmapTypeId()) {
2505 PixmapEditor *ed = new PixmapEditor(m_core, parent);
2506 ed->setPixmapCache(m_fwb->pixmapCache());
2507 ed->setPath(qvariant_cast<PropertySheetPixmapValue>(v: manager->value(property)).path());
2508 ed->setDefaultPixmap(qvariant_cast<QPixmap>(v: manager->attributeValue(property, attribute: QLatin1String(defaultResourceAttributeC))));
2509 ed->setSpacing(m_spacing);
2510 m_pixmapPropertyToEditors[property].append(t: ed);
2511 m_editorToPixmapProperty[ed] = property;
2512 connect(sender: ed, signal: &QObject::destroyed, receiver: this, slot: &DesignerEditorFactory::slotEditorDestroyed);
2513 connect(sender: ed, signal: &PixmapEditor::pathChanged, receiver: this, slot: &DesignerEditorFactory::slotPixmapChanged);
2514 editor = ed;
2515 } else if (type == DesignerPropertyManager::designerIconTypeId()) {
2516 PixmapEditor *ed = new PixmapEditor(m_core, parent);
2517 ed->setPixmapCache(m_fwb->pixmapCache());
2518 ed->setIconThemeModeEnabled(true);
2519 PropertySheetIconValue value = qvariant_cast<PropertySheetIconValue>(v: manager->value(property));
2520 ed->setTheme(value.theme());
2521 ed->setPath(value.pixmap(mode: QIcon::Normal, state: QIcon::Off).path());
2522 QPixmap defaultPixmap;
2523 if (!property->isModified())
2524 defaultPixmap = qvariant_cast<QIcon>(v: manager->attributeValue(property, attribute: QLatin1String(defaultResourceAttributeC))).pixmap(w: 16, h: 16);
2525 else if (m_fwb)
2526 defaultPixmap = m_fwb->iconCache()->icon(value).pixmap(w: 16, h: 16);
2527 ed->setDefaultPixmap(defaultPixmap);
2528 ed->setSpacing(m_spacing);
2529 m_iconPropertyToEditors[property].append(t: ed);
2530 m_editorToIconProperty[ed] = property;
2531 connect(sender: ed, signal: &QObject::destroyed, receiver: this, slot: &DesignerEditorFactory::slotEditorDestroyed);
2532 connect(sender: ed, signal: &PixmapEditor::pathChanged, receiver: this, slot: &DesignerEditorFactory::slotIconChanged);
2533 connect(sender: ed, signal: &PixmapEditor::themeChanged, receiver: this, slot: &DesignerEditorFactory::slotIconThemeChanged);
2534 editor = ed;
2535 } else if (type == DesignerPropertyManager::designerStringTypeId()) {
2536 const TextPropertyValidationMode tvm = static_cast<TextPropertyValidationMode>(manager->attributeValue(property, attribute: QLatin1String(validationModesAttributeC)).toInt());
2537 TextEditor *ed = createTextEditor(parent, vm: tvm, value: qvariant_cast<PropertySheetStringValue>(v: manager->value(property)).value());
2538 const QVariant richTextDefaultFont = manager->attributeValue(property, attribute: QLatin1String(fontAttributeC));
2539 if (richTextDefaultFont.type() == QVariant::Font)
2540 ed->setRichTextDefaultFont(qvariant_cast<QFont>(v: richTextDefaultFont));
2541 m_stringPropertyToEditors[property].append(t: ed);
2542 m_editorToStringProperty[ed] = property;
2543 connect(sender: ed, signal: &QObject::destroyed, receiver: this, slot: &DesignerEditorFactory::slotEditorDestroyed);
2544 connect(sender: ed, signal: &TextEditor::textChanged, receiver: this, slot: &DesignerEditorFactory::slotStringTextChanged);
2545 editor = ed;
2546 } else if (type == DesignerPropertyManager::designerStringListTypeId() || type == QVariant::StringList) {
2547 const QVariant variantValue = manager->value(property);
2548 const QStringList value = type == QVariant::StringList ? variantValue.toStringList() :
2549 qvariant_cast<PropertySheetStringListValue>(v: variantValue).value();
2550 StringListEditorButton *ed = new StringListEditorButton(value, parent);
2551 m_stringListPropertyToEditors[property].append(t: ed);
2552 m_editorToStringListProperty.insert(key: ed, value: property);
2553 connect(sender: ed, signal: &QObject::destroyed, receiver: this, slot: &DesignerEditorFactory::slotEditorDestroyed);
2554 connect(sender: ed, signal: &StringListEditorButton::stringListChanged, receiver: this, slot: &DesignerEditorFactory::slotStringListChanged);
2555 editor = ed;
2556 } else if (type == DesignerPropertyManager::designerKeySequenceTypeId()) {
2557 QKeySequenceEdit *ed = new QKeySequenceEdit(parent);
2558 ed->setKeySequence(qvariant_cast<PropertySheetKeySequenceValue>(v: manager->value(property)).value());
2559 m_keySequencePropertyToEditors[property].append(t: ed);
2560 m_editorToKeySequenceProperty[ed] = property;
2561 connect(sender: ed, signal: &QObject::destroyed, receiver: this, slot: &DesignerEditorFactory::slotEditorDestroyed);
2562 connect(sender: ed, signal: &QKeySequenceEdit::keySequenceChanged, receiver: this, slot: &DesignerEditorFactory::slotKeySequenceChanged);
2563 editor = ed;
2564 } else {
2565 editor = QtVariantEditorFactory::createEditor(manager, property, parent);
2566 }
2567 break;
2568 }
2569 return m_resetDecorator->editor(subEditor: editor,
2570 resettable: manager->variantProperty(property)->attributeValue(attribute: QLatin1String(resettableAttributeC)).toBool(),
2571 manager, property, parent);
2572}
2573
2574template <class Editor>
2575bool removeEditor(QObject *object,
2576 QMap<QtProperty *, QList<Editor> > *propertyToEditors,
2577 QMap<Editor, QtProperty *> *editorToProperty)
2578{
2579 if (!propertyToEditors)
2580 return false;
2581 if (!editorToProperty)
2582 return false;
2583 for (auto e2pIt = editorToProperty->begin(), end = editorToProperty->end(); e2pIt != end; ++e2pIt) {
2584 Editor editor = e2pIt.key();
2585 if (editor == object) {
2586 const auto p2eIt = propertyToEditors->find(e2pIt.value());
2587 if (p2eIt != propertyToEditors->end()) {
2588 p2eIt.value().removeAll(editor);
2589 if (p2eIt.value().isEmpty())
2590 propertyToEditors->erase(p2eIt);
2591 }
2592 editorToProperty->erase(e2pIt);
2593 return true;
2594 }
2595 }
2596 return false;
2597}
2598
2599void DesignerEditorFactory::slotEditorDestroyed(QObject *object)
2600{
2601 if (removeEditor(object, propertyToEditors: &m_stringPropertyToEditors, editorToProperty: &m_editorToStringProperty))
2602 return;
2603 if (removeEditor(object, propertyToEditors: &m_keySequencePropertyToEditors, editorToProperty: &m_editorToKeySequenceProperty))
2604 return;
2605 if (removeEditor(object, propertyToEditors: &m_palettePropertyToEditors, editorToProperty: &m_editorToPaletteProperty))
2606 return;
2607 if (removeEditor(object, propertyToEditors: &m_pixmapPropertyToEditors, editorToProperty: &m_editorToPixmapProperty))
2608 return;
2609 if (removeEditor(object, propertyToEditors: &m_iconPropertyToEditors, editorToProperty: &m_editorToIconProperty))
2610 return;
2611 if (removeEditor(object, propertyToEditors: &m_uintPropertyToEditors, editorToProperty: &m_editorToUintProperty))
2612 return;
2613 if (removeEditor(object, propertyToEditors: &m_longLongPropertyToEditors, editorToProperty: &m_editorToLongLongProperty))
2614 return;
2615 if (removeEditor(object, propertyToEditors: &m_uLongLongPropertyToEditors, editorToProperty: &m_editorToULongLongProperty))
2616 return;
2617 if (removeEditor(object, propertyToEditors: &m_urlPropertyToEditors, editorToProperty: &m_editorToUrlProperty))
2618 return;
2619 if (removeEditor(object, propertyToEditors: &m_byteArrayPropertyToEditors, editorToProperty: &m_editorToByteArrayProperty))
2620 return;
2621 if (removeEditor(object, propertyToEditors: &m_stringListPropertyToEditors, editorToProperty: &m_editorToStringListProperty))
2622 return;
2623}
2624
2625template<class Editor>
2626bool updateManager(QtVariantEditorFactory *factory, bool *changingPropertyValue,
2627 const QMap<Editor, QtProperty *> &editorToProperty, QWidget *editor, const QVariant &value)
2628{
2629 if (!editor)
2630 return false;
2631 for (auto it = editorToProperty.cbegin(), end = editorToProperty.cend(); it != end; ++it) {
2632 if (it.key() == editor) {
2633 QtProperty *prop = it.value();
2634 QtVariantPropertyManager *manager = factory->propertyManager(property: prop);
2635 *changingPropertyValue = true;
2636 manager->variantProperty(property: prop)->setValue(value);
2637 *changingPropertyValue = false;
2638 return true;
2639 }
2640 }
2641 return false;
2642}
2643
2644void DesignerEditorFactory::slotUintChanged(const QString &value)
2645{
2646 updateManager(factory: this, changingPropertyValue: &m_changingPropertyValue, editorToProperty: m_editorToUintProperty, editor: qobject_cast<QWidget *>(o: sender()), value: value.toUInt());
2647}
2648
2649void DesignerEditorFactory::slotLongLongChanged(const QString &value)
2650{
2651 updateManager(factory: this, changingPropertyValue: &m_changingPropertyValue, editorToProperty: m_editorToLongLongProperty, editor: qobject_cast<QWidget *>(o: sender()), value: value.toLongLong());
2652}
2653
2654void DesignerEditorFactory::slotULongLongChanged(const QString &value)
2655{
2656 updateManager(factory: this, changingPropertyValue: &m_changingPropertyValue, editorToProperty: m_editorToULongLongProperty, editor: qobject_cast<QWidget *>(o: sender()), value: value.toULongLong());
2657}
2658
2659void DesignerEditorFactory::slotUrlChanged(const QString &value)
2660{
2661 updateManager(factory: this, changingPropertyValue: &m_changingPropertyValue, editorToProperty: m_editorToUrlProperty, editor: qobject_cast<QWidget *>(o: sender()), value: QUrl(value));
2662}
2663
2664void DesignerEditorFactory::slotByteArrayChanged(const QString &value)
2665{
2666 updateManager(factory: this, changingPropertyValue: &m_changingPropertyValue, editorToProperty: m_editorToByteArrayProperty, editor: qobject_cast<QWidget *>(o: sender()), value: value.toUtf8());
2667}
2668
2669template <class Editor>
2670QtProperty *findPropertyForEditor(const QMap<Editor *, QtProperty *> &editorMap,
2671 const QObject *sender)
2672{
2673 for (auto it = editorMap.constBegin(), cend = editorMap.constEnd(); it != cend; ++it)
2674 if (it.key() == sender)
2675 return it.value();
2676 return nullptr;
2677}
2678
2679void DesignerEditorFactory::slotStringTextChanged(const QString &value)
2680{
2681 if (QtProperty *prop = findPropertyForEditor(editorMap: m_editorToStringProperty, sender: sender())) {
2682 QtVariantPropertyManager *manager = propertyManager(property: prop);
2683 QtVariantProperty *varProp = manager->variantProperty(property: prop);
2684 QVariant val = varProp->value();
2685 if (val.userType() == DesignerPropertyManager::designerStringTypeId()) {
2686 PropertySheetStringValue strVal = qvariant_cast<PropertySheetStringValue>(v: val);
2687 strVal.setValue(value);
2688 // Disable translation if no translation subproperties exist.
2689 if (varProp->subProperties().isEmpty())
2690 strVal.setTranslatable(false);
2691 val = QVariant::fromValue(value: strVal);
2692 } else {
2693 val = QVariant(value);
2694 }
2695 m_changingPropertyValue = true;
2696 manager->variantProperty(property: prop)->setValue(val);
2697 m_changingPropertyValue = false;
2698 }
2699}
2700
2701void DesignerEditorFactory::slotKeySequenceChanged(const QKeySequence &value)
2702{
2703 if (QtProperty *prop = findPropertyForEditor(editorMap: m_editorToKeySequenceProperty, sender: sender())) {
2704 QtVariantPropertyManager *manager = propertyManager(property: prop);
2705 QtVariantProperty *varProp = manager->variantProperty(property: prop);
2706 QVariant val = varProp->value();
2707 if (val.userType() == DesignerPropertyManager::designerKeySequenceTypeId()) {
2708 PropertySheetKeySequenceValue keyVal = qvariant_cast<PropertySheetKeySequenceValue>(v: val);
2709 keyVal.setValue(value);
2710 val = QVariant::fromValue(value: keyVal);
2711 } else {
2712 val = QVariant::fromValue(value);
2713 }
2714 m_changingPropertyValue = true;
2715 manager->variantProperty(property: prop)->setValue(val);
2716 m_changingPropertyValue = false;
2717 }
2718}
2719
2720void DesignerEditorFactory::slotPaletteChanged(const QPalette &value)
2721{
2722 updateManager(factory: this, changingPropertyValue: &m_changingPropertyValue, editorToProperty: m_editorToPaletteProperty, editor: qobject_cast<QWidget *>(o: sender()), value: QVariant::fromValue(value));
2723}
2724
2725void DesignerEditorFactory::slotPixmapChanged(const QString &value)
2726{
2727 updateManager(factory: this, changingPropertyValue: &m_changingPropertyValue, editorToProperty: m_editorToPixmapProperty, editor: qobject_cast<QWidget *>(o: sender()),
2728 value: QVariant::fromValue(value: PropertySheetPixmapValue(value)));
2729}
2730
2731void DesignerEditorFactory::slotIconChanged(const QString &value)
2732{
2733 updateManager(factory: this, changingPropertyValue: &m_changingPropertyValue, editorToProperty: m_editorToIconProperty, editor: qobject_cast<QWidget *>(o: sender()),
2734 value: QVariant::fromValue(value: PropertySheetIconValue(PropertySheetPixmapValue(value))));
2735}
2736
2737void DesignerEditorFactory::slotIconThemeChanged(const QString &value)
2738{
2739 PropertySheetIconValue icon;
2740 icon.setTheme(value);
2741 updateManager(factory: this, changingPropertyValue: &m_changingPropertyValue, editorToProperty: m_editorToIconProperty, editor: qobject_cast<QWidget *>(o: sender()),
2742 value: QVariant::fromValue(value: icon));
2743}
2744
2745void DesignerEditorFactory::slotStringListChanged(const QStringList &value)
2746{
2747 if (QtProperty *prop = findPropertyForEditor(editorMap: m_editorToStringListProperty, sender: sender())) {
2748 QtVariantPropertyManager *manager = propertyManager(property: prop);
2749 QtVariantProperty *varProp = manager->variantProperty(property: prop);
2750 QVariant val = varProp->value();
2751 if (val.userType() == DesignerPropertyManager::designerStringListTypeId()) {
2752 PropertySheetStringListValue listValue = qvariant_cast<PropertySheetStringListValue>(v: val);
2753 listValue.setValue(value);
2754 // Disable translation if no translation subproperties exist.
2755 if (varProp->subProperties().isEmpty())
2756 listValue.setTranslatable(false);
2757 val = QVariant::fromValue(value: listValue);
2758 } else {
2759 val = QVariant(value);
2760 }
2761 m_changingPropertyValue = true;
2762 manager->variantProperty(property: prop)->setValue(val);
2763 m_changingPropertyValue = false;
2764 }
2765}
2766
2767ResetDecorator::ResetDecorator(const QDesignerFormEditorInterface *core, QObject *parent)
2768 : QObject(parent)
2769 , m_spacing(-1)
2770 , m_core(core)
2771{
2772}
2773
2774ResetDecorator::~ResetDecorator()
2775{
2776 const auto editors = m_resetWidgetToProperty.keys();
2777 qDeleteAll(c: editors);
2778}
2779
2780void ResetDecorator::connectPropertyManager(QtAbstractPropertyManager *manager)
2781{
2782 connect(sender: manager, signal: &QtAbstractPropertyManager::propertyChanged,
2783 receiver: this, slot: &ResetDecorator::slotPropertyChanged);
2784}
2785
2786void ResetDecorator::disconnectPropertyManager(QtAbstractPropertyManager *manager)
2787{
2788 disconnect(sender: manager, signal: &QtAbstractPropertyManager::propertyChanged,
2789 receiver: this, slot: &ResetDecorator::slotPropertyChanged);
2790}
2791
2792void ResetDecorator::setSpacing(int spacing)
2793{
2794 m_spacing = spacing;
2795}
2796
2797static inline bool isModifiedInMultiSelection(const QDesignerFormEditorInterface *core,
2798 const QString &propertyName)
2799{
2800 const QDesignerFormWindowInterface *form = core->formWindowManager()->activeFormWindow();
2801 if (!form)
2802 return false;
2803 const QDesignerFormWindowCursorInterface *cursor = form->cursor();
2804 const int selectionSize = cursor->selectedWidgetCount();
2805 if (selectionSize < 2)
2806 return false;
2807 for (int i = 0; i < selectionSize; ++i) {
2808 const QDesignerPropertySheetExtension *sheet =
2809 qt_extension<QDesignerPropertySheetExtension*>(manager: core->extensionManager(),
2810 object: cursor->selectedWidget(index: i));
2811 const int index = sheet->indexOf(name: propertyName);
2812 if (index >= 0 && sheet->isChanged(index))
2813 return true;
2814 }
2815 return false;
2816}
2817
2818QWidget *ResetDecorator::editor(QWidget *subEditor, bool resettable, QtAbstractPropertyManager *manager, QtProperty *property,
2819 QWidget *parent)
2820{
2821 Q_UNUSED(manager);
2822
2823 ResetWidget *resetWidget = nullptr;
2824 if (resettable) {
2825 resetWidget = new ResetWidget(property, parent);
2826 resetWidget->setSpacing(m_spacing);
2827 resetWidget->setResetEnabled(property->isModified() || isModifiedInMultiSelection(core: m_core, propertyName: property->propertyName()));
2828 resetWidget->setValueText(property->valueText());
2829 resetWidget->setValueIcon(property->valueIcon());
2830 resetWidget->setAutoFillBackground(true);
2831 connect(sender: resetWidget, signal: &QObject::destroyed, receiver: this, slot: &ResetDecorator::slotEditorDestroyed);
2832 connect(sender: resetWidget, signal: &ResetWidget::resetProperty, receiver: this, slot: &ResetDecorator::resetProperty);
2833 m_createdResetWidgets[property].append(t: resetWidget);
2834 m_resetWidgetToProperty[resetWidget] = property;
2835 }
2836 if (subEditor) {
2837 if (resetWidget) {
2838 subEditor->setParent(resetWidget);
2839 resetWidget->setWidget(subEditor);
2840 }
2841 }
2842 if (resetWidget)
2843 return resetWidget;
2844 return subEditor;
2845}
2846
2847void ResetDecorator::slotPropertyChanged(QtProperty *property)
2848{
2849 const auto prIt = m_createdResetWidgets.constFind(key: property);
2850 if (prIt == m_createdResetWidgets.constEnd())
2851 return;
2852
2853 for (ResetWidget *widget : prIt.value()) {
2854 widget->setResetEnabled(property->isModified() || isModifiedInMultiSelection(core: m_core, propertyName: property->propertyName()));
2855 widget->setValueText(property->valueText());
2856 widget->setValueIcon(property->valueIcon());
2857 }
2858}
2859
2860void ResetDecorator::slotEditorDestroyed(QObject *object)
2861{
2862 const QMap<ResetWidget *, QtProperty *>::ConstIterator rcend = m_resetWidgetToProperty.constEnd();
2863 for (QMap<ResetWidget *, QtProperty *>::ConstIterator itEditor = m_resetWidgetToProperty.constBegin(); itEditor != rcend; ++itEditor) {
2864 if (itEditor.key() == object) {
2865 ResetWidget *editor = itEditor.key();
2866 QtProperty *property = itEditor.value();
2867 m_resetWidgetToProperty.remove(key: editor);
2868 m_createdResetWidgets[property].removeAll(t: editor);
2869 if (m_createdResetWidgets[property].isEmpty())
2870 m_createdResetWidgets.remove(key: property);
2871 return;
2872 }
2873 }
2874}
2875
2876}
2877
2878QT_END_NAMESPACE
2879
2880#include "designerpropertymanager.moc"
2881

source code of qttools/src/designer/src/components/propertyeditor/designerpropertymanager.cpp