LCOV - code coverage report
Current view: top level - core - qgssettings.h (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 24 59 40.7 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :   qgssettings.h
       3                 :            :   --------------------------------------
       4                 :            :   Date                 : January 2017
       5                 :            :   Copyright            : (C) 2017 by Alessandro Pasotti
       6                 :            :   Email                : apasotti at boundlessgeo 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                 :            : 
      17                 :            : #ifndef QGSSETTINGS_H
      18                 :            : #define QGSSETTINGS_H
      19                 :            : 
      20                 :            : #include <QSettings>
      21                 :            : #include <QMetaEnum>
      22                 :            : 
      23                 :            : #include "qgis_core.h"
      24                 :            : #include "qgis_sip.h"
      25                 :            : #include "qgslogger.h"
      26                 :            : 
      27                 :            : /**
      28                 :            :  * \ingroup core
      29                 :            :  * \class QgsSettings
      30                 :            :  *
      31                 :            :  * \brief This class is a composition of two QSettings instances:
      32                 :            :  *
      33                 :            :  * - the main QSettings instance is the standard User Settings and
      34                 :            :  * - the second one (Global Settings) is meant to provide read-only
      35                 :            :  *   pre-configuration and defaults to the first one.
      36                 :            :  *
      37                 :            :  * For a given settings key, the function call to value(key, default) will return
      38                 :            :  * the first existing setting in the order specified below:
      39                 :            :  *
      40                 :            :  * - User Settings
      41                 :            :  * - Global Settings
      42                 :            :  * - Default Value
      43                 :            :  *
      44                 :            :  * The path to the Global Settings storage can be set before constructing the QgsSettings
      45                 :            :  * objects, with a static call to:
      46                 :            :  * static bool setGlobalSettingsPath( QString path );
      47                 :            :  *
      48                 :            :  * QgsSettings provides some shortcuts to get/set namespaced settings from/to a specific section:
      49                 :            :  *
      50                 :            :  * - Core
      51                 :            :  * - Gui
      52                 :            :  * - Server
      53                 :            :  * - Plugins
      54                 :            :  * - Auth
      55                 :            :  * - App
      56                 :            :  * - Providers
      57                 :            :  * - Misc
      58                 :            :  *
      59                 :            :  * \since QGIS 3.0
      60                 :            :  */
      61                 :            : class CORE_EXPORT QgsSettings : public QObject
      62                 :            : {
      63                 :            :     Q_OBJECT
      64                 :            :   public:
      65                 :            : 
      66                 :            :     //! Sections for namespaced settings
      67                 :            :     enum Section
      68                 :            :     {
      69                 :            :       NoSection,
      70                 :            :       Core,
      71                 :            :       Gui,
      72                 :            :       Server,
      73                 :            :       Plugins,
      74                 :            :       Auth,
      75                 :            :       App,
      76                 :            :       Providers,
      77                 :            :       Expressions,
      78                 :            :       Misc
      79                 :            :     };
      80                 :            : 
      81                 :            :     /**
      82                 :            :      * Constructs a QgsSettings object for accessing settings of the application
      83                 :            :      * called application from the organization called organization, and with parent parent.
      84                 :            :      */
      85                 :            :     explicit QgsSettings( const QString &organization,
      86                 :            :                           const QString &application = QString(), QObject *parent = nullptr );
      87                 :            : 
      88                 :            :     /**
      89                 :            :      * Constructs a QgsSettings object for accessing settings of the application called application
      90                 :            :      * from the organization called organization, and with parent parent.
      91                 :            :      *
      92                 :            :      * If scope is QSettings::UserScope, the QSettings object searches user-specific settings first,
      93                 :            :      * before it searches system-wide settings as a fallback. If scope is QSettings::SystemScope,
      94                 :            :      * the QSettings object ignores user-specific settings and provides access to system-wide settings.
      95                 :            :      *
      96                 :            :      * The storage format is set to QSettings::NativeFormat (i.e. calling setDefaultFormat() before
      97                 :            :      * calling this constructor has no effect).
      98                 :            :      *
      99                 :            :      * If no application name is given, the QSettings object will only access the organization-wide
     100                 :            :      * locations.
     101                 :            :      */
     102                 :            :     QgsSettings( QSettings::Scope scope, const QString &organization,
     103                 :            :                  const QString &application = QString(), QObject *parent = nullptr );
     104                 :            : 
     105                 :            :     /**
     106                 :            :      * Constructs a QgsSettings object for accessing settings of the application called application
     107                 :            :      * from the organization called organization, and with parent parent.
     108                 :            :      *
     109                 :            :      * If scope is QSettings::UserScope, the QSettings object searches user-specific settings first,
     110                 :            :      * before it searches system-wide settings as a fallback. If scope is QSettings::SystemScope,
     111                 :            :      * the QSettings object ignores user-specific settings and provides access to system-wide settings.
     112                 :            :      *
     113                 :            :      * If format is QSettings::NativeFormat, the native API is used for storing settings. If format
     114                 :            :      * is QSettings::IniFormat, the INI format is used.
     115                 :            :      *
     116                 :            :      * If no application name is given, the QSettings object will only access the organization-wide
     117                 :            :      * locations.
     118                 :            :      */
     119                 :            :     QgsSettings( QSettings::Format format, QSettings::Scope scope, const QString &organization,
     120                 :            :                  const QString &application = QString(), QObject *parent = nullptr );
     121                 :            : 
     122                 :            :     /**
     123                 :            :      * Constructs a QgsSettings object for accessing the settings stored in the file called fileName,
     124                 :            :      * with parent parent. If the file doesn't already exist, it is created.
     125                 :            :      *
     126                 :            :      * If format is QSettings::NativeFormat, the meaning of fileName depends on the platform. On Unix,
     127                 :            :      * fileName is the name of an INI file. On macOS and iOS, fileName is the name of a .plist file.
     128                 :            :      * On Windows, fileName is a path in the system registry.
     129                 :            :      *
     130                 :            :      * If format is QSettings::IniFormat, fileName is the name of an INI file.
     131                 :            :      *
     132                 :            :      * \warning This function is provided for convenience. It works well for accessing INI or .plist
     133                 :            :      * files generated by Qt, but might fail on some syntaxes found in such files originated by
     134                 :            :      * other programs. In particular, be aware of the following limitations:
     135                 :            :      *
     136                 :            :      * - QgsSettings provides no way of reading INI "path" entries, i.e., entries with unescaped slash characters.
     137                 :            :      *   (This is because these entries are ambiguous and cannot be resolved automatically.)
     138                 :            :      * - In INI files, QSettings uses the @ character as a metacharacter in some contexts, to encode
     139                 :            :      *   Qt-specific data types (e.g., \@Rect), and might therefore misinterpret it when it occurs
     140                 :            :      *   in pure INI files.
     141                 :            :      */
     142                 :            :     QgsSettings( const QString &fileName, QSettings::Format format, QObject *parent = nullptr );
     143                 :            : 
     144                 :            :     /**
     145                 :            :      * Constructs a QgsSettings object for accessing settings of the application and organization
     146                 :            :      * set previously with a call to QCoreApplication::setOrganizationName(),
     147                 :            :      * QCoreApplication::setOrganizationDomain(), and QCoreApplication::setApplicationName().
     148                 :            :      *
     149                 :            :      * The scope is QSettings::UserScope and the format is defaultFormat() (QSettings::NativeFormat
     150                 :            :      * by default). Use setDefaultFormat() before calling this constructor to change the default
     151                 :            :      * format used by this constructor.
     152                 :            :      */
     153                 :            :     explicit QgsSettings( QObject *parent = nullptr );
     154                 :            :     ~QgsSettings() override;
     155                 :            : 
     156                 :            :     /**
     157                 :            :      * Appends prefix to the current group.
     158                 :            :      * The current group is automatically prepended to all keys specified to QSettings.
     159                 :            :      * In addition, query functions such as childGroups(), childKeys(), and allKeys()
     160                 :            :      * are based on the group. By default, no group is set.
     161                 :            :      */
     162                 :            :     void beginGroup( const QString &prefix, QgsSettings::Section section = QgsSettings::NoSection );
     163                 :            :     //! Resets the group to what it was before the corresponding beginGroup() call.
     164                 :            :     void endGroup();
     165                 :            : 
     166                 :            :     /**
     167                 :            :      * Returns the current group.
     168                 :            :      * \see beginGroup()
     169                 :            :      * \see endGroup()
     170                 :            :      * \since QGIS 3.6
     171                 :            :      */
     172                 :            :     QString group() const;
     173                 :            : 
     174                 :            :     //! Returns a list of all keys, including subkeys, that can be read using the QSettings object.
     175                 :            :     QStringList allKeys() const;
     176                 :            :     //! Returns a list of all top-level keys that can be read using the QSettings object.
     177                 :            :     QStringList childKeys() const;
     178                 :            :     //! Returns a list of all key top-level groups that contain keys that can be read using the QSettings object.
     179                 :            :     QStringList childGroups() const;
     180                 :            :     //! Returns a list of all key top-level groups (same as childGroups) but only for groups defined in global settings.
     181                 :            :     QStringList globalChildGroups() const;
     182                 :            :     //! Returns the path to the Global Settings QSettings storage file
     183                 :            :     static QString globalSettingsPath();
     184                 :            :     //! Sets the Global Settings QSettings storage file
     185                 :            :     static bool setGlobalSettingsPath( const QString &path );
     186                 :            :     //! Adds prefix to the current group and starts reading from an array. Returns the size of the array.
     187                 :            :     int beginReadArray( const QString &prefix );
     188                 :            : 
     189                 :            :     /**
     190                 :            :      * Adds prefix to the current group and starts writing an array of size size.
     191                 :            :      * If size is -1 (the default), it is automatically determined based on the indexes of the entries written.
     192                 :            :      * \note This will completely shadow any existing array with the same name in the global settings
     193                 :            :      */
     194                 :            :     void beginWriteArray( const QString &prefix, int size = -1 );
     195                 :            :     //! Closes the array that was started using beginReadArray() or beginWriteArray().
     196                 :            :     void endArray();
     197                 :            : 
     198                 :            :     /**
     199                 :            :      * Sets the current array index to i. Calls to functions such as setValue(), value(),
     200                 :            :      * remove(), and contains() will operate on the array entry at that index.
     201                 :            :      */
     202                 :            :     void setArrayIndex( int i );
     203                 :            : 
     204                 :            :     /**
     205                 :            :      * Sets the value of setting key to value. If the key already exists, the previous value is overwritten.
     206                 :            :      * An optional Section argument can be used to set a value to a specific Section.
     207                 :            :      */
     208                 :            :     void setValue( const QString &key, const QVariant &value, QgsSettings::Section section = QgsSettings::NoSection );
     209                 :            : 
     210                 :            :     /**
     211                 :            :      * Returns the value for setting key. If the setting doesn't exist, it will be
     212                 :            :      * searched in the Global Settings and if not found, returns defaultValue.
     213                 :            :      * If no default value is specified, a default QVariant is returned.
     214                 :            :      * An optional Section argument can be used to get a value from a specific Section.
     215                 :            :      */
     216                 :            : #ifndef SIP_RUN
     217                 :            :     QVariant value( const QString &key, const QVariant &defaultValue = QVariant(),
     218                 :            :                     Section section = NoSection ) const;
     219                 :            : #else
     220                 :            :     SIP_PYOBJECT value( const QString &key, const QVariant &defaultValue = QVariant(),
     221                 :            :                         SIP_PYOBJECT type = 0,
     222                 :            :                         QgsSettings::Section section = QgsSettings::NoSection ) const / ReleaseGIL /;
     223                 :            :     % MethodCode
     224                 :            :     typedef PyObject *( *pyqt5_from_qvariant_by_type )( QVariant &value, PyObject *type );
     225                 :            :     QVariant value;
     226                 :            : 
     227                 :            :     // QSettings has an internal mutex so release the GIL to avoid the possibility of deadlocks.
     228                 :            :     Py_BEGIN_ALLOW_THREADS
     229                 :            :     value = sipCpp->value( *a0, *a1, a3 );
     230                 :            :     Py_END_ALLOW_THREADS
     231                 :            : 
     232                 :            :     pyqt5_from_qvariant_by_type f = ( pyqt5_from_qvariant_by_type ) sipImportSymbol( "pyqt5_from_qvariant_by_type" );
     233                 :            :     sipRes = f( value, a2 );
     234                 :            : 
     235                 :            :     sipIsErr = !sipRes;
     236                 :            :     % End
     237                 :            : #endif
     238                 :            : 
     239                 :            : #ifndef SIP_RUN
     240                 :            : 
     241                 :            :     /**
     242                 :            :      * Returns the setting value for a setting based on an enum.
     243                 :            :      * This forces the output to be a valid and existing entry of the enum.
     244                 :            :      * Hence if the setting value is incorrect, the given default value is returned.
     245                 :            :      * This tries first with setting as a string (as the enum) and then as an integer value.
     246                 :            :      * \note The enum needs to be declared with Q_ENUM, and flags with Q_FLAG (not Q_FLAGS).
     247                 :            :      * \note for Python bindings, a custom implementation is achieved in Python directly
     248                 :            :      * \see setEnumValue
     249                 :            :      * \see flagValue
     250                 :            :      */
     251                 :            :     template <class T>
     252                 :        106 :     T enumValue( const QString &key, const T &defaultValue,
     253                 :            :                  const Section section = NoSection )
     254                 :            :     {
     255                 :        106 :       QMetaEnum metaEnum = QMetaEnum::fromType<T>();
     256                 :            :       Q_ASSERT( metaEnum.isValid() );
     257                 :        106 :       if ( !metaEnum.isValid() )
     258                 :            :       {
     259                 :          0 :         QgsDebugMsg( QStringLiteral( "Invalid metaenum. Enum probably misses Q_ENUM or Q_FLAG declaration." ) );
     260                 :          0 :       }
     261                 :            : 
     262                 :            :       T v;
     263                 :        106 :       bool ok = false;
     264                 :            : 
     265                 :        106 :       if ( metaEnum.isValid() )
     266                 :            :       {
     267                 :            :         // read as string
     268                 :        106 :         QByteArray ba = value( key, metaEnum.valueToKey( static_cast<int>( defaultValue ) ), section ).toString().toUtf8();
     269                 :        106 :         const char *vs = ba.data();
     270                 :        106 :         v = static_cast<T>( metaEnum.keyToValue( vs, &ok ) );
     271                 :        106 :         if ( ok )
     272                 :        106 :           return v;
     273                 :        106 :       }
     274                 :            : 
     275                 :            :       // if failed, try to read as int (old behavior)
     276                 :            :       // this code shall be removed later (probably after QGIS 3.4 LTR for 3.6)
     277                 :            :       // then the method could be marked as const
     278                 :          0 :       v = static_cast<T>( value( key, static_cast<int>( defaultValue ), section ).toInt( &ok ) );
     279                 :          0 :       if ( metaEnum.isValid() )
     280                 :            :       {
     281                 :          0 :         if ( !ok || !metaEnum.valueToKey( static_cast<int>( v ) ) )
     282                 :            :         {
     283                 :          0 :           v = defaultValue;
     284                 :          0 :         }
     285                 :            :         else
     286                 :            :         {
     287                 :            :           // found setting as an integer
     288                 :            :           // convert the setting to the new form (string)
     289                 :          0 :           setEnumValue( key, v, section );
     290                 :            :         }
     291                 :          0 :       }
     292                 :            : 
     293                 :          0 :       return v;
     294                 :        106 :     }
     295                 :            : 
     296                 :            :     /**
     297                 :            :      * Set the value of a setting based on an enum.
     298                 :            :      * The setting will be saved as string.
     299                 :            :      * \note The enum needs to be declared with Q_ENUM, and flags with Q_FLAG (not Q_FLAGS).
     300                 :            :      * \see enumValue
     301                 :            :      * \see setFlagValue
     302                 :            :      */
     303                 :            :     template <class T>
     304                 :          0 :     void setEnumValue( const QString &key, const T &value,
     305                 :            :                        const Section section = NoSection )
     306                 :            :     {
     307                 :          0 :       QMetaEnum metaEnum = QMetaEnum::fromType<T>();
     308                 :            :       Q_ASSERT( metaEnum.isValid() );
     309                 :          0 :       if ( metaEnum.isValid() )
     310                 :            :       {
     311                 :          0 :         setValue( key, metaEnum.valueToKey( static_cast<int>( value ) ), section );
     312                 :          0 :       }
     313                 :            :       else
     314                 :            :       {
     315                 :          0 :         QgsDebugMsg( QStringLiteral( "Invalid metaenum. Enum probably misses Q_ENUM or Q_FLAG declaration." ) );
     316                 :            :       }
     317                 :          0 :     }
     318                 :            : 
     319                 :            :     /**
     320                 :            :      * Returns the setting value for a setting based on a flag.
     321                 :            :      * This forces the output to be a valid and existing entry of the flag.
     322                 :            :      * Hence if the setting value is incorrect, the given default value is returned.
     323                 :            :      * This tries first with setting as a string (using a byte array) and then as an integer value.
     324                 :            :      * \note The flag needs to be declared with Q_FLAG (not Q_FLAGS).
     325                 :            :      * \note for Python bindings, a custom implementation is achieved in Python directly.
     326                 :            :      * \see setFlagValue
     327                 :            :      * \see enumValue
     328                 :            :      */
     329                 :            :     template <class T>
     330                 :         91 :     T flagValue( const QString &key, const T &defaultValue,
     331                 :            :                  const Section section = NoSection )
     332                 :            :     {
     333                 :         91 :       QMetaEnum metaEnum = QMetaEnum::fromType<T>();
     334                 :            :       Q_ASSERT( metaEnum.isValid() );
     335                 :         91 :       if ( !metaEnum.isValid() )
     336                 :            :       {
     337                 :          0 :         QgsDebugMsg( QStringLiteral( "Invalid metaenum. Enum probably misses Q_ENUM or Q_FLAG declaration." ) );
     338                 :          0 :       }
     339                 :            : 
     340                 :         91 :       T v = defaultValue;
     341                 :         91 :       bool ok = false;
     342                 :            : 
     343                 :         91 :       if ( metaEnum.isValid() )
     344                 :            :       {
     345                 :            :         // read as string
     346                 :         91 :         QByteArray ba = value( key, metaEnum.valueToKeys( defaultValue ) ).toString().toUtf8();
     347                 :         91 :         const char *vs = ba.data();
     348                 :         91 :         v = static_cast<T>( metaEnum.keysToValue( vs, &ok ) );
     349                 :         91 :       }
     350                 :         91 :       if ( !ok )
     351                 :            :       {
     352                 :            :         // if failed, try to read as int (old behavior)
     353                 :            :         // this code shall be removed later (probably after QGIS 3.4 LTR for 3.6)
     354                 :            :         // then the method could be marked as const
     355                 :          0 :         v = T( value( key, static_cast<int>( defaultValue ), section ).toInt( &ok ) );
     356                 :          0 :         if ( metaEnum.isValid() )
     357                 :            :         {
     358                 :          0 :           if ( !ok || metaEnum.valueToKeys( static_cast<int>( v ) ).isEmpty() )
     359                 :            :           {
     360                 :          0 :             v = defaultValue;
     361                 :          0 :           }
     362                 :            :           else
     363                 :            :           {
     364                 :            :             // found setting as an integer
     365                 :            :             // convert the setting to the new form (string)
     366                 :          0 :             setFlagValue( key, v, section );
     367                 :            :           }
     368                 :          0 :         }
     369                 :          0 :       }
     370                 :            : 
     371                 :         91 :       return v;
     372                 :          0 :     }
     373                 :            : 
     374                 :            :     /**
     375                 :            :      * Set the value of a setting based on a flaf.
     376                 :            :      * The setting will be saved as string.
     377                 :            :      * \note The flag needs to be declared with Q_FLAG (not Q_FLAGS).
     378                 :            :      * \see flagValue
     379                 :            :      * \see setEnumValue
     380                 :            :      */
     381                 :            :     template <class T>
     382                 :          0 :     void setFlagValue( const QString &key, const T &value,
     383                 :            :                        const Section section = NoSection )
     384                 :            :     {
     385                 :          0 :       QMetaEnum metaEnum = QMetaEnum::fromType<T>();
     386                 :            :       Q_ASSERT( metaEnum.isValid() );
     387                 :          0 :       if ( metaEnum.isValid() )
     388                 :            :       {
     389                 :          0 :         setValue( key, metaEnum.valueToKeys( value ), section );
     390                 :          0 :       }
     391                 :            :       else
     392                 :            :       {
     393                 :          0 :         QgsDebugMsg( QStringLiteral( "Invalid metaenum. Enum probably misses Q_ENUM or Q_FLAG declaration." ) );
     394                 :            :       }
     395                 :          0 :     }
     396                 :            : #endif
     397                 :            : 
     398                 :            :     /**
     399                 :            :      * Returns TRUE if there exists a setting called key; returns FALSE otherwise.
     400                 :            :      * If a group is set using beginGroup(), key is taken to be relative to that group.
     401                 :            :      */
     402                 :            :     bool contains( const QString &key, QgsSettings::Section section = QgsSettings::NoSection ) const;
     403                 :            :     //! Returns the path where settings written using this QSettings object are stored.
     404                 :            :     QString fileName() const;
     405                 :            : 
     406                 :            :     /**
     407                 :            :      * Writes any unsaved changes to permanent storage, and reloads any settings that have been
     408                 :            :      * changed in the meantime by another application.
     409                 :            :      * This function is called automatically from QSettings's destructor and by the event
     410                 :            :      * loop at regular intervals, so you normally don't need to call it yourself.
     411                 :            :      */
     412                 :            :     void sync();
     413                 :            :     //! Removes the setting key and any sub-settings of key in a section.
     414                 :            :     void remove( const QString &key, QgsSettings::Section section = QgsSettings::NoSection );
     415                 :            :     //! Returns the sanitized and prefixed key
     416                 :            :     QString prefixedKey( const QString &key, QgsSettings::Section section ) const;
     417                 :            :     //! Removes all entries in the user settings
     418                 :            :     void clear();
     419                 :            : 
     420                 :            :   private:
     421                 :            :     void init();
     422                 :            :     QString sanitizeKey( const QString &key ) const;
     423                 :            :     QSettings *mUserSettings = nullptr;
     424                 :            :     QSettings *mGlobalSettings = nullptr;
     425                 :            :     bool mUsingGlobalArray = false;
     426                 :            :     Q_DISABLE_COPY( QgsSettings )
     427                 :            : 
     428                 :            : };
     429                 :            : 
     430                 :            : #endif // QGSSETTINGS_H

Generated by: LCOV version 1.14