diff options
Diffstat (limited to 'src/corelib/io')
35 files changed, 584 insertions, 616 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..83bfe47ab1 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 @@ -265,7 +261,7 @@ static QString selectionHelper(const QString &path, const QString &fileName, con */ Q_ASSERT(path.isEmpty() || path.endsWith(QLatin1Char('/'))); - foreach (const QString &s, selectors) { + for (const QString &s : selectors) { QString prospectiveBase = path + QLatin1Char(selectorIndicator) + s + QLatin1Char('/'); QStringList remainingSelectors = selectors; remainingSelectors.removeAll(s); @@ -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/qfilesystementry.cpp b/src/corelib/io/qfilesystementry.cpp index 709970e3ac..2dc534d356 100644 --- a/src/corelib/io/qfilesystementry.cpp +++ b/src/corelib/io/qfilesystementry.cpp @@ -372,7 +372,7 @@ bool QFileSystemEntry::isClean() const int dots = 0; bool dotok = true; // checking for ".." or "." starts to relative paths bool slashok = true; - for (QString::const_iterator iter = m_filePath.constBegin(); iter != m_filePath.constEnd(); iter++) { + for (QString::const_iterator iter = m_filePath.constBegin(); iter != m_filePath.constEnd(); ++iter) { if (*iter == QLatin1Char('/')) { if (dots == 1 || dots == 2) return false; // path contains "./" or "../" diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp index 8bc06cfcbe..3847e70a1c 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> @@ -245,7 +246,7 @@ QInotifyFileSystemWatcherEngine::QInotifyFileSystemWatcherEngine(int fd, QObject QInotifyFileSystemWatcherEngine::~QInotifyFileSystemWatcherEngine() { notifier.setEnabled(false); - foreach (int id, pathToID) + for (int id : qAsConst(pathToID)) inotify_rm_watch(inotifyFd, id < 0 ? -id : id); ::close(inotifyFd); @@ -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/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp index 80cbcb26cc..43e1719a13 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp +++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp @@ -82,7 +82,7 @@ QKqueueFileSystemWatcherEngine::~QKqueueFileSystemWatcherEngine() notifier.setEnabled(false); close(kqfd); - foreach (int id, pathToID) + for (int id : qAsConst(pathToID)) ::close(id < 0 ? -id : id); } diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index 410753868e..6c263b6847 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -62,11 +62,11 @@ QWindowsFileSystemWatcherEngine::Handle::Handle() QWindowsFileSystemWatcherEngine::~QWindowsFileSystemWatcherEngine() { - foreach(QWindowsFileSystemWatcherEngineThread *thread, threads) { + for (auto *thread : qAsConst(threads)) thread->stop(); + for (auto *thread : qAsConst(threads)) thread->wait(); - delete thread; - } + qDeleteAll(threads); } QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths, @@ -164,7 +164,7 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths, // now look for a thread to insert bool found = false; - foreach(QWindowsFileSystemWatcherEngineThread *thread, threads) { + for (QWindowsFileSystemWatcherEngineThread *thread : qAsConst(threads)) { QMutexLocker(&(thread->mutex)); if (thread->handles.count() < MAXIMUM_WAIT_OBJECTS) { DEBUG() << "Added handle" << handle.handle << "for" << absolutePath << "to watch" << fileInfo.absoluteFilePath() @@ -311,7 +311,7 @@ QWindowsFileSystemWatcherEngineThread::~QWindowsFileSystemWatcherEngineThread() CloseHandle(handles.at(0)); handles[0] = INVALID_HANDLE_VALUE; - foreach (HANDLE h, handles) { + for (HANDLE h : qAsConst(handles)) { if (h == INVALID_HANDLE_VALUE) continue; FindCloseChangeNotification(h); @@ -323,7 +323,7 @@ static inline QString msgFindNextFailed(const QWindowsFileSystemWatcherEngineThr QString result; QTextStream str(&result); str << "QFileSystemWatcher: FindNextChangeNotification failed for"; - foreach (const QWindowsFileSystemWatcherEngine::PathInfo &pathInfo, pathInfos) + for (const QWindowsFileSystemWatcherEngine::PathInfo &pathInfo : pathInfos) str << " \"" << QDir::toNativeSeparators(pathInfo.absolutePath) << '"'; str << ' '; return result; 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..ae776d4137 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 @@ -54,6 +57,8 @@ #elif defined(Q_OS_LINUX) # include <unistd.h> # include <cstdio> +#elif defined(Q_OS_HAIKU) +# include <kernel/OS.h> #elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS) # include <sys/user.h> # if defined(__GLIBC__) && defined(__FreeBSD_kernel__) @@ -248,6 +253,11 @@ QString QLockFilePrivate::processNameByPid(qint64 pid) } buf[len] = 0; return QFileInfo(QFile::decodeName(buf)).fileName(); +#elif defined(Q_OS_HAIKU) + thread_info info; + if (get_thread_info(pid, &info) != B_OK) + return QString(); + return QFile::decodeName(info.name); #elif defined(Q_OS_BSD4) && !defined(Q_OS_IOS) # if defined(__GLIBC__) && defined(__FreeBSD_kernel__) int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid }; diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp index b53e251102..3e6e61b906 100644 --- a/src/corelib/io/qloggingregistry.cpp +++ b/src/corelib/io/qloggingregistry.cpp @@ -364,8 +364,8 @@ void QLoggingRegistry::updateRules() rules = qtConfigRules + configRules + apiRules + envRules; - foreach (QLoggingCategory *cat, categories.keys()) - (*categoryFilter)(cat); + for (auto it = categories.keyBegin(), end = categories.keyEnd(); it != end; ++it) + (*categoryFilter)(*it); } /*! @@ -383,8 +383,8 @@ QLoggingRegistry::installFilter(QLoggingCategory::CategoryFilter filter) QLoggingCategory::CategoryFilter old = categoryFilter; categoryFilter = filter; - foreach (QLoggingCategory *cat, categories.keys()) - (*categoryFilter)(cat); + for (auto it = categories.keyBegin(), end = categories.keyEnd(); it != end; ++it) + (*categoryFilter)(*it); return old; } @@ -400,7 +400,7 @@ QLoggingRegistry *QLoggingRegistry::instance() */ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat) { - QLoggingRegistry *reg = QLoggingRegistry::instance(); + const QLoggingRegistry *reg = QLoggingRegistry::instance(); Q_ASSERT(reg->categories.contains(cat)); QtMsgType enableForLevel = reg->categories.value(cat); @@ -421,7 +421,7 @@ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat) } QString categoryName = QLatin1String(cat->categoryName()); - foreach (const QLoggingRule &item, reg->rules) { + for (const QLoggingRule &item : reg->rules) { int filterpass = item.pass(categoryName, QtDebugMsg); if (filterpass != 0) debug = (filterpass > 0); diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 952116b9db..315142aabe 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -744,6 +744,47 @@ void QProcessPrivate::Channel::clear() */ /*! + \typedef QProcess::CreateProcessArgumentModifier + \note This typedef is only available on desktop Windows and Windows CE. + + On Windows, QProcess uses the Win32 API function \c CreateProcess to + start child processes. While QProcess provides a comfortable way to start + processes without worrying about platform + details, it is in some cases desirable to fine-tune the parameters that are + passed to \c CreateProcess. This is done by defining a + \c CreateProcessArgumentModifier function and passing it to + \c setCreateProcessArgumentsModifier. + + A \c CreateProcessArgumentModifier function takes one parameter: a pointer + to a \c CreateProcessArguments struct. The members of this struct will be + passed to \c CreateProcess after the \c CreateProcessArgumentModifier + function is called. + + The following example demonstrates how to pass custom flags to + \c CreateProcess. + When starting a console process B from a console process A, QProcess will + reuse the console window of process A for process B by default. In this + example, a new console window with a custom color scheme is created for the + child process B instead. + + \snippet qprocess/qprocess-createprocessargumentsmodifier.cpp 0 + + \sa QProcess::CreateProcessArguments + \sa setCreateProcessArgumentsModifier() +*/ + +/*! + \class QProcess::CreateProcessArguments + \note This struct is only available on the Windows platform. + + This struct is a representation of all parameters of the Windows API + function \c CreateProcess. It is used as parameter for + \c CreateProcessArgumentModifier functions. + + \sa QProcess::CreateProcessArgumentModifier +*/ + +/*! \fn void QProcess::error(QProcess::ProcessError error) \obsolete @@ -1563,6 +1604,39 @@ void QProcess::setNativeArguments(const QString &arguments) d->nativeArguments = arguments; } +/*! + \since 5.7 + + Returns a previously set \c CreateProcess modifier function. + + \note This function is available only on the Windows platform. + + \sa setCreateProcessArgumentsModifier() + \sa QProcess::CreateProcessArgumentModifier +*/ +QProcess::CreateProcessArgumentModifier QProcess::createProcessArgumentsModifier() const +{ + Q_D(const QProcess); + return d->modifyCreateProcessArgs; +} + +/*! + \since 5.7 + + Sets the \a modifier for the \c CreateProcess Win32 API call. + Pass \c QProcess::CreateProcessArgumentModifier() to remove a previously set one. + + \note This function is available only on the Windows platform and requires + C++11. + + \sa QProcess::CreateProcessArgumentModifier +*/ +void QProcess::setCreateProcessArgumentsModifier(CreateProcessArgumentModifier modifier) +{ + Q_D(QProcess); + d->modifyCreateProcessArgs = modifier; +} + #endif /*! diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h index f95358250e..52e0316857 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -38,6 +38,8 @@ #include <QtCore/qstringlist.h> #include <QtCore/qshareddata.h> +#include <functional> + QT_BEGIN_NAMESPACE @@ -48,6 +50,8 @@ typedef qint64 Q_PID; #else QT_END_NAMESPACE typedef struct _PROCESS_INFORMATION *Q_PID; +typedef struct _SECURITY_ATTRIBUTES Q_SECURITY_ATTRIBUTES; +typedef struct _STARTUPINFOW Q_STARTUPINFO; QT_BEGIN_NAMESPACE #endif @@ -180,7 +184,23 @@ public: #if defined(Q_OS_WIN) QString nativeArguments() const; void setNativeArguments(const QString &arguments); -#endif + struct CreateProcessArguments + { + const wchar_t *applicationName; + wchar_t *arguments; + Q_SECURITY_ATTRIBUTES *processAttributes; + Q_SECURITY_ATTRIBUTES *threadAttributes; + bool inheritHandles; + unsigned long flags; + void *environment; + const wchar_t *currentDirectory; + Q_STARTUPINFO *startupInfo; + Q_PID processInformation; + }; + typedef std::function<void(CreateProcessArguments *)> CreateProcessArgumentModifier; + CreateProcessArgumentModifier createProcessArgumentsModifier() const; + void setCreateProcessArgumentsModifier(CreateProcessArgumentModifier modifier); +#endif // Q_OS_WIN QString workingDirectory() const; void setWorkingDirectory(const QString &dir); diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index d3f251c399..227a583718 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -329,6 +329,7 @@ public: QStringList arguments; #if defined(Q_OS_WIN) QString nativeArguments; + QProcess::CreateProcessArgumentModifier modifyCreateProcessArgs; #endif QProcessEnvironment environment; @@ -385,11 +386,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 8eb5ac9564..ab5734a298 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -564,7 +564,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 } @@ -676,6 +676,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; @@ -687,6 +688,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; @@ -704,15 +706,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; } @@ -720,8 +726,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(); @@ -736,7 +749,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; } @@ -830,17 +843,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) @@ -850,10 +852,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; @@ -876,11 +874,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; } @@ -928,10 +923,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; @@ -955,11 +946,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; } @@ -1001,10 +989,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; @@ -1028,11 +1012,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/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 80e6d5bb61..69d9ac6e87 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -497,11 +497,22 @@ void QProcessPrivate::startProcess() 0, 0, 0, stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1] }; - success = CreateProcess(0, (wchar_t*)args.utf16(), - 0, 0, TRUE, dwCreationFlags, - environment.isEmpty() ? 0 : envlist.data(), - workingDirectory.isEmpty() ? 0 : (wchar_t*)QDir::toNativeSeparators(workingDirectory).utf16(), - &startupInfo, pid); + + const QString nativeWorkingDirectory = QDir::toNativeSeparators(workingDirectory); + QProcess::CreateProcessArguments cpargs = { + 0, (wchar_t*)args.utf16(), + 0, 0, TRUE, dwCreationFlags, + environment.isEmpty() ? 0 : envlist.data(), + nativeWorkingDirectory.isEmpty() ? Q_NULLPTR : (wchar_t*)nativeWorkingDirectory.utf16(), + &startupInfo, pid + }; + if (modifyCreateProcessArgs) + modifyCreateProcessArgs(&cpargs); + success = CreateProcess(cpargs.applicationName, cpargs.arguments, cpargs.processAttributes, + cpargs.threadAttributes, cpargs.inheritHandles, cpargs.flags, + cpargs.environment, cpargs.currentDirectory, cpargs.startupInfo, + cpargs.processInformation); + QString errorString; if (!success) { // Capture the error string before we do CloseHandle below 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/qsettings_winrt.cpp b/src/corelib/io/qsettings_winrt.cpp index 02c3c7624e..f380ef345c 100644 --- a/src/corelib/io/qsettings_winrt.cpp +++ b/src/corelib/io/qsettings_winrt.cpp @@ -533,10 +533,10 @@ QStringList QWinRTSettingsPrivate::children(const QString &uKey, ChildSpec spec) const QStringList subContainerList = subContainerNames(container.Get(), spec == AllKeys); if (spec == AllKeys) { - foreach (const QString &item, subContainerList) { + for (const QString &item : subContainerList) { const QString subChildren = uKey.isEmpty() ? item : (uKey + QLatin1Char('/') + item); const QStringList subResult = children(subChildren, ChildKeys); - foreach (const QString &subItem, subResult) + for (const QString &subItem : subResult) result += item + QLatin1Char('/') + subItem; } } @@ -644,7 +644,7 @@ IApplicationDataContainer *QWinRTSettingsPrivate::getContainer(IApplicationDataC return current; const QStringList groupPath = group.split(QLatin1Char('/'), QString::SkipEmptyParts); - foreach (const QString &subGroup, groupPath) { + for (const QString &subGroup : groupPath) { ComPtr<IApplicationDataContainer> sub = subContainer(current, subGroup); if (!sub && create) sub = createSubContainer(current, subGroup); diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index 8828e09e8f..7544f5b177 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" @@ -463,7 +443,7 @@ static inline QString searchExecutable(const QStringList &searchPaths, const QString &executableName) { const QDir currentDir = QDir::current(); - foreach (const QString &searchPath, searchPaths) { + for (const QString &searchPath : searchPaths) { const QString candidate = currentDir.absoluteFilePath(searchPath + QLatin1Char('/') + executableName); const QString absPath = checkExecutable(candidate); if (!absPath.isEmpty()) @@ -482,9 +462,9 @@ static inline QString const QStringList &suffixes) { const QDir currentDir = QDir::current(); - foreach (const QString &searchPath, searchPaths) { + for (const QString &searchPath : searchPaths) { const QString candidateRoot = currentDir.absoluteFilePath(searchPath + QLatin1Char('/') + executableName); - foreach (const QString &suffix, suffixes) { + for (const QString &suffix : suffixes) { const QString absPath = checkExecutable(candidateRoot + suffix); if (!absPath.isEmpty()) return absPath; @@ -525,7 +505,7 @@ QString QStandardPaths::findExecutable(const QString &executableName, const QStr // Remove trailing slashes, which occur on Windows. const QStringList rawPaths = QString::fromLocal8Bit(pEnv.constData()).split(QDir::listSeparator(), QString::SkipEmptyParts); searchPaths.reserve(rawPaths.size()); - foreach (const QString &rawPath, rawPaths) { + for (const QString &rawPath : rawPaths) { QString cleanPath = QDir::cleanPath(rawPath); if (cleanPath.size() > 1 && cleanPath.endsWith(QLatin1Char('/'))) cleanPath.truncate(cleanPath.size() - 1); @@ -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..9f0a8c08ed 100644 --- a/src/corelib/io/qtextstream.cpp +++ b/src/corelib/io/qtextstream.cpp @@ -862,6 +862,21 @@ void QTextStreamPrivate::write(QLatin1String data) /*! \internal */ +void QTextStreamPrivate::writePadding(int len) +{ + if (string) { + // ### What about seek()?? + string->resize(string->size() + len, params.padChar); + } else { + writeBuffer.resize(writeBuffer.size() + len, params.padChar); + if (writeBuffer.size() > QTEXTSTREAM_BUFFERSIZE) + flushWriteBuffer(); + } +} + +/*! + \internal +*/ inline bool QTextStreamPrivate::getChar(QChar *ch) { if ((string && stringOffset == string->size()) @@ -916,31 +931,24 @@ QTextStreamPrivate::PaddingResult QTextStreamPrivate::padding(int len) const { Q_ASSERT(params.fieldWidth > len); // calling padding() when no padding is needed is an error - // Do NOT break NRVO in this function or kittens will die! - - PaddingResult result; + int left = 0, right = 0; const int padSize = params.fieldWidth - len; - result.padding.resize(padSize); - std::fill_n(result.padding.begin(), padSize, params.padChar); - switch (params.fieldAlignment) { case QTextStream::AlignLeft: - result.left = 0; - result.right = padSize; + right = padSize; break; case QTextStream::AlignRight: case QTextStream::AlignAccountingStyle: - result.left = padSize; - result.right = 0; + left = padSize; break; case QTextStream::AlignCenter: - result.left = padSize/2; - result.right = padSize - padSize/2; + left = padSize/2; + right = padSize - padSize/2; break; } - + const PaddingResult result = { left, right }; return result; } @@ -965,9 +973,9 @@ void QTextStreamPrivate::putString(const QChar *data, int len, bool number) } } - write(pad.padding.constData(), pad.left); + writePadding(pad.left); write(data, len); - write(pad.padding.constData(), pad.right); + writePadding(pad.right); } else { write(data, len); } @@ -993,9 +1001,9 @@ void QTextStreamPrivate::putString(QLatin1String data, bool number) } } - write(pad.padding.constData(), pad.left); + writePadding(pad.left); write(data); - write(pad.padding.constData(), pad.right); + writePadding(pad.right); } else { write(data); } @@ -2545,6 +2553,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); diff --git a/src/corelib/io/qtextstream_p.h b/src/corelib/io/qtextstream_p.h index 115408a6dd..6c6cbe1e6e 100644 --- a/src/corelib/io/qtextstream_p.h +++ b/src/corelib/io/qtextstream_p.h @@ -169,6 +169,7 @@ public: inline void write(QChar ch); void write(const QChar *data, int len); void write(QLatin1String data); + void writePadding(int len); inline void putString(const QString &ch, bool number = false) { putString(ch.constData(), ch.length(), number); } void putString(const QChar *data, int len, bool number = false); void putString(QLatin1String data, bool number = false); @@ -176,10 +177,7 @@ public: void putNumber(qulonglong number, bool negative); struct PaddingResult { - enum { PreallocatedPadding = 80 }; // typical line length - int left, right; - QVarLengthArray<QChar, PreallocatedPadding> padding; }; PaddingResult padding(int len) const; diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 775a870a27..8e82f00f74 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -4064,7 +4064,7 @@ QStringList QUrl::toStringList(const QList<QUrl> &urls, FormattingOptions option { QStringList lst; lst.reserve(urls.size()); - foreach (const QUrl &url, urls) + for (const QUrl &url : urls) lst.append(url.toString(options)); return lst; @@ -4080,9 +4080,8 @@ QList<QUrl> QUrl::fromStringList(const QStringList &urls, ParsingMode mode) { QList<QUrl> lst; lst.reserve(urls.size()); - foreach (const QString &str, urls) { + for (const QString &str : urls) lst.append(QUrl(str, mode)); - } return lst; } diff --git a/src/corelib/io/qurlquery.cpp b/src/corelib/io/qurlquery.cpp index 2b695a4f7b..65c9dc3339 100644 --- a/src/corelib/io/qurlquery.cpp +++ b/src/corelib/io/qurlquery.cpp @@ -169,7 +169,6 @@ public: Map::iterator findKey(const QString &key) { return itemList.begin() + findRecodedKey(recodeFromUser(key)); } - // use QMap so we end up sorting the items by key Map itemList; QChar valueDelimiter; QChar pairDelimiter; @@ -733,7 +732,7 @@ QStringList QUrlQuery::allQueryItemValues(const QString &key, QUrl::ComponentFor */ void QUrlQuery::removeQueryItem(const QString &key) { - if (d) { + if (d.constData()) { Map::iterator it = d->findKey(key); if (it != d->itemList.end()) d->itemList.erase(it); diff --git a/src/corelib/io/qurlquery.h b/src/corelib/io/qurlquery.h index ae3a79c119..16e186a79b 100644 --- a/src/corelib/io/qurlquery.h +++ b/src/corelib/io/qurlquery.h @@ -154,10 +154,10 @@ inline QList<QPair<QByteArray, QByteArray> > QUrl::encodedQueryItems() const } inline QList<QByteArray> QUrl::allEncodedQueryItemValues(const QByteArray &key) const { - QStringList items = QUrlQuery(*this).allQueryItemValues(fromEncodedComponent_helper(key), QUrl::FullyEncoded); + const QStringList items = QUrlQuery(*this).allQueryItemValues(fromEncodedComponent_helper(key), QUrl::FullyEncoded); QList<QByteArray> result; result.reserve(items.size()); - Q_FOREACH (const QString &item, items) + for (const QString &item : items) result << item.toLatin1(); return result; } |