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