1 /*************************************************************************** 2 qgssearchwidgetwrapper.h 3 -------------------------------------- 4 Date : 31.5.2015 5 Copyright : (C) 2015 Karolina Alexiou (carolinux) 6 Email : carolinegr at gmail dot com 7 *************************************************************************** 8 * * 9 * This program is free software; you can redistribute it and/or modify * 10 * it under the terms of the GNU General Public License as published by * 11 * the Free Software Foundation; either version 2 of the License, or * 12 * (at your option) any later version. * 13 * * 14 ***************************************************************************/ 15 16 #ifndef QGSSEARCHWIDGETWRAPPER_H 17 #define QGSSEARCHWIDGETWRAPPER_H 18 19 #include <QObject> 20 #include "qgis_sip.h" 21 #include <QMap> 22 #include <QVariant> 23 24 class QgsVectorLayer; 25 class QgsField; 26 27 #include "qgsattributeeditorcontext.h" 28 #include "qgswidgetwrapper.h" 29 #include "qgis_gui.h" 30 31 #ifdef SIP_RUN 32 % MappedType QList<QgsSearchWidgetWrapper::FilterFlag> 33 { 34 % TypeHeaderCode 35 #include <QList> 36 % End 37 38 % ConvertFromTypeCode 39 // Create the list. 40 PyObject *l; 41 42 if ( ( l = PyList_New( sipCpp->size() ) ) == NULL ) 43 return NULL; 44 45 // Set the list elements. 46 QList<QgsSearchWidgetWrapper::FilterFlag>::iterator it = sipCpp->begin(); 47 for ( int i = 0; it != sipCpp->end(); ++it, ++i ) 48 { 49 PyObject *tobj; 50 51 if ( ( tobj = sipConvertFromEnum( *it, sipType_QgsSearchWidgetWrapper_FilterFlag ) ) == NULL ) 52 { 53 Py_DECREF( l ); 54 return NULL; 55 } 56 PyList_SET_ITEM( l, i, tobj ); 57 } 58 59 return l; 60 % End 61 62 % ConvertToTypeCode 63 // Check the type if that is all that is required. 64 if ( sipIsErr == NULL ) 65 return PyList_Check( sipPy ); 66 67 QList<QgsSearchWidgetWrapper::FilterFlag> *qlist = new QList<QgsSearchWidgetWrapper::FilterFlag>; 68 69 for ( int i = 0; i < PyList_GET_SIZE( sipPy ); ++i ) 70 { 71 *qlist << ( QgsSearchWidgetWrapper::FilterFlag )SIPLong_AsLong( PyList_GET_ITEM( sipPy, i ) ); 72 } 73 74 *sipCppPtr = qlist; 75 return sipGetState( sipTransferObj ); 76 % End 77 }; 78 #endif 79 80 /** 81 * \ingroup gui 82 * 83 * \brief Shows a search widget on a filter form. 84 */ 85 class GUI_EXPORT QgsSearchWidgetWrapper : public QgsWidgetWrapper 86 { 87 Q_OBJECT 88 public: 89 90 /** 91 * Flags which indicate what types of filtering and searching is possible using the widget 92 * \since QGIS 2.16 93 */ 94 enum FilterFlag 95 { 96 EqualTo = 1 << 1, //!< Supports equal to 97 NotEqualTo = 1 << 2, //!< Supports not equal to 98 GreaterThan = 1 << 3, //!< Supports greater than 99 LessThan = 1 << 4, //!< Supports less than 100 GreaterThanOrEqualTo = 1 << 5, //!< Supports >= 101 LessThanOrEqualTo = 1 << 6, //!< Supports <= 102 Between = 1 << 7, //!< Supports searches between two values 103 CaseInsensitive = 1 << 8, //!< Supports case insensitive searching 104 Contains = 1 << 9, //!< Supports value "contains" searching 105 DoesNotContain = 1 << 10, //!< Supports value does not contain searching 106 IsNull = 1 << 11, //!< Supports searching for null values 107 IsNotBetween = 1 << 12, //!< Supports searching for values outside of a set range 108 IsNotNull = 1 << 13, //!< Supports searching for non-null values 109 StartsWith = 1 << 14, //!< Supports searching for strings that start with 110 EndsWith = 1 << 15, //!< Supports searching for strings that end with 111 }; 112 Q_DECLARE_FLAGS( FilterFlags, FilterFlag ) 113 114 /** 115 * Returns a list of exclusive filter flags, which cannot be combined with other flags (e.g., EqualTo/NotEqualTo) 116 * \see nonExclusiveFilterFlags() 117 * \since QGIS 2.16 118 */ 119 static QList< QgsSearchWidgetWrapper::FilterFlag > exclusiveFilterFlags(); 120 121 /** 122 * Returns a list of non-exclusive filter flags, which can be combined with other flags (e.g., CaseInsensitive) 123 * \see exclusiveFilterFlags() 124 * \since QGIS 2.16 125 */ 126 static QList< QgsSearchWidgetWrapper::FilterFlag > nonExclusiveFilterFlags(); 127 128 /** 129 * Returns a translated string representing a filter flag. 130 * \param flag flag to convert to string 131 * \since QGIS 2.16 132 */ 133 static QString toString( QgsSearchWidgetWrapper::FilterFlag flag ); 134 135 /** 136 * Create a new widget wrapper 137 * 138 * \param vl The layer on which the field is 139 * \param fieldIdx The field which will be controlled 140 * \param parent A parent widget for this widget wrapper and the created widget. 141 */ 142 explicit QgsSearchWidgetWrapper( QgsVectorLayer *vl, int fieldIdx, QWidget *parent SIP_TRANSFERTHIS = nullptr ); 143 144 /** 145 * Returns filter flags supported by the search widget. 146 * \see defaultFlags() 147 * \since QGIS 2.16 148 */ 149 virtual FilterFlags supportedFlags() const; 150 151 /** 152 * Returns the filter flags which should be set by default for the search widget. 153 * \see supportedFlags() 154 * \since QGIS 2.16 155 */ 156 virtual FilterFlags defaultFlags() const; 157 158 /** 159 * Will be used to access the widget's value. Read the value from the widget and 160 * return it properly formatted to be saved in the attribute. 161 * 162 * If an invalid variant is returned this will be interpreted as no change. 163 * Be sure to return a NULL QVariant if it should be set to NULL. 164 * 165 * \returns The current value the widget represents 166 */ 167 virtual QString expression() const = 0; 168 169 /** 170 * If this is TRUE, then this search widget should take effect directly 171 * when its expression changes 172 */ 173 virtual bool applyDirectly() = 0; 174 175 // TODO QGIS 4.0 - make pure virtual 176 177 /** 178 * Creates a filter expression based on the current state of the search widget 179 * and the specified filter flags. 180 * \param flags filter flags 181 * \returns filter expression 182 * \since QGIS 2.16 183 */ createExpression(FilterFlags flags)184 virtual QString createExpression( FilterFlags flags ) const { Q_UNUSED( flags ) return QStringLiteral( "TRUE" ); } 185 186 /** 187 * Gets a field name or expression to use as field comparison. 188 * If in SearchMode returns a quoted field identifier. 189 * If in AggregateSearchMode returns an appropriate aggregate expression. 190 * 191 * \since QGIS 3.0 192 */ 193 QString createFieldIdentifier() const; 194 195 /** 196 * If in AggregateSearch mode, which aggregate should be used to construct 197 * the filter expression. Is a Null String if none. 198 * 199 * \since QGIS 3.0 200 */ 201 QString aggregate() const; 202 203 /** 204 * If in AggregateSearch mode, which aggregate should be used to construct 205 * the filter expression. Is a Null String if none. 206 * 207 * \since QGIS 3.0 208 */ 209 void setAggregate( const QString &aggregate ); 210 211 /** 212 * Returns the field index 213 * \since QGIS 3.10 214 */ 215 int fieldIndex() const; 216 217 public slots: 218 219 /** 220 * Clears the widget's current value and resets it back to the default state 221 * \since QGIS 2.16 222 */ clearWidget()223 virtual void clearWidget() {} 224 225 /** 226 * Toggles whether the search widget is enabled or disabled. 227 * \param enabled set to TRUE to enable widget 228 */ setEnabled(bool enabled)229 void setEnabled( bool enabled ) override { Q_UNUSED( enabled ) } 230 231 signals: 232 233 /** 234 * Emitted whenever the expression changes 235 * \param exp The new search expression 236 */ 237 void expressionChanged( const QString &exp ); 238 239 /** 240 * Emitted when a user changes the value of the search widget. 241 * \since QGIS 2.16 242 */ 243 void valueChanged(); 244 245 /** 246 * Emitted when a user changes the value of the search widget back 247 * to an empty, default state. 248 * \since QGIS 2.16 249 */ 250 void valueCleared(); 251 252 protected slots: 253 254 /** 255 * Set the \a expression which is currently used as filter for this widget. 256 */ 257 virtual void setExpression( const QString &expression ) = 0; 258 259 void setFeature( const QgsFeature &feature ) override; 260 261 protected: 262 //! clears the expression to search for all features 263 void clearExpression(); 264 265 QString mExpression; 266 int mFieldIdx; 267 268 private: 269 QString mAggregate; 270 QgsRelation mAggregateRelation; 271 }; 272 // We'll use this class inside a QVariant in the widgets properties 273 Q_DECLARE_METATYPE( QgsSearchWidgetWrapper * ) 274 275 Q_DECLARE_OPERATORS_FOR_FLAGS( QgsSearchWidgetWrapper::FilterFlags ) 276 277 #endif // QGSSEARCHWIDGETWRAPPER_H 278