Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsproject.h 3 : : 4 : : Implements persistent project state. 5 : : 6 : : ------------------- 7 : : begin : February 24, 2005 8 : : copyright : (C) 2005 by Mark Coletti 9 : : email : mcoletti at gmail.com 10 : : ***************************************************************************/ 11 : : 12 : : /*************************************************************************** 13 : : * * 14 : : * This program is free software; you can redistribute it and/or modify * 15 : : * it under the terms of the GNU General Public License as published by * 16 : : * the Free Software Foundation; either version 2 of the License, or * 17 : : * (at your option) any later version. * 18 : : * * 19 : : ***************************************************************************/ 20 : : 21 : : 22 : : #ifndef QGSPROJECTPROPERTY_H 23 : : #define QGSPROJECTPROPERTY_H 24 : : 25 : : #include <QHash> 26 : : #include <QVariant> 27 : : #include <QStringList> 28 : : #include <QCoreApplication> 29 : : 30 : : #include "qgis_core.h" 31 : : 32 : : class QDomNode; 33 : : class QDomElement; 34 : : class QDomDocument; 35 : : 36 : : 37 : : /** 38 : : * \class QgsProjectProperty 39 : : * \ingroup core 40 : : * \brief An Abstract Base Class for QGIS project property hierarchys. 41 : : * 42 : : * Each sub-class is either a QgsProjectPropertyKey or QgsProjectPropertyValue. QgsProjectPropertyKey can 43 : : * contain either QgsProjectPropertyKey or QgsProjectPropertyValues, thus describing an 44 : : * hierarchy. QgsProjectPropertyValues are always graph leaves. 45 : : * 46 : : * \note This class is used internally by QgsProject. It's generally recommended that the methods in 47 : : * QgsProject are used to modify project properties rather than using these low-level classes. 48 : : * \since QGIS 3.0 49 : : */ 50 : : class CORE_EXPORT QgsProjectProperty 51 : : { 52 : : public: 53 : : QgsProjectProperty(); 54 : 53 : virtual ~QgsProjectProperty() = default; 55 : : 56 : : /** 57 : : * Dumps out the keys and values 58 : : * 59 : : * \param tabs is number of tabs to print; used for pretty-printing hierarchy 60 : : */ 61 : : virtual void dump( int tabs = 0 ) const = 0; 62 : : 63 : : /** 64 : : * Returns TRUE if the property is a QgsProjectPropertyKey. 65 : : * \see isValue() 66 : : * \see isLeaf() 67 : : */ 68 : : virtual bool isKey() const = 0; 69 : : 70 : : /** 71 : : * Returns TRUE if the property is a QgsProjectPropertyValue. 72 : : * \see isKey() 73 : : * \see isLeaf() 74 : : */ 75 : : virtual bool isValue() const = 0; 76 : : 77 : : /** 78 : : * Returns TRUE if property is a leaf node. 79 : : * 80 : : * A leaf node is a key node that has either no value or only a single value. 81 : : * A non-leaf node would be a key node with key sub-nodes. 82 : : * 83 : : * This is used for entryList() and subkeyList() implementation. 84 : : */ 85 : : virtual bool isLeaf() const = 0; 86 : : 87 : : /** 88 : : * Restores the property hierarchy from a specified DOM node. 89 : : * 90 : : * Used for restoring properties from project file 91 : : */ 92 : : virtual bool readXml( const QDomNode &keyNode ) = 0; 93 : : 94 : : /** 95 : : * Writes the property hierarchy to a specified DOM element. 96 : : * 97 : : * Used for saving properties to project file. 98 : : * 99 : : * \param nodeName the tag name associated with this element 100 : : * \param element the parent (or encompassing) property element 101 : : * \param document the overall project file Dom document 102 : : */ 103 : : virtual bool writeXml( const QString &nodeName, 104 : : QDomElement &element, 105 : : QDomDocument &document ) = 0; 106 : : 107 : : /** 108 : : * Returns the node's value. 109 : : * 110 : : * For QgsProjectPropertyValue nodes, this is straightforward -- just return the 111 : : * embedded QVariant, _value. For QgsProjectPropertyKey, this means returning 112 : : * the QgsProjectPropertyValue _value that is keyed by its name, if it exists; 113 : : * i.e., QgsProjectPropertyKey "foo" will return the property value mapped to its 114 : : * name, "foo", in its QHash of QProperties. 115 : : * 116 : : */ 117 : : virtual QVariant value() const = 0; 118 : : 119 : : }; 120 : : 121 : : 122 : : /** 123 : : * \class QgsProjectPropertyValue 124 : : * \ingroup core 125 : : * \brief Project property value node, contains a QgsProjectPropertyKey's value. 126 : : * \since QGIS 3.0 127 : : */ 128 : 62 : class CORE_EXPORT QgsProjectPropertyValue : public QgsProjectProperty 129 : : { 130 : : public: 131 : : 132 : : //! Constructor for QgsProjectPropertyValue. 133 : 0 : QgsProjectPropertyValue() = default; 134 : : 135 : : /** 136 : : * Constructor for QgsProjectPropertyValue, initialized to a specified value. 137 : : */ 138 : 41 : QgsProjectPropertyValue( const QVariant &value ) 139 : 41 : : mValue( value ) 140 : 82 : {} 141 : : 142 : 0 : bool isKey() const override { return false; } 143 : 0 : bool isValue() const override { return true; } 144 : 2 : QVariant value() const override { return mValue; } 145 : : 146 : : //value nodes can also be qualified as leaf nodes even though we only count key nodes. 147 : 0 : bool isLeaf() const override { return true; } 148 : : 149 : : void dump( int tabs = 0 ) const override; 150 : : bool readXml( const QDomNode &keyNode ) override; 151 : : bool writeXml( const QString &nodeName, 152 : : QDomElement &element, 153 : : QDomDocument &document ) override; 154 : : 155 : : private: 156 : : 157 : : // We use QVariant as it's very handy to keep multiple types and provides type conversions 158 : : QVariant mValue; 159 : : 160 : : }; 161 : : 162 : : 163 : : /** 164 : : * \class QgsProjectPropertyKey 165 : : * \ingroup core 166 : : * 167 : : * \brief Project property key node. 168 : : * 169 : : * Can, itself, contain QgsProjectPropertyKey and QgsProjectPropertyValues. 170 : : * 171 : : * The internal QHash, mProperties, maps key names to their respective 172 : : * QgsProjectPropertyValue or next QgsProjectPropertyKey in the key name sequence. The key with 173 : : * the current name should contain its QgsProjectPropertyValue. 174 : : * 175 : : * E.g., given the key sequence "/foo/bar", "foo" will have a corresponding 176 : : * QgsProjectPropertyKey with a name "foo". It will contain an element in its 177 : : * mProperties that maps to "bar", which is another QgsProjectPropertyKey. The "bar" 178 : : * QgsProjectPropertyKey will, in turn, have an element that maps to itself, i.e. "bar", 179 : : * that will contain a QgsProjectPropertyValue. 180 : : * 181 : : * \since QGIS 3.0 182 : : */ 183 : : class CORE_EXPORT QgsProjectPropertyKey : public QgsProjectProperty 184 : : { 185 : 0 : Q_DECLARE_TR_FUNCTIONS( QgsProjectPropertyKey ) 186 : : 187 : : public: 188 : : 189 : : /** 190 : : * Create a new QgsProjectPropertyKey with the specified identifier. 191 : : */ 192 : : QgsProjectPropertyKey( const QString &name = QString() ); 193 : : ~QgsProjectPropertyKey() override; 194 : : 195 : : /** 196 : : * The name of the property is used as identifier. 197 : : * \see setName() 198 : : */ 199 : 322 : QString name() const { return mName; } 200 : : 201 : : /** 202 : : * The name of the property is used as identifier. 203 : : * 204 : : * \see name() 205 : : * \since QGIS 3.0 206 : : */ 207 : : void setName( const QString &name ); 208 : : 209 : : /** 210 : : * If this key has a value, it will be stored by its name in its 211 : : * properties 212 : : */ 213 : : QVariant value() const override; 214 : : 215 : : /** 216 : : * Adds the specified property key as a sub-key. 217 : : */ 218 : 25 : QgsProjectPropertyKey *addKey( const QString &keyName ) 219 : : { 220 : 25 : if ( mProperties.contains( keyName ) ) 221 : 0 : delete mProperties.take( keyName ); 222 : : 223 : 25 : QgsProjectPropertyKey *p = new QgsProjectPropertyKey( keyName ); 224 : 25 : mProperties.insert( keyName, p ); 225 : : 226 : 25 : return p; 227 : 0 : } 228 : : 229 : : /** 230 : : * Removes the specified key. 231 : : */ 232 : 0 : void removeKey( const QString &keyName ) 233 : : { 234 : 0 : delete mProperties.take( keyName ); 235 : 0 : } 236 : : 237 : : /** 238 : : * Sets the value associated with this key. 239 : : * \param name is the key name 240 : : * \param value is the value to set 241 : : * \returns pointer to property value 242 : : */ 243 : 41 : QgsProjectPropertyValue *setValue( const QString &name, const QVariant &value ) 244 : : { 245 : 41 : if ( mProperties.contains( name ) ) 246 : 0 : delete mProperties.take( name ); 247 : : 248 : 41 : QgsProjectPropertyValue *p = new QgsProjectPropertyValue( value ); 249 : 41 : mProperties.insert( name, p ); 250 : : 251 : 41 : return p; 252 : 0 : } 253 : : 254 : : /** 255 : : * Set the value associated with this key 256 : : * 257 : : * \note that the single value node associated with each key is always 258 : : * stored keyed by the current key name 259 : : */ 260 : 0 : QgsProjectPropertyValue *setValue( const QVariant &value ) 261 : : { 262 : 0 : return setValue( name(), value ); 263 : 0 : } 264 : : 265 : : void dump( int tabs = 0 ) const override; 266 : : bool readXml( const QDomNode &keyNode ) override; 267 : : bool writeXml( const QString &nodeName, QDomElement &element, QDomDocument &document ) override; 268 : : 269 : : /** 270 : : * Returns the number of sub-keys contained by this property. 271 : : */ 272 : 0 : int count() const { return mProperties.count(); } 273 : : 274 : : /** 275 : : * Returns TRUE if this property contains no sub-keys. 276 : : */ 277 : 0 : bool isEmpty() const { return mProperties.isEmpty(); } 278 : : 279 : 2 : bool isKey() const override { return true; } 280 : 0 : bool isValue() const override { return false; } 281 : : bool isLeaf() const override; 282 : : 283 : : /** 284 : : * Returns any sub-keys contained by this property that do not contain other keys. 285 : : * \see subkeyList() 286 : : */ 287 : : void entryList( QStringList &entries ) const; 288 : : 289 : : /** 290 : : * Returns any sub-keys contained by this property which themselves contain other keys. 291 : : * \see entryList() 292 : : */ 293 : : void subkeyList( QStringList &entries ) const; 294 : : 295 : : /** 296 : : * Resets the property to a default, empty state. 297 : : */ 298 : 0 : virtual void clear() 299 : : { 300 : 0 : mName.clear(); 301 : 0 : clearKeys(); 302 : 0 : } 303 : : 304 : : /** 305 : : * Deletes any sub-nodes from the property. 306 : : */ 307 : 30 : virtual void clearKeys() 308 : : { 309 : 30 : qDeleteAll( mProperties ); 310 : 30 : mProperties.clear(); 311 : 30 : } 312 : : 313 : : /** 314 : : * Attempts to find a property with a matching sub-key name. 315 : : */ 316 : 322 : QgsProjectProperty *find( const QString &propertyName ) const 317 : : { 318 : 322 : return mProperties.value( propertyName ); 319 : : } 320 : : 321 : : private: 322 : : 323 : : //! Name of the key 324 : : QString mName; 325 : : 326 : : //! Sub-keys 327 : : QHash < QString, QgsProjectProperty * > mProperties; 328 : : 329 : : }; 330 : : 331 : : #endif