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