diff options
Diffstat (limited to 'src/corelib/io')
23 files changed, 411 insertions, 560 deletions
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index b2bcbdf727..218fb5b078 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -149,25 +149,15 @@ win32 { } freebsd: LIBS_PRIVATE += -lutil # qlockfile_unix.cpp requires this mac { + SOURCES += io/qstorageinfo_mac.cpp + OBJECTIVE_SOURCES += io/qstandardpaths_mac.mm osx { OBJECTIVE_SOURCES += io/qfilesystemwatcher_fsevents.mm HEADERS += io/qfilesystemwatcher_fsevents_p.h - } - macx { - SOURCES += io/qstorageinfo_mac.cpp - OBJECTIVE_SOURCES += io/qstandardpaths_mac.mm LIBS += -framework DiskArbitration -framework IOKit } else:ios { - OBJECTIVE_SOURCES += io/qstandardpaths_ios.mm - SOURCES += io/qstorageinfo_mac.cpp LIBS += -framework MobileCoreServices - } else { - SOURCES += io/qstandardpaths_unix.cpp } - } else:blackberry { - SOURCES += \ - io/qstandardpaths_blackberry.cpp \ - io/qstorageinfo_unix.cpp } else:android:!android-no-sdk { SOURCES += \ io/qstandardpaths_android.cpp \ diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index 675178ea80..c32df4c8a6 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -527,6 +527,7 @@ void QDataStream::setByteOrder(ByteOrder bo) \value Qt_5_4 Version 16 (Qt 5.4) \value Qt_5_5 Same as Qt_5_4 \value Qt_5_6 Version 17 (Qt 5.6) + \value Qt_5_7 Same as Qt_5_6 \omitvalue Qt_DefaultCompiledVersion \sa setVersion(), version() diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index 5730c12907..744829c659 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -84,10 +84,11 @@ public: Qt_5_4 = 16, Qt_5_5 = Qt_5_4, Qt_5_6 = 17, -#if QT_VERSION >= 0x050700 + Qt_5_7 = Qt_5_6, +#if QT_VERSION >= 0x050800 #error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion #endif - Qt_DefaultCompiledVersion = Qt_5_6 + Qt_DefaultCompiledVersion = Qt_5_7 }; enum ByteOrder { diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index 81af96b96b..4f85ceb084 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -704,6 +704,15 @@ QDebug &QDebug::resetFormat() */ /*! + \fn QDebug operator<<(QDebug stream, const std::list<T, Alloc> &list) + \relates QDebug + \since 5.7 + + Writes the contents of \a list to \a stream. \c T needs to + support streaming into QDebug. +*/ + +/*! \fn QDebug operator<<(QDebug stream, const QVector<T> &vector) \relates QDebug @@ -712,6 +721,15 @@ QDebug &QDebug::resetFormat() */ /*! + \fn QDebug operator<<(QDebug stream, const std::vector<T, Alloc> &vector) + \relates QDebug + \since 5.7 + + Writes the contents of \a vector to \a stream. \c T needs to + support streaming into QDebug. +*/ + +/*! \fn QDebug operator<<(QDebug stream, const QSet<T> &set) \relates QDebug @@ -728,6 +746,24 @@ QDebug &QDebug::resetFormat() */ /*! + \fn QDebug operator<<(QDebug stream, const std::map<Key, T, Compare, Alloc> &map) + \relates QDebug + \since 5.7 + + Writes the contents of \a map to \a stream. Both \c Key and + \c T need to support streaming into QDebug. +*/ + +/*! + \fn QDebug operator<<(QDebug stream, const std::multimap<Key, T, Compare, Alloc> &map) + \relates QDebug + \since 5.7 + + Writes the contents of \a map to \a stream. Both \c Key and + \c T need to support streaming into QDebug. +*/ + +/*! \fn QDebug operator<<(QDebug stream, const QHash<Key, T> &hash) \relates QDebug @@ -831,6 +867,19 @@ QDebugStateSaver::~QDebugStateSaver() d->restoreState(); } +/*! + \internal + + Specialization of the primary template in qdebug.h to out-of-line + the common case of QFlags<T>::Int being int. + + Just call the generic version so the two don't get out of sync. +*/ +void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, int value) +{ + qt_QMetaEnum_flagDebugOperator<int>(debug, sizeofT, value); +} + #ifndef QT_NO_QOBJECT /*! \internal diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index b1a0396f35..858231e118 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -45,6 +45,12 @@ #include <QtCore/qset.h> #include <QtCore/qcontiguouscache.h> +// all these have already been included by various headers above, but don't rely on indirect includes: +#include <vector> +#include <list> +#include <map> +#include <utility> + QT_BEGIN_NAMESPACE @@ -192,28 +198,63 @@ inline QDebug &QDebug::operator=(const QDebug &other) return *this; } -template <class T> -inline QDebug operator<<(QDebug debug, const QList<T> &list) +namespace QtPrivate { + +template <typename SequentialContainer> +inline QDebug printSequentialContainer(QDebug debug, const char *which, const SequentialContainer &c) { const bool oldSetting = debug.autoInsertSpaces(); - debug.nospace() << '('; - for (typename QList<T>::size_type i = 0; i < list.count(); ++i) { - if (i) - debug << ", "; - debug << list.at(i); + debug.nospace() << which << '('; + typename SequentialContainer::const_iterator it = c.begin(), end = c.end(); + if (it != end) { + debug << *it; + ++it; + } + while (it != end) { + debug << ", " << *it; + ++it; } debug << ')'; debug.setAutoInsertSpaces(oldSetting); return debug.maybeSpace(); } +} // namespace QtPrivate + +template <class T> +inline QDebug operator<<(QDebug debug, const QList<T> &list) +{ + return QtPrivate::printSequentialContainer(debug, "" /*for historical reasons*/, list); +} + template <typename T> inline QDebug operator<<(QDebug debug, const QVector<T> &vec) { - const bool oldSetting = debug.autoInsertSpaces(); - debug.nospace() << "QVector"; - debug.setAutoInsertSpaces(oldSetting); - return operator<<(debug, vec.toList()); + return QtPrivate::printSequentialContainer(debug, "QVector", vec); +} + +template <typename T, typename Alloc> +inline QDebug operator<<(QDebug debug, const std::vector<T, Alloc> &vec) +{ + return QtPrivate::printSequentialContainer(debug, "std::vector", vec); +} + +template <typename T, typename Alloc> +inline QDebug operator<<(QDebug debug, const std::list<T, Alloc> &vec) +{ + return QtPrivate::printSequentialContainer(debug, "std::list", vec); +} + +template <typename Key, typename T, typename Compare, typename Alloc> +inline QDebug operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map) +{ + return QtPrivate::printSequentialContainer(debug, "std::map", map); // yes, sequential: *it is std::pair +} + +template <typename Key, typename T, typename Compare, typename Alloc> +inline QDebug operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map) +{ + return QtPrivate::printSequentialContainer(debug, "std::multimap", map); // yes, sequential: *it is std::pair } template <class Key, class T> @@ -252,13 +293,19 @@ inline QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair) return debug.maybeSpace(); } -template <typename T> -inline QDebug operator<<(QDebug debug, const QSet<T> &set) +template <class T1, class T2> +inline QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair) { const bool oldSetting = debug.autoInsertSpaces(); - debug.nospace() << "QSet"; + debug.nospace() << "std::pair(" << pair.first << ',' << pair.second << ')'; debug.setAutoInsertSpaces(oldSetting); - return operator<<(debug, set.toList()); + return debug.maybeSpace(); +} + +template <typename T> +inline QDebug operator<<(QDebug debug, const QSet<T> &set) +{ + return QtPrivate::printSequentialContainer(debug, "QSet", set); } template <class T> @@ -276,6 +323,27 @@ inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache) return debug.maybeSpace(); } +Q_CORE_EXPORT void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, int value); + +template <typename Int> +void qt_QMetaEnum_flagDebugOperator(QDebug &debug, size_t sizeofT, Int value) +{ + const QDebugStateSaver saver(debug); + debug.resetFormat(); + debug.nospace() << "QFlags(" << hex << showbase; + bool needSeparator = false; + for (uint i = 0; i < sizeofT * 8; ++i) { + if (value & (Int(1) << i)) { + if (needSeparator) + debug << '|'; + else + needSeparator = true; + debug << (Int(1) << i); + } + } + debug << ')'; +} + #if !defined(QT_NO_QOBJECT) && !defined(Q_QDOC) Q_CORE_EXPORT QDebug qt_QMetaEnum_debugOperator(QDebug&, int value, const QMetaObject *meta, const char *name); Q_CORE_EXPORT QDebug qt_QMetaEnum_flagDebugOperator(QDebug &dbg, quint64 value, const QMetaObject *meta, const char *name); @@ -310,20 +378,7 @@ template <class T> inline QDebug qt_QMetaEnum_flagDebugOperator_helper(QDebug debug, const QFlags<T> &flags) #endif { - QDebugStateSaver saver(debug); - debug.resetFormat(); - debug.nospace() << "QFlags(" << hex << showbase; - bool needSeparator = false; - for (uint i = 0; i < sizeof(T) * 8; ++i) { - if (flags.testFlag(T(1 << i))) { - if (needSeparator) - debug << '|'; - else - needSeparator = true; - debug << (typename QFlags<T>::Int(1) << i); - } - } - debug << ')'; + qt_QMetaEnum_flagDebugOperator(debug, sizeof(T), typename QFlags<T>::Int(flags)); return debug; } diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index ce1684a943..2f3525bbdb 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -232,7 +232,7 @@ QFile::QFile(QFilePrivate &dd) } #else /*! - \internal + Constructs a QFile object. */ QFile::QFile() : QFileDevice(*new QFilePrivate, 0) diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp index 85d9b0bfcb..32b98e32d8 100644 --- a/src/corelib/io/qfileselector.cpp +++ b/src/corelib/io/qfileselector.cpp @@ -92,8 +92,6 @@ QFileSelectorPrivate::QFileSelectorPrivate() QString defaultsPath = "data/defaults.conf"; #if defined(Q_OS_ANDROID) defaultsPath = "data/android/defaults.conf"; -#elif defined(Q_OS_BLACKBERRY) - defaultsPath = "data/blackberry/defaults.conf"; #elif defined(Q_OS_IOS) defaultsPath = "data/ios/defaults.conf"; #endif @@ -116,7 +114,6 @@ QFileSelectorPrivate::QFileSelectorPrivate() \code data/defaults.conf data/+android/defaults.conf - data/+blackberry/defaults.conf data/+ios/+en_GB/defaults.conf \endcode @@ -127,9 +124,8 @@ QFileSelectorPrivate::QFileSelectorPrivate() \code images/background.png images/+android/+en_GB/background.png - images/+blackberry/+en_GB/background.png \endcode - With those files available, you would select a different file on android and blackberry platforms, + With those files available, you would select a different file on the android platform, but only if the locale was en_GB. QFileSelector will not attempt to select if the base file does not exist. For error handling in @@ -145,8 +141,8 @@ QFileSelectorPrivate::QFileSelectorPrivate() Selectors normally available are \list \li platform, any of the following strings which match the platform the application is running - on (list not exhaustive): android, blackberry, ios, osx, darwin, mac, linux, wince, unix, - windows. On Linux, if it can be determined, the name of the distribution too, like debian, + on (list not exhaustive): android, ios, osx, darwin, mac, linux, wince, unix, windows. + On Linux, if it can be determined, the name of the distribution too, like debian, fedora or opensuse. \li locale, same as QLocale().name(). \endlist @@ -368,8 +364,8 @@ QStringList QFileSelectorPrivate::platformSelectors() # endif #elif defined(Q_OS_UNIX) ret << QStringLiteral("unix"); -# if !defined(Q_OS_ANDROID) && !defined(Q_OS_BLACKBERRY) - // we don't want "linux" for Android or "qnx" for Blackberry here +# if !defined(Q_OS_ANDROID) + // we don't want "linux" for Android ret << QSysInfo::kernelType(); # ifdef Q_OS_MAC ret << QStringLiteral("mac"); // compatibility, since kernelType() is "darwin" @@ -377,7 +373,7 @@ QStringList QFileSelectorPrivate::platformSelectors() # endif QString productName = QSysInfo::productType(); if (productName != QLatin1String("unknown")) - ret << productName; // "opensuse", "fedora", "osx", "ios", "blackberry", "android" + ret << productName; // "opensuse", "fedora", "osx", "ios", "android" #endif return ret; } diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 7bc2293b0d..8f6d9911e8 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -345,17 +345,17 @@ QString QFileSystemEngine::resolveUserName(uint userId) QVarLengthArray<char, 1024> buf(size_max); #endif - struct passwd *pw = 0; #if !defined(Q_OS_INTEGRITY) + struct passwd *pw = 0; #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) struct passwd entry; getpwuid_r(userId, &entry, buf.data(), buf.size(), &pw); #else pw = getpwuid(userId); #endif -#endif if (pw) return QFile::decodeName(QByteArray(pw->pw_name)); +#endif return QString(); } @@ -369,8 +369,8 @@ QString QFileSystemEngine::resolveGroupName(uint groupId) QVarLengthArray<char, 1024> buf(size_max); #endif - struct group *gr = 0; #if !defined(Q_OS_INTEGRITY) + struct group *gr = 0; #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) size_max = sysconf(_SC_GETGR_R_SIZE_MAX); if (size_max == -1) @@ -390,9 +390,9 @@ QString QFileSystemEngine::resolveGroupName(uint groupId) #else gr = getgrgid(groupId); #endif -#endif if (gr) return QFile::decodeName(QByteArray(gr->gr_name)); +#endif return QString(); } @@ -694,16 +694,6 @@ QString QFileSystemEngine::tempPath() { #ifdef QT_UNIX_TEMP_PATH_OVERRIDE return QLatin1String(QT_UNIX_TEMP_PATH_OVERRIDE); -#elif defined(Q_OS_BLACKBERRY) - QString temp = QFile::decodeName(qgetenv("TEMP")); - if (temp.isEmpty()) - temp = QFile::decodeName(qgetenv("TMPDIR")); - - if (temp.isEmpty()) { - qWarning("Neither the TEMP nor the TMPDIR environment variable is set, falling back to /var/tmp."); - temp = QLatin1String("/var/tmp"); - } - return QDir::cleanPath(temp); #else QString temp = QFile::decodeName(qgetenv("TMPDIR")); if (temp.isEmpty()) diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp index 8bc06cfcbe..5e9e19aab1 100644 --- a/src/corelib/io/qfilesystemwatcher_inotify.cpp +++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp @@ -37,6 +37,7 @@ #ifndef QT_NO_FILESYSTEMWATCHER #include "private/qcore_unix_p.h" +#include "private/qsystemerror_p.h" #include <qdebug.h> #include <qfile.h> @@ -287,7 +288,7 @@ QStringList QInotifyFileSystemWatcherEngine::addPaths(const QStringList &paths, | IN_DELETE_SELF ))); if (wd < 0) { - perror("QInotifyFileSystemWatcherEngine::addPaths: inotify_add_watch failed"); + qWarning().nospace() << "inotify_add_watch(" << path << ") failed: " << QSystemError(errno, QSystemError::NativeError).toString(); continue; } diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 3c7a7d69e4..64078b5c54 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -670,7 +670,7 @@ bool QIODevice::seek(qint64 pos) // operation will then refill the buffer. We can optimize this, if we // find that seeking backwards becomes a significant performance hit. d->buffer.clear(); - else if (!d->buffer.isEmpty()) + else d->buffer.skip(offset); #if defined QIODEVICE_DEBUG diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 365f3e07ab..d7a4a70da7 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -44,7 +44,10 @@ #include "private/qabstractfileengine_p.h" #include "private/qtemporaryfile_p.h" +#if !defined(Q_OS_INTEGRITY) #include <sys/file.h> // flock +#endif + #include <sys/types.h> // kill #include <signal.h> // kill #include <unistd.h> // gethostname diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index d3f251c399..af88d07a7a 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -385,11 +385,6 @@ public: void cleanup(); void setError(QProcess::ProcessError error, const QString &description = QString()); void setErrorAndEmit(QProcess::ProcessError error, const QString &description = QString()); - -#ifdef Q_OS_BLACKBERRY - QList<QSocketNotifier *> defaultNotifiers() const; -#endif // Q_OS_BLACKBERRY - }; QT_END_NAMESPACE diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index a5488f48cc..9a25f56c5f 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -560,7 +560,7 @@ static int doSpawn(pid_t *ppid, const posix_spawn_file_actions_t *file_actions, qWarning("ThreadCtl(): failed to chdir to %s", oldWorkingDir); # ifdef Q_OS_QNX - if (ThreadCtl(_NTO_TCTL_THREADS_CONT, 0) == -1) + if (Q_UNLIKELY(ThreadCtl(_NTO_TCTL_THREADS_CONT, 0) == -1)) qFatal("ThreadCtl(): cannot resume threads: %s", qPrintable(qt_error_string(errno))); # endif } @@ -672,6 +672,7 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv qt_safe_close(childStartedPipe[0]); // enter the working directory + const char *callthatfailed = "chdir: "; if (workingDir && QT_CHDIR(workingDir) == -1) { // failed, stop the process goto report_errno; @@ -683,6 +684,7 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv // execute the process if (!envp) { qt_safe_execvp(argv[0], argv); + callthatfailed = "execvp: "; } else { if (path) { char **arg = path; @@ -700,15 +702,19 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv #endif qt_safe_execve(argv[0], argv, envp); } + callthatfailed = "execve: "; } // notify failure + // we're running in the child process, so we don't need to be thread-safe; + // we can use strerror report_errno: - QString error = qt_error_string(errno); + const char *msg = strerror(errno); #if defined (QPROCESS_DEBUG) - fprintf(stderr, "QProcessPrivate::execChild() failed (%s), notifying parent process\n", qPrintable(error)); + fprintf(stderr, "QProcessPrivate::execChild() failed (%s), notifying parent process\n", msg); #endif - qt_safe_write(childStartedPipe[1], error.data(), error.length() * sizeof(QChar)); + qt_safe_write(childStartedPipe[1], callthatfailed, strlen(callthatfailed)); + qt_safe_write(childStartedPipe[1], msg, strlen(msg)); qt_safe_close(childStartedPipe[1]); childStartedPipe[1] = -1; } @@ -716,8 +722,15 @@ report_errno: bool QProcessPrivate::processStarted(QString *errorMessage) { - ushort buf[errorBufferMax]; - int i = qt_safe_read(childStartedPipe[0], &buf, sizeof buf); + char buf[errorBufferMax]; + int i = 0; + int ret; + do { + ret = qt_safe_read(childStartedPipe[0], buf + i, sizeof buf - i); + if (ret > 0) + i += ret; + } while (ret > 0 && i < int(sizeof buf)); + if (startupSocketNotifier) { startupSocketNotifier->setEnabled(false); startupSocketNotifier->deleteLater(); @@ -732,7 +745,7 @@ bool QProcessPrivate::processStarted(QString *errorMessage) // did we read an error message? if ((i > 0) && errorMessage) - *errorMessage = QString((const QChar *)buf, i / sizeof(QChar)); + *errorMessage = QString::fromLocal8Bit(buf, i); return i <= 0; } @@ -826,17 +839,6 @@ bool QProcessPrivate::waitForStarted(int msecs) return startedEmitted; } -#ifdef Q_OS_BLACKBERRY -QList<QSocketNotifier *> QProcessPrivate::defaultNotifiers() const -{ - QList<QSocketNotifier *> notifiers; - notifiers << stdoutChannel.notifier - << stderrChannel.notifier - << stdinChannel.notifier; - return notifiers; -} -#endif // Q_OS_BLACKBERRY - bool QProcessPrivate::waitForReadyRead(int msecs) { #if defined (QPROCESS_DEBUG) @@ -846,10 +848,6 @@ bool QProcessPrivate::waitForReadyRead(int msecs) QElapsedTimer stopWatch; stopWatch.start(); -#ifdef Q_OS_BLACKBERRY - QList<QSocketNotifier *> notifiers = defaultNotifiers(); -#endif - forever { fd_set fdread; fd_set fdwrite; @@ -872,11 +870,8 @@ bool QProcessPrivate::waitForReadyRead(int msecs) add_fd(nfds, stdinChannel.pipe[1], &fdwrite); int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed()); -#ifdef Q_OS_BLACKBERRY - int ret = bb_select(notifiers, nfds + 1, &fdread, &fdwrite, timeout); -#else int ret = qt_select_msecs(nfds + 1, &fdread, &fdwrite, timeout); -#endif + if (ret < 0) { break; } @@ -924,10 +919,6 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) QElapsedTimer stopWatch; stopWatch.start(); -#ifdef Q_OS_BLACKBERRY - QList<QSocketNotifier *> notifiers = defaultNotifiers(); -#endif - while (!stdinChannel.buffer.isEmpty()) { fd_set fdread; fd_set fdwrite; @@ -951,11 +942,8 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) add_fd(nfds, stdinChannel.pipe[1], &fdwrite); int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed()); -#ifdef Q_OS_BLACKBERRY - int ret = bb_select(notifiers, nfds + 1, &fdread, &fdwrite, timeout); -#else int ret = qt_select_msecs(nfds + 1, &fdread, &fdwrite, timeout); -#endif + if (ret < 0) { break; } @@ -997,10 +985,6 @@ bool QProcessPrivate::waitForFinished(int msecs) QElapsedTimer stopWatch; stopWatch.start(); -#ifdef Q_OS_BLACKBERRY - QList<QSocketNotifier *> notifiers = defaultNotifiers(); -#endif - forever { fd_set fdread; fd_set fdwrite; @@ -1024,11 +1008,8 @@ bool QProcessPrivate::waitForFinished(int msecs) add_fd(nfds, stdinChannel.pipe[1], &fdwrite); int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed()); -#ifdef Q_OS_BLACKBERRY - int ret = bb_select(notifiers, nfds + 1, &fdread, &fdwrite, timeout); -#else int ret = qt_select_msecs(nfds + 1, &fdread, &fdwrite, timeout); -#endif + if (ret < 0) { break; } diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 0c44582af8..efdb86bd7f 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -100,7 +100,7 @@ using namespace ABI::Windows::Storage; #define CSIDL_APPDATA 0x001a // <username>\Application Data #endif -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_BLACKBERRY) && !defined(Q_OS_ANDROID) +#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_ANDROID) #define Q_XDG_PLATFORM #endif @@ -1073,7 +1073,7 @@ static void initDefaultPaths(QMutexLocker *locker) #else #ifndef QSETTINGS_USE_QSTANDARDPATHS - // Non XDG platforms (OS X, iOS, Blackberry, Android...) have used this code path erroneously + // Non XDG platforms (OS X, iOS, Android...) have used this code path erroneously // for some time now. Moving away from that would require migrating existing settings. QString userPath; QByteArray env = qgetenv("XDG_CONFIG_HOME"); @@ -1140,7 +1140,6 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format, org = QLatin1String("Unknown Organization"); } -#if !defined(Q_OS_BLACKBERRY) QString appFile = org + QDir::separator() + application + extension; QString orgFile = org + extension; @@ -1155,13 +1154,6 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format, if (!application.isEmpty()) confFiles[F_System | F_Application].reset(QConfFile::fromName(systemPath + appFile, false)); confFiles[F_System | F_Organization].reset(QConfFile::fromName(systemPath + orgFile, false)); -#else - QString confName = getPath(format, QSettings::UserScope) + org; - if (!application.isEmpty()) - confName += QDir::separator() + application; - confName += extension; - confFiles[SandboxConfFile].reset(QConfFile::fromName(confName, true)); -#endif for (i = 0; i < NumConfFiles; ++i) { if (confFiles[i]) { @@ -2249,7 +2241,6 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, stored in the following registry path: \c{HKEY_LOCAL_MACHINE\Software\WOW6432node}. - On BlackBerry only a single file is used (see \l{Platform Limitations}). If the file format is NativeFormat, this is "Settings/MySoft/Star Runner.conf" in the application's home directory. @@ -2277,7 +2268,6 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, %COMMON_APPDATA% path is usually \tt{C:\\Documents and Settings\\All Users\\Application Data}. - On BlackBerry only a single file is used (see \l{Platform Limitations}). If the file format is IniFormat, this is "Settings/MySoft/Star Runner.ini" in the application's home directory. @@ -2382,15 +2372,6 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, 10.8 (Mountain Lion), only root can. However, 10.9 (Mavericks) changes that rule again but only for the native format (plist files). - \li On the BlackBerry platform, applications run in a sandbox. They are not - allowed to read or write outside of this sandbox. This involves the - following limitations: - \list - \li As there is only a single scope the scope is simply ignored, - i.e. there is no difference between SystemScope and UserScope. - \li The \l{Fallback Mechanism} is not applied, i.e. only a single - location is considered. - \li It is advised against setting and using custom file paths. \endlist \endlist @@ -2413,14 +2394,24 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, This enum type specifies the storage format used by QSettings. - \value NativeFormat Store the settings using the most - appropriate storage format for the platform. - On Windows, this means the system registry; - on OS X and iOS, this means the CFPreferences - API; on Unix, this means textual - configuration files in INI format. - \value IniFormat Store the settings in INI files. - \value InvalidFormat Special value returned by registerFormat(). + \value NativeFormat Store the settings using the most + appropriate storage format for the platform. + On Windows, this means the system registry; + on OS X and iOS, this means the CFPreferences + API; on Unix, this means textual + configuration files in INI format. + \value Registry32Format Windows only: Explicitly access the 32-bit system registry + from a 64-bit application running on 64-bit Windows. + On 32-bit Windows or from a 32-bit application on 64-bit Windows, + this works the same as specifying NativeFormat. + This enum value was added in Qt 5.7. + \value Registry64Format Windows only: Explicitly access the 64-bit system registry + from a 32-bit application running on 64-bit Windows. + On 32-bit Windows or from a 64-bit application on 64-bit Windows, + this works the same as specifying NativeFormat. + This enum value was added in Qt 5.7. + \value IniFormat Store the settings in INI files. + \value InvalidFormat Special value returned by registerFormat(). \omitvalue CustomFormat1 \omitvalue CustomFormat2 \omitvalue CustomFormat3 diff --git a/src/corelib/io/qsettings.h b/src/corelib/io/qsettings.h index 8f41273ffa..dd0c4a9bfb 100644 --- a/src/corelib/io/qsettings.h +++ b/src/corelib/io/qsettings.h @@ -79,6 +79,11 @@ public: NativeFormat, IniFormat, +#ifdef Q_OS_WIN + Registry32Format, + Registry64Format, +#endif + InvalidFormat = 16, CustomFormat1, CustomFormat2, diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h index 5a3eb58a58..919485b5c3 100644 --- a/src/corelib/io/qsettings_p.h +++ b/src/corelib/io/qsettings_p.h @@ -236,16 +236,11 @@ public: because their values are respectively 1 and 2. */ enum { -#if !defined(Q_OS_BLACKBERRY) F_Application = 0x0, F_Organization = 0x1, F_User = 0x0, F_System = 0x2, NumConfFiles = 4 -#else - SandboxConfFile = 0, - NumConfFiles = 1 -#endif }; QSettings::Format format; diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp index 1546219c3b..88f58422a8 100644 --- a/src/corelib/io/qsettings_win.cpp +++ b/src/corelib/io/qsettings_win.cpp @@ -41,6 +41,18 @@ #include "qdebug.h" #include <qt_windows.h> +// See "Accessing an Alternate Registry View" at: +// http://msdn.microsoft.com/en-us/library/aa384129%28VS.85%29.aspx +#ifndef KEY_WOW64_64KEY + // Access a 32-bit key from either a 32-bit or 64-bit application. +# define KEY_WOW64_64KEY 0x0100 +#endif + +#ifndef KEY_WOW64_32KEY + // Access a 64-bit key from either a 32-bit or 64-bit application. +# define KEY_WOW64_32KEY 0x0200 +#endif + QT_BEGIN_NAMESPACE /* Keys are stored in QStrings. If the variable name starts with 'u', this is a "user" @@ -135,12 +147,13 @@ static QString errorCodeToString(DWORD errorCode) return result; } -// Open a key with the specified perms -static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey) +// Open a key with the specified "perms". +// "access" is to explicitly use the 32- or 64-bit branch. +static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey, REGSAM access = 0) { HKEY resultHandle = 0; LONG res = RegOpenKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), - 0, perms, &resultHandle); + 0, perms | access, &resultHandle); if (res == ERROR_SUCCESS) return resultHandle; @@ -148,17 +161,18 @@ static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey) return 0; } -// Open a key with the specified perms, create it if it does not exist -static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey) +// Open a key with the specified "perms", create it if it does not exist. +// "access" is to explicitly use the 32- or 64-bit branch. +static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey, REGSAM access = 0) { // try to open it - HKEY resultHandle = openKey(parentHandle, perms, rSubKey); + HKEY resultHandle = openKey(parentHandle, perms, rSubKey, access); if (resultHandle != 0) return resultHandle; // try to create it LONG res = RegCreateKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), 0, 0, - REG_OPTION_NON_VOLATILE, perms, 0, &resultHandle, 0); + REG_OPTION_NON_VOLATILE, perms | access, 0, &resultHandle, 0); if (res == ERROR_SUCCESS) return resultHandle; @@ -169,11 +183,12 @@ static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSub return 0; } -// Open or create a key in read-write mode if possible, otherwise read-only -static HKEY createOrOpenKey(HKEY parentHandle, const QString &rSubKey, bool *readOnly) +// Open or create a key in read-write mode if possible, otherwise read-only. +// "access" is to explicitly use the 32- or 64-bit branch. +static HKEY createOrOpenKey(HKEY parentHandle, const QString &rSubKey, bool *readOnly, REGSAM access = 0) { // try to open or create it read/write - HKEY resultHandle = createOrOpenKey(parentHandle, registryPermissions, rSubKey); + HKEY resultHandle = createOrOpenKey(parentHandle, registryPermissions, rSubKey, access); if (resultHandle != 0) { if (readOnly != 0) *readOnly = false; @@ -181,7 +196,7 @@ static HKEY createOrOpenKey(HKEY parentHandle, const QString &rSubKey, bool *rea } // try to open or create it read/only - resultHandle = createOrOpenKey(parentHandle, KEY_READ, rSubKey); + resultHandle = createOrOpenKey(parentHandle, KEY_READ, rSubKey, access); if (resultHandle != 0) { if (readOnly != 0) *readOnly = true; @@ -247,9 +262,9 @@ static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildS return result; } -static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result) +static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result, REGSAM access = 0) { - HKEY handle = openKey(parentHandle, KEY_READ, rSubKey); + HKEY handle = openKey(parentHandle, KEY_READ, rSubKey, access); if (handle == 0) return; @@ -270,11 +285,11 @@ static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result) if (!s.isEmpty()) s += QLatin1Char('\\'); s += childGroups.at(i); - allKeys(parentHandle, s, result); + allKeys(parentHandle, s, result, access); } } -static void deleteChildGroups(HKEY parentHandle) +static void deleteChildGroups(HKEY parentHandle, REGSAM access = 0) { QStringList childGroups = childKeysOrGroups(parentHandle, QSettingsPrivate::ChildGroups); @@ -282,10 +297,10 @@ static void deleteChildGroups(HKEY parentHandle) QString group = childGroups.at(i); // delete subgroups in group - HKEY childGroupHandle = openKey(parentHandle, registryPermissions, group); + HKEY childGroupHandle = openKey(parentHandle, registryPermissions, group, access); if (childGroupHandle == 0) continue; - deleteChildGroups(childGroupHandle); + deleteChildGroups(childGroupHandle, access); RegCloseKey(childGroupHandle); // delete group itself @@ -305,7 +320,7 @@ static void deleteChildGroups(HKEY parentHandle) class RegistryKey { public: - RegistryKey(HKEY parent_handle = 0, const QString &key = QString(), bool read_only = true); + RegistryKey(HKEY parent_handle = 0, const QString &key = QString(), bool read_only = true, REGSAM access = 0); QString key() const; HKEY handle() const; HKEY parentHandle() const; @@ -316,13 +331,15 @@ private: mutable HKEY m_handle; QString m_key; mutable bool m_read_only; + REGSAM m_access; }; -RegistryKey::RegistryKey(HKEY parent_handle, const QString &key, bool read_only) +RegistryKey::RegistryKey(HKEY parent_handle, const QString &key, bool read_only, REGSAM access) : m_parent_handle(parent_handle), m_handle(0), m_key(key), - m_read_only(read_only) + m_read_only(read_only), + m_access(access) { } @@ -337,9 +354,9 @@ HKEY RegistryKey::handle() const return m_handle; if (m_read_only) - m_handle = openKey(m_parent_handle, KEY_READ, m_key); + m_handle = openKey(m_parent_handle, KEY_READ, m_key, m_access); else - m_handle = createOrOpenKey(m_parent_handle, m_key, &m_read_only); + m_handle = createOrOpenKey(m_parent_handle, m_key, &m_read_only, m_access); return m_handle; } @@ -371,8 +388,8 @@ class QWinSettingsPrivate : public QSettingsPrivate { public: QWinSettingsPrivate(QSettings::Scope scope, const QString &organization, - const QString &application); - QWinSettingsPrivate(QString rKey); + const QString &application, REGSAM access = 0); + QWinSettingsPrivate(QString rKey, REGSAM access = 0); ~QWinSettingsPrivate(); void remove(const QString &uKey); @@ -390,11 +407,13 @@ public: private: RegistryKeyList regList; // list of registry locations to search for keys bool deleteWriteHandleOnExit; + REGSAM access; }; QWinSettingsPrivate::QWinSettingsPrivate(QSettings::Scope scope, const QString &organization, - const QString &application) - : QSettingsPrivate(QSettings::NativeFormat, scope, organization, application) + const QString &application, REGSAM access) + : QSettingsPrivate(QSettings::NativeFormat, scope, organization, application), + access(access) { deleteWriteHandleOnExit = false; @@ -405,23 +424,24 @@ QWinSettingsPrivate::QWinSettingsPrivate(QSettings::Scope scope, const QString & if (scope == QSettings::UserScope) { if (!application.isEmpty()) - regList.append(RegistryKey(HKEY_CURRENT_USER, appPrefix, !regList.isEmpty())); + regList.append(RegistryKey(HKEY_CURRENT_USER, appPrefix, !regList.isEmpty(), access)); - regList.append(RegistryKey(HKEY_CURRENT_USER, orgPrefix, !regList.isEmpty())); + regList.append(RegistryKey(HKEY_CURRENT_USER, orgPrefix, !regList.isEmpty(), access)); } if (!application.isEmpty()) - regList.append(RegistryKey(HKEY_LOCAL_MACHINE, appPrefix, !regList.isEmpty())); + regList.append(RegistryKey(HKEY_LOCAL_MACHINE, appPrefix, !regList.isEmpty(), access)); - regList.append(RegistryKey(HKEY_LOCAL_MACHINE, orgPrefix, !regList.isEmpty())); + regList.append(RegistryKey(HKEY_LOCAL_MACHINE, orgPrefix, !regList.isEmpty(), access)); } if (regList.isEmpty()) setStatus(QSettings::AccessError); } -QWinSettingsPrivate::QWinSettingsPrivate(QString rPath) - : QSettingsPrivate(QSettings::NativeFormat) +QWinSettingsPrivate::QWinSettingsPrivate(QString rPath, REGSAM access) + : QSettingsPrivate(QSettings::NativeFormat), + access(access) { deleteWriteHandleOnExit = false; @@ -460,9 +480,9 @@ QWinSettingsPrivate::QWinSettingsPrivate(QString rPath) } if (rPath.length() == keyLength) - regList.append(RegistryKey(keyName, QString(), false)); + regList.append(RegistryKey(keyName, QString(), false, access)); else if (rPath[keyLength] == QLatin1Char('\\')) - regList.append(RegistryKey(keyName, rPath.mid(keyLength+1), false)); + regList.append(RegistryKey(keyName, rPath.mid(keyLength+1), false, access)); } bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVariant *value) const @@ -471,7 +491,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa QString rSubkeyPath = keyPath(rSubKey); // open a handle on the subkey - HKEY handle = openKey(parentHandle, KEY_READ, rSubkeyPath); + HKEY handle = openKey(parentHandle, KEY_READ, rSubkeyPath, access); if (handle == 0) return false; @@ -604,16 +624,16 @@ void QWinSettingsPrivate::remove(const QString &uKey) // try to delete value bar in key foo LONG res; - HKEY handle = openKey(writeHandle(), registryPermissions, keyPath(rKey)); + HKEY handle = openKey(writeHandle(), registryPermissions, keyPath(rKey), access); if (handle != 0) { res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16())); RegCloseKey(handle); } // try to delete key foo/bar and all subkeys - handle = openKey(writeHandle(), registryPermissions, rKey); + handle = openKey(writeHandle(), registryPermissions, rKey, access); if (handle != 0) { - deleteChildGroups(handle); + deleteChildGroups(handle, access); if (rKey.isEmpty()) { QStringList childKeys = childKeysOrGroups(handle, QSettingsPrivate::ChildKeys); @@ -661,7 +681,7 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value) QString rKey = escapedKey(uKey); - HKEY handle = createOrOpenKey(writeHandle(), registryPermissions, keyPath(rKey)); + HKEY handle = createOrOpenKey(writeHandle(), registryPermissions, keyPath(rKey), access); if (handle == 0) { setStatus(QSettings::AccessError); return; @@ -775,13 +795,13 @@ QStringList QWinSettingsPrivate::children(const QString &uKey, ChildSpec spec) c HKEY parent_handle = regList.at(i).handle(); if (parent_handle == 0) continue; - HKEY handle = openKey(parent_handle, KEY_READ, rKey); + HKEY handle = openKey(parent_handle, KEY_READ, rKey, access); if (handle == 0) continue; if (spec == AllKeys) { NameSet keys; - allKeys(handle, QLatin1String(""), &keys); + allKeys(handle, QLatin1String(""), &keys, access); mergeKeySets(&result, keys); } else { // ChildGroups or ChildKeys QStringList names = childKeysOrGroups(handle, spec); @@ -836,20 +856,26 @@ bool QWinSettingsPrivate::isWritable() const QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope, const QString &organization, const QString &application) { - if (format == QSettings::NativeFormat) { + if (format == QSettings::NativeFormat) return new QWinSettingsPrivate(scope, organization, application); - } else { + else if (format == QSettings::Registry32Format) + return new QWinSettingsPrivate(scope, organization, application, KEY_WOW64_32KEY); + else if (format == QSettings::Registry64Format) + return new QWinSettingsPrivate(scope, organization, application, KEY_WOW64_64KEY); + else return new QConfFileSettingsPrivate(format, scope, organization, application); - } } QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format) { - if (format == QSettings::NativeFormat) { + if (format == QSettings::NativeFormat) return new QWinSettingsPrivate(fileName); - } else { + else if (format == QSettings::Registry32Format) + return new QWinSettingsPrivate(fileName, KEY_WOW64_32KEY); + else if (format == QSettings::Registry64Format) + return new QWinSettingsPrivate(fileName, KEY_WOW64_64KEY); + else return new QConfFileSettingsPrivate(fileName, format); - } } QT_END_NAMESPACE diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index 8828e09e8f..497191fd32 100644 --- a/src/corelib/io/qstandardpaths.cpp +++ b/src/corelib/io/qstandardpaths.cpp @@ -210,66 +210,46 @@ QT_BEGIN_NAMESPACE \endtable \table - \header \li Path type \li Blackberry \li Linux + \header \li Path type \li Linux \row \li DesktopLocation - \li "<APPROOT>/data" \li "~/Desktop" \row \li DocumentsLocation - \li "<APPROOT>/shared/documents" \li "~/Documents" \row \li FontsLocation - \li "/base/usr/fonts" (not writable) \li "~/.fonts" \row \li ApplicationsLocation - \li not supported (directory not readable) \li "~/.local/share/applications", "/usr/local/share/applications", "/usr/share/applications" \row \li MusicLocation - \li "<APPROOT>/shared/music" \li "~/Music" \row \li MoviesLocation - \li "<APPROOT>/shared/videos" \li "~/Videos" \row \li PicturesLocation - \li "<APPROOT>/shared/photos" \li "~/Pictures" \row \li TempLocation - \li "/var/tmp" \li "/tmp" \row \li HomeLocation - \li "<APPROOT>/data" \li "~" \row \li DataLocation - \li "<APPROOT>/data", "<APPROOT>/app/native/assets" \li "~/.local/share/<APPNAME>", "/usr/local/share/<APPNAME>", "/usr/share/<APPNAME>" \row \li CacheLocation - \li "<APPROOT>/data/Cache" \li "~/.cache/<APPNAME>" \row \li GenericDataLocation - \li "<APPROOT>/shared/misc" \li "~/.local/share", "/usr/local/share", "/usr/share" \row \li RuntimeLocation - \li "/var/tmp" \li "/run/user/<USER>" \row \li ConfigLocation - \li "<APPROOT>/data/Settings" \li "~/.config", "/etc/xdg" \row \li GenericConfigLocation - \li "<APPROOT>/data/Settings" \li "~/.config", "/etc/xdg" \row \li DownloadLocation - \li "<APPROOT>/shared/downloads" \li "~/Downloads" \row \li GenericCacheLocation - \li "<APPROOT>/data/Cache" (there is no shared cache) \li "~/.cache" \row \li AppDataLocation - \li "<APPROOT>/data", "<APPROOT>/app/native/assets" \li "~/.local/share/<APPNAME>", "/usr/local/share/<APPNAME>", "/usr/share/<APPNAME>" \row \li AppLocalDataLocation - \li "<APPROOT>/data", "<APPROOT>/app/native/assets" \li "~/.local/share/<APPNAME>", "/usr/local/share/<APPNAME>", "/usr/share/<APPNAME>" \row \li AppConfigLocation - \li "<APPROOT>/data/Settings" \li "~/.config/<APPNAME>", "/etc/xdg/<APPNAME>" \endtable @@ -277,13 +257,13 @@ QT_BEGIN_NAMESPACE \header \li Path type \li Android \li iOS \row \li DesktopLocation \li "<APPROOT>/files" - \li "<APPROOT>/<APPDIR>" (not writable) + \li "<APPROOT>/Documents/Desktop" \row \li DocumentsLocation \li "<USER>/Documents", "<USER>/<APPNAME>/Documents" \li "<APPROOT>/Documents" \row \li FontsLocation \li "/system/fonts" (not writable) - \li "<APPROOT>/Documents/.fonts" + \li "<APPROOT>/Library/Fonts" \row \li ApplicationsLocation \li not supported (directory not readable) \li not supported @@ -301,7 +281,7 @@ QT_BEGIN_NAMESPACE \li "<APPROOT>/tmp" \row \li HomeLocation \li "<APPROOT>/files" - \li "<APPROOT>/<APPDIR>" (not writable) + \li "<APPROOT>" (not writable) \row \li DataLocation \li "<APPROOT>/files", "<USER>/<APPNAME>/files" \li "<APPROOT>/Library/Application Support" @@ -316,13 +296,13 @@ QT_BEGIN_NAMESPACE \li not supported \row \li ConfigLocation \li "<APPROOT>/files/settings" - \li "<APPROOT>/Documents" + \li "<APPROOT>/Library/Preferences" \row \li GenericConfigLocation \li "<APPROOT>/files/settings" (there is no shared settings) - \li "<APPROOT>/Documents" + \li "<APPROOT>/Library/Preferences" \row \li DownloadLocation \li "<USER>/Downloads", "<USER>/<APPNAME>/Downloads" - \li "<APPROOT>/Documents/Download" + \li "<APPROOT>/Documents/Downloads" \row \li GenericCacheLocation \li "<APPROOT>/cache" (there is no shared cache) \li "<APPROOT>/Library/Caches" @@ -331,7 +311,7 @@ QT_BEGIN_NAMESPACE \li "<APPROOT>/Library/Application Support" \row \li AppConfigLocation \li "<APPROOT>/files/settings" - \li "<APPROOT>/Documents" + \li "<APPROOT>/Library/Preferences/<APPNAME>" \row \li AppLocalDataLocation \li "<APPROOT>/files", "<USER>/<APPNAME>/files" \li "<APPROOT>/Library/Application Support" @@ -555,7 +535,7 @@ QString QStandardPaths::findExecutable(const QString &executableName, const QStr an empty QString if no relevant location can be found. */ -#if !defined(Q_OS_OSX) && !defined(QT_BOOTSTRAPPED) +#if !defined(Q_OS_MAC) && !defined(QT_BOOTSTRAPPED) QString QStandardPaths::displayName(StandardLocation type) { switch (type) { diff --git a/src/corelib/io/qstandardpaths_blackberry.cpp b/src/corelib/io/qstandardpaths_blackberry.cpp deleted file mode 100644 index 4b29ad7ed9..0000000000 --- a/src/corelib/io/qstandardpaths_blackberry.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2012 Research In Motion -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qstandardpaths.h" -#include <qdir.h> - -#ifndef QT_NO_STANDARDPATHS - -#include <qstring.h> - -QT_BEGIN_NAMESPACE - -static QString testModeInsert() { - if (QStandardPaths::isTestModeEnabled()) - return QStringLiteral("/.qttest"); - else - return QStringLiteral(""); -} - -QString QStandardPaths::writableLocation(StandardLocation type) -{ - QDir sharedDir = QDir::home(); - sharedDir.cd(QLatin1String("../shared")); - - const QString sharedRoot = sharedDir.absolutePath(); - - switch (type) { - case AppDataLocation: - case AppLocalDataLocation: - return QDir::homePath() + testModeInsert(); - case DesktopLocation: - case HomeLocation: - return QDir::homePath(); - case RuntimeLocation: - case TempLocation: - return QDir::tempPath(); - case CacheLocation: - case GenericCacheLocation: - return QDir::homePath() + testModeInsert() + QLatin1String("/Cache"); - case ConfigLocation: - case GenericConfigLocation: - case AppConfigLocation: - return QDir::homePath() + testModeInsert() + QLatin1String("/Settings"); - case GenericDataLocation: - return sharedRoot + testModeInsert() + QLatin1String("/misc"); - case DocumentsLocation: - return sharedRoot + QLatin1String("/documents"); - case PicturesLocation: - return sharedRoot + QLatin1String("/photos"); - case FontsLocation: - // this is not a writable location - return QString(); - case MusicLocation: - return sharedRoot + QLatin1String("/music"); - case MoviesLocation: - return sharedRoot + QLatin1String("/videos"); - case DownloadLocation: - return sharedRoot + QLatin1String("/downloads"); - case ApplicationsLocation: - return QString(); - default: - break; - } - - return QString(); -} - -QStringList QStandardPaths::standardLocations(StandardLocation type) -{ - QStringList dirs; - - if (type == FontsLocation) - return QStringList(QLatin1String("/base/usr/fonts")); - - if (type == AppDataLocation || type == AppLocalDataLocation) - dirs.append(QDir::homePath() + testModeInsert() + QLatin1String("native/assets")); - - const QString localDir = writableLocation(type); - dirs.prepend(localDir); - return dirs; -} - -QT_END_NAMESPACE - -#endif // QT_NO_STANDARDPATHS diff --git a/src/corelib/io/qstandardpaths_ios.mm b/src/corelib/io/qstandardpaths_ios.mm deleted file mode 100644 index eb85e2fd23..0000000000 --- a/src/corelib/io/qstandardpaths_ios.mm +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#import <UIKit/UIKit.h> - -#include "qstandardpaths.h" - -#ifndef QT_NO_STANDARDPATHS - -QT_BEGIN_NAMESPACE - -static QString pathForDirectory(NSSearchPathDirectory directory) -{ - return QString::fromNSString( - [NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES) lastObject]); -} - -static QString bundlePath() -{ - return QString::fromNSString([[NSBundle mainBundle] bundlePath]); -} - -QString QStandardPaths::writableLocation(StandardLocation type) -{ - QString location; - - switch (type) { - case DocumentsLocation: - location = pathForDirectory(NSDocumentDirectory); - break; - case FontsLocation: - location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/.fonts"); - break; - case ApplicationsLocation: - // NSApplicationDirectory points to a non-existing write-protected path. - break; - case MusicLocation: - // NSMusicDirectory points to a non-existing write-protected path. Use sensible fallback. - location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/Music"); - break; - case MoviesLocation: - // NSMoviesDirectory points to a non-existing write-protected path. Use sensible fallback. - location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/Movies"); - break; - case PicturesLocation: - // NSPicturesDirectory points to a non-existing write-protected path. Use sensible fallback. - location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/Pictures"); - break; - case TempLocation: - location = QString::fromNSString(NSTemporaryDirectory()); - break; - case DesktopLocation: - case HomeLocation: - location = bundlePath(); - break; - case AppDataLocation: - case AppLocalDataLocation: - location = pathForDirectory(NSApplicationSupportDirectory); - break; - case GenericDataLocation: - location = pathForDirectory(NSDocumentDirectory); - break; - case CacheLocation: - case GenericCacheLocation: - location = pathForDirectory(NSCachesDirectory); - break; - case ConfigLocation: - case GenericConfigLocation: - case AppConfigLocation: - location = pathForDirectory(NSDocumentDirectory); - break; - case DownloadLocation: - // NSDownloadsDirectory points to a non-existing write-protected path. - location = pathForDirectory(NSDocumentDirectory) + QLatin1String("/Download"); - break; - case RuntimeLocation: - break; - default: - break; - } - - return location; -} - -QStringList QStandardPaths::standardLocations(StandardLocation type) -{ - QStringList dirs; - - switch (type) { - case PicturesLocation: - dirs << writableLocation(PicturesLocation) << QLatin1String("assets-library://"); - break; - default: - dirs << writableLocation(type); - break; - } - - return dirs; -} - -QT_END_NAMESPACE - -#endif // QT_NO_STANDARDPATHS diff --git a/src/corelib/io/qstandardpaths_mac.mm b/src/corelib/io/qstandardpaths_mac.mm index 7b97a03db2..341a504168 100644 --- a/src/corelib/io/qstandardpaths_mac.mm +++ b/src/corelib/io/qstandardpaths_mac.mm @@ -32,6 +32,9 @@ ****************************************************************************/ #include "qstandardpaths.h" + +#ifndef QT_NO_STANDARDPATHS + #include <qdir.h> #include <qurl.h> #include <private/qcore_mac_p.h> @@ -40,63 +43,47 @@ #include <qcoreapplication.h> #endif -#include <CoreFoundation/CoreFoundation.h> -#include <ApplicationServices/ApplicationServices.h> +#import <Foundation/Foundation.h> QT_BEGIN_NAMESPACE -/* - Translates a QStandardPaths::StandardLocation into the mac equivalent. -*/ -OSType translateLocation(QStandardPaths::StandardLocation type) +static QString pathForDirectory(NSSearchPathDirectory directory, + NSSearchPathDomainMask mask) +{ + return QString::fromNSString( + [NSSearchPathForDirectoriesInDomains(directory, mask, YES) lastObject]); +} + +static NSSearchPathDirectory searchPathDirectory(QStandardPaths::StandardLocation type) { switch (type) { - case QStandardPaths::ConfigLocation: - case QStandardPaths::GenericConfigLocation: - case QStandardPaths::AppConfigLocation: - return kPreferencesFolderType; case QStandardPaths::DesktopLocation: - return kDesktopFolderType; + return NSDesktopDirectory; case QStandardPaths::DocumentsLocation: - return kDocumentsFolderType; - case QStandardPaths::FontsLocation: - // There are at least two different font directories on the mac: /Library/Fonts and ~/Library/Fonts. - // To select a specific one we have to specify a different first parameter when calling FSFindFolder. - return kFontsFolderType; + return NSDocumentDirectory; case QStandardPaths::ApplicationsLocation: - return kApplicationsFolderType; + return NSApplicationDirectory; case QStandardPaths::MusicLocation: - return kMusicDocumentsFolderType; + return NSMusicDirectory; case QStandardPaths::MoviesLocation: - return kMovieDocumentsFolderType; + return NSMoviesDirectory; case QStandardPaths::PicturesLocation: - return kPictureDocumentsFolderType; - case QStandardPaths::TempLocation: - return kTemporaryFolderType; + return NSPicturesDirectory; case QStandardPaths::GenericDataLocation: case QStandardPaths::RuntimeLocation: case QStandardPaths::AppDataLocation: case QStandardPaths::AppLocalDataLocation: - return kApplicationSupportFolderType; + return NSApplicationSupportDirectory; case QStandardPaths::GenericCacheLocation: case QStandardPaths::CacheLocation: - return kCachedDataFolderType; + return NSCachesDirectory; + case QStandardPaths::DownloadLocation: + return NSDownloadsDirectory; default: - return kDesktopFolderType; + return (NSSearchPathDirectory)0; } } -/* - Constructs a full unicode path from a FSRef. -*/ -static QString getFullPath(const FSRef &ref) -{ - QByteArray ba(2048, 0); - if (FSRefMakePath(&ref, reinterpret_cast<UInt8 *>(ba.data()), ba.size()) == noErr) - return QString::fromUtf8(ba.constData()).normalized(QString::NormalizationForm_C); - return QString(); -} - static void appendOrganizationAndApp(QString &path) { #ifndef QT_BOOTSTRAPPED @@ -111,28 +98,65 @@ static void appendOrganizationAndApp(QString &path) #endif } -static QString macLocation(QStandardPaths::StandardLocation type, short domain) +static QString baseWritableLocation(QStandardPaths::StandardLocation type, + NSSearchPathDomainMask mask = NSUserDomainMask, + bool appendOrgAndApp = false) { - // https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/index.html - if (type == QStandardPaths::DownloadLocation) { - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSURL *url = [fileManager URLForDirectory:NSDownloadsDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; - if (!url) - return QString(); - return QString::fromNSString([url path]); + QString path; + const NSSearchPathDirectory dir = searchPathDirectory(type); + switch (type) { + case QStandardPaths::HomeLocation: + path = QDir::homePath(); + break; + case QStandardPaths::TempLocation: + path = QDir::tempPath(); + break; +#ifdef Q_OS_IOS + // These locations point to non-existing write-protected paths. Use sensible fallbacks. + case QStandardPaths::MusicLocation: + path = pathForDirectory(NSDocumentDirectory, mask) + QLatin1String("/Music"); + break; + case QStandardPaths::MoviesLocation: + path = pathForDirectory(NSDocumentDirectory, mask) + QLatin1String("/Movies"); + break; + case QStandardPaths::PicturesLocation: + path = pathForDirectory(NSDocumentDirectory, mask) + QLatin1String("/Pictures"); + break; + case QStandardPaths::DownloadLocation: + path = pathForDirectory(NSDocumentDirectory, mask) + QLatin1String("/Downloads"); + break; + case QStandardPaths::DesktopLocation: + path = pathForDirectory(NSDocumentDirectory, mask) + QLatin1String("/Desktop"); + break; + case QStandardPaths::ApplicationsLocation: + break; +#endif + case QStandardPaths::FontsLocation: + path = pathForDirectory(NSLibraryDirectory, mask) + QLatin1String("/Fonts"); + break; + case QStandardPaths::ConfigLocation: + case QStandardPaths::GenericConfigLocation: + case QStandardPaths::AppConfigLocation: + path = pathForDirectory(NSLibraryDirectory, mask) + QLatin1String("/Preferences"); + break; + default: + path = pathForDirectory(dir, mask); + break; } - // http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html - FSRef ref; - OSErr err = FSFindFolder(domain, translateLocation(type), false, &ref); - if (err) - return QString(); - - QString path = getFullPath(ref); + if (appendOrgAndApp) { + switch (type) { + case QStandardPaths::AppDataLocation: + case QStandardPaths::AppLocalDataLocation: + case QStandardPaths::AppConfigLocation: + case QStandardPaths::CacheLocation: + appendOrganizationAndApp(path); + break; + default: + break; + } + } - if (type == QStandardPaths::AppDataLocation || type == QStandardPaths::AppLocalDataLocation || - type == QStandardPaths::CacheLocation || type == QStandardPaths::AppConfigLocation) - appendOrganizationAndApp(path); return path; } @@ -167,31 +191,32 @@ QString QStandardPaths::writableLocation(StandardLocation type) } } - switch (type) { - case HomeLocation: - return QDir::homePath(); - case TempLocation: - return QDir::tempPath(); - case GenericDataLocation: - case AppDataLocation: - case AppLocalDataLocation: - case GenericCacheLocation: - case CacheLocation: - case RuntimeLocation: - return macLocation(type, kUserDomain); - default: - return macLocation(type, kOnAppropriateDisk); - } + return baseWritableLocation(type, NSUserDomainMask, true); } QStringList QStandardPaths::standardLocations(StandardLocation type) { QStringList dirs; - if (type == GenericDataLocation || type == AppDataLocation || type == AppLocalDataLocation || type == GenericCacheLocation || type == CacheLocation) { - const QString path = macLocation(type, kOnAppropriateDisk); - if (!path.isEmpty()) - dirs.append(path); +#ifdef Q_OS_IOS + if (type == PicturesLocation) + dirs << writableLocation(PicturesLocation) << QLatin1String("assets-library://"); +#endif + + if (type == GenericDataLocation || type == FontsLocation || type == ApplicationsLocation + || type == AppDataLocation || type == AppLocalDataLocation + || type == GenericCacheLocation || type == CacheLocation) { + QList<NSSearchPathDomainMask> masks; + masks << NSLocalDomainMask; + if (type == FontsLocation || type == GenericCacheLocation) + masks << NSSystemDomainMask; + + for (QList<NSSearchPathDomainMask>::const_iterator it = masks.begin(); + it != masks.end(); ++it) { + const QString path = baseWritableLocation(type, *it, true); + if (!path.isEmpty() && !dirs.contains(path)) + dirs.append(path); + } } if (type == AppDataLocation || type == AppLocalDataLocation) { @@ -219,28 +244,41 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) } } const QString localDir = writableLocation(type); - dirs.prepend(localDir); + if (!localDir.isEmpty()) + dirs.prepend(localDir); return dirs; } #ifndef QT_BOOTSTRAPPED QString QStandardPaths::displayName(StandardLocation type) { + // Use "Home" instead of the user's Unix username if (QStandardPaths::HomeLocation == type) return QCoreApplication::translate("QStandardPaths", "Home"); - FSRef ref; - OSErr err = FSFindFolder(kOnAppropriateDisk, translateLocation(type), false, &ref); - if (err) - return QString(); + // The temporary directory returned by the old Carbon APIs is ~/Library/Caches/TemporaryItems, + // the display name of which ("TemporaryItems") isn't translated by the system. The standard + // temporary directory has no reasonable display name either, so use something more sensible. + if (QStandardPaths::TempLocation == type) + return QCoreApplication::translate("QStandardPaths", "Temporary Items"); - QCFString displayName; - err = LSCopyDisplayNameForRef(&ref, &displayName); - if (err) - return QString(); + // standardLocations() may return an empty list on some platforms + if (QStandardPaths::ApplicationsLocation == type) + return QCoreApplication::translate("QStandardPaths", "Applications"); - return static_cast<QString>(displayName); + if (QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, + standardLocations(type).first().toCFString(), + kCFURLPOSIXPathStyle, true)) { + QCFString name; + CFURLCopyResourcePropertyForKey(url, kCFURLLocalizedNameKey, &name, NULL); + if (name && CFStringGetLength(name)) + return QString::fromCFString(name); + } + + return QFileInfo(baseWritableLocation(type)).fileName(); } #endif QT_END_NAMESPACE + +#endif // QT_NO_STANDARDPATHS diff --git a/src/corelib/io/qtemporarydir.cpp b/src/corelib/io/qtemporarydir.cpp index 71436c6497..1096cb8c31 100644 --- a/src/corelib/io/qtemporarydir.cpp +++ b/src/corelib/io/qtemporarydir.cpp @@ -45,7 +45,7 @@ #endif #include <stdlib.h> // mkdtemp -#if defined(Q_OS_QNX) || defined(Q_OS_WIN) || defined(Q_OS_ANDROID) +#if defined(Q_OS_QNX) || defined(Q_OS_WIN) || defined(Q_OS_ANDROID) || defined(Q_OS_INTEGRITY) #include <private/qfilesystemengine_p.h> #endif @@ -91,7 +91,7 @@ static QString defaultTemplateName() return QDir::tempPath() + QLatin1Char('/') + baseName + QLatin1String("-XXXXXX"); } -#if defined(Q_OS_QNX ) || defined(Q_OS_WIN) || defined(Q_OS_ANDROID) +#if defined(Q_OS_QNX ) || defined(Q_OS_WIN) || defined(Q_OS_ANDROID) || defined(Q_OS_INTEGRITY) static int nextRand(int &v) { diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp index a8fd2dd7ab..adf9e1aa55 100644 --- a/src/corelib/io/qtextstream.cpp +++ b/src/corelib/io/qtextstream.cpp @@ -2545,6 +2545,8 @@ QTextStream &QTextStream::operator<<(double f) flags |= QLocaleData::Alternate; if (locale() != QLocale::c() && !(locale().numberOptions() & QLocale::OmitGroupSeparator)) flags |= QLocaleData::ThousandsGroup; + if (!(locale().numberOptions() & QLocale::OmitLeadingZeroInExponent)) + flags |= QLocaleData::ZeroPadExponent; const QLocaleData *dd = d->locale.d->m_data; QString num = dd->doubleToString(f, d->params.realNumberPrecision, form, -1, flags); |