/ proxyroles / switchrole.cpp
switchrole.cpp
1 #include "switchrole.h" 2 #include "qqmlsortfilterproxymodel.h" 3 #include "filters/filter.h" 4 #include <QtQml> 5 6 namespace qqsfpm { 7 8 /*! 9 \qmltype SwitchRole 10 \inherits SingleRole 11 \inqmlmodule SortFilterProxyModel 12 \ingroup ProxyRoles 13 \ingroup FilterContainer 14 \brief A role using \l Filter to conditionnaly compute its data. 15 16 A SwitchRole is a \l ProxyRole that computes its data with the help of \l Filter. 17 Each top level filters specified in the \l SwitchRole is evaluated on the rows of the model, if a \l Filter evaluates to true, the data of the \l SwitchRole for this row will be the one of the attached \l {value} {SwitchRole.value} property. 18 If no top level filters evaluate to true, the data will default to the one of the \l defaultRoleName (or the \l defaultValue if no \l defaultRoleName is specified). 19 20 In the following example, the \c favoriteOrFirstNameSection role is equal to \c * if the \c favorite role of a row is true, otherwise it's the same as the \c firstName role : 21 \code 22 SortFilterProxyModel { 23 sourceModel: contactModel 24 proxyRoles: SwitchRole { 25 name: "favoriteOrFirstNameSection" 26 filters: ValueFilter { 27 roleName: "favorite" 28 value: true 29 SwitchRole.value: "*" 30 } 31 defaultRoleName: "firstName" 32 } 33 } 34 \endcode 35 \sa FilterContainer 36 */ 37 SwitchRoleAttached::SwitchRoleAttached(QObject* parent) : QObject (parent) 38 { 39 if (!qobject_cast<Filter*>(parent)) 40 qmlInfo(parent) << "SwitchRole must be attached to a Filter"; 41 } 42 43 /*! 44 \qmlattachedproperty var SwitchRole::value 45 46 This property attaches a value to a \l Filter. 47 */ 48 QVariant SwitchRoleAttached::value() const 49 { 50 return m_value; 51 } 52 53 void SwitchRoleAttached::setValue(const QVariant &value) 54 { 55 if (m_value == value) 56 return; 57 58 m_value = value; 59 Q_EMIT valueChanged(); 60 } 61 62 /*! 63 \qmlproperty string SwitchRole::defaultRoleName 64 65 This property holds the default role name of the role. 66 If no filter match a row, the data of this role will be the data of the role whose name is \c defaultRoleName. 67 */ 68 QString SwitchRole::defaultRoleName() const 69 { 70 return m_defaultRoleName; 71 } 72 73 void SwitchRole::setDefaultRoleName(const QString& defaultRoleName) 74 { 75 if (m_defaultRoleName == defaultRoleName) 76 return; 77 78 m_defaultRoleName = defaultRoleName; 79 Q_EMIT defaultRoleNameChanged(); 80 invalidate(); 81 } 82 83 /*! 84 \qmlproperty var SwitchRole::defaultValue 85 86 This property holds the default value of the role. 87 If no filter match a row, and no \l defaultRoleName is set, the data of this role will be \c defaultValue. 88 */ 89 QVariant SwitchRole::defaultValue() const 90 { 91 return m_defaultValue; 92 } 93 94 void SwitchRole::setDefaultValue(const QVariant& defaultValue) 95 { 96 if (m_defaultValue == defaultValue) 97 return; 98 99 m_defaultValue = defaultValue; 100 Q_EMIT defaultValueChanged(); 101 invalidate(); 102 } 103 104 /*! 105 \qmlproperty list<Filter> SwitchRole::filters 106 \default 107 108 This property holds the list of filters for this proxy role. 109 The data of this role will be equal to the attached \l {value} {SwitchRole.value} property of the first filter that matches the model row. 110 111 \sa Filter, FilterContainer 112 */ 113 114 void SwitchRole::proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) 115 { 116 for (Filter* filter : qAsConst(m_filters)) 117 filter->proxyModelCompleted(proxyModel); 118 } 119 120 SwitchRoleAttached* SwitchRole::qmlAttachedProperties(QObject* object) 121 { 122 return new SwitchRoleAttached(object); 123 } 124 125 QVariant SwitchRole::data(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel &proxyModel) 126 { 127 for (auto filter: qAsConst(m_filters)) { 128 if (!filter->enabled()) 129 continue; 130 if (filter->filterAcceptsRow(sourceIndex, proxyModel)) { 131 auto attached = static_cast<SwitchRoleAttached*>(qmlAttachedPropertiesObject<SwitchRole>(filter, false)); 132 if (!attached) { 133 qWarning() << "No SwitchRole.value provided for this filter" << filter; 134 continue; 135 } 136 QVariant value = attached->value(); 137 if (!value.isValid()) { 138 qWarning() << "No SwitchRole.value provided for this filter" << filter; 139 continue; 140 } 141 return value; 142 } 143 } 144 if (!m_defaultRoleName.isEmpty()) 145 return proxyModel.sourceData(sourceIndex, m_defaultRoleName); 146 return m_defaultValue; 147 } 148 149 void SwitchRole::onFilterAppended(Filter *filter) 150 { 151 connect(filter, &Filter::invalidated, this, &SwitchRole::invalidate); 152 auto attached = static_cast<SwitchRoleAttached*>(qmlAttachedPropertiesObject<SwitchRole>(filter, true)); 153 connect(attached, &SwitchRoleAttached::valueChanged, this, &SwitchRole::invalidate); 154 invalidate(); 155 } 156 157 void SwitchRole::onFilterRemoved(Filter *filter) 158 { 159 Q_UNUSED(filter) 160 invalidate(); 161 } 162 163 void SwitchRole::onFiltersCleared() 164 { 165 invalidate(); 166 } 167 168 }