author | zecke <zecke> | 2004-07-15 17:36:57 (UTC) |
---|---|---|
committer | zecke <zecke> | 2004-07-15 17:36:57 (UTC) |
commit | 323e9a7472a110b4befba7320540263147505bae (patch) (side-by-side diff) | |
tree | 14c810bdb9c0603a30356b17b4bdf9ccb72741c6 /qmake/tools/qsettings.cpp | |
parent | aa292b322f1ecb43dd8f4e3cd295855730dd9f59 (diff) | |
download | opie-323e9a7472a110b4befba7320540263147505bae.zip opie-323e9a7472a110b4befba7320540263147505bae.tar.gz opie-323e9a7472a110b4befba7320540263147505bae.tar.bz2 |
Manually updatet to qmake1.06a which includes support for precompiled
headers.
Opies 'PRO' keyword was already reintroduced
-rw-r--r-- | qmake/tools/qsettings.cpp | 371 |
1 files changed, 191 insertions, 180 deletions
diff --git a/qmake/tools/qsettings.cpp b/qmake/tools/qsettings.cpp index 35fc039..598e94b 100644 --- a/qmake/tools/qsettings.cpp +++ b/qmake/tools/qsettings.cpp @@ -1,20 +1,20 @@ /**************************************************************************** -** $Id$ +** ** ** Implementation of QSettings class ** ** Created : 000626 ** -** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. +** Copyright (C) 2000-2003 Trolltech AS. All rights reserved. ** ** This file is part of the tools module of the Qt GUI Toolkit. ** ** This file may be distributed under the terms of the Q Public License ** as defined by Trolltech AS of Norway and appearing in the file ** LICENSE.QPL included in the packaging of this file. ** ** This file may be distributed and/or modified under the terms of the ** GNU General Public License version 2 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. ** @@ -51,25 +51,27 @@ static inline int qt_open( const char *pathname, int flags, mode_t mode ) #include "qsettings.h" #ifndef QT_NO_SETTINGS #include "qdir.h" #include "qfile.h" #include "qfileinfo.h" #include "qmap.h" #include "qtextstream.h" #include "qregexp.h" #include <private/qsettings_p.h> +#ifndef NO_ERRNO_H #include <errno.h> +#endif /*! \class QSettings \brief The QSettings class provides persistent platform-independent application settings. \ingroup io \ingroup misc \mainclass On Unix systems, QSettings uses text files to store settings. On Windows systems, QSettings uses the system registry. On Mac OS X, QSettings uses the Carbon preferences API. @@ -92,46 +94,49 @@ static inline int qt_open( const char *pathname, int flags, mode_t mode ) /MyCompany/MyApplication/background color /MyCompany/MyApplication/foreground color /MyCompany/MyApplication/geometry/x /MyCompany/MyApplication/geometry/y /MyCompany/MyApplication/geometry/width /MyCompany/MyApplication/geometry/height /MyCompany/MyApplication/recent files/1 /MyCompany/MyApplication/recent files/2 /MyCompany/MyApplication/recent files/3 \endcode Each line above is a complete key, made up of subkeys. - A typical usage pattern for reading application startup: + A typical usage pattern for reading settings at application + startup: \code QSettings settings; settings.setPath( "MyCompany.com", "MyApplication" ); QString bgColor = settings.readEntry( "/colors/background", "white" ); int width = settings.readNumEntry( "/geometry/width", 640 ); // ... \endcode - A typical usage pattern for application exit or 'save preferences': + A typical usage pattern for saving settings at application exit or + 'save preferences': \code QSettings settings; settings.setPath( "MyCompany.com", "MyApplication" ); settings.writeEntry( "/colors/background", bgColor ); settings.writeEntry( "/geometry/width", width ); // ... \endcode - QSettings can build a key prefix that is prepended to all keys. To - build the key prefix, use beginGroup() and endGroup(). + A key prefix can be prepended to all keys using beginGroup(). The + application of the prefix is stopped using endGroup(). For + example: \code QSettings settings; settings.beginGroup( "/MainWindow" ); settings.beginGroup( "/Geometry" ); int x = settings.readEntry( "/x" ); // ... settings.endGroup(); settings.beginGroup( "/Toolbars" ); // ... settings.endGroup(); settings.endGroup(); @@ -145,89 +150,90 @@ static inline int qt_open( const char *pathname, int flags, mode_t mode ) // keys contains 'background color' and 'foreground color'. QStringList keys = entryList( "/MyApplication/recent files" ); // keys contains '1', '2' and '3'. QStringList subkeys = subkeyList( "/MyApplication" ); // subkeys contains 'geometry' and 'recent files' QStringList subkeys = subkeyList( "/MyApplication/recent files" ); // subkeys is empty. \endcode - Since settings for Windows are stored in the registry there are size - limits as follows: + Since settings for Windows are stored in the registry there are + some size limitations as follows: \list \i A subkey may not exceed 255 characters. \i An entry's value may not exceed 16,300 characters. \i All the values of a key (for example, all the 'recent files' subkeys values), may not exceed 65,535 characters. \endlist These limitations are not enforced on Unix or Mac OS X. - If you wish to use a different search path call insertSearchPath() - as often as necessary to add your preferred paths. Call - removeSearchPath() to remove any unwanted paths. + \warning Creating multiple, simultaneous instances of QSettings writing + to a text file may lead to data loss! This is a known issue which will + be fixed in a future release of Qt. \section1 Notes for Mac OS X Applications - Internal to the CFPreferences API it is not defined (for Mac OS 9 - support) where the settings will ultimitely be stored. However, at the - time of this writing the settings will be stored (either on a global or - user basis, preferring locally) into a plist file in - $ROOT/System/Library/Preferences (in XML format). QSettings will create - an appropriate plist file (com.<first group name>.plist) out of the - full path to a key. + The location where settings are stored is not formally defined by + the CFPreferences API. + + At the time of writing settings are stored (either on a global or + user basis, preferring locally) into a plist file in \c + $ROOT/System/Library/Preferences (in XML format). QSettings will + create an appropriate plist file (\c{com.<first group name>.plist}) + out of the full path to a key. - For further information on CFPreferences see also - \link http://developer.apple.com/techpubs/macosx/CoreFoundation/PreferenceServices/preferenceservices_carbon.html + For further information on CFPreferences see + \link http://developer.apple.com/documentation/CoreFoundation/Conceptual/CFPreferences/index.html Apple's Specifications\endlink \section1 Notes for Unix Applications There is no universally accepted place for storing application settings under Unix. In the examples the settings file will be searched for in the following directories: \list 1 - \i INSTALL/etc/settings - \i /opt/MyCompany/share/etc - \i /opt/MyCompany/share/MyApplication/etc - \i $HOME/.qt + \i \c SYSCONF - the default value is \c INSTALL/etc/settings + \i \c /opt/MyCompany/share/etc + \i \c /opt/MyCompany/share/MyApplication/etc + \i \c $HOME/.qt \endlist When reading settings the files are searched in the order shown above, with later settings overriding earlier settings. Files for which the user doesn't have read permission are ignored. When saving settings QSettings works in the order shown above, writing to the first settings file for which the user has write permission. (\c INSTALL is the directory where Qt was installed. This can be modified by using the configure script's -prefix argument ) If you want to put the settings in a particular place in the filesystem you could do this: \code settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share" ); \endcode But in practice you may prefer not to use a search path for Unix. For example the following code: \code settings.writeEntry( "/MyApplication/geometry/width", width ); \endcode will end up writing the "geometry/width" setting to the file \c{$HOME/.qt/myapplicationrc} (assuming that the application is being run by an ordinary user, i.e. not by root). - For cross-platform applications you should ensure that the Windows - size limitations are not exceeded. + For cross-platform applications you should ensure that the + \link #sizelimit Windows size limitations \endlink are not exceeded. */ /*! \enum QSettings::System \value Mac Macintosh execution environments \value Unix Mac OS X, Unix, Linux and Unix-like execution environments \value Windows Windows execution environments */ /*! \enum QSettings::Format @@ -301,119 +307,84 @@ static void closelock( HANDLE fd ) } struct flock fl; fl.l_type = F_UNLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; // ignore the return value, so that the unlock fails silently (void) fcntl( fd, F_SETLKW, &fl ); close( fd ); } -#elif defined(Q_WS_WIN) -#define Q_LOCKREAD 1 -#define Q_LOCKWRITE 2 - -static HANDLE openlock( const QString &name, int /*type*/ ) -{ - if ( !QFile::exists( name ) ) - return 0; - - return 0; - - HANDLE fd = 0; - - QT_WA( { - fd = CreateFileW( (TCHAR*)name.ucs2(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); - } , { - fd = CreateFileA( name.local8Bit(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); - } ); - - if ( !LockFile( fd, 0, 0, (DWORD)-1, (DWORD)-1 ) ) { // ### (DWORD)-1 ??? -#ifdef QT_CHECK_STATE - qWarning( "QSettings: openlock failed!" ); -#endif - } - return fd; -} - -static void closelock( HANDLE fd ) -{ - if ( !fd ) - return; - - if ( !UnlockFile( fd, 0, 0, (DWORD)-1, (DWORD)-1 ) ) { // ### (DWORD)-1 ??? -#ifdef QT_CHECK_STATE - qWarning( "QSettings: closelock failed!"); -#endif - } - CloseHandle( fd ); -} #endif QSettingsGroup::QSettingsGroup() : modified(FALSE) { } void QSettingsHeading::read(const QString &filename) { if (! QFileInfo(filename).exists()) return; +#ifndef Q_WS_WIN HANDLE lockfd = openlock( filename, Q_LOCKREAD ); +#endif QFile file(filename); if (! file.open(IO_ReadOnly)) { #if defined(QT_CHECK_STATE) qWarning("QSettings: failed to open file '%s'", filename.latin1()); #endif return; } git = end(); QTextStream stream(&file); stream.setEncoding(QTextStream::UnicodeUTF8); while (! stream.atEnd()) parseLine(stream); git = end(); file.close(); +#ifndef Q_WS_WIN closelock( lockfd ); +#endif } void QSettingsHeading::parseLine(QTextStream &stream) { QString line = stream.readLine(); if (line.isEmpty()) // empty line... we'll allow it return; if (line[0] == QChar('#')) // commented line return; if (line[0] == QChar('[')) { QString gname = line; - gname = gname.remove(0, 1); + gname = gname.remove((uint)0, 1); if (gname[(int)gname.length() - 1] == QChar(']')) gname = gname.remove(gname.length() - 1, 1); git = find(gname); if (git == end()) git = replace(gname, QSettingsGroup()); } else { if (git == end()) { #if defined(QT_CHECK_STATE) qWarning("QSettings: line '%s' out of group", line.latin1()); #endif return; @@ -517,29 +488,25 @@ QSettingsPrivate::QSettingsPrivate( QSettings::Format format ) typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, char*, int, BOOL); GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve( "SHGetSpecialFolderPathA" ); if ( SHGetSpecialFolderPath ) { char path[MAX_PATH]; SHGetSpecialFolderPath( 0, path, CSIDL_APPDATA, FALSE ); appSettings = QString::fromLocal8Bit( path ); SHGetSpecialFolderPath( 0, path, CSIDL_COMMON_APPDATA, FALSE ); defPath = QString::fromLocal8Bit( path ); } } ); #endif // Q_OS_TEMP #else -// for now -#define QSETTINGS_DEFAULT_PATH_SUFFIX "/etc/settings" - - defPath = qInstallPath(); - defPath += QSETTINGS_DEFAULT_PATH_SUFFIX; + defPath = qInstallPathSysconf(); #endif QDir dir(appSettings); if (! dir.exists()) { if (! dir.mkdir(dir.path())) #if defined(QT_CHECK_STATE) qWarning("QSettings: error creating %s", dir.path().latin1()); #else ; #endif } if ( !!defPath ) @@ -692,45 +659,50 @@ QDateTime QSettingsPrivate::modificationTime() ++it; while (it != searchPaths.end()) { QFileInfo fi((*it++) + "/" + heading + "rc"); if (fi.exists() && fi.lastModified() > datetime) datetime = fi.lastModified(); } return datetime; } bool qt_verify_key( const QString &key ) { - if ( key.isEmpty() || key[0] != '/' || key.contains( QRegExp("[=\\\\r\\\\n" ) ) ) + if ( key.isEmpty() || key[0] != '/' || key.contains( QRegExp("[=\\r\\n]" ) ) ) return FALSE; return TRUE; } -static inline QString groupKey( const QString &group, const QString &key ) +static QString groupKey( const QString &group, const QString &key ) { + QString grp_key; if ( group.isEmpty() || ( group.length() == 1 && group[0] == '/' ) ) { // group is empty, or it contains a single '/', so we just return the key if ( key.startsWith( "/" ) ) - return key; - return "/" + key; + grp_key = key; + else + grp_key = "/" + key; } else if ( group.endsWith( "/" ) || key.startsWith( "/" ) ) { - return group + key; + grp_key = group + key; + } else { + grp_key = group + "/" + key; } - return group + "/" + key; + return grp_key; } /*! Inserts \a path into the settings search path. The semantics of \a - path depends on the system \a s. + path depends on the system \a s. It is usually easier and better to + use setPath() instead of this function. When \a s is \e Windows and the execution environment is \e not Windows the function does nothing. Similarly when \a s is \e Unix and the execution environment is \e not Unix the function does nothing. When \a s is \e Windows, and the execution environment is Windows, the search path list will be used as the first subfolder of the "Software" folder in the registry. When reading settings the folders are searched forwards from the first folder (listed below) to the last, returning the first settings found, and ignoring any folders for which the user doesn't @@ -757,74 +729,78 @@ static inline QString groupKey( const QString &group, const QString &key ) \i HKEY_CURRENT_USER/Software/MyApplication \endlist If a setting is found in the HKEY_CURRENT_USER space, this setting is overwritten independently of write permissions in the HKEY_LOCAL_MACHINE space. When \a s is \e Unix, and the execution environment is Unix, the search path list will be used when trying to determine a suitable filename for reading and writing settings files. By default, there are two entries in the search path: \list 1 - \i INSTALL/etc - where \c INSTALL is the directory where Qt was installed. - \i $HOME/.qt/ - where \c $HOME is the user's home directory. + \i \c SYSCONF - where \c SYSCONF is a directory specified when + configuring Qt; by default it is INSTALL/etc/settings. + \i \c $HOME/.qt/ - where \c $HOME is the user's home directory. \endlist All insertions into the search path will go before $HOME/.qt/. For example: \code QSettings settings; settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share/etc" ); settings.insertSearchPath( QSettings::Unix, "/opt/MyCompany/share/MyApplication/etc" ); // ... \endcode Will result in a search path of: \list 1 - \i INSTALL/etc + \i SYSCONF \i /opt/MyCompany/share/etc \i /opt/MyCompany/share/MyApplication/etc \i $HOME/.qt \endlist When reading settings the files are searched in the order shown above, with later settings overriding earlier settings. Files for which the user doesn't have read permission are ignored. When saving settings QSettings works in the order shown above, writing to the first settings file for which the user has write permission. + Note that paths in the file system are not created by this + function, so they must already exist to be useful. + Settings under Unix are stored in files whose names are based on the first subkey of the key (not including the search path). The algorithm for creating names is essentially: lowercase the first subkey, replace spaces with underscores and add 'rc', e.g. <tt>/MyCompany/MyApplication/background color</tt> will be stored in <tt>myapplicationrc</tt> (assuming that <tt>/MyCompany</tt> is part of the search path). \sa removeSearchPath() */ void QSettings::insertSearchPath( System s, const QString &path) { #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) { d->sysInsertSearchPath( s, path ); return; } #endif #if !defined(Q_WS_WIN) if ( s == Windows ) return; #endif -#if !defined(Q_WS_WIN) +#if !defined(Q_OS_MAC) if ( s == Mac ) return; #endif if ( !qt_verify_key( path ) ) { #if defined(QT_CHECK_STATE) qWarning( "QSettings::insertSearchPath: Invalid key: '%s'", path.isNull() ? "(null)" : path.latin1() ); #endif return; } #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) @@ -955,55 +931,69 @@ bool QSettings::sync() #endif if (! d->modified) // fake success return TRUE; bool success = TRUE; QMap<QString,QSettingsHeading>::Iterator it = d->headings.begin(); while (it != d->headings.end()) { // determine filename QSettingsHeading hd(*it); QSettingsHeading::Iterator hdit = hd.begin(); - QFile file; + QString filename; QStringList::Iterator pit = d->searchPaths.begin(); if ( !d->globalScope ) ++pit; while (pit != d->searchPaths.end()) { QString filebase = it.key().lower().replace(QRegExp("\\s+"), "_"); QFileInfo di(*pit); + if ( !di.exists() ) { + QDir dir; + dir.mkdir( *pit ); + } + QFileInfo fi((*pit++) + "/" + filebase + "rc"); if ((fi.exists() && fi.isFile() && fi.isWritable()) || - (! fi.exists() && di.isDir() && di.isWritable())) { - file.setName(fi.filePath()); + (! fi.exists() && di.isDir() +#ifndef Q_WS_WIN + && di.isWritable() +#else + && ((qWinVersion()&Qt::WV_NT_based) > Qt::WV_2000 || di.isWritable()) +#endif + )) { + filename = fi.filePath(); break; } } ++it; - if ( file.name().isEmpty() ) { + if ( filename.isEmpty() ) { #ifdef QT_CHECK_STATE qWarning("QSettings::sync: filename is null/empty"); #endif // QT_CHECK_STATE success = FALSE; continue; } - HANDLE lockfd = openlock( file.name(), Q_LOCKWRITE ); +#ifndef Q_WS_WIN + HANDLE lockfd = openlock( filename, Q_LOCKWRITE ); +#endif + QFile file( filename + ".tmp" ); if (! file.open(IO_WriteOnly)) { #ifdef QT_CHECK_STATE qWarning("QSettings::sync: failed to open '%s' for writing", file.name().latin1()); #endif // QT_CHECK_STATE success = FALSE; continue; } // spew to file @@ -1038,62 +1028,82 @@ bool QSettings::sync() if (file.status() != IO_Ok) { #ifdef QT_CHECK_STATE qWarning("QSettings::sync: error at end of write"); #endif // QT_CHECK_STATE success = FALSE; } file.close(); + if ( success ) { + QDir dir( QFileInfo( file ).dir( TRUE ) ); + if ( dir.exists( filename ) && !dir.remove( filename ) || + !dir.rename( file.name(), filename, TRUE ) ) { + +#ifdef QT_CHECK_STATE + qWarning( "QSettings::sync: error writing file '%s'", + QFile::encodeName( filename ).data() ); +#endif // QT_CHECK_STATE + + success = FALSE; + } + } + + // remove temporary file + file.remove(); + +#ifndef Q_WS_WIN closelock( lockfd ); +#endif } d->modified = FALSE; return success; } /*! \fn bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok ) const Reads the entry specified by \a key, and returns a bool, or the default value, \a def, if the entry couldn't be read. If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE otherwise. \sa readEntry(), readNumEntry(), readDoubleEntry(), writeEntry(), removeEntry() */ /*! \internal */ bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok ) { - if ( !qt_verify_key( key ) ) { + QString grp_key( groupKey( group(), key ) ); + if ( !qt_verify_key( grp_key ) ) { #if defined(QT_CHECK_STATE) - qWarning( "QSettings::readBoolEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); + qWarning( "QSettings::readBoolEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() ); #endif if ( ok ) *ok = FALSE; return def; } #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysReadBoolEntry( groupKey( group(), key ), def, ok ); + return d->sysReadBoolEntry( grp_key, def, ok ); #endif QString value = readEntry( key, ( def ? "true" : "false" ), ok ); if (value.lower() == "true") return TRUE; else if (value.lower() == "false") return FALSE; else if (value == "1") return TRUE; else if (value == "0") return FALSE; @@ -1114,37 +1124,38 @@ bool QSettings::readBoolEntry(const QString &key, bool def, bool *ok ) default value, \a def, if the entry couldn't be read. If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE otherwise. \sa readEntry(), readNumEntry(), readBoolEntry(), writeEntry(), removeEntry() */ /*! \internal */ double QSettings::readDoubleEntry(const QString &key, double def, bool *ok ) { - if ( !qt_verify_key( key ) ) { + QString grp_key( groupKey( group(), key ) ); + if ( !qt_verify_key( grp_key ) ) { #if defined(QT_CHECK_STATE) - qWarning( "QSettings::readDoubleEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); + qWarning( "QSettings::readDoubleEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() ); #endif if ( ok ) *ok = FALSE; return def; } #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysReadDoubleEntry( groupKey( group(), key ), def, ok ); + return d->sysReadDoubleEntry( grp_key, def, ok ); #endif QString value = readEntry( key, QString::number(def), ok ); bool conv_ok; double retval = value.toDouble( &conv_ok ); if ( conv_ok ) return retval; if ( ! value.isEmpty() ) qWarning( "QSettings::readDoubleEntry: '%s' is not a number", value.latin1() ); if ( ok ) *ok = FALSE; @@ -1159,36 +1170,37 @@ double QSettings::readDoubleEntry(const QString &key, double def, bool *ok ) default value, \a def, if the entry couldn't be read. If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE otherwise. \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry() */ /*! \internal */ int QSettings::readNumEntry(const QString &key, int def, bool *ok ) { - if ( !qt_verify_key( key ) ) { + QString grp_key( groupKey( group(), key ) ); + if ( !qt_verify_key( grp_key ) ) { #if defined(QT_CHECK_STATE) - qWarning( "QSettings::readNumEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); + qWarning( "QSettings::readNumEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() ); #endif if ( ok ) *ok = FALSE; return def; } #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysReadNumEntry( groupKey( group(), key ), def, ok ); + return d->sysReadNumEntry( grp_key, def, ok ); #endif QString value = readEntry( key, QString::number( def ), ok ); bool conv_ok; int retval = value.toInt( &conv_ok ); if ( conv_ok ) return retval; if ( ! value.isEmpty() ) qWarning( "QSettings::readNumEntry: '%s' is not a number", value.latin1() ); if ( ok ) *ok = FALSE; @@ -1203,76 +1215,76 @@ int QSettings::readNumEntry(const QString &key, int def, bool *ok ) default value, \a def, if the entry couldn't be read. If \a ok is non-null, *ok is set to TRUE if the key was read, FALSE otherwise. \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry() */ /*! \internal */ QString QSettings::readEntry(const QString &key, const QString &def, bool *ok ) { - if ( !qt_verify_key( key ) ) { + QString grp_key( groupKey( group(), key ) ); + if ( !qt_verify_key( grp_key ) ) { #if defined(QT_CHECK_STATE) - qWarning( "QSettings::readEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); + qWarning( "QSettings::readEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() ); #endif if ( ok ) *ok = FALSE; return def; } - QString theKey = groupKey( group(), key ); - #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysReadEntry( theKey, def, ok ); + return d->sysReadEntry( grp_key, def, ok ); #endif if ( ok ) // no, everything is not ok *ok = FALSE; QString realkey; - if (theKey[0] == '/') { + if (grp_key[0] == '/') { // parse our key - QStringList list(QStringList::split('/', theKey)); + QStringList list(QStringList::split('/', grp_key)); if (list.count() < 2) { #ifdef QT_CHECK_STATE - qWarning("QSettings::readEntry: invalid key '%s'", theKey.latin1()); + qWarning("QSettings::readEntry: invalid key '%s'", grp_key.latin1()); #endif // QT_CHECK_STATE if ( ok ) *ok = FALSE; return def; } if (list.count() == 2) { d->heading = list[0]; d->group = "General"; realkey = list[1]; } else { d->heading = list[0]; d->group = list[1]; // remove the group from the list list.remove(list.at(1)); // remove the heading from the list list.remove(list.at(0)); realkey = list.join("/"); } - } else - realkey = theKey; + } else { + realkey = grp_key; + } QSettingsGroup grp = d->readGroup(); QSettingsGroup::const_iterator it = grp.find( realkey ), end = grp.end(); QString retval = def; if ( it != end ) { // found the value we needed retval = *it; if ( ok ) *ok = TRUE; } return retval; } @@ -1281,248 +1293,243 @@ QString QSettings::readEntry(const QString &key, const QString &def, bool *ok ) /*! Writes the boolean entry \a value into key \a key. The \a key is created if it doesn't exist. Any previous value is overwritten by \a value. If an error occurs the settings are left unchanged and FALSE is returned; otherwise TRUE is returned. \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() */ bool QSettings::writeEntry(const QString &key, bool value) { - if ( !qt_verify_key( key ) ) { + QString grp_key( groupKey( group(), key ) ); + if ( !qt_verify_key( grp_key ) ) { #if defined(QT_CHECK_STATE) - qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); + qWarning( "QSettings::writeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() ); #endif return FALSE; } #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysWriteEntry( groupKey( group(), key ), value ); + return d->sysWriteEntry( grp_key, value ); #endif QString s(value ? "true" : "false"); return writeEntry(key, s); } #endif /*! \overload Writes the double entry \a value into key \a key. The \a key is created if it doesn't exist. Any previous value is overwritten by \a value. If an error occurs the settings are left unchanged and FALSE is returned; otherwise TRUE is returned. \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() */ bool QSettings::writeEntry(const QString &key, double value) { - if ( !qt_verify_key( key ) ) { + QString grp_key( groupKey( group(), key ) ); + if ( !qt_verify_key( grp_key ) ) { #if defined(QT_CHECK_STATE) - qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); + qWarning( "QSettings::writeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() ); #endif return FALSE; } #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysWriteEntry( groupKey( group(), key ), value ); + return d->sysWriteEntry( grp_key, value ); #endif QString s(QString::number(value)); return writeEntry(key, s); } /*! \overload Writes the integer entry \a value into key \a key. The \a key is created if it doesn't exist. Any previous value is overwritten by \a value. If an error occurs the settings are left unchanged and FALSE is returned; otherwise TRUE is returned. \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() */ bool QSettings::writeEntry(const QString &key, int value) { - if ( !qt_verify_key( key ) ) { + QString grp_key( groupKey( group(), key ) ); + if ( !qt_verify_key( grp_key ) ) { #if defined(QT_CHECK_STATE) - qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); + qWarning( "QSettings::writeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() ); #endif return FALSE; } #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysWriteEntry( groupKey( group(), key ), value ); + return d->sysWriteEntry( grp_key, value ); #endif QString s(QString::number(value)); return writeEntry(key, s); } /*! \internal Writes the entry specified by \a key with the string-literal \a value, replacing any previous setting. If \a value is zero-length or null, the entry is replaced by an empty setting. \e NOTE: This function is provided because some compilers use the writeEntry (const QString &, bool) overload for this code: writeEntry ("/foo/bar", "baz") If an error occurs, this functions returns FALSE and the object is left unchanged. \sa readEntry(), removeEntry() */ bool QSettings::writeEntry(const QString &key, const char *value) { - if ( !qt_verify_key( key ) ) { -#if defined(QT_CHECK_STATE) - qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); -#endif - return FALSE; - } - return writeEntry(key, QString(value)); } /*! \overload Writes the string entry \a value into key \a key. The \a key is created if it doesn't exist. Any previous value is overwritten by \a value. If \a value is an empty string or a null string the key's value will be an empty string. If an error occurs the settings are left unchanged and FALSE is returned; otherwise TRUE is returned. \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() */ bool QSettings::writeEntry(const QString &key, const QString &value) { - if ( !qt_verify_key( key ) ) { + QString grp_key( groupKey( group(), key ) ); + if ( !qt_verify_key( grp_key ) ) { #if defined(QT_CHECK_STATE) - qWarning( "QSettings::writeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); + qWarning( "QSettings::writeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() ); #endif return FALSE; } - QString theKey = groupKey( group(), key ); - #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysWriteEntry( theKey, value ); + return d->sysWriteEntry( grp_key, value ); #endif // NOTE: we *do* allow value to be a null/empty string QString realkey; - if (theKey[0] == '/') { + if (grp_key[0] == '/') { // parse our key - QStringList list(QStringList::split('/', theKey)); + QStringList list(QStringList::split('/', grp_key)); if (list.count() < 2) { #ifdef QT_CHECK_STATE - qWarning("QSettings::writeEntry: invalid key '%s'", theKey.latin1()); + qWarning("QSettings::writeEntry: invalid key '%s'", grp_key.latin1()); #endif // QT_CHECK_STATE return FALSE; } if (list.count() == 2) { d->heading = list[0]; d->group = "General"; realkey = list[1]; } else { d->heading = list[0]; d->group = list[1]; // remove the group from the list list.remove(list.at(1)); // remove the heading from the list list.remove(list.at(0)); realkey = list.join("/"); } - } else - realkey = theKey; + } else { + realkey = grp_key; + } d->writeGroup(realkey, value); return TRUE; } /*! Removes the entry specified by \a key. Returns TRUE if the entry existed and was removed; otherwise returns FALSE. \sa readEntry(), writeEntry() */ bool QSettings::removeEntry(const QString &key) { - if ( !qt_verify_key( key ) ) { + QString grp_key( groupKey( group(), key ) ); + if ( !qt_verify_key( grp_key ) ) { #if defined(QT_CHECK_STATE) - qWarning( "QSettings::removeEntry: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); + qWarning( "QSettings::removeEntry: Invalid key: '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() ); #endif return FALSE; } - QString theKey = groupKey( group(), key ); - #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysRemoveEntry( theKey ); + return d->sysRemoveEntry( grp_key ); #endif QString realkey; - - if (theKey[0] == '/') { + if (grp_key[0] == '/') { // parse our key - QStringList list(QStringList::split('/', theKey)); + QStringList list(QStringList::split('/', grp_key)); if (list.count() < 2) { #ifdef QT_CHECK_STATE - qWarning("QSettings::removeEntry: invalid key '%s'", theKey.latin1()); + qWarning("QSettings::removeEntry: invalid key '%s'", grp_key.latin1()); #endif // QT_CHECK_STATE return FALSE; } if (list.count() == 2) { d->heading = list[0]; d->group = "General"; realkey = list[1]; } else { d->heading = list[0]; d->group = list[1]; // remove the group from the list list.remove(list.at(1)); // remove the heading from the list list.remove(list.at(0)); realkey = list.join("/"); } - } else - realkey = theKey; + } else { + realkey = grp_key; + } d->removeGroup(realkey); return TRUE; } /*! Returns a list of the keys which contain entries under \a key. Does \e not return any keys that contain keys. Example settings: \code @@ -1539,67 +1546,66 @@ bool QSettings::removeEntry(const QString &key) \c keys contains 'background color' and 'foreground color'. It does not contain 'geometry' because this key contains keys not entries. To access the geometry values could either use subkeyList() to read the keys and then read each entry, or simply read each entry directly by specifying its full key, e.g. "/MyCompany/MyApplication/geometry/y". \sa subkeyList() */ QStringList QSettings::entryList(const QString &key) const { - if ( !qt_verify_key( key ) ) { + QString grp_key( groupKey( group(), key ) ); + if ( !qt_verify_key( grp_key ) ) { #if defined(QT_CHECK_STATE) - qWarning( "QSettings::entryList: Invalid key: %s", key.isNull() ? "(null)" : key.latin1() ); + qWarning( "QSettings::entryList: Invalid key: %s", grp_key.isNull() ? "(null)" : grp_key.latin1() ); #endif return QStringList(); } - QString theKey = groupKey( group(), key ); - #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysEntryList( theKey ); + return d->sysEntryList( grp_key ); #endif QString realkey; - if (theKey[0] == '/') { + if (grp_key[0] == '/') { // parse our key - QStringList list(QStringList::split('/', theKey)); + QStringList list(QStringList::split('/', grp_key)); if (list.count() < 1) { #ifdef QT_CHECK_STATE - qWarning("QSettings::listEntries: invalid key '%s'", theKey.latin1()); + qWarning("QSettings::listEntries: invalid key '%s'", grp_key.latin1()); #endif // QT_CHECK_STATE return QStringList(); } if (list.count() == 1) { d->heading = list[0]; d->group = "General"; } else { d->heading = list[0]; d->group = list[1]; // remove the group from the list list.remove(list.at(1)); // remove the heading from the list list.remove(list.at(0)); realkey = list.join("/"); } } else - realkey = theKey; + realkey = grp_key; QSettingsGroup grp = d->readGroup(); QSettingsGroup::Iterator it = grp.begin(); QStringList ret; QString itkey; while (it != grp.end()) { itkey = it.key(); ++it; if ( realkey.length() > 0 ) { if ( itkey.left( realkey.length() ) != realkey ) continue; @@ -1636,71 +1642,70 @@ QStringList QSettings::entryList(const QString &key) const \code QStringList keys = subkeyList( "/MyCompany/MyApplication" ); \endcode \c keys contains 'geometry' and 'recent files'. It does not contain 'background color' or 'foreground color' because they are keys which contain entries not keys. To get a list of keys that have values rather than subkeys use entryList(). \sa entryList() */ QStringList QSettings::subkeyList(const QString &key) const { - if ( !qt_verify_key( key ) ) { + QString grp_key( groupKey( group(), key ) ); + if ( !qt_verify_key( grp_key ) ) { #if defined(QT_CHECK_STATE) - qWarning( "QSettings::subkeyList: Invalid key: %s", key.isNull() ? "(null)" : key.latin1() ); + qWarning( "QSettings::subkeyList: Invalid key: %s", grp_key.isNull() ? "(null)" : grp_key.latin1() ); #endif return QStringList(); } - QString theKey = groupKey( group(), key ); - #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) - return d->sysSubkeyList( theKey ); + return d->sysSubkeyList( grp_key ); #endif QString realkey; int subkeycount = 2; - if (theKey[0] == '/') { + if (grp_key[0] == '/') { // parse our key - QStringList list(QStringList::split('/', theKey)); + QStringList list(QStringList::split('/', grp_key)); if (list.count() < 1) { #ifdef QT_CHECK_STATE - qWarning("QSettings::subkeyList: invalid key '%s'", theKey.latin1()); + qWarning("QSettings::subkeyList: invalid key '%s'", grp_key.latin1()); #endif // QT_CHECK_STATE return QStringList(); } subkeycount = list.count(); if (list.count() == 1) { d->heading = list[0]; d->group = "General"; } else { d->heading = list[0]; d->group = list[1]; // remove the group from the list list.remove(list.at(1)); // remove the heading from the list list.remove(list.at(0)); realkey = list.join("/"); } } else - realkey = theKey; + realkey = grp_key; QStringList ret; if ( subkeycount == 1 ) { QMap<QString,QSettingsHeading>::Iterator it = d->headings.begin(); while ( it != d->headings.end() ) { if ( it.key() != "General" && ! ret.contains( it.key() ) ) ret << it.key(); ++it; } return ret; } @@ -1728,87 +1733,88 @@ QStringList QSettings::subkeyList(const QString &key) const ret << itkey; } return ret; } /*! \internal This function returns the time of last modification for \a key. */ -QDateTime QSettings::lastModficationTime(const QString &key) +QDateTime QSettings::lastModificationTime( const QString &key ) { - if ( !qt_verify_key( key ) ) { + QString grp_key( groupKey( group(), key ) ); + if ( !qt_verify_key( grp_key ) ) { #if defined(QT_CHECK_STATE) - qWarning( "QSettings::lastModficationTime: Invalid key: '%s'", key.isNull() ? "(null)" : key.latin1() ); + qWarning( "QSettings::lastModificationTime: Invalid key '%s'", grp_key.isNull() ? "(null)" : grp_key.latin1() ); #endif return QDateTime(); } - QString theKey = groupKey( group(), key ); - #if !defined(QWS) && (defined(Q_WS_WIN) || defined(Q_OS_MAC)) if ( d->sysd ) return QDateTime(); #endif - if (theKey[0] == '/') { + if (grp_key[0] == '/') { // parse our key - QStringList list(QStringList::split('/', theKey)); + QStringList list(QStringList::split('/', grp_key)); if (list.count() < 2) { #ifdef QT_CHECK_STATE - qWarning("QSettings::lastModficationTime: invalid key '%s'", theKey.latin1()); + qWarning("QSettings::lastModificationTime: Invalid key '%s'", grp_key.latin1()); #endif // QT_CHECK_STATE return QDateTime(); } if (list.count() == 2) { d->heading = list[0]; d->group = "General"; } else { d->heading = list[0]; d->group = list[1]; } } return d->modificationTime(); } /*! \overload + \obsolete Writes the string list entry \a value into key \a key. The \a key is created if it doesn't exist. Any previous value is overwritten by \a value. The list is stored as a sequence of strings separated by \a separator (using QStringList::join()), so none of the strings in the list should contain the separator. If the list is empty or null the key's value will be an empty string. \warning The list should not contain empty or null strings, as readListEntry() will use QStringList::split() to recreate the list. As the documentation states, QStringList::split() will omit empty strings from the list. Because of this, it is impossible to retrieve identical list data that is stored with this function. We recommend using the writeEntry() and readListEntry() overloads that do not take a \a separator argument. + If an error occurs the settings are left unchanged and FALSE is returned; otherwise returns TRUE. - \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry() + \sa readListEntry(), readNumEntry(), readDoubleEntry(), readBoolEntry(), removeEntry(), QStringList::join() */ bool QSettings::writeEntry(const QString &key, const QStringList &value, const QChar &separator) { QString s(value.join(separator)); return writeEntry(key, s); } /*! \overload Writes the string list entry \a value into key \a key. The \a key @@ -1830,37 +1836,37 @@ bool QSettings::writeEntry(const QString &key, const QStringList &value) } else { el.replace("^", "^^"); } s+=el; s+="^e"; // end of element } return writeEntry(key, s); } /*! \overload QStringList QSettings::readListEntry(const QString &key, const QChar &separator, bool *ok ) const + \obsolete Reads the entry specified by \a key as a string. The \a separator is used to create a QStringList by calling QStringList::split(\a - separator, entry). If \a ok is not 0: \a *ok is set to TRUE if the - key was read, otherwise \a *ok is set to FALSE. + separator, entry). If \a ok is not 0: \a *ok is set to TRUE + if the key was read, otherwise \a *ok is set to FALSE. \warning As the documentation states, QStringList::split() will omit empty strings from the list. Because of this, it is impossible to retrieve identical list data with this function. We recommend using the readListEntry() and writeEntry() overloads that do not take a \a separator argument. - Note that if you want to iterate over the list, you should iterate over a copy, e.g. \code QStringList list = mySettings.readListEntry( "size", " " ); QStringList::Iterator it = list.begin(); while( it != list.end() ) { myProcessing( *it ); ++it; } \endcode \sa readEntry(), readDoubleEntry(), readBoolEntry(), writeEntry(), removeEntry(), QStringList::split() @@ -1940,26 +1946,25 @@ void qt_setSettingsBasePath(const QString &); //qsettings_mac.cpp The \a domain should be an Internet domain name controlled by the producer of the software, eg. Trolltech products use "trolltech.com". The \a product should be the official name of the product. The \a scope should be QSettings::User for user-specific settings, or QSettings::Global for system-wide settings (generally these will be read-only to many users). - Not all information is relevant on all systems (e.g. scoping is - currently used only if QSettings accesses the Windows registry). + Not all information is relevant on all systems. */ void QSettings::setPath( const QString &domain, const QString &product, Scope scope ) { // On Windows, any trailing ".com(\..*)" is stripped from the domain. The // Global scope corresponds to HKEY_LOCAL_MACHINE, and User corresponds to // HKEY_CURRENT_USER. Note that on some installations, not all users can // write to the Global scope. On UNIX, any trailing ".com(\..*)" is stripped // from the domain. The Global scope corresponds to "/opt" (this would be // configurable at library build time - eg. to "/usr/local" or "/usr"), // while the User scope corresponds to $HOME/.*rc. // Note that on most installations, not all users can write to the System @@ -1971,31 +1976,37 @@ void QSettings::setPath( const QString &domain, const QString &product, Scope sc // User scope corresponds to ~/Library/Preferences/*.plist. // Note that on most installations, not all users can write to the System // scope. d->globalScope = scope == Global; QString actualSearchPath; int lastDot = domain.findRev( '.' ); #if defined(Q_WS_WIN) actualSearchPath = "/" + domain.mid( 0, lastDot ) + "/" + product; insertSearchPath( Windows, actualSearchPath ); #elif !defined(QWS) && defined(Q_OS_MAC) - QString topLevelDomain = domain.right( domain.length() - lastDot - 1 ) + "."; - if ( !topLevelDomain.isEmpty() ) - qt_setSettingsBasePath( topLevelDomain ); - actualSearchPath = "/" + domain.left( lastDot ) + product; + if(lastDot != -1) { + QString topLevelDomain = domain.right( domain.length() - lastDot - 1 ) + "."; + if ( !topLevelDomain.isEmpty() ) + qt_setSettingsBasePath( topLevelDomain ); + } + actualSearchPath = "/" + domain.left( lastDot ) + "." + product; insertSearchPath( Mac, actualSearchPath ); #else - actualSearchPath = "/" + domain.mid( 0, lastDot ) + "/" + product; + if (scope == User) + actualSearchPath = QDir::homeDirPath() + "/."; + else + actualSearchPath = QString(qInstallPathSysconf()) + "/"; + actualSearchPath += domain.mid( 0, lastDot ) + "/" + product; insertSearchPath( Unix, actualSearchPath ); #endif } /*! Appends \a group to the current key prefix. \code QSettings settings; settings.beginGroup( "/MainWindow" ); // read values settings.endGroup(); |