diff --git a/examples/window.h b/examples/window.h --- a/examples/window.h +++ b/examples/window.h @@ -1,6 +1,6 @@ /* This file is part of the KDE project Copyright (C) 2004-2005 Cedric Pasteur - Copyright (C) 2008-2009 Jarosław Staniek + Copyright (C) 2008-2017 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -25,7 +25,6 @@ #include #include -class QCheckBox; class KPropertyEditorView; /*! @internal @@ -51,8 +50,6 @@ QCommandLineOption m_propertyOption; QCommandLineOption m_roOption; KPropertyEditorView *m_editorView; - QCheckBox *m_showGrid; - QCheckBox *m_showFrame; }; #endif diff --git a/examples/window.cpp b/examples/window.cpp --- a/examples/window.cpp +++ b/examples/window.cpp @@ -1,6 +1,6 @@ /* This file is part of the KDE project Copyright (C) 2004 Cedric Pasteur - Copyright (C) 2008-2016 Jarosław Staniek + Copyright (C) 2008-2017 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -74,20 +74,21 @@ KProperty *p = 0; m_set.setReadOnly(m_parser.isSet(m_roOption)); QByteArray group; - if (!m_parser.isSet(m_flatOption)) { + const bool addGroups = !m_parser.isSet(m_flatOption); + if (addGroups) { group = "SimpleGroup"; m_set.setGroupCaption(group, "Simple Group"); } if (singleProperty.isEmpty() || singleProperty=="String") { m_set.addProperty(p = new KProperty("String", "String"), group); - p->setAutoSync(1); + p->setValueSyncPolicy(KProperty::ValueSyncPolicy::Auto); p->setReadOnly(false); // this should not work: // - not needed if the property set is read-write // - ignored if the property set is read-only } if (singleProperty.isEmpty() || singleProperty=="MultiLine") { m_set.addProperty(p = new KProperty("MultiLine", "Multi\nLine\nContent"), group); - p->setAutoSync(1); + p->setValueSyncPolicy(KProperty::ValueSyncPolicy::Auto); p->setOption("multiLine", true); } @@ -146,7 +147,7 @@ } // Complex - if (!m_parser.isSet(m_flatOption)) { + if (addGroups) { group = "ComplexGroup"; m_set.setGroupCaption(group, "Complex Group"); } @@ -170,7 +171,7 @@ } // Appearance - if (!m_parser.isSet(m_flatOption)) { + if (addGroups) { group = "Appearance Group"; m_set.setGroupCaption(group, "Appearance Group"); m_set.setGroupIconName(group, "appearance"); @@ -231,21 +232,30 @@ QVBoxLayout *lyr = new QVBoxLayout(this); m_editorView = new KPropertyEditorView(this); lyr->addWidget(m_editorView); - m_editorView->changeSet(&m_set, KPropertyEditorView::ExpandChildItems); + m_editorView->changeSet(&m_set); lyr->addSpacing(lyr->spacing()); QHBoxLayout *hlyr = new QHBoxLayout; lyr->addLayout(hlyr); - m_showGrid = new QCheckBox("Show grid"); - m_showGrid->setChecked(true); - connect(m_showGrid, &QCheckBox::stateChanged, this, &Window::showGrid); - hlyr->addWidget(m_showGrid); + QCheckBox *showGrid = new QCheckBox("Show grid"); + showGrid->setChecked(true); + connect(showGrid, &QCheckBox::stateChanged, this, &Window::showGrid); + hlyr->addWidget(showGrid); - m_showFrame = new QCheckBox("Show frame"); - m_showFrame->setChecked(true); - connect(m_showFrame, &QCheckBox::stateChanged, this, &Window::showFrame); - hlyr->addWidget(m_showFrame); + QCheckBox *showFrame = new QCheckBox("Show frame"); + showFrame->setChecked(true); + connect(showFrame, &QCheckBox::stateChanged, this, &Window::showFrame); + hlyr->addWidget(showFrame); + + QCheckBox *showGroups = new QCheckBox("Show groups"); + if (addGroups) { + connect(showGroups, &QCheckBox::toggled, m_editorView, &KPropertyEditorView::setGroupsVisible); + showGroups->setChecked(m_editorView->groupsVisible()); + } else { + showGroups->setEnabled(false); + } + hlyr->addWidget(showGroups); QCheckBox *readOnly = new QCheckBox("Read-only"); connect(readOnly, &QCheckBox::toggled, &m_set, &KPropertySet::setReadOnly); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -107,6 +107,7 @@ target_link_libraries(KPropertyWidgets PUBLIC KPropertyCore + Qt5::Widgets PRIVATE KPropertyUtilsPrivate ) diff --git a/src/KProperty.h b/src/KProperty.h --- a/src/KProperty.h +++ b/src/KProperty.h @@ -372,21 +372,25 @@ /*! Sets "storable" flag for this property. @see isStorable() */ void setStorable(bool storable); - /*! \return 1 if the property should be synced automatically in the property editor - as soon as editor contents change (e.g. when the user types text). - If autoSync() == 0, property value will be updated when the user presses Enter - or when another editor gets the focus. - Property follows property editor's global rule if autoSync() !=0 and !=1 (the default). - */ - int autoSync() const; - - /*! If \a sync is 1, the property will be synced automatically in the property editor - as soon as editor's contents change (e.g. when the user types text). - If \a sync is 0, property value will be updated when the user presses - Enter or when another editor gets the focus. - Property follows property editor's global rule if sync !=0 and !=1 (the default). - */ - void setAutoSync(int sync); + //! Synchronization policy for property values + //! @since 3.1 + enum class ValueSyncPolicy { + Editor, //!< Allow to synchronize by the property editor using its valueSync setting (default) + FocusOut, //!< Synchronize the value when focus is out of the editor widget for this property + //!< or when the user presses the Enter key + Auto //!< Synchronize automatically as soon as the editor widget for this property signals + //! (using commitData) that the value has been changed, e.g. when the user types + //! another letter in a text box + }; + + //! @return synchronization policy for property values of this property + //! @since 3.1 + ValueSyncPolicy valueSyncPolicy() const; + + //! Sets synchronization policy for property values of this property + //! See ValueSyncPolicy for details. + //! @since 3.1 + void setValueSyncPolicy(ValueSyncPolicy policy); /*! Sets value \a val for option \a name. Options are used to override default settings of individual properties. diff --git a/src/KProperty.cpp b/src/KProperty.cpp --- a/src/KProperty.cpp +++ b/src/KProperty.cpp @@ -1,7 +1,7 @@ /* This file is part of the KDE project Copyright (C) 2004 Cedric Pasteur Copyright (C) 2004 Alexander Dymo - Copyright (C) 2004-2015 Jarosław Staniek + Copyright (C) 2004-2017 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -51,7 +51,7 @@ KProperty::Private::Private(KProperty *prop) : q(prop), type(KProperty::Auto), caption(0), listData(0), changed(false), storable(true), readOnly(false), visible(true), - autosync(-1), composed(0), useComposedProperty(true), + composed(0), useComposedProperty(true), sets(0), parent(0), children(0), relatedProperties(0) { } @@ -571,16 +571,15 @@ d->visible = visible; } -int -KProperty::autoSync() const +KProperty::ValueSyncPolicy KProperty::valueSyncPolicy() const { - return d->autosync; + return d->valueSyncPolicy; } void -KProperty::setAutoSync(int sync) +KProperty::setValueSyncPolicy(KProperty::ValueSyncPolicy policy) { - d->autosync = sync; + d->valueSyncPolicy = policy; } bool @@ -642,7 +641,7 @@ d->type = property.d->type; d->iconName = property.d->iconName; - d->autosync = property.d->autosync; + d->valueSyncPolicy = property.d->valueSyncPolicy; d->visible = property.d->visible; d->storable = property.d->storable; d->readOnly = property.d->readOnly; diff --git a/src/KPropertyEditorDataModel.h b/src/KPropertyEditorDataModel.h --- a/src/KPropertyEditorDataModel.h +++ b/src/KPropertyEditorDataModel.h @@ -1,5 +1,5 @@ /* This file is part of the KDE project - Copyright (C) 2008 Jarosław Staniek + Copyright (C) 2008-2017 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -35,15 +35,15 @@ class KPropertyEditorDataModel : public QAbstractItemModel { Q_OBJECT - public: //! Creates a new model. @a propertySet is required. explicit KPropertyEditorDataModel(KPropertySet *propertySet, QObject *parent = 0, KPropertySetIterator::Order order = KPropertySetIterator::InsertionOrder); ~KPropertyEditorDataModel(); enum Role { - PropertyModifiedRole = Qt::UserRole + 0 + PropertyModifiedRole = Qt::UserRole + 0, + PropertyGroupRole = Qt::UserRole + 1 }; QVariant data(const QModelIndex &index, int role) const; QVariant headerData(int section, Qt::Orientation orientation, @@ -78,16 +78,28 @@ //! @return a sibling for model index @a index and columnd @a column QModelIndex indexForColumn(const QModelIndex& index, int column) const; - //! Sets order for properties. Restarts the iterator. - void setOrder(KPropertySetIterator::Order order); - //! @return order for properties. KPropertySetIterator::Order order() const; //! Reimplemented for optimization. bool hasChildren(const QModelIndex & parent = QModelIndex()) const; + /*! @return @c true if the property groups should be visible. + @see KPropertyEditorView::groupsVisible() + @since 3.1 */ + bool groupsVisible() const; + +public Q_SLOTS: + //! Sets order for properties. + void setOrder(KPropertySetIterator::Order order); + + /*! Shows the property groups if @a set is @c true. + @see KPropertyEditorView::setGroupsVisible(bool) + @since 3.1 */ + void setGroupsVisible(bool set); + private: + //! Collects persistent indices for the model. They are dependent on groupping and sorting. void collectIndices() const; class Private; diff --git a/src/KPropertyEditorDataModel.cpp b/src/KPropertyEditorDataModel.cpp --- a/src/KPropertyEditorDataModel.cpp +++ b/src/KPropertyEditorDataModel.cpp @@ -1,5 +1,5 @@ /* This file is part of the KDE project - Copyright (C) 2008-2009 Jarosław Staniek + Copyright (C) 2008-2017 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -34,10 +34,13 @@ kprCritical() << "KPropertyEditorDataModel requires a KPropertySet object"; } } + inline KPropertySetPrivate* set_d() { return KPropertySetPrivate::d(set); } KPropertySet *set; KProperty rootItem; + KProperty groupItem; //!< Pseudo group item used for all group items QHash indicesForNames; KPropertySetIterator::Order order; //!< order of properties + bool groupsVisible = true; }; // ------------------- @@ -80,14 +83,29 @@ void KPropertyEditorDataModel::collectIndices() const { - KPropertySetIterator it(*d->set, VisiblePropertySelector()); - if (d->order == KPropertySetIterator::AlphabeticalOrder) { - it.setOrder(KPropertySetIterator::AlphabeticalOrder); - } d->indicesForNames.clear(); - for (int row = 0; it.current(); row++, ++it) { - // kprDebug() << it.current()->name() << "->" << row; - d->indicesForNames.insert( it.current()->name(), QPersistentModelIndex( createIndex(row, 0, it.current()) ) ); + if (d->groupsVisible) { + for (const QByteArray &groupName : d->set_d()->groupNames) { + const QList* propertyNames = d->set_d()->propertiesOfGroup.value(groupName); + if (!propertyNames) { + continue; + } + int row = 0; // row within the group + //! @todo Care about sorting + for (const QByteArray &propertyName : *propertyNames) { + d->indicesForNames.insert(propertyName, + QPersistentModelIndex(createIndex(row, 0, d->set_d()->property(propertyName)))); + } + } + } else { + KPropertySetIterator it(*d->set, VisiblePropertySelector()); + if (d->order == KPropertySetIterator::AlphabeticalOrder) { + it.setOrder(KPropertySetIterator::AlphabeticalOrder); + } + for (int row = 0; it.current(); row++, ++it) { // flat list + d->indicesForNames.insert(it.current()->name(), + QPersistentModelIndex( createIndex(row, 0, it.current()))); + } } } @@ -115,9 +133,22 @@ return QVariant(); const int col = index.column(); + const KProperty *prop = propertyForIndex(index); + if (role == PropertyGroupRole) { + return prop == &d->groupItem; + } if (col == 0) { - KProperty *prop = propertyForIndex(index); - if (role == Qt::DisplayRole) { + if (prop == &d->groupItem) { + const QByteArray groupName(d->set_d()->groupNames.value(index.row())); + Q_ASSERT(!groupName.isEmpty()); + switch(role) { + case Qt::DisplayRole: + return d->set->groupCaption(groupName); + case Qt::DecorationRole: + return QIcon::fromTheme(d->set->groupIconName(groupName)); + default:; + } + } else if (role == Qt::DisplayRole) { if (!prop->caption().isEmpty()) return prop->caption(); return prop->name(); @@ -127,7 +158,6 @@ } } else if (col == 1) { - KProperty *prop = propertyForIndex(index); if (role == Qt::EditRole) { return prop->value(); } @@ -144,10 +174,11 @@ return Qt::ItemIsEnabled; const int col = index.column(); - Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable; - KProperty *prop = propertyForIndex(index); - if (prop) { - if (col == 1 && !prop->isReadOnly() && !d->set->isReadOnly()) { + Qt::ItemFlags f = Qt::ItemIsEnabled; + const KProperty *prop = propertyForIndex(index); + if (prop != &d->groupItem) { + f |= Qt::ItemIsSelectable; + if (col == 1 && prop != &d->rootItem && !prop->isReadOnly() && !d->set->isReadOnly()) { f |= Qt::ItemIsEditable; } } @@ -179,57 +210,106 @@ QModelIndex KPropertyEditorDataModel::index(int row, int column, const QModelIndex &parent) const { - if (parent.isValid() && parent.column() != 0) + //qDebug() << row << column << parent; + if (row < 0 || column < 0 || /*!parent.isValid() ||*/ (parent.isValid() && parent.column() != 0)) { return QModelIndex(); + } KProperty *parentItem = propertyForIndex(parent); - KProperty *childItem; - if (parentItem == &d->rootItem) { // special case: top level - int visibleRows = 0; - KPropertySetIterator it(*d->set, VisiblePropertySelector()); - if (d->order == KPropertySetIterator::AlphabeticalOrder) { - it.setOrder(KPropertySetIterator::AlphabeticalOrder); + KProperty *childItem = nullptr; + if (parentItem == &d->rootItem && d->groupsVisible && d->set_d()->hasGroups()) { + // top level with groups: return group item + return createIndex(row, column, &d->groupItem); + } else if (parentItem == &d->rootItem || parentItem == &d->groupItem) { + // top level without groups or group level: return top-level visible property item + if (d->groupsVisible && d->set_d()->hasGroups()) { + const QByteArray groupName(d->set_d()->groupNames.value(parent.row())); + const QList* propertyNames = d->set_d()->propertiesOfGroup.value(groupName); + if (propertyNames) { + int visiblePropertiesForGroup = -1; + //! @todo sort? + for (const QByteArray &propertyName : *propertyNames) { + KProperty *property = d->set_d()->property(propertyName); + if (property->isVisible()) { + ++visiblePropertiesForGroup; + } + if (visiblePropertiesForGroup == row) { + childItem = property; + break; + } + } + } + } else { // all properties, flat + KPropertySetIterator it(*d->set, VisiblePropertySelector()); + if (d->order == KPropertySetIterator::AlphabeticalOrder) { + it.setOrder(KPropertySetIterator::AlphabeticalOrder); + } + //! @todo use qBinaryFind()? + for (int visibleRows = 0; visibleRows < row && it.current(); ++it) { + ++visibleRows; + } + childItem = it.current(); } -//! @todo use qBinaryFind()? - for (; visibleRows < row && it.current(); visibleRows++, ++it) - ; - childItem = it.current(); - } else { + } else { // child properties of composed properties const QList* children = parentItem->children(); - if (!children) - return QModelIndex(); - childItem = children->value(row); + if (children) { + childItem = children->value(row); + } } - if (!childItem) + if (!childItem) { return QModelIndex(); + } return createIndex(row, column, childItem); } QModelIndex KPropertyEditorDataModel::parent(const QModelIndex &index) const { - if (!index.isValid()) + if (!index.isValid()) { return QModelIndex(); - - KProperty *childItem = propertyForIndex(index); - KProperty *parentItem = childItem->parent(); - - if (!parentItem) + } + const KProperty *childItem = propertyForIndex(index); + if (childItem == &d->rootItem || childItem == &d->groupItem) { + // parent for the root or a group item: null + // (parent for a group item is root since group item is top level) return QModelIndex(); - - const QList* children = parentItem->children(); - Q_ASSERT(children); - const int indexOfItem = children->indexOf(childItem); - Q_ASSERT(indexOfItem != -1); - - return createIndex(indexOfItem, 0, parentItem); + } + KProperty *parentItem = childItem->parent(); + if (parentItem) { // child property: parent property is the parent + // find index of parent within the grandparent + const int indexOfParentItem = d->set_d()->indexOfProperty(parentItem); + return createIndex(indexOfParentItem, 0, parentItem); + } + if (d->groupsVisible && d->set_d()->hasGroups()) { + // top-level property within a group: group item is the parent + const QByteArray group(d->set_d()->groupForProperty(childItem)); + const int indexOfGroup = d->set_d()->groupNames.indexOf(group); + return createIndex(indexOfGroup, 0, &d->groupItem); + } + return QModelIndex(); } int KPropertyEditorDataModel::rowCount(const QModelIndex &parent) const { KProperty *parentItem = propertyForIndex(parent); - if (!parentItem || parentItem == &d->rootItem) { // top level - return d->set->count(VisiblePropertySelector()); + if (parentItem == &d->rootItem) { // top level: return group count or top-level properties count + if (d->groupsVisible && d->set_d()->hasGroups()) { + return d->set_d()->groupNames.count(); + } + return d->set->count(VisiblePropertySelector()); // number of visible properties + } else if (parentItem == &d->groupItem) { // group level: return property count within the group + const QByteArray groupName = d->set_d()->groupNames.value(parent.row()); + Q_ASSERT(!groupName.isEmpty()); + const QList* propertyNames = d->set_d()->propertiesOfGroup.value(groupName); + Q_ASSERT(propertyNames); + int visiblePropertiesForGroup = 0; + for(const QByteArray &propertyName : *propertyNames) { + if (d->set_d()->property(propertyName)->isVisible()) { + ++visiblePropertiesForGroup; + } + } + return visiblePropertiesForGroup; } + // property level: return child properties count const QList* children = parentItem->children(); return children ? children->count() : 0; } @@ -241,7 +321,7 @@ return false; KProperty *item = propertyForIndex(index); - if (item == &d->rootItem) + if (item == &d->rootItem || item == &d->groupItem) return false; item->setValue(value); //don't do that or cursor position and editor state will be reset: @@ -287,9 +367,37 @@ bool KPropertyEditorDataModel::hasChildren(const QModelIndex & parent) const { KProperty *parentItem = propertyForIndex(parent); - if (!parentItem || parentItem == &d->rootItem) { // top level + if (parentItem == &d->rootItem) { // top level return d->set->hasVisibleProperties(); + } else if (parentItem == &d->groupItem) { // group level + const QByteArray groupName(d->set_d()->groupNames.value(parent.row())); + Q_ASSERT(!groupName.isEmpty()); + const QList* propertyNames = d->set_d()->propertiesOfGroup.value(groupName); + Q_ASSERT(propertyNames); + for (const QByteArray &propertyName : *propertyNames) { + if (d->set_d()->property(propertyName)->isVisible()) { + return true; // at least one visible property in this group + } + } + return false; // no visible properties in this group } + // property level const QList* children = parentItem->children(); return children && !children->isEmpty(); } + +bool KPropertyEditorDataModel::groupsVisible() const +{ + return d->groupsVisible; +} + +void KPropertyEditorDataModel::setGroupsVisible(bool set) +{ + if (d->groupsVisible == set) { + return; + } + beginResetModel(); + d->groupsVisible = set; + collectIndices(); + endResetModel(); +} diff --git a/src/KPropertyEditorView.h b/src/KPropertyEditorView.h --- a/src/KPropertyEditorView.h +++ b/src/KPropertyEditorView.h @@ -1,5 +1,5 @@ /* This file is part of the KDE project - Copyright (C) 2008-2016 Jarosław Staniek + Copyright (C) 2008-2017 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -42,8 +42,7 @@ NoOptions = 0, PreservePreviousSelection = 1, //!< If used, previously selected editor item //!< will be kept selected. - AlphabeticalOrder = 2, //!< Alphabetical order of properties (the default is insert-order) - ExpandChildItems = 4 //!< Child property items are expanded (the default is "collapsed") + AlphabeticalOrder = 2 //!< Alphabetical order of properties (the default is insert-order) }; Q_DECLARE_FLAGS(SetOptions, SetOption) @@ -60,39 +59,93 @@ //! is currently assigned. KPropertySet* propertySet() const; + /*! @return @c true if items for parent composed properties are expanded so items for child + properties are displayed. + @since 3.1 */ + bool childPropertyItemsExpanded() const; + + /*! @return value of the valueSyncEnabled flag. + @since 3.1 */ + bool isValueSyncEnabled() const; + + /*! @return @c true if the property groups should be visible. + By default groups are visible. + A group is visualized as a subtree displaying group caption and group icon at its root node + (see KProperty::groupCaption and KProperty::groupIconName) and properties as children of this node. + A property is assigned to a group while KPropertySet::addProperty() is called. + + @note Regardless of this flag, no groups are displayed if there is only the default group + "common". + + When the group visibility flag is off or only the "common" group is present, all properties + are displayed on the same (top) level. + @since 3.1 */ + bool groupsVisible() const; + + /*! @return @c true if group items for newly added groups are exapanded so properties for these + groups are displayed. + @see setGroupItemsExpanded() + @since 3.1 */ + bool groupItemsExpanded() const; + public Q_SLOTS: - /*! Populates the editor view with items for each property from the @ set set. + /*! Populates the editor view with items for each property from the @a set set. Child items for composed properties are also created. See SetOption documentation for description of @a options options. If @a preservePreviousSelection is true, previously selected editor item will be kept selected, if present. */ void changeSet(KPropertySet *set, SetOptions options = NoOptions); - /*! Populates the editor view with items for each property from the @ set set. + /*! Populates the editor view with items for each property from the @a set set. Child items for composed properties are also created. If @a propertyToSelect is provided, item for this property name will be selected, if present. */ void changeSet(KPropertySet *set, const QByteArray& propertyToSelect, SetOptions options = NoOptions); - /*! If @a enable is true (the default), property values are automatically synced as + /*! If @a set is @c true (the default), items for parent composed properties are expanded + so items for child properties are displayed. + If @a set is @c false, the items are collapsed. + @note Appearance of the existing child items is not altered. This method can be typically called + before a changeSet() call or before adding properties. + @note Expansion of group items is not affected by this method. Use setGroupItemsExpanded() + to control expansion of group items. + @note To expand all items use expandAll(). To collapse all items use collapseAll(). + @since 3.1 */ + void setChildPropertyItemsExpanded(bool set); + + /*! If @a set is @c true (the default), property values are automatically synchronized as soon as editor contents change (e.g. every time the user types a character) - and the values are written back to the assigned property set. - If @a enable is false, property set is updated only when selection within - the property editor or user presses Enter/Return key. - Each property can overwrite this setting by changing its own autoSync flag. - */ - void setAutoSync(bool enable); - - /*! @return value of autoSync flag. */ - bool isAutoSync() const; + and the values are saved back to the assigned property set. + If @a enable is false, property set is updated only when selection within the property editor + or user presses Enter/Return key. + Each property can override this policy by changing its own valueSyncPolicy flag. + @see KProperty::setValueSyncPolicy() + @since 3.1 */ + void setValueSyncEnabled(bool set); /*! Accepts the changes made to the current editor item (if any) (as if the user had pressed Enter key). */ void acceptInput(); //! Sets color of grid lines. Use invalid color QColor() to hide grid lines. void setGridLineColor(const QColor& color); + /*! Shows the property groups if @a set is @c true. + @see groupsVisible() + @since 3.1 */ + void setGroupsVisible(bool set); + + /*! If @a set is @c true (the default), group items for newly added groups are exapanded + so properties for these groups are displayed. + If @a set is @c false, the items are collapsed. + @note Appearance of the existing group items is not altered. This method can be typically called + before a changeSet() call or before adding properties. + @note Expansion of child items for composed properties is not affected by this method. + Use setChildPropertyItemsExpanded() to control expansion child items for composed properties. + @note To expand all items use expandAll(). To collapse all items use collapseAll(). + @since 3.1 */ + void setGroupItemsExpanded(bool set); + Q_SIGNALS: /*! Emitted when current property set has been changed. May be 0. */ void propertySetChanged(KPropertySet *set); @@ -124,6 +177,10 @@ void changeSetInternal(KPropertySet *set, SetOptions options, const QByteArray& propertyToSelect); virtual bool edit( const QModelIndex & index, EditTrigger trigger, QEvent * event ); virtual void drawBranches( QPainter * painter, const QRect & rect, const QModelIndex & index ) const; + + //! Reimplemented to draw group header text by hand. + void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + virtual void mousePressEvent( QMouseEvent * event ); //! @return true if @a x is within the area of the revert button for @a index index. diff --git a/src/KPropertyEditorView.cpp b/src/KPropertyEditorView.cpp --- a/src/KPropertyEditorView.cpp +++ b/src/KPropertyEditorView.cpp @@ -1,5 +1,5 @@ /* This file is part of the KDE project - Copyright (C) 2008-2016 Jarosław Staniek + Copyright (C) 2008-2017 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -67,10 +67,12 @@ }; #endif -static bool computeAutoSync(const KProperty *property, bool defaultAutoSync) +static bool effectiveValueSyncPolicy(const KProperty *property, bool defaultValue) { - return (property->autoSync() != 0 && property->autoSync() != 1) ? - defaultAutoSync : (property->autoSync() != 0); + if (property->valueSyncPolicy() == KProperty::ValueSyncPolicy::Editor) { + return defaultValue; + } + return property->valueSyncPolicy() == KProperty::ValueSyncPolicy::Auto; } //---------- @@ -116,20 +118,21 @@ const QModelIndex &index) const { QStyleOptionViewItem alteredOption(option); - const QColor gridLineColor(qobject_cast(parent())->gridLineColor()); - if (gridLineColor.isValid()) { - alteredOption.rect.setTop(alteredOption.rect.top() + 1); - } const KPropertyUtilsPrivate::PainterSaver saver(painter); - QRect r(option.rect); const KPropertyEditorDataModel *editorModel = qobject_cast(index.model()); if (!editorModel) { return; } + + QRect r(option.rect); bool modified = false; + const QColor gridLineColor(qobject_cast(parent())->gridLineColor()); + if (gridLineColor.isValid()) { + alteredOption.rect.setTop(alteredOption.rect.top() + 1); + } if (index.column()==0) { r.setWidth(r.width() - 1); - r.setLeft(0); + r.setLeft(-1); // to avoid displaying double left border QVariant modifiedVariant( editorModel->data(index, KPropertyEditorDataModel::PropertyModifiedRole) ); if (modifiedVariant.isValid() && modifiedVariant.toBool()) { @@ -149,44 +152,51 @@ alteredOption.rect.setRight( alteredOption.rect.right() - iconSize * 1 ); } - KProperty *property = editorModel->propertyForIndex(index); - const int t = typeForProperty( property ); - bool useQItemDelegatePaint = true; // ValueDisplayInterface is used by default - if (index.column() == 1 && KPropertyWidgetsPluginManager::self()->paint(t, painter, alteredOption, index)) { - useQItemDelegatePaint = false; - } - if (useQItemDelegatePaint) { - QItemDelegate::paint(painter, alteredOption, index); - } + const bool isGroupHeader(editorModel->data(index, KPropertyEditorDataModel::PropertyGroupRole).toBool()); + if (!isGroupHeader) { + KProperty *property = editorModel->propertyForIndex(index); + const int t = typeForProperty( property ); + bool useQItemDelegatePaint = true; // ValueDisplayInterface is used by default + if (index.column() == 1 && KPropertyWidgetsPluginManager::self()->paint(t, painter, alteredOption, index)) { + useQItemDelegatePaint = false; + } + if (useQItemDelegatePaint) { + QItemDelegate::paint(painter, alteredOption, index); + } - if (modified) { - alteredOption.rect.setRight( alteredOption.rect.right() - iconSize * 3 / 2 ); - int y1 = alteredOption.rect.top(); - QLinearGradient grad(x2 - iconSize * 2, y1, x2 - iconSize / 2, y1); - QColor color( - alteredOption.palette.color( - (alteredOption.state & QStyle::State_Selected) ? QPalette::Highlight : QPalette::Base )); - color.setAlpha(0); - grad.setColorAt(0.0, color); - color.setAlpha(255); - grad.setColorAt(0.5, color); - QBrush gradBrush(grad); - painter->fillRect(x2 - iconSize * 2, y1, - iconSize * 2, y2 - y1 + 1, gradBrush); - QPixmap revertIcon(QIcon::fromTheme(QLatin1String("edit-undo")).pixmap(iconSize, iconSize)); - - //!TODO - //revertIcon = KIconEffect().apply(revertIcon, KIconEffect::Colorize, 1.0, - // alteredOption.palette.color( - // (alteredOption.state & QStyle::State_Selected) ? QPalette::HighlightedText : QPalette::Text ), false); - //painter->drawPixmap( x2 - iconSize - 2, - // y1 + 1 + (alteredOption.rect.height() - revertIcon.height()) / 2, revertIcon); + if (modified) { + alteredOption.rect.setRight( alteredOption.rect.right() - iconSize * 3 / 2 ); + int y1 = alteredOption.rect.top(); + QLinearGradient grad(x2 - iconSize * 2, y1, x2 - iconSize / 2, y1); + QColor color( + alteredOption.palette.color( + (alteredOption.state & QStyle::State_Selected) ? QPalette::Highlight : QPalette::Base )); + color.setAlpha(0); + grad.setColorAt(0.0, color); + color.setAlpha(255); + grad.setColorAt(0.5, color); + QBrush gradBrush(grad); + painter->fillRect(x2 - iconSize * 2, y1, iconSize * 2, y2 - y1 + 1, gradBrush); + + //!TODO + //QPixmap revertIcon(QIcon::fromTheme(QLatin1String("edit-undo")).pixmap(iconSize, iconSize)); + //revertIcon = KIconEffect().apply(revertIcon, KIconEffect::Colorize, 1.0, + // alteredOption.palette.color( + // (alteredOption.state & QStyle::State_Selected) ? QPalette::HighlightedText : QPalette::Text ), false); + //painter->drawPixmap( x2 - iconSize - 2, + // y1 + 1 + (alteredOption.rect.height() - revertIcon.height()) / 2, revertIcon); + } } if (gridLineColor.isValid()) { QPen pen(gridLineColor); painter->setPen(pen); - painter->drawRect(r); + painter->drawLine(r.topLeft(), r.topRight() + QPoint(1, 0)); + painter->drawLine(r.bottomLeft() + QPoint(0, 1), r.bottomRight() + QPoint(1, 1)); + if (!isGroupHeader) { + painter->drawLine(r.topRight() + QPoint(1, 0), r.bottomRight() + QPoint(1, 1)); + painter->drawLine(r.topLeft(), r.bottomLeft() + QPoint(0, 1)); + } } else { QPen pen(alteredOption.palette.color(QPalette::AlternateBase)); @@ -230,7 +240,9 @@ } QObject::disconnect(w, SIGNAL(commitData(QWidget*)), this, SIGNAL(commitData(QWidget*))); - if (property && computeAutoSync( property, static_cast(this->parent())->isAutoSync() )) { + if (property && effectiveValueSyncPolicy(property, + qobject_cast(this->parent())->isValueSyncEnabled())) + { QObject::connect(w, SIGNAL(commitData(QWidget*)), this, SIGNAL(commitData(QWidget*))); } @@ -243,25 +255,59 @@ class Q_DECL_HIDDEN KPropertyEditorView::Private { public: - Private() + explicit Private(KPropertyEditorView *view) : set(0) , model(0) , gridLineColor( KPropertyEditorView::defaultGridLineColor() ) - , autoSync(true) + , valueSync(true) , slotPropertyChangedEnabled(true) + , q(view) { } + + //! Expands group and parent propertiey items if needed (based on settings) + void expandIfNeeded() { + const int rowCount = model->rowCount(); + for (int row = 0; row < rowCount; row++) { + expandChildItemsIfNeeded(model->index(row, 0)); + } + } + + //! Expands property child items in a subtree recursively if needed (based on settings) + void expandChildItemsIfNeeded(const QModelIndex &parent) { + const bool isGroupHeader(model->data(parent, KPropertyEditorDataModel::PropertyGroupRole).toBool()); + if (isGroupHeader) { + if (groupItemsExpanded) { + q->expand(parent); + } + } else { + if (childPropertyItemsExpanded) { + q->expand(parent); + } + } + const int rowCount = model->rowCount(parent); + for (int row = 0; row < rowCount; row++) { + const QModelIndex child(model->index(row, 0, parent)); + expandChildItemsIfNeeded(child); + } + } + KPropertySet *set; KPropertyEditorDataModel *model; ItemDelegate *itemDelegate; QColor gridLineColor; - bool autoSync; + bool valueSync; bool slotPropertyChangedEnabled; + bool childPropertyItemsExpanded = true; + bool groupItemsExpanded = true; + +private: + KPropertyEditorView * const q; }; KPropertyEditorView::KPropertyEditorView(QWidget* parent) : QTreeView(parent) - , d( new Private ) + , d(new Private(this)) { setObjectName(QLatin1String("KPropertyEditorView")); setAlternatingRowColors(true); @@ -382,11 +428,8 @@ setModel( d->model ); delete oldModel; - if (d->model && d->set && !d->set->isEmpty() && (options & ExpandChildItems)) { - const int rowCount = d->model->rowCount(); - for (int row = 0; row < rowCount; row++) { - expand( d->model->index(row, 0) ); - } + if (d->model && d->set && !d->set->isEmpty()) { + d->expandIfNeeded(); } emit propertySetChanged(d->set); @@ -426,14 +469,49 @@ } } -void KPropertyEditorView::setAutoSync(bool enable) +void KPropertyEditorView::setValueSyncEnabled(bool set) +{ + d->valueSync = set; +} + +bool KPropertyEditorView::isValueSyncEnabled() const +{ + return d->valueSync; +} + +void KPropertyEditorView::setChildPropertyItemsExpanded(bool set) +{ + d->childPropertyItemsExpanded = set; +} + +bool KPropertyEditorView::childPropertyItemsExpanded() const { - d->autoSync = enable; + return d->childPropertyItemsExpanded; } -bool KPropertyEditorView::isAutoSync() const +void KPropertyEditorView::setGroupItemsExpanded(bool set) { - return d->autoSync; + d->groupItemsExpanded = set; +} + +bool KPropertyEditorView::groupItemsExpanded() const +{ + return d->groupItemsExpanded; +} + +bool KPropertyEditorView::groupsVisible() const +{ + return d->model->groupsVisible(); +} + +void KPropertyEditorView::setGroupsVisible(bool set) +{ + if (d->model->groupsVisible() == set) { + return; + } + d->model->setGroupsVisible(set); + d->expandIfNeeded(); + viewport()->update(); } void KPropertyEditorView::currentChanged( const QModelIndex & current, const QModelIndex & previous ) @@ -464,6 +542,26 @@ QTreeView::drawBranches( painter, rect, index ); } +void KPropertyEditorView::drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + const KPropertyUtilsPrivate::PainterSaver saver(painter); + const bool isGroupHeader(d->model->data(index, KPropertyEditorDataModel::PropertyGroupRole).toBool()); + QStyleOptionViewItem alteredOption(option); + QTreeView::drawRow(painter, alteredOption, index); + if (isGroupHeader) { + // Special case: group header should be displayed over both columns. There's an issue with + // alternate background which is painted over text in the 2nd column, so draw the text here + // by hand. + QFont font(alteredOption.font); + font.setBold(true); + alteredOption.font = font; + painter->setFont(font); + painter->drawText( + alteredOption.rect.adjusted(style()->pixelMetric(QStyle::PM_TreeViewIndentation), 0, 0, 0), + index.data(Qt::DisplayRole).toString()); + } +} + QRect KPropertyEditorView::revertButtonArea( const QModelIndex& index ) const { if (index.column() != 0) @@ -504,8 +602,9 @@ return; KProperty *property = d->model->propertyForIndex(currentIndex()); - if (computeAutoSync( property, d->autoSync )) + if (effectiveValueSyncPolicy(property, d->valueSync)) { property->resetValue(); + } } void KPropertyEditorView::acceptInput() diff --git a/src/KPropertyLineStyleSelector_p.h b/src/KPropertyLineStyleSelector_p.h --- a/src/KPropertyLineStyleSelector_p.h +++ b/src/KPropertyLineStyleSelector_p.h @@ -35,6 +35,13 @@ explicit KPropertyLineStyleSelector(QWidget *parent = 0); virtual ~KPropertyLineStyleSelector(); + //! @return the current line style + Qt::PenStyle lineStyle() const; + + //! @return the dashes of the current line style + QVector lineDashes() const; + +public Q_SLOTS: /** * Adds a new line style to the combobox. * @@ -56,12 +63,6 @@ */ void setLineStyle(Qt::PenStyle style, const QVector &dashes = QVector()); - //! @return the current line style - Qt::PenStyle lineStyle() const; - - //! @return the dashes of the current line style - QVector lineDashes() const; - protected: void paintEvent(QPaintEvent *pe); diff --git a/src/KPropertySet.h b/src/KPropertySet.h --- a/src/KPropertySet.h +++ b/src/KPropertySet.h @@ -113,7 +113,6 @@ class KPROPERTYCORE_EXPORT KPropertySet : public QObject { Q_OBJECT - public: //! Constructs a new property set object. explicit KPropertySet(QObject *parent = 0); @@ -124,22 +123,6 @@ virtual ~KPropertySet(); - /*! Adds the property to the set, in the group. - The property becomes owned by the set. - Any name can be used for the @a group. "common" is the default for a basic top-level group. */ - void addProperty(KProperty *property, const QByteArray &group = "common"); - - /*! Removes property from the set and deletes the object. - Emits aboutToDeleteProperty before removing. */ - void removeProperty(KProperty *property); - - /*! Removes property with the given name from the set and deletes the object. - Emits aboutToDeleteProperty() before removing.*/ - void removeProperty(const QByteArray &name); - - /*! Removes all property objects from the property set and deletes them. */ - void clear(); - /*! @return the number of top-level properties in the set. */ uint count() const; @@ -167,10 +150,6 @@ KProperty::resetValue(), etc. */ bool isReadOnly() const; - /*! Sets this set to be read-only. - @see isReadOnly */ - void setReadOnly(bool readOnly); - /*! \return true if the set contains property names \a name. */ bool contains(const QByteArray &name) const; @@ -204,55 +183,74 @@ /*! Creates a deep copy of \a set and assigns it to this property set. */ KPropertySet& operator= (const KPropertySet &set); - /*! Change the value of property whose key is \a property to \a value. - @see void changePropertyIfExists(const QByteArray &, const QVariant &) */ - void changeProperty(const QByteArray &property, const QVariant &value); - - /*! Change the value of property whose key is \a property to \a value - only if it exists in the set. - @see void changeProperty(const QByteArray &, const QVariant &) */ - void changePropertyIfExists(const QByteArray &property, const QVariant &value) { - if (contains(property)) - changeProperty(property, value); - } - - /*! Sets @a caption as a user-visible translated string that will be shown in editor to represent - \a group. */ - void setGroupCaption(const QByteArray &group, const QString &caption); - /*! \return the user-visible translated caption string for \a group that will be shown in property editor to represent \a group. If there is no special caption set for the group, \a group is just returned. */ QString groupCaption(const QByteArray &group) const; - /*! Sets the icon name \a icon to be displayed for \a group. */ - void setGroupIconName(const QByteArray &group, const QString& iconName); - /*! \return the icons name for \a group. */ QString groupIconName(const QByteArray &group) const; /*! \return a list of all group names. The order of items is undefined. */ QList groupNames() const; - /*! \return a list of all property names for group @ group. + /*! \return a list of all property names for group @a group. The order of items is undefined. */ QList propertyNamesForGroup(const QByteArray &group) const; /*! Used by property editor to preserve previous selection when this set is assigned again. */ QByteArray previousSelection() const; - void setPreviousSelection(const QByteArray& prevSelection); - /*! Prints debug output for this set. */ void debug() const; //! @return property values for this set QMap propertyValues() const; -protected: - /*! Constructs a set which owns or does not own it's properties.*/ - explicit KPropertySet(bool propertyOwner); +public Q_SLOTS: + /*! Adds the property to the set, in the group. + The property becomes owned by the set. + Any name can be used for the @a group. "common" is the default for a basic top-level group. */ + void addProperty(KProperty *property, const QByteArray &group = "common"); + + /*! Removes property from the set and deletes the object. + Emits aboutToDeleteProperty before removing. */ + void removeProperty(KProperty *property); + + /*! Removes property with the given name from the set and deletes the object. + Emits aboutToDeleteProperty() before removing.*/ + void removeProperty(const QByteArray &name); + + /*! Removes all property objects from the property set and deletes them. */ + void clear(); + + /*! Change the value of property whose key is \a property to \a value. + @see void changePropertyIfExists(const QByteArray &, const QVariant &) */ + void changeProperty(const QByteArray &property, const QVariant &value); + + /*! Change the value of property whose key is \a property to \a value + only if it exists in the set. + @see void changeProperty(const QByteArray &, const QVariant &) */ + void changePropertyIfExists(const QByteArray &property, const QVariant &value) { + if (contains(property)) + changeProperty(property, value); + } + + /*! Sets @a caption as a user-visible translated string that will be shown in editor to represent + \a group. */ + void setGroupCaption(const QByteArray &group, const QString &caption); + + /*! Sets the icon name \a icon to be displayed for \a group. */ + void setGroupIconName(const QByteArray &group, const QString& iconName); + + //! Sets previous section. + //! @see previousSelection() + void setPreviousSelection(const QByteArray &prevSelection); + + /*! Sets this set to be read-only. + @see isReadOnly */ + void setReadOnly(bool readOnly); Q_SIGNALS: /*! Emitted when the value of the property is changed.*/ @@ -278,6 +276,10 @@ /*! Emitted when property set object's read-only flag has changed.*/ void readOnlyFlagChanged(); +protected: + /*! Constructs a set which owns or does not own it's properties.*/ + explicit KPropertySet(bool propertyOwner); + private: KPropertySetPrivate * const d; friend class KPropertySetPrivate; diff --git a/src/KPropertySet.cpp b/src/KPropertySet.cpp --- a/src/KPropertySet.cpp +++ b/src/KPropertySet.cpp @@ -1,7 +1,7 @@ /* This file is part of the KDE project Copyright (C) 2004 Cedric Pasteur Copyright (C) 2004 Alexander Dymo - Copyright (C) 2004-2009 Jarosław Staniek + Copyright (C) 2004-2017 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -183,6 +183,11 @@ removePropertyFromGroup(property); } +bool KPropertySetPrivate::hasGroups() const +{ + return groupNames.count() > 1 || (groupNames.count() == 1 && groupNames.first() != "common"); +} + void KPropertySetPrivate::informAboutClearing(bool* cleared) { Q_ASSERT(cleared); @@ -195,6 +200,29 @@ p1->d->addRelatedProperty(p2); } +int KPropertySetPrivate::indexOfProperty(const KProperty *property) const +{ + KProperty *parentProperty = property->parent(); + if (parentProperty) { + const QList* children = parentProperty->children(); + Q_ASSERT(children); + const int index = children->indexOf(parentProperty); + Q_ASSERT(index != -1); + return index; + } + return indexOfPropertyInGroup(property); +} + +int KPropertySetPrivate::indexOfPropertyInGroup(const KProperty *property) const +{ + const QByteArray group(groupForProperties.value(const_cast(property))); + QList* propertiesOfGroup = this->propertiesOfGroup.value(group); + if (!propertiesOfGroup) { + return -1; + } + return propertiesOfGroup->indexOf(property->name()); +} + ////////////////////////////////////////////// KPropertySelector::KPropertySelector() diff --git a/src/KPropertySet_p.h b/src/KPropertySet_p.h --- a/src/KPropertySet_p.h +++ b/src/KPropertySet_p.h @@ -1,7 +1,7 @@ /* This file is part of the KDE project Copyright (C) 2004 Cedric Pasteur Copyright (C) 2004 Alexander Dymo - Copyright (C) 2004-2009 Jarosław Staniek + Copyright (C) 2004-2017 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -62,6 +62,13 @@ inline bool isEmpty() const { return list.isEmpty(); } + /*! @return @c true if there are groups explicitly defined. + In this case groups are displayed by the property editor. + If there is only one "common" group, it means that all properties belong to this group, + and no groups are displayed. + @since 3.1 */ + bool hasGroups() const; + inline QByteArray groupForProperty(const KProperty *property) const { return groupForProperties.value(const_cast(property)); } diff --git a/src/KPropertyUtils.h b/src/KPropertyUtils.h --- a/src/KPropertyUtils.h +++ b/src/KPropertyUtils.h @@ -30,10 +30,12 @@ //! for a property editor-like panes. class KPROPERTYWIDGETS_EXPORT KPropertyGroupWidget : public QWidget { + Q_OBJECT public: explicit KPropertyGroupWidget(const QString& title, QWidget* parent = 0); ~KPropertyGroupWidget(); +public Q_SLOTS: void setContents(QWidget* contents); protected: diff --git a/src/KProperty_p.h b/src/KProperty_p.h --- a/src/KProperty_p.h +++ b/src/KProperty_p.h @@ -1,5 +1,5 @@ /* This file is part of the KDE project - Copyright (C) 2009-2016 Jarosław Staniek + Copyright (C) 2009-2017 Jarosław Staniek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -80,7 +80,7 @@ bool storable; bool readOnly; bool visible; - int autosync; + KProperty::ValueSyncPolicy valueSyncPolicy = KProperty::ValueSyncPolicy::Editor; QMap options; KComposedPropertyInterface *composed; diff --git a/src/editors/KPropertyGenericSelectionEditor.h b/src/editors/KPropertyGenericSelectionEditor.h --- a/src/editors/KPropertyGenericSelectionEditor.h +++ b/src/editors/KPropertyGenericSelectionEditor.h @@ -29,12 +29,12 @@ class KPROPERTYWIDGETS_EXPORT KPropertyGenericSelectionEditor : public QWidget { Q_OBJECT - public: explicit KPropertyGenericSelectionEditor(QWidget *parent = 0); ~KPropertyGenericSelectionEditor(); +public Q_SLOTS: //! Sets the visibility of the "..." select button void setSelectionButtonVisible(bool set); diff --git a/src/editors/combobox.h b/src/editors/combobox.h --- a/src/editors/combobox.h +++ b/src/editors/combobox.h @@ -56,14 +56,14 @@ virtual QVariant value() const; - void setListData(const KPropertyListData & listData); - static QString borderSheet(const QWidget *widget); Q_SIGNALS: void commitData( QWidget * editor ); public Q_SLOTS: + void setListData(const KPropertyListData & listData); + virtual void setValue(const QVariant &value); protected Q_SLOTS: diff --git a/src/editors/cursoredit.h b/src/editors/cursoredit.h --- a/src/editors/cursoredit.h +++ b/src/editors/cursoredit.h @@ -34,6 +34,8 @@ virtual ~KPropertyCursorEditor(); virtual QCursor cursorValue() const; + +public Q_SLOTS: virtual void setCursorValue(const QCursor &value); }; diff --git a/src/editors/dummywidget.h b/src/editors/dummywidget.h --- a/src/editors/dummywidget.h +++ b/src/editors/dummywidget.h @@ -28,17 +28,18 @@ class KPROPERTYWIDGETS_EXPORT KPropertyDummyWidget: public Widget { Q_OBJECT - public: explicit KPropertyDummyWidget(KProperty *property, QWidget *parent = 0); virtual ~KPropertyDummyWidget(); virtual QVariant value() const; - virtual void setValue(const QVariant &value, bool emitChange = true); virtual void drawViewer(QPainter *p, const QColorGroup &cg, const QRect &r, const QVariant &value); -protected: +public Q_SLOTS: + virtual void setValue(const QVariant &value, bool emitChange = true); + +protected Q_SLOTS: virtual void setReadOnlyInternal(bool readOnly); private: diff --git a/src/editors/stringlistedit.h b/src/editors/stringlistedit.h --- a/src/editors/stringlistedit.h +++ b/src/editors/stringlistedit.h @@ -31,17 +31,18 @@ class KPROPERTYWIDGETS_EXPORT KPropertyStringListEditor : public Widget { Q_OBJECT - public: explicit KPropertyStringListEditor(KProperty *property, QWidget *parent = 0); virtual ~KPropertyStringListEditor(); virtual QVariant value() const; - virtual void setValue(const QVariant &value, bool emitChange = true); virtual void drawViewer(QPainter *p, const QColorGroup &cg, const QRect &r, const QVariant &value); -protected: +public Q_SLOTS: + virtual void setValue(const QVariant &value, bool emitChange = true); + +protected Q_SLOTS: virtual void setReadOnlyInternal(bool readOnly); protected Q_SLOTS: diff --git a/src/editors/symbolcombo.h b/src/editors/symbolcombo.h --- a/src/editors/symbolcombo.h +++ b/src/editors/symbolcombo.h @@ -35,11 +35,13 @@ virtual ~KPropertySymbolComboEditor(); virtual QVariant value() const; - virtual void setValue(const QVariant &value, bool emitChange = true); virtual void drawViewer(QPainter *p, const QColorGroup &cg, const QRect &r, const QVariant &value); -protected: +public Q_SLOTS: + virtual void setValue(const QVariant &value, bool emitChange = true); + +protected Q_SLOTS: virtual void setReadOnlyInternal(bool readOnly); protected Q_SLOTS: