// Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qteditorfactory.h" #include "qtpropertybrowserutils_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(Q_CC_MSVC) # pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */ #endif QT_BEGIN_NAMESPACE // Set a hard coded left margin to account for the indentation // of the tree view icon when switching to an editor static inline void setupTreeViewEditorMargin(QLayout *lt) { enum { DecorationMargin = 4 }; if (QApplication::layoutDirection() == Qt::LeftToRight) lt->setContentsMargins(DecorationMargin, 0, 0, 0); else lt->setContentsMargins(0, 0, DecorationMargin, 0); } // ---------- EditorFactoryPrivate : // Base class for editor factory private classes. Manages mapping of properties to editors and vice versa. template class EditorFactoryPrivate { public: using EditorList = QList; using PropertyToEditorListMap = QHash; using EditorToPropertyMap = QHash; Editor *createEditor(QtProperty *property, QWidget *parent); void initializeEditor(QtProperty *property, Editor *e); void slotEditorDestroyed(QObject *object); PropertyToEditorListMap m_createdEditors; EditorToPropertyMap m_editorToProperty; }; template Editor *EditorFactoryPrivate::createEditor(QtProperty *property, QWidget *parent) { auto *editor = new Editor(parent); initializeEditor(property, editor); return editor; } template void EditorFactoryPrivate::initializeEditor(QtProperty *property, Editor *editor) { auto it = m_createdEditors.find(property); if (it == m_createdEditors.end()) it = m_createdEditors.insert(property, EditorList()); it.value().append(editor); m_editorToProperty.insert(editor, property); } template void EditorFactoryPrivate::slotEditorDestroyed(QObject *object) { const auto ecend = m_editorToProperty.end(); for (auto itEditor = m_editorToProperty.begin(); itEditor != ecend; ++itEditor) { if (itEditor.key() == object) { Editor *editor = itEditor.key(); QtProperty *property = itEditor.value(); const auto pit = m_createdEditors.find(property); if (pit != m_createdEditors.end()) { pit.value().removeAll(editor); if (pit.value().isEmpty()) m_createdEditors.erase(pit); } m_editorToProperty.erase(itEditor); return; } } } // ------------ QtSpinBoxFactory class QtSpinBoxFactoryPrivate : public EditorFactoryPrivate { QtSpinBoxFactory *q_ptr; Q_DECLARE_PUBLIC(QtSpinBoxFactory) public: void slotPropertyChanged(QtProperty *property, int value); void slotRangeChanged(QtProperty *property, int min, int max); void slotSingleStepChanged(QtProperty *property, int step); void slotSetValue(int value); }; void QtSpinBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.cend()) return; for (QSpinBox *editor : it.value()) { if (editor->value() != value) { editor->blockSignals(true); editor->setValue(value); editor->blockSignals(false); } } } void QtSpinBoxFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.cend()) return; QtIntPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; for (QSpinBox *editor : it.value()) { editor->blockSignals(true); editor->setRange(min, max); editor->setValue(manager->value(property)); editor->blockSignals(false); } } void QtSpinBoxFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.cend()) return; for (QSpinBox *editor : it.value()) { editor->blockSignals(true); editor->setSingleStep(step); editor->blockSignals(false); } } void QtSpinBoxFactoryPrivate::slotSetValue(int value) { QObject *object = q_ptr->sender(); for (auto itEditor = m_editorToProperty.cbegin(), ecend = m_editorToProperty.cend(); itEditor != ecend; ++itEditor) { if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtIntPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } } /*! \class QtSpinBoxFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtSpinBoxFactory class provides QSpinBox widgets for properties created by QtIntPropertyManager objects. \sa QtAbstractEditorFactory, QtIntPropertyManager */ /*! Creates a factory with the given \a parent. */ QtSpinBoxFactory::QtSpinBoxFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtSpinBoxFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtSpinBoxFactory::~QtSpinBoxFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtSpinBoxFactory::connectPropertyManager(QtIntPropertyManager *manager) { connect(manager, &QtIntPropertyManager::valueChanged, this, [this](QtProperty *property, int value) { d_ptr->slotPropertyChanged(property, value); }); connect(manager, &QtIntPropertyManager::rangeChanged, this, [this](QtProperty *property, int min, int max) { d_ptr->slotRangeChanged(property, min, max); }); connect(manager, &QtIntPropertyManager::singleStepChanged, this, [this](QtProperty *property, int value) { d_ptr->slotSingleStepChanged(property, value); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtSpinBoxFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property, QWidget *parent) { QSpinBox *editor = d_ptr->createEditor(property, parent); editor->setSingleStep(manager->singleStep(property)); editor->setRange(manager->minimum(property), manager->maximum(property)); editor->setValue(manager->value(property)); editor->setKeyboardTracking(false); connect(editor, &QSpinBox::valueChanged, this, [this](int value) { d_ptr->slotSetValue(value); }); connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtSpinBoxFactory::disconnectPropertyManager(QtIntPropertyManager *manager) { disconnect(manager, &QtIntPropertyManager::valueChanged, this, nullptr); disconnect(manager, &QtIntPropertyManager::rangeChanged, this, nullptr); disconnect(manager, &QtIntPropertyManager::singleStepChanged, this, nullptr); } // QtSliderFactory class QtSliderFactoryPrivate : public EditorFactoryPrivate { QtSliderFactory *q_ptr; Q_DECLARE_PUBLIC(QtSliderFactory) public: void slotPropertyChanged(QtProperty *property, int value); void slotRangeChanged(QtProperty *property, int min, int max); void slotSingleStepChanged(QtProperty *property, int step); void slotSetValue(int value); }; void QtSliderFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.cend()) return; for (QSlider *editor : it.value()) { editor->blockSignals(true); editor->setValue(value); editor->blockSignals(false); } } void QtSliderFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.cend()) return; QtIntPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; for (QSlider *editor : it.value()) { editor->blockSignals(true); editor->setRange(min, max); editor->setValue(manager->value(property)); editor->blockSignals(false); } } void QtSliderFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.cend()) return; for (QSlider *editor : it.value()) { editor->blockSignals(true); editor->setSingleStep(step); editor->blockSignals(false); } } void QtSliderFactoryPrivate::slotSetValue(int value) { QObject *object = q_ptr->sender(); for (auto itEditor = m_editorToProperty.cbegin(), ecend = m_editorToProperty.cend(); itEditor != ecend; ++itEditor ) { if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtIntPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } } /*! \class QtSliderFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtSliderFactory class provides QSlider widgets for properties created by QtIntPropertyManager objects. \sa QtAbstractEditorFactory, QtIntPropertyManager */ /*! Creates a factory with the given \a parent. */ QtSliderFactory::QtSliderFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtSliderFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtSliderFactory::~QtSliderFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtSliderFactory::connectPropertyManager(QtIntPropertyManager *manager) { connect(manager, &QtIntPropertyManager::valueChanged, this, [this](QtProperty *property, int value) { d_ptr->slotPropertyChanged(property, value); }); connect(manager, &QtIntPropertyManager::rangeChanged, this, [this](QtProperty *property, int min, int max) { d_ptr->slotRangeChanged(property, min, max); }); connect(manager, &QtIntPropertyManager::singleStepChanged, this, [this](QtProperty *property, int value) { d_ptr->slotSingleStepChanged(property, value); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtSliderFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property, QWidget *parent) { auto *editor = new QSlider(Qt::Horizontal, parent); d_ptr->initializeEditor(property, editor); editor->setSingleStep(manager->singleStep(property)); editor->setRange(manager->minimum(property), manager->maximum(property)); editor->setValue(manager->value(property)); connect(editor, &QSlider::valueChanged, this, [this](int value) { d_ptr->slotSetValue(value); }); connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtSliderFactory::disconnectPropertyManager(QtIntPropertyManager *manager) { disconnect(manager, &QtIntPropertyManager::valueChanged, this, nullptr); disconnect(manager, &QtIntPropertyManager::rangeChanged, this, nullptr); disconnect(manager, &QtIntPropertyManager::singleStepChanged, this, nullptr); } // QtSliderFactory class QtScrollBarFactoryPrivate : public EditorFactoryPrivate { QtScrollBarFactory *q_ptr; Q_DECLARE_PUBLIC(QtScrollBarFactory) public: void slotPropertyChanged(QtProperty *property, int value); void slotRangeChanged(QtProperty *property, int min, int max); void slotSingleStepChanged(QtProperty *property, int step); void slotSetValue(int value); }; void QtScrollBarFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.cend()) return; for (QScrollBar *editor : it.value()) { editor->blockSignals(true); editor->setValue(value); editor->blockSignals(false); } } void QtScrollBarFactoryPrivate::slotRangeChanged(QtProperty *property, int min, int max) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.cend()) return; QtIntPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; for (QScrollBar *editor : it.value()) { editor->blockSignals(true); editor->setRange(min, max); editor->setValue(manager->value(property)); editor->blockSignals(false); } } void QtScrollBarFactoryPrivate::slotSingleStepChanged(QtProperty *property, int step) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.cend()) return; for (QScrollBar *editor : it.value()) { editor->blockSignals(true); editor->setSingleStep(step); editor->blockSignals(false); } } void QtScrollBarFactoryPrivate::slotSetValue(int value) { QObject *object = q_ptr->sender(); for (auto itEditor = m_editorToProperty.cbegin(), ecend = m_editorToProperty.cend(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtIntPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtScrollBarFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtScrollBarFactory class provides QScrollBar widgets for properties created by QtIntPropertyManager objects. \sa QtAbstractEditorFactory, QtIntPropertyManager */ /*! Creates a factory with the given \a parent. */ QtScrollBarFactory::QtScrollBarFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtScrollBarFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtScrollBarFactory::~QtScrollBarFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtScrollBarFactory::connectPropertyManager(QtIntPropertyManager *manager) { connect(manager, &QtIntPropertyManager::valueChanged, this, [this](QtProperty *property, int value) { d_ptr->slotPropertyChanged(property, value); }); connect(manager, &QtIntPropertyManager::rangeChanged, this, [this](QtProperty *property, int min, int max) { d_ptr->slotRangeChanged(property, min, max); }); connect(manager, &QtIntPropertyManager::singleStepChanged, this, [this](QtProperty *property, int value) { d_ptr->slotSingleStepChanged(property, value); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtScrollBarFactory::createEditor(QtIntPropertyManager *manager, QtProperty *property, QWidget *parent) { auto *editor = new QScrollBar(Qt::Horizontal, parent); d_ptr->initializeEditor(property, editor); editor->setSingleStep(manager->singleStep(property)); editor->setRange(manager->minimum(property), manager->maximum(property)); editor->setValue(manager->value(property)); connect(editor, &QScrollBar::valueChanged, this, [this](int value) { d_ptr->slotSetValue(value); }); connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtScrollBarFactory::disconnectPropertyManager(QtIntPropertyManager *manager) { disconnect(manager, &QtIntPropertyManager::valueChanged, this, nullptr); disconnect(manager, &QtIntPropertyManager::rangeChanged, this, nullptr); disconnect(manager, &QtIntPropertyManager::singleStepChanged, this, nullptr); } // QtCheckBoxFactory class QtCheckBoxFactoryPrivate : public EditorFactoryPrivate { QtCheckBoxFactory *q_ptr; Q_DECLARE_PUBLIC(QtCheckBoxFactory) public: void slotPropertyChanged(QtProperty *property, bool value); void slotSetValue(bool value); }; void QtCheckBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, bool value) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.cend()) return; for (QtBoolEdit *editor : it.value()) { editor->blockCheckBoxSignals(true); editor->setChecked(value); editor->blockCheckBoxSignals(false); } } void QtCheckBoxFactoryPrivate::slotSetValue(bool value) { QObject *object = q_ptr->sender(); for (auto itEditor = m_editorToProperty.cbegin(), ecend = m_editorToProperty.cend(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtBoolPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtCheckBoxFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtCheckBoxFactory class provides QCheckBox widgets for properties created by QtBoolPropertyManager objects. \sa QtAbstractEditorFactory, QtBoolPropertyManager */ /*! Creates a factory with the given \a parent. */ QtCheckBoxFactory::QtCheckBoxFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtCheckBoxFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtCheckBoxFactory::~QtCheckBoxFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtCheckBoxFactory::connectPropertyManager(QtBoolPropertyManager *manager) { connect(manager, &QtBoolPropertyManager::valueChanged, this, [this](QtProperty *property, bool value) { d_ptr->slotPropertyChanged(property, value); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtCheckBoxFactory::createEditor(QtBoolPropertyManager *manager, QtProperty *property, QWidget *parent) { QtBoolEdit *editor = d_ptr->createEditor(property, parent); editor->setChecked(manager->value(property)); connect(editor, &QtBoolEdit::toggled, this, [this](bool value) { d_ptr->slotSetValue(value); }); connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtCheckBoxFactory::disconnectPropertyManager(QtBoolPropertyManager *manager) { disconnect(manager, &QtBoolPropertyManager::valueChanged, this, nullptr); } // QtDoubleSpinBoxFactory class QtDoubleSpinBoxFactoryPrivate : public EditorFactoryPrivate { QtDoubleSpinBoxFactory *q_ptr; Q_DECLARE_PUBLIC(QtDoubleSpinBoxFactory) public: void slotPropertyChanged(QtProperty *property, double value); void slotRangeChanged(QtProperty *property, double min, double max); void slotSingleStepChanged(QtProperty *property, double step); void slotDecimalsChanged(QtProperty *property, int prec); void slotSetValue(double value); }; void QtDoubleSpinBoxFactoryPrivate::slotPropertyChanged(QtProperty *property, double value) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.cend()) return; for (QDoubleSpinBox *editor : it.value()) { if (editor->value() != value) { editor->blockSignals(true); editor->setValue(value); editor->blockSignals(false); } } } void QtDoubleSpinBoxFactoryPrivate::slotRangeChanged(QtProperty *property, double min, double max) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.cend()) return; QtDoublePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; for (QDoubleSpinBox *editor : it.value()) { editor->blockSignals(true); editor->setRange(min, max); editor->setValue(manager->value(property)); editor->blockSignals(false); } } void QtDoubleSpinBoxFactoryPrivate::slotSingleStepChanged(QtProperty *property, double step) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.cend()) return; QtDoublePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; for (QDoubleSpinBox *editor : it.value()) { editor->blockSignals(true); editor->setSingleStep(step); editor->blockSignals(false); } } void QtDoubleSpinBoxFactoryPrivate::slotDecimalsChanged(QtProperty *property, int prec) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.constEnd()) return; QtDoublePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; for (QDoubleSpinBox *editor : it.value()) { editor->blockSignals(true); editor->setDecimals(prec); editor->setValue(manager->value(property)); editor->blockSignals(false); } } void QtDoubleSpinBoxFactoryPrivate::slotSetValue(double value) { QObject *object = q_ptr->sender(); for (auto itEditor = m_editorToProperty.cbegin(), itcend = m_editorToProperty.cend(); itEditor != itcend; ++itEditor) { if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtDoublePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } } /*! \class QtDoubleSpinBoxFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtDoubleSpinBoxFactory class provides QDoubleSpinBox widgets for properties created by QtDoublePropertyManager objects. \sa QtAbstractEditorFactory, QtDoublePropertyManager */ /*! Creates a factory with the given \a parent. */ QtDoubleSpinBoxFactory::QtDoubleSpinBoxFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtDoubleSpinBoxFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtDoubleSpinBoxFactory::~QtDoubleSpinBoxFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtDoubleSpinBoxFactory::connectPropertyManager(QtDoublePropertyManager *manager) { connect(manager, &QtDoublePropertyManager::valueChanged, this, [this](QtProperty *property, double value) { d_ptr->slotPropertyChanged(property, value); }); connect(manager, &QtDoublePropertyManager::rangeChanged, this, [this](QtProperty *property, double min, double max) { d_ptr->slotRangeChanged(property, min, max); }); connect(manager, &QtDoublePropertyManager::singleStepChanged, this, [this](QtProperty *property, double value) { d_ptr->slotSingleStepChanged(property, value); }); connect(manager, &QtDoublePropertyManager::decimalsChanged, this, [this](QtProperty *property, int value) { d_ptr->slotDecimalsChanged(property, value); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtDoubleSpinBoxFactory::createEditor(QtDoublePropertyManager *manager, QtProperty *property, QWidget *parent) { QDoubleSpinBox *editor = d_ptr->createEditor(property, parent); editor->setSingleStep(manager->singleStep(property)); editor->setDecimals(manager->decimals(property)); editor->setRange(manager->minimum(property), manager->maximum(property)); editor->setValue(manager->value(property)); editor->setKeyboardTracking(false); connect(editor, &QDoubleSpinBox::valueChanged, this, [this](double value) { d_ptr->slotSetValue(value); }); connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtDoubleSpinBoxFactory::disconnectPropertyManager(QtDoublePropertyManager *manager) { disconnect(manager, &QtDoublePropertyManager::valueChanged, this, nullptr); disconnect(manager, &QtDoublePropertyManager::rangeChanged, this, nullptr); disconnect(manager, &QtDoublePropertyManager::singleStepChanged, this, nullptr); disconnect(manager, &QtDoublePropertyManager::decimalsChanged, this, nullptr); } // QtLineEditFactory class QtLineEditFactoryPrivate : public EditorFactoryPrivate { QtLineEditFactory *q_ptr; Q_DECLARE_PUBLIC(QtLineEditFactory) public: void slotPropertyChanged(QtProperty *property, const QString &value); void slotRegExpChanged(QtProperty *property, const QRegularExpression ®Exp); void slotSetValue(const QString &value); }; void QtLineEditFactoryPrivate::slotPropertyChanged(QtProperty *property, const QString &value) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.constEnd()) return; for (QLineEdit *editor : it.value()) { if (editor->text() != value) editor->setText(value); } } void QtLineEditFactoryPrivate::slotRegExpChanged(QtProperty *property, const QRegularExpression ®Exp) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.constEnd()) return; QtStringPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; for (QLineEdit *editor : it.value()) { editor->blockSignals(true); const QValidator *oldValidator = editor->validator(); QValidator *newValidator = nullptr; if (regExp.isValid()) { newValidator = new QRegularExpressionValidator(regExp, editor); } editor->setValidator(newValidator); if (oldValidator) delete oldValidator; editor->blockSignals(false); } } void QtLineEditFactoryPrivate::slotSetValue(const QString &value) { QObject *object = q_ptr->sender(); for (auto itEditor = m_editorToProperty.cbegin(), ecend = m_editorToProperty.cend(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtStringPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtLineEditFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtLineEditFactory class provides QLineEdit widgets for properties created by QtStringPropertyManager objects. \sa QtAbstractEditorFactory, QtStringPropertyManager */ /*! Creates a factory with the given \a parent. */ QtLineEditFactory::QtLineEditFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtLineEditFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtLineEditFactory::~QtLineEditFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtLineEditFactory::connectPropertyManager(QtStringPropertyManager *manager) { connect(manager, &QtStringPropertyManager::valueChanged, this, [this](QtProperty *property, const QString &value) { d_ptr->slotPropertyChanged(property, value); }); connect(manager, &QtStringPropertyManager::regExpChanged, this, [this](QtProperty *property, const QRegularExpression &value) { d_ptr->slotRegExpChanged(property, value); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtLineEditFactory::createEditor(QtStringPropertyManager *manager, QtProperty *property, QWidget *parent) { QLineEdit *editor = d_ptr->createEditor(property, parent); QRegularExpression regExp = manager->regExp(property); if (regExp.isValid() && !regExp.pattern().isEmpty()) { auto *validator = new QRegularExpressionValidator(regExp, editor); editor->setValidator(validator); } editor->setText(manager->value(property)); connect(editor, &QLineEdit::textEdited, this, [this](const QString &value) { d_ptr->slotSetValue(value); }); connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtLineEditFactory::disconnectPropertyManager(QtStringPropertyManager *manager) { disconnect(manager, &QtStringPropertyManager::valueChanged, this, nullptr); disconnect(manager, &QtStringPropertyManager::regExpChanged, this, nullptr); } // QtDateEditFactory class QtDateEditFactoryPrivate : public EditorFactoryPrivate { QtDateEditFactory *q_ptr; Q_DECLARE_PUBLIC(QtDateEditFactory) public: void slotPropertyChanged(QtProperty *property, QDate value); void slotRangeChanged(QtProperty *property, QDate min, QDate max); void slotSetValue(QDate value); }; void QtDateEditFactoryPrivate::slotPropertyChanged(QtProperty *property, QDate value) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.constEnd()) return; for (QDateEdit *editor : it.value()) { editor->blockSignals(true); editor->setDate(value); editor->blockSignals(false); } } void QtDateEditFactoryPrivate::slotRangeChanged(QtProperty *property, QDate min, QDate max) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.constEnd()) return; QtDatePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; for (QDateEdit *editor : it.value()) { editor->blockSignals(true); editor->setDateRange(min, max); editor->setDate(manager->value(property)); editor->blockSignals(false); } } void QtDateEditFactoryPrivate::slotSetValue(QDate value) { QObject *object = q_ptr->sender(); for (auto itEditor = m_editorToProperty.cbegin(), ecend = m_editorToProperty.cend(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtDatePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtDateEditFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtDateEditFactory class provides QDateEdit widgets for properties created by QtDatePropertyManager objects. \sa QtAbstractEditorFactory, QtDatePropertyManager */ /*! Creates a factory with the given \a parent. */ QtDateEditFactory::QtDateEditFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtDateEditFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtDateEditFactory::~QtDateEditFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtDateEditFactory::connectPropertyManager(QtDatePropertyManager *manager) { connect(manager, &QtDatePropertyManager::valueChanged, this, [this](QtProperty *property, const QDate &value) { d_ptr->slotPropertyChanged(property, value); }); connect(manager, &QtDatePropertyManager::rangeChanged, this, [this](QtProperty *property, const QDate &min, const QDate &max) { d_ptr->slotRangeChanged(property, min, max); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtDateEditFactory::createEditor(QtDatePropertyManager *manager, QtProperty *property, QWidget *parent) { QDateEdit *editor = d_ptr->createEditor(property, parent); editor->setDisplayFormat(QtPropertyBrowserUtils::dateFormat()); editor->setCalendarPopup(true); editor->setDateRange(manager->minimum(property), manager->maximum(property)); editor->setDate(manager->value(property)); connect(editor, &QDateEdit::dateChanged, this, [this](const QDate &value) { d_ptr->slotSetValue(value); }); connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtDateEditFactory::disconnectPropertyManager(QtDatePropertyManager *manager) { disconnect(manager, &QtDatePropertyManager::valueChanged, this, nullptr); disconnect(manager, &QtDatePropertyManager::rangeChanged, this, nullptr); } // QtTimeEditFactory class QtTimeEditFactoryPrivate : public EditorFactoryPrivate { QtTimeEditFactory *q_ptr; Q_DECLARE_PUBLIC(QtTimeEditFactory) public: void slotPropertyChanged(QtProperty *property, QTime value); void slotSetValue(QTime value); }; void QtTimeEditFactoryPrivate::slotPropertyChanged(QtProperty *property, QTime value) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.constEnd()) return; for (QTimeEdit *editor : it.value()) { editor->blockSignals(true); editor->setTime(value); editor->blockSignals(false); } } void QtTimeEditFactoryPrivate::slotSetValue(QTime value) { QObject *object = q_ptr->sender(); for (auto itEditor = m_editorToProperty.cbegin(), ecend = m_editorToProperty.cend(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtTimePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtTimeEditFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtTimeEditFactory class provides QTimeEdit widgets for properties created by QtTimePropertyManager objects. \sa QtAbstractEditorFactory, QtTimePropertyManager */ /*! Creates a factory with the given \a parent. */ QtTimeEditFactory::QtTimeEditFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtTimeEditFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtTimeEditFactory::~QtTimeEditFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtTimeEditFactory::connectPropertyManager(QtTimePropertyManager *manager) { connect(manager, &QtTimePropertyManager::valueChanged, this, [this](QtProperty *property, const QTime &value) { d_ptr->slotPropertyChanged(property, value); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtTimeEditFactory::createEditor(QtTimePropertyManager *manager, QtProperty *property, QWidget *parent) { QTimeEdit *editor = d_ptr->createEditor(property, parent); editor->setDisplayFormat(QtPropertyBrowserUtils::timeFormat()); editor->setTime(manager->value(property)); connect(editor, &QTimeEdit::timeChanged, this, [this](const QTime &value) { d_ptr->slotSetValue(value); }); connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtTimeEditFactory::disconnectPropertyManager(QtTimePropertyManager *manager) { disconnect(manager, &QtTimePropertyManager::valueChanged, this, nullptr); } // QtDateTimeEditFactory class QtDateTimeEditFactoryPrivate : public EditorFactoryPrivate { QtDateTimeEditFactory *q_ptr; Q_DECLARE_PUBLIC(QtDateTimeEditFactory) public: void slotPropertyChanged(QtProperty *property, const QDateTime &value); void slotSetValue(const QDateTime &value); }; void QtDateTimeEditFactoryPrivate::slotPropertyChanged(QtProperty *property, const QDateTime &value) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.constEnd()) return; for (QDateTimeEdit *editor : it.value()) { editor->blockSignals(true); editor->setDateTime(value); editor->blockSignals(false); } } void QtDateTimeEditFactoryPrivate::slotSetValue(const QDateTime &value) { QObject *object = q_ptr->sender(); for (auto itEditor = m_editorToProperty.cbegin(), ecend = m_editorToProperty.cend(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtDateTimePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtDateTimeEditFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtDateTimeEditFactory class provides QDateTimeEdit widgets for properties created by QtDateTimePropertyManager objects. \sa QtAbstractEditorFactory, QtDateTimePropertyManager */ /*! Creates a factory with the given \a parent. */ QtDateTimeEditFactory::QtDateTimeEditFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtDateTimeEditFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtDateTimeEditFactory::~QtDateTimeEditFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtDateTimeEditFactory::connectPropertyManager(QtDateTimePropertyManager *manager) { connect(manager, &QtDateTimePropertyManager::valueChanged, this, [this](QtProperty *property, const QDateTime &value) { d_ptr->slotPropertyChanged(property, value); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtDateTimeEditFactory::createEditor(QtDateTimePropertyManager *manager, QtProperty *property, QWidget *parent) { QDateTimeEdit *editor = d_ptr->createEditor(property, parent); editor->setDisplayFormat(QtPropertyBrowserUtils::dateTimeFormat()); editor->setDateTime(manager->value(property)); connect(editor, &QDateTimeEdit::dateTimeChanged, this, [this](const QDateTime &value) { d_ptr->slotSetValue(value); }); connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtDateTimeEditFactory::disconnectPropertyManager(QtDateTimePropertyManager *manager) { disconnect(manager, &QtDateTimePropertyManager::valueChanged, this, nullptr); } // QtKeySequenceEditorFactory class QtKeySequenceEditorFactoryPrivate : public EditorFactoryPrivate { QtKeySequenceEditorFactory *q_ptr; Q_DECLARE_PUBLIC(QtKeySequenceEditorFactory) public: void slotPropertyChanged(QtProperty *property, const QKeySequence &value); void slotSetValue(const QKeySequence &value); }; void QtKeySequenceEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, const QKeySequence &value) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.constEnd()) return; for (QKeySequenceEdit *editor : it.value()) { editor->blockSignals(true); editor->setKeySequence(value); editor->blockSignals(false); } } void QtKeySequenceEditorFactoryPrivate::slotSetValue(const QKeySequence &value) { QObject *object = q_ptr->sender(); for (auto itEditor = m_editorToProperty.cbegin(), ecend = m_editorToProperty.cend(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtKeySequencePropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtKeySequenceEditorFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtKeySequenceEditorFactory class provides editor widgets for properties created by QtKeySequencePropertyManager objects. \sa QtAbstractEditorFactory */ /*! Creates a factory with the given \a parent. */ QtKeySequenceEditorFactory::QtKeySequenceEditorFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtKeySequenceEditorFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtKeySequenceEditorFactory::~QtKeySequenceEditorFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtKeySequenceEditorFactory::connectPropertyManager(QtKeySequencePropertyManager *manager) { connect(manager, &QtKeySequencePropertyManager::valueChanged, this, [this](QtProperty *property, const QKeySequence &value) { d_ptr->slotPropertyChanged(property, value); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtKeySequenceEditorFactory::createEditor(QtKeySequencePropertyManager *manager, QtProperty *property, QWidget *parent) { QKeySequenceEdit *editor = d_ptr->createEditor(property, parent); editor->setKeySequence(manager->value(property)); connect(editor, &QKeySequenceEdit::keySequenceChanged, this, [this](const QKeySequence &value) { d_ptr->slotSetValue(value); }); connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtKeySequenceEditorFactory::disconnectPropertyManager(QtKeySequencePropertyManager *manager) { disconnect(manager, &QtKeySequencePropertyManager::valueChanged, this, nullptr); } // QtCharEdit class QtCharEdit : public QWidget { Q_OBJECT public: QtCharEdit(QWidget *parent = 0); QChar value() const; bool eventFilter(QObject *o, QEvent *e) override; public Q_SLOTS: void setValue(const QChar &value); Q_SIGNALS: void valueChanged(const QChar &value); protected: void focusInEvent(QFocusEvent *e) override; void focusOutEvent(QFocusEvent *e) override; void keyPressEvent(QKeyEvent *e) override; void keyReleaseEvent(QKeyEvent *e) override; bool event(QEvent *e) override; private slots: void slotClearChar(); private: void handleKeyEvent(QKeyEvent *e); QChar m_value; QLineEdit *m_lineEdit; }; QtCharEdit::QtCharEdit(QWidget *parent) : QWidget(parent), m_lineEdit(new QLineEdit(this)) { auto *layout = new QHBoxLayout(this); layout->addWidget(m_lineEdit); layout->setContentsMargins(QMargins()); m_lineEdit->installEventFilter(this); m_lineEdit->setReadOnly(true); m_lineEdit->setFocusProxy(this); setFocusPolicy(m_lineEdit->focusPolicy()); setAttribute(Qt::WA_InputMethodEnabled); } bool QtCharEdit::eventFilter(QObject *o, QEvent *e) { if (o == m_lineEdit && e->type() == QEvent::ContextMenu) { QContextMenuEvent *c = static_cast(e); QMenu *menu = m_lineEdit->createStandardContextMenu(); const auto actions = menu->actions(); for (QAction *action : actions) { action->setShortcut(QKeySequence()); QString actionString = action->text(); const int pos = actionString.lastIndexOf(QLatin1Char('\t')); if (pos > 0) actionString = actionString.remove(pos, actionString.size() - pos); action->setText(actionString); } QAction *actionBefore = nullptr; if (actions.size() > 0) actionBefore = actions[0]; auto *clearAction = new QAction(tr("Clear Char"), menu); menu->insertAction(actionBefore, clearAction); menu->insertSeparator(actionBefore); clearAction->setEnabled(!m_value.isNull()); connect(clearAction, &QAction::triggered, this, &QtCharEdit::slotClearChar); menu->exec(c->globalPos()); delete menu; e->accept(); return true; } return QWidget::eventFilter(o, e); } void QtCharEdit::slotClearChar() { if (m_value.isNull()) return; setValue(QChar()); emit valueChanged(m_value); } void QtCharEdit::handleKeyEvent(QKeyEvent *e) { const int key = e->key(); switch (key) { case Qt::Key_Control: case Qt::Key_Shift: case Qt::Key_Meta: case Qt::Key_Alt: case Qt::Key_Super_L: case Qt::Key_Return: return; default: break; } const QString text = e->text(); if (text.size() != 1) return; const QChar c = text.at(0); if (!c.isPrint()) return; if (m_value == c) return; m_value = c; const QString str = m_value.isNull() ? QString() : QString(m_value); m_lineEdit->setText(str); e->accept(); emit valueChanged(m_value); } void QtCharEdit::setValue(const QChar &value) { if (value == m_value) return; m_value = value; QString str = value.isNull() ? QString() : QString(value); m_lineEdit->setText(str); } QChar QtCharEdit::value() const { return m_value; } void QtCharEdit::focusInEvent(QFocusEvent *e) { m_lineEdit->event(e); m_lineEdit->selectAll(); QWidget::focusInEvent(e); } void QtCharEdit::focusOutEvent(QFocusEvent *e) { m_lineEdit->event(e); QWidget::focusOutEvent(e); } void QtCharEdit::keyPressEvent(QKeyEvent *e) { handleKeyEvent(e); e->accept(); } void QtCharEdit::keyReleaseEvent(QKeyEvent *e) { m_lineEdit->event(e); } bool QtCharEdit::event(QEvent *e) { switch(e->type()) { case QEvent::Shortcut: case QEvent::ShortcutOverride: case QEvent::KeyRelease: e->accept(); return true; default: break; } return QWidget::event(e); } // QtCharEditorFactory class QtCharEditorFactoryPrivate : public EditorFactoryPrivate { QtCharEditorFactory *q_ptr; Q_DECLARE_PUBLIC(QtCharEditorFactory) public: void slotPropertyChanged(QtProperty *property, const QChar &value); void slotSetValue(const QChar &value); }; void QtCharEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, const QChar &value) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.constEnd()) return; for (QtCharEdit *editor : it.value()) { editor->blockSignals(true); editor->setValue(value); editor->blockSignals(false); } } void QtCharEditorFactoryPrivate::slotSetValue(const QChar &value) { QObject *object = q_ptr->sender(); for (auto itEditor = m_editorToProperty.cbegin(), ecend = m_editorToProperty.cend(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtCharPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtCharEditorFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtCharEditorFactory class provides editor widgets for properties created by QtCharPropertyManager objects. \sa QtAbstractEditorFactory */ /*! Creates a factory with the given \a parent. */ QtCharEditorFactory::QtCharEditorFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtCharEditorFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtCharEditorFactory::~QtCharEditorFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtCharEditorFactory::connectPropertyManager(QtCharPropertyManager *manager) { connect(manager, &QtCharPropertyManager::valueChanged, this, [this](QtProperty *property, const QChar &value) { d_ptr->slotPropertyChanged(property, value); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtCharEditorFactory::createEditor(QtCharPropertyManager *manager, QtProperty *property, QWidget *parent) { QtCharEdit *editor = d_ptr->createEditor(property, parent); editor->setValue(manager->value(property)); connect(editor, &QtCharEdit::valueChanged, this, [this](const QChar &value) { d_ptr->slotSetValue(value); }); connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtCharEditorFactory::disconnectPropertyManager(QtCharPropertyManager *manager) { disconnect(manager, &QtCharPropertyManager::valueChanged, this, nullptr); } // QtEnumEditorFactory class QtEnumEditorFactoryPrivate : public EditorFactoryPrivate { QtEnumEditorFactory *q_ptr; Q_DECLARE_PUBLIC(QtEnumEditorFactory) public: void slotPropertyChanged(QtProperty *property, int value); void slotEnumNamesChanged(QtProperty *property, const QStringList &); void slotEnumIconsChanged(QtProperty *property, const QMap &); void slotSetValue(int value); }; void QtEnumEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, int value) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.constEnd()) return; for (QComboBox *editor : it.value()) { editor->blockSignals(true); editor->setCurrentIndex(value); editor->blockSignals(false); } } void QtEnumEditorFactoryPrivate::slotEnumNamesChanged(QtProperty *property, const QStringList &enumNames) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.constEnd()) return; QtEnumPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; QMap enumIcons = manager->enumIcons(property); for (QComboBox *editor : it.value()) { editor->blockSignals(true); editor->clear(); editor->addItems(enumNames); const int nameCount = enumNames.size(); for (int i = 0; i < nameCount; i++) editor->setItemIcon(i, enumIcons.value(i)); editor->setCurrentIndex(manager->value(property)); editor->blockSignals(false); } } void QtEnumEditorFactoryPrivate::slotEnumIconsChanged(QtProperty *property, const QMap &enumIcons) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.constEnd()) return; QtEnumPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; const QStringList enumNames = manager->enumNames(property); for (QComboBox *editor : it.value()) { editor->blockSignals(true); const int nameCount = enumNames.size(); for (int i = 0; i < nameCount; i++) editor->setItemIcon(i, enumIcons.value(i)); editor->setCurrentIndex(manager->value(property)); editor->blockSignals(false); } } void QtEnumEditorFactoryPrivate::slotSetValue(int value) { QObject *object = q_ptr->sender(); for (auto itEditor = m_editorToProperty.cbegin(), ecend = m_editorToProperty.cend(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtEnumPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtEnumEditorFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtEnumEditorFactory class provides QComboBox widgets for properties created by QtEnumPropertyManager objects. \sa QtAbstractEditorFactory, QtEnumPropertyManager */ /*! Creates a factory with the given \a parent. */ QtEnumEditorFactory::QtEnumEditorFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtEnumEditorFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtEnumEditorFactory::~QtEnumEditorFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtEnumEditorFactory::connectPropertyManager(QtEnumPropertyManager *manager) { connect(manager, &QtEnumPropertyManager::valueChanged, this, [this](QtProperty *property, int value) { d_ptr->slotPropertyChanged(property, value); }); connect(manager, &QtEnumPropertyManager::enumNamesChanged, this, [this](QtProperty *property, const QStringList &value) { d_ptr->slotEnumNamesChanged(property, value); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtEnumEditorFactory::createEditor(QtEnumPropertyManager *manager, QtProperty *property, QWidget *parent) { QComboBox *editor = d_ptr->createEditor(property, parent); editor->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); editor->view()->setTextElideMode(Qt::ElideRight); QStringList enumNames = manager->enumNames(property); editor->addItems(enumNames); QMap enumIcons = manager->enumIcons(property); const int enumNamesCount = enumNames.size(); for (int i = 0; i < enumNamesCount; i++) editor->setItemIcon(i, enumIcons.value(i)); editor->setCurrentIndex(manager->value(property)); connect(editor, &QComboBox::currentIndexChanged, this, [this](int value) { d_ptr->slotSetValue(value); }); connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtEnumEditorFactory::disconnectPropertyManager(QtEnumPropertyManager *manager) { disconnect(manager, &QtEnumPropertyManager::valueChanged, this, nullptr); disconnect(manager, &QtEnumPropertyManager::enumNamesChanged, this, nullptr); } // QtCursorEditorFactory class QtCursorEditorFactoryPrivate { QtCursorEditorFactory *q_ptr; Q_DECLARE_PUBLIC(QtCursorEditorFactory) public: QtCursorEditorFactoryPrivate(); void slotPropertyChanged(QtProperty *property, const QCursor &cursor); void slotEnumChanged(QtProperty *property, int value); void slotEditorDestroyed(QObject *object); QtEnumEditorFactory *m_enumEditorFactory; QtEnumPropertyManager *m_enumPropertyManager; QHash m_propertyToEnum; QHash m_enumToProperty; QHash m_enumToEditors; QHash m_editorToEnum; bool m_updatingEnum; }; QtCursorEditorFactoryPrivate::QtCursorEditorFactoryPrivate() : m_updatingEnum(false) { } void QtCursorEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, const QCursor &cursor) { // update enum property QtProperty *enumProp = m_propertyToEnum.value(property); if (!enumProp) return; m_updatingEnum = true; auto *cdb = QtCursorDatabase::instance(); m_enumPropertyManager->setValue(enumProp, cdb->cursorToValue(cursor)); m_updatingEnum = false; } void QtCursorEditorFactoryPrivate::slotEnumChanged(QtProperty *property, int value) { if (m_updatingEnum) return; // update cursor property QtProperty *prop = m_enumToProperty.value(property); if (!prop) return; QtCursorPropertyManager *cursorManager = q_ptr->propertyManager(prop); if (!cursorManager) return; #ifndef QT_NO_CURSOR auto *cdb = QtCursorDatabase::instance(); cursorManager->setValue(prop, QCursor(cdb->valueToCursor(value))); #endif } void QtCursorEditorFactoryPrivate::slotEditorDestroyed(QObject *object) { // remove from m_editorToEnum map; // remove from m_enumToEditors map; // if m_enumToEditors doesn't contains more editors delete enum property; for (auto itEditor = m_editorToEnum.cbegin(), ecend = m_editorToEnum.cend(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QWidget *editor = itEditor.key(); QtProperty *enumProp = itEditor.value(); m_editorToEnum.remove(editor); m_enumToEditors[enumProp].removeAll(editor); if (m_enumToEditors[enumProp].isEmpty()) { m_enumToEditors.remove(enumProp); QtProperty *property = m_enumToProperty.value(enumProp); m_enumToProperty.remove(enumProp); m_propertyToEnum.remove(property); delete enumProp; } return; } } /*! \class QtCursorEditorFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtCursorEditorFactory class provides QComboBox widgets for properties created by QtCursorPropertyManager objects. \sa QtAbstractEditorFactory, QtCursorPropertyManager */ /*! Creates a factory with the given \a parent. */ QtCursorEditorFactory::QtCursorEditorFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtCursorEditorFactoryPrivate()) { d_ptr->q_ptr = this; d_ptr->m_enumEditorFactory = new QtEnumEditorFactory(this); d_ptr->m_enumPropertyManager = new QtEnumPropertyManager(this); connect(d_ptr->m_enumPropertyManager, &QtEnumPropertyManager::valueChanged, this, [this](QtProperty *property, int value) { d_ptr->slotEnumChanged(property, value); }); d_ptr->m_enumEditorFactory->addPropertyManager(d_ptr->m_enumPropertyManager); } /*! Destroys this factory, and all the widgets it has created. */ QtCursorEditorFactory::~QtCursorEditorFactory() { } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtCursorEditorFactory::connectPropertyManager(QtCursorPropertyManager *manager) { connect(manager, &QtCursorPropertyManager::valueChanged, this, [this](QtProperty *property, const QCursor &value) { d_ptr->slotPropertyChanged(property, value); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtCursorEditorFactory::createEditor(QtCursorPropertyManager *manager, QtProperty *property, QWidget *parent) { QtProperty *enumProp = nullptr; if (d_ptr->m_propertyToEnum.contains(property)) { enumProp = d_ptr->m_propertyToEnum[property]; } else { enumProp = d_ptr->m_enumPropertyManager->addProperty(property->propertyName()); auto *cdb = QtCursorDatabase::instance(); d_ptr->m_enumPropertyManager->setEnumNames(enumProp, cdb->cursorShapeNames()); d_ptr->m_enumPropertyManager->setEnumIcons(enumProp, cdb->cursorShapeIcons()); #ifndef QT_NO_CURSOR d_ptr->m_enumPropertyManager->setValue(enumProp, cdb->cursorToValue(manager->value(property))); #endif d_ptr->m_propertyToEnum[property] = enumProp; d_ptr->m_enumToProperty[enumProp] = property; } QtAbstractEditorFactoryBase *af = d_ptr->m_enumEditorFactory; QWidget *editor = af->createEditor(enumProp, parent); d_ptr->m_enumToEditors[enumProp].append(editor); d_ptr->m_editorToEnum[editor] = enumProp; connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtCursorEditorFactory::disconnectPropertyManager(QtCursorPropertyManager *manager) { disconnect(manager, &QtCursorPropertyManager::valueChanged, this, nullptr); } // QtColorEditWidget class QtColorEditWidget : public QWidget { Q_OBJECT public: QtColorEditWidget(QWidget *parent); bool eventFilter(QObject *obj, QEvent *ev) override; public Q_SLOTS: void setValue(const QColor &value); private Q_SLOTS: void buttonClicked(); Q_SIGNALS: void valueChanged(const QColor &value); private: QColor m_color; QLabel *m_pixmapLabel; QLabel *m_label; QToolButton *m_button; }; QtColorEditWidget::QtColorEditWidget(QWidget *parent) : QWidget(parent), m_pixmapLabel(new QLabel), m_label(new QLabel), m_button(new QToolButton) { auto *lt = new QHBoxLayout(this); setupTreeViewEditorMargin(lt); lt->setSpacing(0); lt->addWidget(m_pixmapLabel); lt->addWidget(m_label); lt->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored); m_button->setFixedWidth(20); setFocusProxy(m_button); setFocusPolicy(m_button->focusPolicy()); m_button->setText(tr("...")); m_button->installEventFilter(this); connect(m_button, &QAbstractButton::clicked, this, &QtColorEditWidget::buttonClicked); lt->addWidget(m_button); m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::brushValuePixmap(QBrush(m_color))); m_label->setText(QtPropertyBrowserUtils::colorValueText(m_color)); } void QtColorEditWidget::setValue(const QColor &c) { if (m_color != c) { m_color = c; m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::brushValuePixmap(QBrush(c))); m_label->setText(QtPropertyBrowserUtils::colorValueText(c)); } } void QtColorEditWidget::buttonClicked() { const QColor newColor = QColorDialog::getColor(m_color, this, QString(), QColorDialog::ShowAlphaChannel); if (newColor.isValid() && newColor != m_color) { setValue(newColor); emit valueChanged(m_color); } } bool QtColorEditWidget::eventFilter(QObject *obj, QEvent *ev) { if (obj == m_button) { switch (ev->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: { // Prevent the QToolButton from handling Enter/Escape meant control the delegate switch (static_cast(ev)->key()) { case Qt::Key_Escape: case Qt::Key_Enter: case Qt::Key_Return: ev->ignore(); return true; default: break; } } break; default: break; } } return QWidget::eventFilter(obj, ev); } // QtColorEditorFactoryPrivate class QtColorEditorFactoryPrivate : public EditorFactoryPrivate { QtColorEditorFactory *q_ptr; Q_DECLARE_PUBLIC(QtColorEditorFactory) public: void slotPropertyChanged(QtProperty *property, const QColor &value); void slotSetValue(const QColor &value); }; void QtColorEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, const QColor &value) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.constEnd()) return; for (QtColorEditWidget *e : it.value()) e->setValue(value); } void QtColorEditorFactoryPrivate::slotSetValue(const QColor &value) { QObject *object = q_ptr->sender(); for (auto itEditor = m_editorToProperty.cbegin(), ecend = m_editorToProperty.cend(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtColorPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtColorEditorFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtColorEditorFactory class provides color editing for properties created by QtColorPropertyManager objects. \sa QtAbstractEditorFactory, QtColorPropertyManager */ /*! Creates a factory with the given \a parent. */ QtColorEditorFactory::QtColorEditorFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtColorEditorFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtColorEditorFactory::~QtColorEditorFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtColorEditorFactory::connectPropertyManager(QtColorPropertyManager *manager) { connect(manager, &QtColorPropertyManager::valueChanged, this, [this](QtProperty *property, const QColor &value) { d_ptr->slotPropertyChanged(property, value); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtColorEditorFactory::createEditor(QtColorPropertyManager *manager, QtProperty *property, QWidget *parent) { QtColorEditWidget *editor = d_ptr->createEditor(property, parent); editor->setValue(manager->value(property)); connect(editor, &QtColorEditWidget::valueChanged, this, [this](const QColor &value) { d_ptr->slotSetValue(value); }); connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtColorEditorFactory::disconnectPropertyManager(QtColorPropertyManager *manager) { disconnect(manager, &QtColorPropertyManager::valueChanged, this, nullptr); } // QtFontEditWidget class QtFontEditWidget : public QWidget { Q_OBJECT public: QtFontEditWidget(QWidget *parent); bool eventFilter(QObject *obj, QEvent *ev) override; public Q_SLOTS: void setValue(const QFont &value); private Q_SLOTS: void buttonClicked(); Q_SIGNALS: void valueChanged(const QFont &value); private: QFont m_font; QLabel *m_pixmapLabel; QLabel *m_label; QToolButton *m_button; }; QtFontEditWidget::QtFontEditWidget(QWidget *parent) : QWidget(parent), m_pixmapLabel(new QLabel), m_label(new QLabel), m_button(new QToolButton) { auto *lt = new QHBoxLayout(this); setupTreeViewEditorMargin(lt); lt->setSpacing(0); lt->addWidget(m_pixmapLabel); lt->addWidget(m_label); lt->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored); m_button->setFixedWidth(20); setFocusProxy(m_button); setFocusPolicy(m_button->focusPolicy()); m_button->setText(tr("...")); m_button->installEventFilter(this); connect(m_button, &QAbstractButton::clicked, this, &QtFontEditWidget::buttonClicked); lt->addWidget(m_button); m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::fontValuePixmap(m_font)); m_label->setText(QtPropertyBrowserUtils::fontValueText(m_font)); } void QtFontEditWidget::setValue(const QFont &f) { if (m_font != f) { m_font = f; m_pixmapLabel->setPixmap(QtPropertyBrowserUtils::fontValuePixmap(f)); m_label->setText(QtPropertyBrowserUtils::fontValueText(f)); } } void QtFontEditWidget::buttonClicked() { bool ok = false; QFont newFont = QFontDialog::getFont(&ok, m_font, this, tr("Select Font")); if (ok && newFont != m_font) { QFont f = m_font; // prevent mask for unchanged attributes, don't change other attributes (like kerning, etc...) if (m_font.family() != newFont.family()) f.setFamily(newFont.family()); if (m_font.pointSize() != newFont.pointSize()) f.setPointSize(newFont.pointSize()); if (m_font.bold() != newFont.bold()) f.setBold(newFont.bold()); if (m_font.italic() != newFont.italic()) f.setItalic(newFont.italic()); if (m_font.underline() != newFont.underline()) f.setUnderline(newFont.underline()); if (m_font.strikeOut() != newFont.strikeOut()) f.setStrikeOut(newFont.strikeOut()); setValue(f); emit valueChanged(m_font); } } bool QtFontEditWidget::eventFilter(QObject *obj, QEvent *ev) { if (obj == m_button) { switch (ev->type()) { case QEvent::KeyPress: case QEvent::KeyRelease: { // Prevent the QToolButton from handling Enter/Escape meant control the delegate switch (static_cast(ev)->key()) { case Qt::Key_Escape: case Qt::Key_Enter: case Qt::Key_Return: ev->ignore(); return true; default: break; } } break; default: break; } } return QWidget::eventFilter(obj, ev); } // QtFontEditorFactoryPrivate class QtFontEditorFactoryPrivate : public EditorFactoryPrivate { QtFontEditorFactory *q_ptr; Q_DECLARE_PUBLIC(QtFontEditorFactory) public: void slotPropertyChanged(QtProperty *property, const QFont &value); void slotSetValue(const QFont &value); }; void QtFontEditorFactoryPrivate::slotPropertyChanged(QtProperty *property, const QFont &value) { const auto it = m_createdEditors.constFind(property); if (it == m_createdEditors.constEnd()) return; for (QtFontEditWidget *e : it.value()) e->setValue(value); } void QtFontEditorFactoryPrivate::slotSetValue(const QFont &value) { QObject *object = q_ptr->sender(); for (auto itEditor = m_editorToProperty.cbegin(), ecend = m_editorToProperty.cend(); itEditor != ecend; ++itEditor) if (itEditor.key() == object) { QtProperty *property = itEditor.value(); QtFontPropertyManager *manager = q_ptr->propertyManager(property); if (!manager) return; manager->setValue(property, value); return; } } /*! \class QtFontEditorFactory \internal \inmodule QtDesigner \since 4.4 \brief The QtFontEditorFactory class provides font editing for properties created by QtFontPropertyManager objects. \sa QtAbstractEditorFactory, QtFontPropertyManager */ /*! Creates a factory with the given \a parent. */ QtFontEditorFactory::QtFontEditorFactory(QObject *parent) : QtAbstractEditorFactory(parent), d_ptr(new QtFontEditorFactoryPrivate()) { d_ptr->q_ptr = this; } /*! Destroys this factory, and all the widgets it has created. */ QtFontEditorFactory::~QtFontEditorFactory() { qDeleteAll(d_ptr->m_editorToProperty.keys()); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtFontEditorFactory::connectPropertyManager(QtFontPropertyManager *manager) { connect(manager, &QtFontPropertyManager::valueChanged, this, [this](QtProperty *property, const QFont &value) { d_ptr->slotPropertyChanged(property, value); }); } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ QWidget *QtFontEditorFactory::createEditor(QtFontPropertyManager *manager, QtProperty *property, QWidget *parent) { QtFontEditWidget *editor = d_ptr->createEditor(property, parent); editor->setValue(manager->value(property)); connect(editor, &QtFontEditWidget::valueChanged, this, [this](const QFont &value) { d_ptr->slotSetValue(value); }); connect(editor, &QObject::destroyed, this, [this](QObject *object) { d_ptr->slotEditorDestroyed(object); }); return editor; } /*! \internal Reimplemented from the QtAbstractEditorFactory class. */ void QtFontEditorFactory::disconnectPropertyManager(QtFontPropertyManager *manager) { disconnect(manager, &QtFontPropertyManager::valueChanged, this, nullptr); } QT_END_NAMESPACE #include "moc_qteditorfactory.cpp" #include "qteditorfactory.moc"