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