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
propertyeditor.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
5
12
15#include "shared_enums_p.h"
16
17// sdk
18#include <QtDesigner/abstractformeditor.h>
19#include <QtDesigner/abstractformwindowmanager.h>
20#include <QtDesigner/qextensionmanager.h>
21#include <QtDesigner/propertysheet.h>
22#include <QtDesigner/abstractwidgetdatabase.h>
23#include <QtDesigner/abstractsettings.h>
24// shared
25#include <qdesigner_utils_p.h>
26#include <qdesigner_propertycommand_p.h>
27#include <metadatabase_p.h>
28#include <iconloader_p.h>
29#include <widgetfactory_p.h>
30
31#include <QtWidgets/qlabel.h>
32#include <QtWidgets/qlineedit.h>
33#include <QtWidgets/qmenu.h>
34#include <QtWidgets/qapplication.h>
35#include <QtWidgets/qboxlayout.h>
36#include <QtWidgets/qscrollarea.h>
37#include <QtWidgets/qstackedwidget.h>
38#include <QtWidgets/qtoolbar.h>
39#include <QtWidgets/qtoolbutton.h>
40
41#include <QtGui/qaction.h>
42#include <QtGui/qactiongroup.h>
43#include <QtGui/qpainter.h>
44
45#include <QtCore/qdebug.h>
46#include <QtCore/qtextstream.h>
47#include <QtCore/qtimezone.h>
48
49enum SettingsView { TreeView, ButtonView };
50
51QT_BEGIN_NAMESPACE
52
53using namespace Qt::StringLiterals;
54
55static constexpr auto SettingsGroupC = "PropertyEditor"_L1;
56static constexpr auto ViewKeyC = "View"_L1;
57static constexpr auto ColorKeyC = "Colored"_L1;
58static constexpr auto SortedKeyC = "Sorted"_L1;
59static constexpr auto ExpansionKeyC = "ExpandedItems"_L1;
60static constexpr auto SplitterPositionKeyC = "SplitterPosition"_L1;
61
62// ---------------------------------------------------------------------------------
63
64namespace qdesigner_internal {
65
66// ----------- ElidingLabel
67// QLabel does not support text eliding so we need a helper class
68
69class ElidingLabel : public QWidget
70{
71public:
72 explicit ElidingLabel(const QString &text = QString(),
73 QWidget *parent = nullptr) : QWidget(parent), m_text(text)
74 { setContentsMargins(3, 2, 3, 2); }
75
76 void setText(const QString &text) {
77 m_text = text;
78 updateGeometry();
79 }
80 void setElidemode(Qt::TextElideMode mode) {
81 m_mode = mode;
82 updateGeometry();
83 }
84
85protected:
86 QSize sizeHint() const override;
87 void paintEvent(QPaintEvent *e) override;
88
89private:
90 QString m_text;
91 Qt::TextElideMode m_mode = Qt::ElideRight;
92};
93
95{
96 QSize size = fontMetrics().boundingRect(m_text).size();
97 size += QSize(contentsMargins().left() + contentsMargins().right(),
98 contentsMargins().top() + contentsMargins().bottom());
99 return size;
100}
101
102void ElidingLabel::paintEvent(QPaintEvent *) {
103 QPainter painter(this);
104 painter.setPen(QColor(0, 0, 0, 60));
105 painter.setBrush(QColor(255, 255, 255, 40));
106 painter.drawRect(rect().adjusted(0, 0, -1, -1));
107 painter.setPen(palette().windowText().color());
108 painter.drawText(contentsRect(), Qt::AlignLeft,
109 fontMetrics().elidedText(m_text, Qt::ElideRight, width(), 0));
110}
111
112
113// ----------- PropertyEditor::Strings
114
115PropertyEditor::Strings::Strings() :
116 m_alignmentProperties{u"alignment"_s,
117 u"layoutLabelAlignment"_s, // QFormLayout
118 u"layoutFormAlignment"_s},
119 m_fontProperty(u"font"_s),
120 m_qLayoutWidget(u"QLayoutWidget"_s),
121 m_designerPrefix(u"QDesigner"_s),
122 m_layout(u"Layout"_s),
123 m_validationModeAttribute(u"validationMode"_s),
124 m_fontAttribute(u"font"_s),
125 m_superPaletteAttribute(u"superPalette"_s),
126 m_enumNamesAttribute(u"enumNames"_s),
127 m_resettableAttribute(u"resettable"_s),
128 m_flagsAttribute(u"flags"_s)
129{
130}
131
132// ----------- PropertyEditor
133
134QDesignerMetaDataBaseItemInterface* PropertyEditor::metaDataBaseItem() const
135{
136 QObject *o = object();
137 if (!o)
138 return nullptr;
139 QDesignerMetaDataBaseInterface *db = core()->metaDataBase();
140 if (!db)
141 return nullptr;
142 return db->item(o);
143}
144
145void PropertyEditor::setupStringProperty(QtVariantProperty *property, bool isMainContainer)
146{
147 const StringPropertyParameters params = textPropertyValidationMode(core(), m_object, property->propertyName(), isMainContainer);
148 // Does a meta DB entry exist - add comment
149 const bool hasComment = params.second;
150 property->setAttribute(m_strings.m_validationModeAttribute, params.first);
151 // assuming comment cannot appear or disappear for the same property in different object instance
152 if (!hasComment)
153 qDeleteAll(property->subProperties());
154}
155
156void PropertyEditor::setupPaletteProperty(QtVariantProperty *property)
157{
158 QPalette superPalette = QPalette();
159 QWidget *currentWidget = qobject_cast<QWidget *>(m_object);
160 if (currentWidget) {
161 if (currentWidget->isWindow())
162 superPalette = QApplication::palette(currentWidget);
163 else {
164 if (currentWidget->parentWidget())
165 superPalette = currentWidget->parentWidget()->palette();
166 }
167 }
168 m_updatingBrowser = true;
169 property->setAttribute(m_strings.m_superPaletteAttribute, superPalette);
170 m_updatingBrowser = false;
171}
172
180
181PropertyEditor::PropertyEditor(QDesignerFormEditorInterface *core, QWidget *parent, Qt::WindowFlags flags) :
182 QDesignerPropertyEditor(parent, flags),
183 m_core(core),
184 m_propertyManager(new DesignerPropertyManager(m_core, this)),
185 m_stackedWidget(new QStackedWidget),
186 m_filterWidget(new QLineEdit),
187 m_addDynamicAction(new QAction(createIconSet("plus.png"_L1), tr("Add Dynamic Property..."), this)),
188 m_removeDynamicAction(new QAction(createIconSet("minus.png"_L1), tr("Remove Dynamic Property"), this)),
189 m_sortingAction(new QAction(createIconSet("sort.png"_L1), tr("Sorting"), this)),
190 m_coloringAction(new QAction(createIconSet("color.png"_L1), tr("Color Groups"), this)),
191 m_treeAction(new QAction(tr("Tree View"), this)),
192 m_buttonAction(new QAction(tr("Drop Down Button View"), this)),
193 m_classLabel(new ElidingLabel)
194{
195 const QColor colors[] = {{255, 230, 191}, {255, 255, 191}, {191, 255, 191},
196 {199, 255, 255}, {234, 191, 255}, {255, 191, 239}};
197 const int darknessFactor = 250;
198 m_colors.reserve(std::size(colors));
199 for (const QColor &c : colors)
200 m_colors.append({c, c.darker(darknessFactor)});
201 QColor dynamicColor(191, 207, 255);
202 QColor layoutColor(255, 191, 191);
203 m_dynamicColor = {dynamicColor, dynamicColor.darker(darknessFactor)};
204 m_layoutColor = {layoutColor, layoutColor.darker(darknessFactor)};
205
206 updateForegroundBrightness();
207
208 QActionGroup *actionGroup = new QActionGroup(this);
209
210 m_treeAction->setCheckable(true);
211 m_treeAction->setIcon(createIconSet("widgets/listview.png"_L1));
212 m_buttonAction->setCheckable(true);
213 m_buttonAction->setIcon(createIconSet("dropdownbutton.png"_L1));
214
215 actionGroup->addAction(m_treeAction);
216 actionGroup->addAction(m_buttonAction);
217 connect(actionGroup, &QActionGroup::triggered,
218 this, &PropertyEditor::slotViewTriggered);
219
220 // Add actions
221 QActionGroup *addDynamicActionGroup = new QActionGroup(this);
222 connect(addDynamicActionGroup, &QActionGroup::triggered,
223 this, &PropertyEditor::slotAddDynamicProperty);
224
225 QMenu *addDynamicActionMenu = new QMenu(this);
226 m_addDynamicAction->setMenu(addDynamicActionMenu);
227 m_addDynamicAction->setEnabled(false);
228 QAction *addDynamicAction = addDynamicActionGroup->addAction(tr("String..."));
229 addDynamicAction->setData(static_cast<int>(QMetaType::QString));
230 addDynamicActionMenu->addAction(addDynamicAction);
231 addDynamicAction = addDynamicActionGroup->addAction(tr("Bool..."));
232 addDynamicAction->setData(static_cast<int>(QMetaType::Bool));
233 addDynamicActionMenu->addAction(addDynamicAction);
234 addDynamicActionMenu->addSeparator();
235 addDynamicAction = addDynamicActionGroup->addAction(tr("Other..."));
236 addDynamicAction->setData(static_cast<int>(QMetaType::UnknownType));
237 addDynamicActionMenu->addAction(addDynamicAction);
238 // remove
239 m_removeDynamicAction->setEnabled(false);
240 connect(m_removeDynamicAction, &QAction::triggered, this, &PropertyEditor::slotRemoveDynamicProperty);
241 // Configure
242 QAction *configureAction = new QAction(tr("Configure Property Editor"), this);
243 configureAction->setIcon(createIconSet("configure.png"_L1));
244 QMenu *configureMenu = new QMenu(this);
245 configureAction->setMenu(configureMenu);
246
247 m_sortingAction->setCheckable(true);
248 connect(m_sortingAction, &QAction::toggled, this, &PropertyEditor::slotSorting);
249
250 m_coloringAction->setCheckable(true);
251 connect(m_coloringAction, &QAction::toggled, this, &PropertyEditor::slotColoring);
252
253 configureMenu->addAction(m_sortingAction);
254 configureMenu->addAction(m_coloringAction);
255 configureMenu->addSeparator();
256 configureMenu->addAction(m_treeAction);
257 configureMenu->addAction(m_buttonAction);
258 // Assemble toolbar
259 QToolBar *toolBar = new QToolBar;
260 toolBar->addWidget(m_filterWidget);
261 toolBar->addWidget(createDropDownButton(m_addDynamicAction));
262 toolBar->addAction(m_removeDynamicAction);
263 toolBar->addWidget(createDropDownButton(configureAction));
264 // Views
265 QScrollArea *buttonScroll = new QScrollArea(m_stackedWidget);
266 m_buttonBrowser = new QtButtonPropertyBrowser(buttonScroll);
267 buttonScroll->setWidgetResizable(true);
268 buttonScroll->setWidget(m_buttonBrowser);
269 m_buttonIndex = m_stackedWidget->addWidget(buttonScroll);
270 connect(m_buttonBrowser, &QtAbstractPropertyBrowser::currentItemChanged,
271 this, &PropertyEditor::slotCurrentItemChanged);
272
273 m_treeBrowser = new QtTreePropertyBrowser(m_stackedWidget);
274 m_treeBrowser->setRootIsDecorated(false);
276 m_treeBrowser->setResizeMode(QtTreePropertyBrowser::Interactive);
277 m_treeIndex = m_stackedWidget->addWidget(m_treeBrowser);
278 connect(m_treeBrowser, &QtAbstractPropertyBrowser::currentItemChanged,
279 this, &PropertyEditor::slotCurrentItemChanged);
280 m_filterWidget->setPlaceholderText(tr("Filter"));
281 m_filterWidget->setClearButtonEnabled(true);
282 connect(m_filterWidget, &QLineEdit::textChanged, this, &PropertyEditor::setFilter);
283
284 QVBoxLayout *layout = new QVBoxLayout(this);
285 layout->addWidget(toolBar);
286 layout->addWidget(m_classLabel);
287 layout->addSpacerItem(new QSpacerItem(0,1));
288 layout->addWidget(m_stackedWidget);
289 layout->setContentsMargins(QMargins());
290 layout->setSpacing(0);
291
292 m_treeFactory = new DesignerEditorFactory(m_core, this);
293 m_treeFactory->setSpacing(0);
294 m_groupFactory = new DesignerEditorFactory(m_core, this);
295 QtVariantPropertyManager *variantManager = m_propertyManager;
296 m_buttonBrowser->setFactoryForManager(variantManager, m_groupFactory);
297 m_treeBrowser->setFactoryForManager(variantManager, m_treeFactory);
298
299 m_stackedWidget->setCurrentIndex(m_treeIndex);
300 m_currentBrowser = m_treeBrowser;
301 m_treeAction->setChecked(true);
302
303 connect(m_groupFactory, &DesignerEditorFactory::resetProperty,
304 this, &PropertyEditor::slotResetProperty);
305 connect(m_treeFactory, &DesignerEditorFactory::resetProperty,
306 this, &PropertyEditor::slotResetProperty);
307 connect(m_propertyManager, &DesignerPropertyManager::valueChanged,
308 this, &PropertyEditor::slotValueChanged);
309
310 // retrieve initial settings
311 QDesignerSettingsInterface *settings = m_core->settingsManager();
312 settings->beginGroup(SettingsGroupC);
313 const SettingsView view = settings->value(ViewKeyC, TreeView).toInt() == TreeView ? TreeView : ButtonView;
314 // Coloring not available unless treeview and not sorted
315 m_sorting = settings->value(SortedKeyC, false).toBool();
316 m_coloring = settings->value(ColorKeyC, true).toBool();
317 const QVariantMap expansionState = settings->value(ExpansionKeyC, QVariantMap()).toMap();
318 const int splitterPosition = settings->value(SplitterPositionKeyC, 150).toInt();
319 settings->endGroup();
320 // Apply settings
321 m_sortingAction->setChecked(m_sorting);
322 m_coloringAction->setChecked(m_coloring);
323 m_treeBrowser->setSplitterPosition(splitterPosition);
324 switch (view) {
325 case TreeView:
326 m_currentBrowser = m_treeBrowser;
327 m_stackedWidget->setCurrentIndex(m_treeIndex);
328 m_treeAction->setChecked(true);
329 break;
330 case ButtonView:
331 m_currentBrowser = m_buttonBrowser;
332 m_stackedWidget->setCurrentIndex(m_buttonIndex);
333 m_buttonAction->setChecked(true);
334 break;
335 }
336 // Restore expansionState from QVariant map
337 for (auto it = expansionState.cbegin(), cend = expansionState.cend(); it != cend; ++it)
338 m_expansionState.insert(it.key(), it.value().toBool());
339
340 updateActionsState();
341}
342
344{
345 // Prevent emission of QtTreePropertyBrowser::itemChanged() when deleting
346 // the current item, causing asserts.
347 m_treeBrowser->setCurrentItem(nullptr);
348 storeExpansionState();
349 saveSettings();
350}
351
352void PropertyEditor::saveSettings() const
353{
354 QDesignerSettingsInterface *settings = m_core->settingsManager();
355 settings->beginGroup(SettingsGroupC);
356 settings->setValue(ViewKeyC, QVariant(m_treeAction->isChecked() ? TreeView : ButtonView));
357 settings->setValue(ColorKeyC, QVariant(m_coloring));
358 settings->setValue(SortedKeyC, QVariant(m_sorting));
359 // Save last expansionState as QVariant map
360 QVariantMap expansionState;
361 for (auto it = m_expansionState.cbegin(), cend = m_expansionState.cend(); it != cend; ++it)
362 expansionState.insert(it.key(), QVariant(it.value()));
363 settings->setValue(ExpansionKeyC, expansionState);
364 settings->setValue(SplitterPositionKeyC, m_treeBrowser->splitterPosition());
365 settings->endGroup();
366}
367
368void PropertyEditor::setExpanded(QtBrowserItem *item, bool expanded)
369{
370 if (m_buttonBrowser == m_currentBrowser)
371 m_buttonBrowser->setExpanded(item, expanded);
372 else if (m_treeBrowser == m_currentBrowser)
373 m_treeBrowser->setExpanded(item, expanded);
374}
375
376bool PropertyEditor::isExpanded(QtBrowserItem *item) const
377{
378 if (m_buttonBrowser == m_currentBrowser)
379 return m_buttonBrowser->isExpanded(item);
380 if (m_treeBrowser == m_currentBrowser)
381 return m_treeBrowser->isExpanded(item);
382 return false;
383}
384
385void PropertyEditor::setItemVisible(QtBrowserItem *item, bool visible)
386{
387 if (m_currentBrowser == m_treeBrowser) {
388 m_treeBrowser->setItemVisible(item, visible);
389 } else {
390 qWarning("** WARNING %s is not implemented for this browser.", Q_FUNC_INFO);
391 }
392}
393
394bool PropertyEditor::isItemVisible(QtBrowserItem *item) const
395{
396 return m_currentBrowser == m_treeBrowser ? m_treeBrowser->isItemVisible(item) : true;
397}
398
399/* Default handling of items not found in the map:
400 * - Top-level items (classes) are assumed to be expanded
401 * - Anything below (properties) is assumed to be collapsed
402 * That is, the map is required, the state cannot be stored in a set */
403
404void PropertyEditor::storePropertiesExpansionState(const QList<QtBrowserItem *> &items)
405{
406 for (QtBrowserItem *propertyItem : items) {
407 if (!propertyItem->children().isEmpty()) {
408 QtProperty *property = propertyItem->property();
409 const QString propertyName = property->propertyName();
410 const auto itGroup = m_propertyToGroup.constFind(property);
411 if (itGroup != m_propertyToGroup.constEnd()) {
412 const QString key = itGroup.value() + u'|' + propertyName;
413 m_expansionState[key] = isExpanded(propertyItem);
414 }
415 }
416 }
417}
418
419void PropertyEditor::storeExpansionState()
420{
421 const auto items = m_currentBrowser->topLevelItems();
422 if (m_sorting) {
423 storePropertiesExpansionState(items);
424 } else {
425 for (QtBrowserItem *item : items) {
426 const QString groupName = item->property()->propertyName();
427 auto propertyItems = item->children();
428 if (!propertyItems.isEmpty())
429 m_expansionState[groupName] = isExpanded(item);
430
431 // properties stuff here
432 storePropertiesExpansionState(propertyItems);
433 }
434 }
435}
436
437void PropertyEditor::collapseAll()
438{
439 const auto items = m_currentBrowser->topLevelItems();
440 for (QtBrowserItem *group : items)
441 setExpanded(group, false);
442}
443
444void PropertyEditor::applyPropertiesExpansionState(const QList<QtBrowserItem *> &items)
445{
446 for (QtBrowserItem *propertyItem : items) {
447 const auto excend = m_expansionState.cend();
448 QtProperty *property = propertyItem->property();
449 const QString propertyName = property->propertyName();
450 const auto itGroup = m_propertyToGroup.constFind(property);
451 if (itGroup != m_propertyToGroup.constEnd()) {
452 const QString key = itGroup.value() + u'|' + propertyName;
453 const auto pit = m_expansionState.constFind(key);
454 if (pit != excend)
455 setExpanded(propertyItem, pit.value());
456 else
457 setExpanded(propertyItem, false);
458 }
459 }
460}
461
462void PropertyEditor::applyExpansionState()
463{
464 const auto items = m_currentBrowser->topLevelItems();
465 if (m_sorting) {
466 applyPropertiesExpansionState(items);
467 } else {
468 const auto excend = m_expansionState.cend();
469 for (QtBrowserItem *item : items) {
470 const QString groupName = item->property()->propertyName();
471 const auto git = m_expansionState.constFind(groupName);
472 if (git != excend)
473 setExpanded(item, git.value());
474 else
475 setExpanded(item, true);
476 // properties stuff here
477 applyPropertiesExpansionState(item->children());
478 }
479 }
480}
481
482int PropertyEditor::applyPropertiesFilter(const QList<QtBrowserItem *> &items)
483{
484 int showCount = 0;
485 const bool matchAll = m_filterPattern.isEmpty();
486 for (QtBrowserItem *propertyItem : items) {
487 QtProperty *property = propertyItem->property();
488 const QString propertyName = property->propertyName();
489 const bool showProperty = matchAll || propertyName.contains(m_filterPattern, Qt::CaseInsensitive);
490 setItemVisible(propertyItem, showProperty);
491 if (showProperty)
492 showCount++;
493 }
494 return showCount;
495}
496
497void PropertyEditor::applyFilter()
498{
499 const auto items = m_currentBrowser->topLevelItems();
500 if (m_sorting) {
501 applyPropertiesFilter(items);
502 } else {
503 for (QtBrowserItem *item : items)
504 setItemVisible(item, applyPropertiesFilter(item->children()));
505 }
506}
507
508void PropertyEditor::clearView()
509{
510 m_currentBrowser->clear();
511}
512
513bool PropertyEditor::event(QEvent *event)
514{
515 if (event->type() == QEvent::PaletteChange)
516 updateForegroundBrightness();
517
518 return QDesignerPropertyEditor::event(event);
519}
520
521void PropertyEditor::updateForegroundBrightness()
522{
523 QColor c = palette().color(QPalette::Text);
524 bool newBrightness = qRound(0.3 * c.redF() + 0.59 * c.greenF() + 0.11 * c.blueF());
525
526 if (m_brightness == newBrightness)
527 return;
528
529 m_brightness = newBrightness;
530
531 updateColors();
532}
533
534QColor PropertyEditor::propertyColor(QtProperty *property) const
535{
536 if (!m_coloring)
537 return QColor();
538
539 QtProperty *groupProperty = property;
540
541 const auto itProp = m_propertyToGroup.constFind(property);
542 if (itProp != m_propertyToGroup.constEnd())
543 groupProperty = m_nameToGroup.value(itProp.value());
544
545 const int groupIdx = m_groups.indexOf(groupProperty);
546 std::pair<QColor, QColor> pair;
547 if (groupIdx != -1) {
548 if (groupProperty == m_dynamicGroup)
549 pair = m_dynamicColor;
550 else if (isLayoutGroup(groupProperty))
551 pair = m_layoutColor;
552 else
553 pair = m_colors[groupIdx % m_colors.size()];
554 }
555 if (!m_brightness)
556 return pair.first;
557 return pair.second;
558}
559
560void PropertyEditor::fillView()
561{
562 if (m_sorting) {
563 for (auto itProperty = m_nameToProperty.cbegin(), end = m_nameToProperty.cend(); itProperty != end; ++itProperty)
564 m_currentBrowser->addProperty(itProperty.value());
565 } else {
566 for (QtProperty *group : std::as_const(m_groups)) {
567 QtBrowserItem *item = m_currentBrowser->addProperty(group);
568 if (m_currentBrowser == m_treeBrowser)
569 m_treeBrowser->setBackgroundColor(item, propertyColor(group));
570 group->setModified(m_currentBrowser == m_treeBrowser);
571 }
572 }
573}
574
575bool PropertyEditor::isLayoutGroup(QtProperty *group) const
576{
577 return group->propertyName() == m_strings.m_layout;
578}
579
580void PropertyEditor::updateActionsState()
581{
582 m_coloringAction->setEnabled(m_treeAction->isChecked() && !m_sortingAction->isChecked());
583}
584
585void PropertyEditor::slotViewTriggered(QAction *action)
586{
588 collapseAll();
589 {
590 UpdateBlocker ub(this);
591 clearView();
592 int idx = 0;
593 if (action == m_treeAction) {
596 } else if (action == m_buttonAction) {
599 }
600 fillView();
603 applyFilter();
604 }
606}
607
608void PropertyEditor::slotSorting(bool sort)
609{
610 if (sort == m_sorting)
611 return;
612
613 storeExpansionState();
614 m_sorting = sort;
615 collapseAll();
616 {
617 UpdateBlocker ub(this);
618 clearView();
619 m_treeBrowser->setRootIsDecorated(sort);
620 fillView();
621 applyExpansionState();
622 applyFilter();
623 }
624 updateActionsState();
625}
626
627void PropertyEditor::updateColors()
628{
629 if (m_treeBrowser && m_currentBrowser == m_treeBrowser) {
630 const auto items = m_treeBrowser->topLevelItems();
631 for (QtBrowserItem *item : items)
632 m_treeBrowser->setBackgroundColor(item, propertyColor(item->property()));
633 }
634}
635
636void PropertyEditor::slotColoring(bool coloring)
637{
638 if (coloring == m_coloring)
639 return;
640
641 m_coloring = coloring;
642
643 updateColors();
644}
645
646void PropertyEditor::slotAddDynamicProperty(QAction *action)
647{
648 if (!m_propertySheet)
649 return;
650
653
654 if (!dynamicSheet)
655 return;
656
659 { // Make sure the dialog is closed before the signal is emitted.
660 const int type = action->data().toInt();
662 if (type != QMetaType::UnknownType)
664
666 const int propertyCount = m_propertySheet->count();
667 for (int i = 0; i < propertyCount; i++) {
670 }
672 if (dlg.exec() == QDialog::Rejected)
673 return;
676 }
679}
680
681QDesignerFormEditorInterface *PropertyEditor::core() const
682{
683 return m_core;
684}
685
687{
688 return false;
689}
690
691void PropertyEditor::setReadOnly(bool /*readOnly*/)
692{
693 qDebug() << "PropertyEditor::setReadOnly() request";
694}
695
696void PropertyEditor::setPropertyValue(const QString &name, const QVariant &value, bool changed)
697{
698 const auto it = m_nameToProperty.constFind(name);
699 if (it == m_nameToProperty.constEnd())
700 return;
701 QtVariantProperty *property = it.value();
702 updateBrowserValue(property, value);
703 property->setModified(changed);
704}
705
706/* Quick update that assumes the actual count of properties has not changed
707 * N/A when for example executing a layout command and margin properties appear. */
709{
710 if (!m_propertySheet)
711 return;
712
713 updateToolBarLabel();
714
715 const int propertyCount = m_propertySheet->count();
716 const auto npcend = m_nameToProperty.cend();
717 for (int i = 0; i < propertyCount; ++i) {
718 const QString propertyName = m_propertySheet->propertyName(i);
719 const auto it = m_nameToProperty.constFind(propertyName);
720 if (it != npcend)
721 updateBrowserValue(it.value(), m_propertySheet->property(i));
722 }
723}
724
725static inline QLayout *layoutOfQLayoutWidget(QObject *o)
726{
727 if (o->isWidgetType() && !qstrcmp(o->metaObject()->className(), "QLayoutWidget"))
728 return static_cast<QWidget*>(o)->layout();
729 return nullptr;
730}
731
732void PropertyEditor::updateToolBarLabel()
733{
734 QString objectName;
735 QString className;
736 if (m_object) {
737 if (QLayout *l = layoutOfQLayoutWidget(m_object))
738 objectName = l->objectName();
739 else
740 objectName = m_object->objectName();
741 className = realClassName(m_object);
742 }
743
744 m_classLabel->setVisible(!objectName.isEmpty() || !className.isEmpty());
745 m_classLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
746
747 QString classLabelText;
748 if (!objectName.isEmpty())
749 classLabelText += objectName + " : "_L1;
750 classLabelText += className;
751
752 m_classLabel->setText(classLabelText);
753 m_classLabel->setToolTip(tr("Object: %1\nClass: %2")
754 .arg(objectName, className));
755}
756
757void PropertyEditor::updateBrowserValue(QtVariantProperty *property, const QVariant &value)
758{
759 QVariant v = value;
760 const int type = property->propertyType();
762 const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(v);
763 v = e.metaEnum.keys().indexOf(e.metaEnum.valueToKey(e.value));
765 const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(v);
766 v = QVariant(f.value);
768 const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(v);
769 v = QVariant(f.value);
770 }
771 QDesignerPropertySheet *sheet = qobject_cast<QDesignerPropertySheet*>(m_core->extensionManager()->extension(m_object, Q_TYPEID(QDesignerPropertySheetExtension)));
772 int index = -1;
773 if (sheet)
774 index = sheet->indexOf(property->propertyName());
775 if (sheet && m_propertyToGroup.contains(property)) { // don't do it for comments since property sheet doesn't keep them
776 property->setEnabled(sheet->isEnabled(index));
777 }
778
779 // Rich text string property with comment: Store/Update the font the rich text editor dialog starts out with
780 if (type == QMetaType::QString && !property->subProperties().isEmpty()) {
781 const int fontIndex = m_propertySheet->indexOf(m_strings.m_fontProperty);
782 if (fontIndex != -1)
783 property->setAttribute(m_strings.m_fontAttribute, m_propertySheet->property(fontIndex));
784 }
785
786 m_updatingBrowser = true;
787 property->setValue(v);
788 if (sheet && sheet->isResourceProperty(index))
789 property->setAttribute(u"defaultResource"_s, sheet->defaultResourceProperty(index));
790 m_updatingBrowser = false;
791}
792
793int PropertyEditor::toBrowserType(const QVariant &value, const QString &propertyName) const
794{
795 if (value.canConvert<PropertySheetFlagValue>()) {
796 if (m_strings.m_alignmentProperties.contains(propertyName))
799 }
800 if (value.canConvert<PropertySheetEnumValue>())
802
803 return value.userType();
804}
805
806QString PropertyEditor::realClassName(QObject *object) const
807{
808 if (!object)
809 return QString();
810
811 QString className = QLatin1StringView(object->metaObject()->className());
812 const QDesignerWidgetDataBaseInterface *db = core()->widgetDataBase();
813 if (QDesignerWidgetDataBaseItemInterface *widgetItem = db->item(db->indexOfObject(object, true))) {
814 className = widgetItem->name();
815
816 if (object->isWidgetType() && className == m_strings.m_qLayoutWidget
817 && static_cast<QWidget*>(object)->layout()) {
818 className = QLatin1StringView(static_cast<QWidget*>(object)->layout()->metaObject()->className());
819 }
820 }
821
822 if (className.startsWith(m_strings.m_designerPrefix))
823 className.remove(1, m_strings.m_designerPrefix.size() - 1);
824
825 return className;
826}
827
828static const char *typeName(int type)
829{
830 if (type == qMetaTypeId<PropertySheetStringValue>())
831 type = QMetaType::QString;
832 if (type < int(QMetaType::User))
833 return QMetaType(type).name();
834 if (type == qMetaTypeId<PropertySheetIconValue>())
835 return "QIcon";
836 if (type == qMetaTypeId<PropertySheetPixmapValue>())
837 return "QPixmap";
838 if (type == qMetaTypeId<PropertySheetKeySequenceValue>())
839 return "QKeySequence";
840 if (type == qMetaTypeId<PropertySheetFlagValue>())
841 return "QFlags";
842 if (type == qMetaTypeId<PropertySheetEnumValue>())
843 return "enum";
844 if (type == QMetaType::UnknownType)
845 return "invalid";
846 if (type == QMetaType::User)
847 return "user type";
848 const auto metaType = QMetaType(type);
849 if (metaType.isValid())
850 return metaType.name();
851 return nullptr;
852}
853
854static QString msgUnsupportedType(const QString &propertyName, int type)
855{
856 QString rc;
857 QTextStream str(&rc);
858 const char *typeS = typeName(type);
859 str << "The property \"" << propertyName << "\" of type ("
860 << (typeS ? typeS : "unknown") << ") is not supported yet.";
861 return rc;
862}
863
864void PropertyEditor::setObject(QObject *object)
865{
866 QDesignerFormWindowInterface *oldFormWindow = QDesignerFormWindowInterface::findFormWindow(m_object);
867 // In the first setObject() call following the addition of a dynamic property, focus and edit it.
868 const bool editNewDynamicProperty = object != nullptr && m_object == object && !m_recentlyAddedDynamicProperty.isEmpty();
869 m_object = object;
870 m_propertyManager->setObject(object);
871 QDesignerFormWindowInterface *formWindow = QDesignerFormWindowInterface::findFormWindow(m_object);
872 // QTBUG-68507: Form window can be null for objects in Morph Undo macros with buddies
873 if (object != nullptr && formWindow == nullptr) {
874 formWindow = m_core->formWindowManager()->activeFormWindow();
875 if (formWindow == nullptr) {
876 qWarning("PropertyEditor::setObject(): Unable to find form window for \"%s\".",
877 qPrintable(object->objectName()));
878 return;
879 }
880 }
881 FormWindowBase *fwb = qobject_cast<FormWindowBase *>(formWindow);
882 const bool idIdBasedTranslation = fwb && fwb->useIdBasedTranslations();
883 const bool idIdBasedTranslationUnchanged = (idIdBasedTranslation == DesignerPropertyManager::useIdBasedTranslations());
885 m_treeFactory->setFormWindowBase(fwb);
886 m_groupFactory->setFormWindowBase(fwb);
887
888 storeExpansionState();
889
890 UpdateBlocker ub(this);
891
892 updateToolBarLabel();
893
894 QMap<QString, QtVariantProperty *> toRemove = m_nameToProperty;
895
896 const QDesignerDynamicPropertySheetExtension *dynamicSheet =
897 qt_extension<QDesignerDynamicPropertySheetExtension*>(m_core->extensionManager(), m_object);
898 const QDesignerPropertySheet *sheet = qobject_cast<QDesignerPropertySheet*>(m_core->extensionManager()->extension(m_object, Q_TYPEID(QDesignerPropertySheetExtension)));
899
900 // Optimizization: Instead of rebuilding the complete list every time, compile a list of properties to remove,
901 // remove them, traverse the sheet, in case property exists just set a value, otherwise - create it.
902 QExtensionManager *m = m_core->extensionManager();
903
904 m_propertySheet = qobject_cast<QDesignerPropertySheetExtension*>(m->extension(object, Q_TYPEID(QDesignerPropertySheetExtension)));
905 if (m_propertySheet) {
906 const int stringTypeId = qMetaTypeId<PropertySheetStringValue>();
907 const int propertyCount = m_propertySheet->count();
908 for (int i = 0; i < propertyCount; ++i) {
909 if (!m_propertySheet->isVisible(i))
910 continue;
911
912 const QString propertyName = m_propertySheet->propertyName(i);
913 if (m_propertySheet->indexOf(propertyName) != i)
914 continue;
915 const QString groupName = m_propertySheet->propertyGroup(i);
916 const auto rit = toRemove.constFind(propertyName);
917 if (rit != toRemove.constEnd()) {
918 QtVariantProperty *property = rit.value();
919 const int propertyType = property->propertyType();
920 // Also remove string properties in case a change in translation mode
921 // occurred since different sub-properties are used (disambiguation/id).
922 if (m_propertyToGroup.value(property) == groupName
923 && (idIdBasedTranslationUnchanged || propertyType != stringTypeId)
924 && toBrowserType(m_propertySheet->property(i), propertyName) == propertyType) {
925 toRemove.remove(propertyName);
926 }
927 }
928 }
929 }
930
931 for (auto itRemove = toRemove.cbegin(), end = toRemove.cend(); itRemove != end; ++itRemove) {
932 QtVariantProperty *property = itRemove.value();
933 m_nameToProperty.remove(itRemove.key());
934 m_propertyToGroup.remove(property);
935 delete property;
936 }
937
938 if (oldFormWindow != formWindow)
940
941 bool isMainContainer = false;
942 if (QWidget *widget = qobject_cast<QWidget*>(object)) {
943 if (QDesignerFormWindowInterface *fw = QDesignerFormWindowInterface::findFormWindow(widget)) {
944 isMainContainer = (fw->mainContainer() == widget);
945 }
946 }
947 m_groups.clear();
948
949 if (m_propertySheet) {
950 const QString className = WidgetFactory::classNameOf(formWindow->core(), m_object);
951 const QDesignerCustomWidgetData customData = formWindow->core()->pluginManager()->customWidgetData(className);
952
953 QtProperty *lastProperty = nullptr;
954 QtProperty *lastGroup = nullptr;
955 const int propertyCount = m_propertySheet->count();
956 for (int i = 0; i < propertyCount; ++i) {
957 if (!m_propertySheet->isVisible(i))
958 continue;
959
960 const QString propertyName = m_propertySheet->propertyName(i);
961 if (m_propertySheet->indexOf(propertyName) != i)
962 continue;
963 const QVariant value = m_propertySheet->property(i);
964
965 const int type = toBrowserType(value, propertyName);
966
967 QtVariantProperty *property = m_nameToProperty.value(propertyName, 0);
968 bool newProperty = property == nullptr;
969 if (newProperty) {
970 property = m_propertyManager->addProperty(type, propertyName);
971 if (property) {
972 newProperty = true;
974 const PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(value);
975 m_updatingBrowser = true;
976 property->setAttribute(m_strings.m_enumNamesAttribute, e.metaEnum.keys());
977 m_updatingBrowser = false;
979 const PropertySheetFlagValue f = qvariant_cast<PropertySheetFlagValue>(value);
980 QList<std::pair<QString, uint>> flags;
981 for (const QString &name : f.metaFlags.keys()) {
982 const uint val = f.metaFlags.keyToValue(name);
983 flags.append({name, val});
984 }
985 m_updatingBrowser = true;
986 QVariant v;
987 v.setValue(flags);
988 property->setAttribute(m_strings.m_flagsAttribute, v);
989 m_updatingBrowser = false;
990 }
991 }
992 }
993
994 if (property != nullptr) {
995 const bool dynamicProperty = (dynamicSheet && dynamicSheet->isDynamicProperty(i))
996 || (sheet && sheet->isDefaultDynamicProperty(i));
997 QString descriptionToolTip;
998 if (!dynamicProperty && !customData.isNull())
999 descriptionToolTip = customData.propertyToolTip(propertyName);
1000 if (descriptionToolTip.isEmpty()) {
1001 if (const char *typeS = typeName(type)) {
1002 descriptionToolTip = propertyName + " ("_L1
1003 + QLatin1StringView(typeS) + ')'_L1;
1004 }
1005 }
1006 if (!descriptionToolTip.isEmpty())
1007 property->setDescriptionToolTip(descriptionToolTip);
1008 switch (type) {
1009 case QMetaType::QPalette:
1010 setupPaletteProperty(property);
1011 break;
1012 case QMetaType::QKeySequence:
1013 //addCommentProperty(property, propertyName);
1014 break;
1015 default:
1016 break;
1017 }
1018 if (type == QMetaType::QString || type == qMetaTypeId<PropertySheetStringValue>())
1019 setupStringProperty(property, isMainContainer);
1020 property->setAttribute(m_strings.m_resettableAttribute, m_propertySheet->hasReset(i));
1021
1022 const QString groupName = m_propertySheet->propertyGroup(i);
1023 QtVariantProperty *groupProperty = nullptr;
1024
1025 if (newProperty) {
1026 auto itPrev = m_nameToProperty.insert(propertyName, property);
1027 m_propertyToGroup[property] = groupName;
1028 if (m_sorting) {
1029 QtProperty *previous = nullptr;
1030 if (itPrev != m_nameToProperty.begin())
1031 previous = (--itPrev).value();
1032 m_currentBrowser->insertProperty(property, previous);
1033 }
1034 }
1035 const auto gnit = m_nameToGroup.constFind(groupName);
1036 if (gnit != m_nameToGroup.constEnd()) {
1037 groupProperty = gnit.value();
1038 } else {
1039 groupProperty = m_propertyManager->addProperty(QtVariantPropertyManager::groupTypeId(), groupName);
1040 QtBrowserItem *item = nullptr;
1041 if (!m_sorting)
1042 item = m_currentBrowser->insertProperty(groupProperty, lastGroup);
1043 m_nameToGroup[groupName] = groupProperty;
1044 m_groups.append(groupProperty);
1045 if (dynamicProperty)
1046 m_dynamicGroup = groupProperty;
1047 if (m_currentBrowser == m_treeBrowser && item) {
1048 m_treeBrowser->setBackgroundColor(item, propertyColor(groupProperty));
1049 groupProperty->setModified(true);
1050 }
1051 }
1052 /* Group changed or new group. Append to last subproperty of
1053 * that group. Note that there are cases in which a derived
1054 * property sheet appends fake properties for the class
1055 * which will appear after the layout group properties
1056 * (QWizardPage). To make them appear at the end of the
1057 * actual class group, goto last element. */
1058 if (lastGroup != groupProperty) {
1059 lastGroup = groupProperty;
1060 lastProperty = nullptr; // Append at end
1061 const auto subProperties = lastGroup->subProperties();
1062 if (!subProperties.isEmpty())
1063 lastProperty = subProperties.constLast();
1064 lastGroup = groupProperty;
1065 }
1066 if (!m_groups.contains(groupProperty))
1067 m_groups.append(groupProperty);
1068 if (newProperty)
1069 groupProperty->insertSubProperty(property, lastProperty);
1070
1071 lastProperty = property;
1072
1073 updateBrowserValue(property, value);
1074
1075 property->setModified(m_propertySheet->isChanged(i));
1076 if (propertyName == "geometry"_L1 && type == QMetaType::QRect) {
1077 const auto &subProperties = property->subProperties();
1078 for (QtProperty *subProperty : subProperties) {
1079 const QString subPropertyName = subProperty->propertyName();
1080 if (subPropertyName == "X"_L1 || subPropertyName == "Y"_L1)
1081 subProperty->setEnabled(!isMainContainer);
1082 }
1083 }
1084 } else {
1085 // QTBUG-80417, suppress warning for QDateEdit::timeZone
1086 const int typeId = value.typeId();
1087 if (typeId != qMetaTypeId<QTimeZone>())
1088 qWarning("%s", qPrintable(msgUnsupportedType(propertyName, type)));
1089 }
1090 }
1091 }
1092 QMap<QString, QtVariantProperty *> groups = m_nameToGroup;
1093 for (auto itGroup = groups.cbegin(), end = groups.cend(); itGroup != end; ++itGroup) {
1094 QtVariantProperty *groupProperty = itGroup.value();
1095 if (groupProperty->subProperties().isEmpty()) {
1096 if (groupProperty == m_dynamicGroup)
1097 m_dynamicGroup = nullptr;
1098 delete groupProperty;
1099 m_nameToGroup.remove(itGroup.key());
1100 }
1101 }
1102 const bool addEnabled = dynamicSheet ? dynamicSheet->dynamicPropertiesAllowed() : false;
1103 m_addDynamicAction->setEnabled(addEnabled);
1104 m_removeDynamicAction->setEnabled(false);
1105 applyExpansionState();
1106 applyFilter();
1107 // In the first setObject() call following the addition of a dynamic property, focus and edit it.
1108 if (editNewDynamicProperty) {
1109 // Have QApplication process the events related to completely closing the modal 'add' dialog,
1110 // otherwise, we cannot focus the property editor in docked mode.
1111 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
1112 editProperty(m_recentlyAddedDynamicProperty);
1113 }
1114 m_recentlyAddedDynamicProperty.clear();
1115 m_filterWidget->setEnabled(object);
1116}
1117
1119{
1120 m_updatingBrowser = true;
1121 m_propertyManager->reloadResourceProperties();
1122 m_updatingBrowser = false;
1123}
1124
1125QtBrowserItem *PropertyEditor::nonFakePropertyBrowserItem(QtBrowserItem *item) const
1126{
1127 // Top-level properties are QObject/QWidget groups, etc. Find first item property below
1128 // which should be nonfake
1129 const auto topLevelItems = m_currentBrowser->topLevelItems();
1130 do {
1131 if (topLevelItems.contains(item->parent()))
1132 return item;
1133 item = item->parent();
1134 } while (item);
1135 return nullptr;
1136}
1137
1139{
1140 if (QtBrowserItem *browserItem = m_currentBrowser->currentItem())
1141 if (QtBrowserItem *topLevelItem = nonFakePropertyBrowserItem(browserItem)) {
1142 return topLevelItem->property()->propertyName();
1143 }
1144 return QString();
1145}
1146
1147void PropertyEditor::slotResetProperty(QtProperty *property)
1148{
1149 QDesignerFormWindowInterface *form = m_core->formWindowManager()->activeFormWindow();
1150 if (!form)
1151 return;
1152
1153 if (m_propertyManager->resetFontSubProperty(property))
1154 return;
1155
1156 if (m_propertyManager->resetIconSubProperty(property))
1157 return;
1158
1159 if (m_propertyManager->resetTextAlignmentProperty(property))
1160 return;
1161
1162 if (!m_propertyToGroup.contains(property))
1163 return;
1164
1165 emit resetProperty(property->propertyName());
1166}
1167
1168void PropertyEditor::slotValueChanged(QtProperty *property, const QVariant &value, bool enableSubPropertyHandling)
1169{
1170 if (m_updatingBrowser)
1171 return;
1172
1173 if (!m_propertySheet)
1174 return;
1175
1176 QtVariantProperty *varProp = m_propertyManager->variantProperty(property);
1177
1178 if (!varProp)
1179 return;
1180
1181 if (!m_propertyToGroup.contains(property))
1182 return;
1183
1185 PropertySheetEnumValue e = qvariant_cast<PropertySheetEnumValue>(m_propertySheet->property(m_propertySheet->indexOf(property->propertyName())));
1186 const int val = value.toInt();
1187 const QString valName = varProp->attributeValue(m_strings.m_enumNamesAttribute).toStringList().at(val);
1188 bool ok = false;
1189 e.value = e.metaEnum.parseEnum(valName, &ok);
1190 Q_ASSERT(ok);
1191 QVariant v;
1192 v.setValue(e);
1193 emitPropertyValueChanged(property->propertyName(), v, true);
1194 return;
1195 }
1196
1197 emitPropertyValueChanged(property->propertyName(), value, enableSubPropertyHandling);
1198}
1199
1200bool PropertyEditor::isDynamicProperty(const QtBrowserItem* item) const
1201{
1202 if (!item)
1203 return false;
1204
1205 const QDesignerDynamicPropertySheetExtension *dynamicSheet =
1206 qt_extension<QDesignerDynamicPropertySheetExtension*>(m_core->extensionManager(), m_object);
1207
1208 if (!dynamicSheet)
1209 return false;
1210
1211 return m_propertyToGroup.contains(item->property())
1212 && dynamicSheet->isDynamicProperty(m_propertySheet->indexOf(item->property()->propertyName()));
1213}
1214
1215void PropertyEditor::editProperty(const QString &name)
1216{
1217 // find the browser item belonging to the property, make it current and edit it
1218 QtBrowserItem *browserItem = nullptr;
1219 if (QtVariantProperty *property = m_nameToProperty.value(name, 0)) {
1220 const auto items = m_currentBrowser->items(property);
1221 if (items.size() == 1)
1222 browserItem = items.constFirst();
1223 }
1224 if (browserItem == nullptr)
1225 return;
1226 m_currentBrowser->setFocus(Qt::OtherFocusReason);
1227 if (m_currentBrowser == m_treeBrowser) { // edit is currently only supported in tree view
1228 m_treeBrowser->editItem(browserItem);
1229 } else {
1230 m_currentBrowser->setCurrentItem(browserItem);
1231 }
1232}
1233
1234void PropertyEditor::slotCurrentItemChanged(QtBrowserItem *item)
1235{
1236 m_removeDynamicAction->setEnabled(isDynamicProperty(item));
1237
1238}
1239
1240void PropertyEditor::slotRemoveDynamicProperty()
1241{
1242 if (QtBrowserItem* item = m_currentBrowser->currentItem())
1243 if (isDynamicProperty(item))
1244 emit removeDynamicProperty(item->property()->propertyName());
1245}
1246
1247void PropertyEditor::setFilter(const QString &pattern)
1248{
1249 m_filterPattern = pattern;
1250 applyFilter();
1251}
1252}
1253
1254QT_END_NAMESPACE
virtual bool dynamicPropertiesAllowed() const =0
virtual bool isDynamicProperty(int index) const =0
The QDesignerMetaDataBaseItemInterface class provides an interface to individual items in \QD's meta ...
friend class QWidget
Definition qpainter.h:421
QtBrowserItem * currentItem() const
Returns the current item in the property browser.
QtBrowserItem * insertProperty(QtProperty *property, QtProperty *afterProperty)
Inserts the given property (and its subproperties) after the specified afterProperty in the browser's...
void setCurrentItem(QtBrowserItem *)
Sets the current item in the property browser to item.
void clear()
Removes all the properties from the editor, but does not delete them since they can still be used in ...
The QtBrowserItem class represents a property in a property browser instance.
QtProperty * property() const
Returns the property which is accosiated with this item.
QtBrowserItem * parent() const
Returns the parent item of this item.
The QtButtonPropertyBrowser class provides a drop down QToolButton based property browser.
bool isExpanded(QtBrowserItem *item) const
Returns true if the item is expanded; otherwise returns false.
void setExpanded(QtBrowserItem *item, bool expanded)
Sets the item to either collapse or expanded, depending on the value of expanded.
The QtProperty class encapsulates an instance of a property.
void setModified(bool modified)
Sets the property's modified state according to the passed modified value.
void setEnabled(bool enable)
Enables or disables the property according to the passed enable value.
void insertSubProperty(QtProperty *property, QtProperty *afterProperty)
Inserts the given property after the specified precedingProperty into this property's list of subprop...
bool isExpanded(QtBrowserItem *item) const
Returns true if the item is expanded; otherwise returns false.
void editItem(QtBrowserItem *item)
Sets the current item to item and opens the relevant editor for it.
void setItemVisible(QtBrowserItem *item, bool visible)
Sets the item to be visible, depending on the value of visible.
void setExpanded(QtBrowserItem *item, bool expanded)
Sets the item to either collapse or expanded, depending on the value of expanded.
bool isItemVisible(QtBrowserItem *item) const
Returns true if the item is visible; otherwise returns false.
void setSplitterPosition(int position)
void setPropertiesWithoutValueMarked(bool mark)
The QtVariantPropertyManager class provides and manages QVariant based properties.
static int groupTypeId()
Returns the type id for a group property.
static int enumTypeId()
Returns the type id for an enum property.
QtVariantProperty * variantProperty(const QtProperty *property) const
Returns the given property converted into a QtVariantProperty.
The QtVariantProperty class is a convenience class handling QVariant based properties.
int propertyType() const
Returns this property's type.
QSize sizeHint() const override
void setElidemode(Qt::TextElideMode mode)
void paintEvent(QPaintEvent *e) override
This event handler can be reimplemented in a subclass to receive paint events passed in event.
void setText(const QString &text)
ElidingLabel(const QString &text=QString(), QWidget *parent=nullptr)
QString currentPropertyName() const override
Returns the name of the currently selected property in the property editor.
bool event(QEvent *event) override
This virtual function receives events to an object and should return true if the event e was recogniz...
QDesignerFormEditorInterface * core() const override
Returns a pointer to \QD's current QDesignerFormEditorInterface object.
void setObject(QObject *object) override
Changes the currently selected object in \QD's workspace, to object.
void setReadOnly(bool readOnly) override
If readOnly is true, the property editor is made write protected; otherwise the write protection is r...
bool isReadOnly() const override
Returns true if the property editor is write protected; otherwise false.
Auxiliary methods to store/retrieve settings.
static const char * typeName(int type)
static QToolButton * createDropDownButton(QAction *defaultAction, QWidget *parent=nullptr)
static QLayout * layoutOfQLayoutWidget(QObject *o)
static QString msgUnsupportedType(const QString &propertyName, int type)
static constexpr auto SplitterPositionKeyC
static constexpr auto SettingsGroupC
static constexpr auto ViewKeyC
static constexpr auto ColorKeyC
static constexpr auto ExpansionKeyC
static constexpr auto SortedKeyC