diff options
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/Qt5ModuleLocationForInstall.cmake.in | 4 | ||||
-rw-r--r-- | src/corelib/global/qcompilerdetection.h | 4 | ||||
-rw-r--r-- | src/corelib/global/qglobal.h | 14 | ||||
-rw-r--r-- | src/corelib/global/qversiontagging.h | 2 | ||||
-rw-r--r-- | src/corelib/io/io.pri | 5 | ||||
-rw-r--r-- | src/corelib/io/qfile.cpp | 8 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemengine_p.h | 2 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemengine_unix.cpp | 43 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemengine_win.cpp | 6 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemwatcher_win.cpp | 47 | ||||
-rw-r--r-- | src/corelib/io/qfsfileengine_unix.cpp | 7 | ||||
-rw-r--r-- | src/corelib/io/qstorageinfo_win.cpp | 52 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qdeadlinetimer.cpp | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qobjectdefs.h | 1 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 13 | ||||
-rw-r--r-- | src/corelib/tools/qbytearray.cpp | 24 | ||||
-rw-r--r-- | src/corelib/tools/qdatetime.cpp | 53 | ||||
-rw-r--r-- | src/corelib/tools/qlocale.cpp | 17 |
19 files changed, 208 insertions, 100 deletions
diff --git a/src/corelib/Qt5ModuleLocationForInstall.cmake.in b/src/corelib/Qt5ModuleLocationForInstall.cmake.in index e401b1fe34..8751e4acbc 100644 --- a/src/corelib/Qt5ModuleLocationForInstall.cmake.in +++ b/src/corelib/Qt5ModuleLocationForInstall.cmake.in @@ -1,4 +1,6 @@ set(_qt5_root_dir ${_qt5_install_prefix}) set(_qt5_module_paths ${_qt5_install_prefix}) -set(_qt5_module_location_template ${_qt5_install_prefix}/Qt5@module@/Qt5@module@Config.cmake) +set(_qt5_at "@") +set(_qt5_module_location_template ${_qt5_install_prefix}/Qt5${_qt5_at}module${_qt5_at}/Qt5${_qt5_at}module${_qt5_at}Config.cmake) +unset(_qt5_at) diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 9ffd164b61..05e3f6c45a 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1336,14 +1336,14 @@ do {\ Q_ASSERT_X(false, "Q_UNREACHABLE()", "Q_UNREACHABLE was reached");\ Q_UNREACHABLE_IMPL();\ - } while (0) + } while (false) #define Q_ASSUME(Expr) \ do {\ const bool valueOfExpression = Expr;\ Q_ASSERT_X(valueOfExpression, "Q_ASSUME()", "Assumption in Q_ASSUME(\"" #Expr "\") was not correct");\ Q_ASSUME_IMPL(valueOfExpression);\ - } while (0) + } while (false) #if defined(__cplusplus) #if QT_HAS_CPP_ATTRIBUTE(fallthrough) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 429cd63ab6..d58e568447 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -341,10 +341,10 @@ typedef double qreal; #define Q_INIT_RESOURCE(name) \ do { extern int QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); \ - QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); } while (0) + QT_MANGLE_NAMESPACE(qInitResources_ ## name) (); } while (false) #define Q_CLEANUP_RESOURCE(name) \ do { extern int QT_MANGLE_NAMESPACE(qCleanupResources_ ## name) (); \ - QT_MANGLE_NAMESPACE(qCleanupResources_ ## name) (); } while (0) + QT_MANGLE_NAMESPACE(qCleanupResources_ ## name) (); } while (false) /* * If we're compiling C++ code: @@ -664,7 +664,7 @@ inline void qt_noop(void) {} # define QT_CATCH(A) else # define QT_THROW(A) qt_noop() # define QT_RETHROW qt_noop() -# define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (0) +# define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (false) #else # define QT_TRY try # define QT_CATCH(A) catch (A) @@ -672,9 +672,9 @@ inline void qt_noop(void) {} # define QT_RETHROW throw Q_NORETURN Q_CORE_EXPORT void qTerminate() Q_DECL_NOTHROW; # ifdef Q_COMPILER_NOEXCEPT -# define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (0) +# define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (false) # else -# define QT_TERMINATE_ON_EXCEPTION(expr) do { try { expr; } catch (...) { qTerminate(); } } while (0) +# define QT_TERMINATE_ON_EXCEPTION(expr) do { try { expr; } catch (...) { qTerminate(); } } while (false) # endif #endif @@ -778,10 +778,10 @@ Q_CORE_EXPORT void qBadAlloc(); # if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS) # define Q_CHECK_PTR(p) qt_noop() # else -# define Q_CHECK_PTR(p) do {if(!(p))qt_check_pointer(__FILE__,__LINE__);} while (0) +# define Q_CHECK_PTR(p) do {if (!(p)) qt_check_pointer(__FILE__,__LINE__);} while (false) # endif #else -# define Q_CHECK_PTR(p) do { if (!(p)) qBadAlloc(); } while (0) +# define Q_CHECK_PTR(p) do { if (!(p)) qBadAlloc(); } while (false) #endif template <typename T> diff --git a/src/corelib/global/qversiontagging.h b/src/corelib/global/qversiontagging.h index 3ed02c7376..75c2e9df7e 100644 --- a/src/corelib/global/qversiontagging.h +++ b/src/corelib/global/qversiontagging.h @@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE # endif # define QT_VERSION_TAG(sym) \ asm ( \ - ".section .qtversion, \"aG\", @progbits, qt_version_tag, comdat\n" \ + ".section .qtversion, \"aG\", @progbits, " QT_STRINGIFY(QT_MANGLE_NAMESPACE(sym)) ", comdat\n" \ ".align 8\n" \ QT_VERSION_TAG_RELOC(sym) \ ".long " QT_STRINGIFY(QT_VERSION) "\n" \ diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 38e5c23c05..cc43608d8c 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -113,7 +113,10 @@ win32 { SOURCES += io/qfilesystemwatcher_win.cpp HEADERS += io/qfilesystemwatcher_win_p.h SOURCES += io/qfilesystemengine_win.cpp - SOURCES += io/qfilesystemiterator_win.cpp + + qtConfig(filesystemiterator) { + SOURCES += io/qfilesystemiterator_win.cpp + } !winrt { HEADERS += \ diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index ddd343b515..c7a06e49d5 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -568,9 +568,11 @@ QFile::rename(const QString &newName) } // If the file exists and it is a case-changing rename ("foo" -> "Foo"), // compare Ids to make sure it really is a different file. - if (QFile::exists(newName)) { - if (d->fileName.compare(newName, Qt::CaseInsensitive) - || QFileSystemEngine::id(QFileSystemEntry(d->fileName)) != QFileSystemEngine::id(QFileSystemEntry(newName))) { + // Note: this does not take file engines into account. + QByteArray targetId = QFileSystemEngine::id(QFileSystemEntry(newName)); + if (!targetId.isNull()) { + QByteArray fileId = QFileSystemEngine::id(QFileSystemEntry(d->fileName)); + if (fileId != targetId || d->fileName.compare(newName, Qt::CaseInsensitive)) { // ### Race condition. If a file is moved in after this, it /will/ be // overwritten. On Unix, the proper solution is to use hardlinks: // return ::link(old, new) && ::remove(old); diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h index de18c997df..196ed8df69 100644 --- a/src/corelib/io/qfilesystemengine_p.h +++ b/src/corelib/io/qfilesystemengine_p.h @@ -92,6 +92,8 @@ public: QFileSystemMetaData::MetaDataFlags what); #if defined(Q_OS_UNIX) static bool fillMetaData(int fd, QFileSystemMetaData &data); // what = PosixStatFlags + static bool setPermissions(int fd, QFile::Permissions permissions, QSystemError &error, + QFileSystemMetaData *data = nullptr); #endif #if defined(Q_OS_WIN) diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 2c8c4e8f9e..940a0a2122 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -315,9 +315,10 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry) //static QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry) { - struct stat statResult; - if (stat(entry.nativeFilePath().constData(), &statResult)) { - qErrnoWarning("stat() failed for '%s'", entry.nativeFilePath().constData()); + QT_STATBUF statResult; + if (QT_STAT(entry.nativeFilePath().constData(), &statResult)) { + if (errno != ENOENT) + qErrnoWarning("stat() failed for '%s'", entry.nativeFilePath().constData()); return QByteArray(); } QByteArray result = QByteArray::number(quint64(statResult.st_dev), 16); @@ -428,15 +429,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM data.entryFlags &= ~what; - const char * nativeFilePath; - int nativeFilePathLength; - { - const QByteArray &path = entry.nativeFilePath(); - nativeFilePath = path.constData(); - nativeFilePathLength = path.size(); - Q_UNUSED(nativeFilePathLength); - } - + const QByteArray nativeFilePath = entry.nativeFilePath(); bool entryExists = true; // innocent until proven otherwise QT_STATBUF statBuffer; @@ -660,8 +653,7 @@ bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError & } -//static -bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data) +static mode_t toMode_t(QFile::Permissions permissions) { mode_t mode = 0; if (permissions & (QFile::ReadOwner | QFile::ReadUser)) @@ -682,6 +674,13 @@ bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Per mode |= S_IWOTH; if (permissions & QFile::ExeOther) mode |= S_IXOTH; + return mode; +} + +//static +bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data) +{ + mode_t mode = toMode_t(permissions); bool success = ::chmod(entry.nativeFilePath().constData(), mode) == 0; if (success && data) { @@ -694,6 +693,22 @@ bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Per return success; } +//static +bool QFileSystemEngine::setPermissions(int fd, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data) +{ + mode_t mode = toMode_t(permissions); + + bool success = ::fchmod(fd, mode) == 0; + if (success && data) { + data->entryFlags &= ~QFileSystemMetaData::Permissions; + data->entryFlags |= QFileSystemMetaData::MetaDataFlag(uint(permissions)); + data->knownFlagsMask |= QFileSystemMetaData::Permissions; + } + if (!success) + error = QSystemError(errno, QSystemError::StandardLibraryError); + return success; +} + QString QFileSystemEngine::homePath() { QString home = QFile::decodeName(qgetenv("HOME")); diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index d95a6de777..889fbfea7b 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -602,13 +602,13 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry) QByteArray result; const HANDLE handle = #ifndef Q_OS_WINRT - CreateFile((wchar_t*)entry.nativeFilePath().utf16(), GENERIC_READ, + CreateFile((wchar_t*)entry.nativeFilePath().utf16(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); #else // !Q_OS_WINRT - CreateFile2((const wchar_t*)entry.nativeFilePath().utf16(), GENERIC_READ, + CreateFile2((const wchar_t*)entry.nativeFilePath().utf16(), 0, FILE_SHARE_READ, OPEN_EXISTING, NULL); #endif // Q_OS_WINRT - if (handle) { + if (handle != INVALID_HANDLE_VALUE) { result = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8 ? fileIdWin8(handle) : fileId(handle); CloseHandle(handle); diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index c385a82fc5..ff0d45935c 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -71,6 +71,19 @@ QT_BEGIN_NAMESPACE # define DEBUG if (false) qDebug #endif +static Qt::HANDLE createChangeNotification(const QString &path, uint flags) +{ + // Volume and folder paths need a trailing slash for proper notification + // (e.g. "c:" -> "c:/"). + QString nativePath = QDir::toNativeSeparators(path); + if ((flags & FILE_NOTIFY_CHANGE_ATTRIBUTES) == 0 && !nativePath.endsWith(QLatin1Char('\\'))) + nativePath.append(QLatin1Char('\\')); + const HANDLE result = FindFirstChangeNotification(reinterpret_cast<const wchar_t *>(nativePath.utf16()), + FALSE, flags); + DEBUG() << __FUNCTION__ << nativePath << hex <<showbase << flags << "returns" << result; + return result; +} + #ifndef Q_OS_WINRT /////////// // QWindowsRemovableDriveListener @@ -404,8 +417,29 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths, thread = *jt; QMutexLocker locker(&(thread->mutex)); - handle = thread->handleForDir.value(QFileSystemWatcherPathKey(absolutePath)); - if (handle.handle != INVALID_HANDLE_VALUE && handle.flags == flags) { + const auto hit = thread->handleForDir.find(QFileSystemWatcherPathKey(absolutePath)); + if (hit != thread->handleForDir.end() && hit.value().flags < flags) { + // Requesting to add a file whose directory has been added previously. + // Recreate the notification handle to add the missing notification attributes + // for files (FILE_NOTIFY_CHANGE_ATTRIBUTES...) + DEBUG() << "recreating" << absolutePath << hex << showbase << hit.value().flags + << "->" << flags; + const Qt::HANDLE fileHandle = createChangeNotification(absolutePath, flags); + if (fileHandle != INVALID_HANDLE_VALUE) { + const int index = thread->handles.indexOf(hit.value().handle); + const auto pit = thread->pathInfoForHandle.find(hit.value().handle); + Q_ASSERT(index != -1); + Q_ASSERT(pit != thread->pathInfoForHandle.end()); + FindCloseChangeNotification(hit.value().handle); + thread->handles[index] = hit.value().handle = fileHandle; + hit.value().flags = flags; + thread->pathInfoForHandle.insert(fileHandle, pit.value()); + thread->pathInfoForHandle.erase(pit); + } + } + // In addition, check on flags for sufficient notification attributes + if (hit != thread->handleForDir.end() && hit.value().flags >= flags) { + handle = hit.value(); // found a thread now insert... DEBUG() << "Found a thread" << thread; @@ -426,14 +460,9 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths, } // no thread found, first create a handle - if (handle.handle == INVALID_HANDLE_VALUE || handle.flags != flags) { + if (handle.handle == INVALID_HANDLE_VALUE) { DEBUG() << "No thread found"; - // Volume and folder paths need a trailing slash for proper notification - // (e.g. "c:" -> "c:/"). - const QString effectiveAbsolutePath = - isDir ? (absolutePath + QLatin1Char('/')) : absolutePath; - - handle.handle = FindFirstChangeNotification((wchar_t*) QDir::toNativeSeparators(effectiveAbsolutePath).utf16(), false, flags); + handle.handle = createChangeNotification(absolutePath, flags); handle.flags = flags; if (handle.handle == INVALID_HANDLE_VALUE) continue; diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 62e613ed14..69961ff76a 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -600,7 +600,12 @@ bool QFSFileEngine::setPermissions(uint perms) { Q_D(QFSFileEngine); QSystemError error; - if (!QFileSystemEngine::setPermissions(d->fileEntry, QFile::Permissions(perms), error, 0)) { + bool ok; + if (d->fd != -1) + ok = QFileSystemEngine::setPermissions(d->fd, QFile::Permissions(perms), error, 0); + else + ok = QFileSystemEngine::setPermissions(d->fileEntry, QFile::Permissions(perms), error, 0); + if (!ok) { setError(QFile::PermissionsError, error.toString()); return false; } diff --git a/src/corelib/io/qstorageinfo_win.cpp b/src/corelib/io/qstorageinfo_win.cpp index f02e46f095..3830c5480c 100644 --- a/src/corelib/io/qstorageinfo_win.cpp +++ b/src/corelib/io/qstorageinfo_win.cpp @@ -43,36 +43,52 @@ #include <QtCore/qfileinfo.h> #include <QtCore/qvarlengtharray.h> +#include "qfilesystementry_p.h" + #include <qt_windows.h> QT_BEGIN_NAMESPACE static const int defaultBufferSize = MAX_PATH + 1; -void QStorageInfoPrivate::initRootPath() +static QString canonicalPath(const QString &rootPath) { - rootPath = QFileInfo(rootPath).canonicalFilePath(); - - if (rootPath.isEmpty()) - return; - - QString path = QDir::toNativeSeparators(rootPath); - rootPath.clear(); + QString path = QDir::toNativeSeparators(QFileInfo(rootPath).canonicalFilePath()); + if (path.isEmpty()) + return path; if (path.startsWith(QLatin1String("\\\\?\\"))) path.remove(0, 4); if (path.length() < 2 || path.at(1) != QLatin1Char(':')) - return; + return QString(); + path[0] = path[0].toUpper(); if (!(path.at(0).unicode() >= 'A' && path.at(0).unicode() <= 'Z')) - return; + return QString(); if (!path.endsWith(QLatin1Char('\\'))) path.append(QLatin1Char('\\')); + return path; +} + +void QStorageInfoPrivate::initRootPath() +{ + // Do not unnecessarily call QFileInfo::canonicalFilePath() if the path is + // already a drive root since it may hang on network drives. + const QString path = QFileSystemEntry::isDriveRootPath(rootPath) + ? QDir::toNativeSeparators(rootPath) + : canonicalPath(rootPath); + + if (path.isEmpty()) { + valid = ready = false; + return; + } // ### test if disk mounted to folder on other disk wchar_t buffer[defaultBufferSize]; if (::GetVolumePathName(reinterpret_cast<const wchar_t *>(path.utf16()), buffer, defaultBufferSize)) rootPath = QDir::fromNativeSeparators(QString::fromWCharArray(buffer)); + else + valid = ready = false; } static inline QByteArray getDevice(const QString &rootPath) @@ -108,11 +124,14 @@ static inline QByteArray getDevice(const QString &rootPath) void QStorageInfoPrivate::doStat() { + valid = ready = true; initRootPath(); - if (rootPath.isEmpty()) + if (!valid || !ready) return; retrieveVolumeInfo(); + if (!valid || !ready) + return; device = getDevice(rootPath); retrieveDiskFreeSpace(); } @@ -137,9 +156,6 @@ void QStorageInfoPrivate::retrieveVolumeInfo() ready = false; valid = ::GetLastError() == ERROR_NOT_READY; } else { - ready = true; - valid = true; - fileSystemType = QString::fromWCharArray(fileSystemTypeBuffer).toLatin1(); name = QString::fromWCharArray(nameBuffer); @@ -154,10 +170,10 @@ void QStorageInfoPrivate::retrieveDiskFreeSpace() const UINT oldmode = ::SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); const QString path = QDir::toNativeSeparators(rootPath); - ::GetDiskFreeSpaceEx(reinterpret_cast<const wchar_t *>(path.utf16()), - PULARGE_INTEGER(&bytesAvailable), - PULARGE_INTEGER(&bytesTotal), - PULARGE_INTEGER(&bytesFree)); + ready = ::GetDiskFreeSpaceEx(reinterpret_cast<const wchar_t *>(path.utf16()), + PULARGE_INTEGER(&bytesAvailable), + PULARGE_INTEGER(&bytesTotal), + PULARGE_INTEGER(&bytesFree)); ::SetErrorMode(oldmode); } diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index a08021be96..6141a73966 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1911,8 +1911,8 @@ void QCoreApplication::quit() Installing or removing a QTranslator, or changing an installed QTranslator generates a \l{QEvent::LanguageChange}{LanguageChange} event for the - QCoreApplication instance. A QGuiApplication instance will propagate the event - to all toplevel windows, where a reimplementation of changeEvent can + QCoreApplication instance. A QApplication instance will propagate the event + to all toplevel widgets, where a reimplementation of changeEvent can re-translate the user interface by passing user-visible strings via the tr() function to the respective property setters. User-interface classes generated by Qt Designer provide a \c retranslateUi() function that can be diff --git a/src/corelib/kernel/qdeadlinetimer.cpp b/src/corelib/kernel/qdeadlinetimer.cpp index a2ec813f11..ae4ffdcefc 100644 --- a/src/corelib/kernel/qdeadlinetimer.cpp +++ b/src/corelib/kernel/qdeadlinetimer.cpp @@ -420,7 +420,7 @@ void QDeadlineTimer::setTimerType(Qt::TimerType timerType) qint64 QDeadlineTimer::remainingTime() const Q_DECL_NOTHROW { qint64 ns = remainingTimeNSecs(); - return ns <= 0 ? ns : ns / (1000 * 1000); + return ns <= 0 ? ns : (ns + 999999) / (1000 * 1000); } /*! diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index b6307fcfcf..5fc8937f23 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -205,6 +205,7 @@ private: \ QT_ANNOTATE_CLASS(qt_qgadget, "") \ /*end*/ +/* qmake ignore Q_NAMESPACE */ #define Q_NAMESPACE \ extern const QMetaObject staticMetaObject; \ QT_ANNOTATE_CLASS(qt_qnamespace, "") \ diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 17c94e4e9d..e6262124fb 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -855,6 +855,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) if (qstrcmp(QMetaType::typeName(d->type), "QMap<QString, QVariant>") == 0) { *static_cast<QVariantMap *>(result) = *static_cast<QMap<QString, QVariant> *>(d->data.shared->ptr); + } else if (d->type == QVariant::Hash) { + QVariantMap *map = static_cast<QVariantMap *>(result); + const QVariantHash *hash = v_cast<QVariantHash>(d); + const auto end = hash->end(); + for (auto it = hash->begin(); it != end; ++it) + map->insertMulti(it.key(), it.value()); #ifndef QT_BOOTSTRAPPED } else if (d->type == QMetaType::QJsonValue) { if (!v_cast<QJsonValue>(d)->isObject()) @@ -871,6 +877,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) if (qstrcmp(QMetaType::typeName(d->type), "QHash<QString, QVariant>") == 0) { *static_cast<QVariantHash *>(result) = *static_cast<QHash<QString, QVariant> *>(d->data.shared->ptr); + } else if (d->type == QVariant::Map) { + QVariantHash *hash = static_cast<QVariantHash *>(result); + const QVariantMap *map = v_cast<QVariantMap>(d); + const auto end = map->end(); + for (auto it = map->begin(); it != end; ++it) + hash->insertMulti(it.key(), it.value()); #ifndef QT_BOOTSTRAPPED } else if (d->type == QMetaType::QJsonValue) { if (!v_cast<QJsonValue>(d)->isObject()) @@ -2070,6 +2082,7 @@ void QVariant::load(QDataStream &s) typeId = QMetaType::type(name.constData()); if (typeId == QMetaType::UnknownType) { s.setStatus(QDataStream::ReadCorruptData); + qWarning("QVariant::load: unknown user type with name %s.", name.constData()); return; } } diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index bbac058f2f..3ecb2ac662 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -1583,13 +1583,13 @@ void QByteArray::chop(int n) \snippet code/src_corelib_tools_qbytearray.cpp 12 Note: QByteArray is an \l{implicitly shared} class. Consequently, - if \e this is an empty QByteArray, then \e this will just share - the data held in \a ba. In this case, no copying of data is done, + if you append to an empty byte array, then the byte array will just + share the data held in \a ba. In this case, no copying of data is done, taking \l{constant time}. If a shared instance is modified, it will be copied (copy-on-write), taking \l{linear time}. - If \e this is not an empty QByteArray, a deep copy of the data is - performed, taking \l{linear time}. + If the byte array being appended to is not empty, a deep copy of the + data is performed, taking \l{linear time}. This operation typically does not suffer from allocation overhead, because QByteArray preallocates extra space at the end of the data @@ -1848,13 +1848,13 @@ QByteArray QByteArray::nulTerminated() const This is the same as insert(0, \a ba). Note: QByteArray is an \l{implicitly shared} class. Consequently, - if \e this is an empty QByteArray, then \e this will just share - the data held in \a ba. In this case, no copying of data is done, + if you prepend to an empty byte array, then the byte array will just + share the data held in \a ba. In this case, no copying of data is done, taking \l{constant time}. If a shared instance is modified, it will be copied (copy-on-write), taking \l{linear time}. - If \e this is not an empty QByteArray, a deep copy of the data is - performed, taking \l{linear time}. + If the byte array being prepended to is not empty, a deep copy of the + data is performed, taking \l{linear time}. \sa append(), insert() */ @@ -1936,13 +1936,13 @@ QByteArray &QByteArray::prepend(char ch) This is the same as insert(size(), \a ba). Note: QByteArray is an \l{implicitly shared} class. Consequently, - if \e this is an empty QByteArray, then \e this will just share - the data held in \a ba. In this case, no copying of data is done, + if you append to an empty byte array, then the byte array will just + share the data held in \a ba. In this case, no copying of data is done, taking \l{constant time}. If a shared instance is modified, it will be copied (copy-on-write), taking \l{linear time}. - If \e this is not an empty QByteArray, a deep copy of the data is - performed, taking \l{linear time}. + If the byte array being appended to is not empty, a deep copy of the + data is performed, taking \l{linear time}. This operation typically does not suffer from allocation overhead, because QByteArray preallocates extra space at the end of the data diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 5b15ffad9d..88270643d9 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -1647,10 +1647,14 @@ QString QTime::toString(Qt::DateFormat format) const \li the hour with a leading zero (00 to 23, even with AM/PM display) \row \li m \li the minute without a leading zero (0 to 59) \row \li mm \li the minute with a leading zero (00 to 59) - \row \li s \li the second without a leading zero (0 to 59) - \row \li ss \li the second with a leading zero (00 to 59) - \row \li z \li the milliseconds without leading zeroes (0 to 999) - \row \li zzz \li the milliseconds with leading zeroes (000 to 999) + \row \li s \li the whole second, without any leading zero (0 to 59) + \row \li ss \li the whole second, with a leading zero where applicable (00 to 59) + \row \li z \li the fractional part of the second, to go after a decimal + point, without trailing zeroes (0 to 999). Thus "\c{s.z}" + reports the seconds to full available (millisecond) precision + without trailing zeroes. + \row \li zzz \li the fractional part of the second, to millisecond + precision, including trailing zeroes where applicable (000 to 999). \row \li AP or A \li use AM/PM display. \e A/AP will be replaced by either QLocale::amText() or QLocale::pmText(). @@ -2005,10 +2009,14 @@ QTime QTime::fromString(const QString& string, Qt::DateFormat format) \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) \row \li m \li the minute without a leading zero (0 to 59) \row \li mm \li the minute with a leading zero (00 to 59) - \row \li s \li the second without a leading zero (0 to 59) - \row \li ss \li the second with a leading zero (00 to 59) - \row \li z \li the milliseconds without leading zeroes (0 to 999) - \row \li zzz \li the milliseconds with leading zeroes (000 to 999) + \row \li s \li the whole second, without any leading zero (0 to 59) + \row \li ss \li the whole second, with a leading zero where applicable (00 to 59) + \row \li z \li the fractional part of the second, to go after a decimal + point, without trailing zeroes (0 to 999). Thus "\c{s.z}" + reports the seconds to full available (millisecond) precision + without trailing zeroes. + \row \li zzz \li the fractional part of the second, to millisecond + precision, including trailing zeroes where applicable (000 to 999). \row \li AP \li interpret as an AM/PM time. \e AP must be either "AM" or "PM". \row \li ap @@ -3932,10 +3940,14 @@ QString QDateTime::toString(Qt::DateFormat format) const \li the hour with a leading zero (00 to 23, even with AM/PM display) \row \li m \li the minute without a leading zero (0 to 59) \row \li mm \li the minute with a leading zero (00 to 59) - \row \li s \li the second without a leading zero (0 to 59) - \row \li ss \li the second with a leading zero (00 to 59) - \row \li z \li the milliseconds without leading zeroes (0 to 999) - \row \li zzz \li the milliseconds with leading zeroes (000 to 999) + \row \li s \li the whole second without a leading zero (0 to 59) + \row \li ss \li the whole second with a leading zero where applicable (00 to 59) + \row \li z \li the fractional part of the second, to go after a decimal + point, without trailing zeroes (0 to 999). Thus "\c{s.z}" + reports the seconds to full available (millisecond) precision + without trailing zeroes. + \row \li zzz \li the fractional part of the second, to millisecond + precision, including trailing zeroes where applicable (000 to 999). \row \li AP or A \li use AM/PM display. \e A/AP will be replaced by either "AM" or "PM". \row \li ap or a @@ -3949,13 +3961,14 @@ QString QDateTime::toString(Qt::DateFormat format) const in the output. Formats without separators (e.g. "HHmm") are currently not supported. Example format strings (assumed that the QDateTime is 21 May 2001 - 14:13:09): + 14:13:09.120): \table \header \li Format \li Result \row \li dd.MM.yyyy \li 21.05.2001 \row \li ddd MMMM d yy \li Tue May 21 01 - \row \li hh:mm:ss.zzz \li 14:13:09.042 + \row \li hh:mm:ss.zzz \li 14:13:09.120 + \row \li hh:mm:ss.z \li 14:13:09.12 \row \li h:m:s ap \li 2:13:9 pm \endtable @@ -4963,10 +4976,14 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format) \li the hour with a leading zero (00 to 23, even with AM/PM display) \row \li m \li the minute without a leading zero (0 to 59) \row \li mm \li the minute with a leading zero (00 to 59) - \row \li s \li the second without a leading zero (0 to 59) - \row \li ss \li the second with a leading zero (00 to 59) - \row \li z \li the milliseconds without leading zeroes (0 to 999) - \row \li zzz \li the milliseconds with leading zeroes (000 to 999) + \row \li s \li the whole second without a leading zero (0 to 59) + \row \li ss \li the whole second with a leading zero where applicable (00 to 59) + \row \li z \li the fractional part of the second, to go after a decimal + point, without trailing zeroes (0 to 999). Thus "\c{s.z}" + reports the seconds to full available (millisecond) precision + without trailing zeroes. + \row \li zzz \li the fractional part of the second, to millisecond + precision, including trailing zeroes where applicable (000 to 999). \row \li AP or A \li interpret as an AM/PM time. \e AP must be either "AM" or "PM". \row \li ap or a diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 43d83db835..789a15dded 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -2964,14 +2964,17 @@ QString QLocalePrivate::dateTimeToString(QStringView format, const QDateTime &da } else { repeat = 1; } - switch (repeat) { - case 1: - result.append(m_data->longLongToString(time.msec())); - break; - case 3: - result.append(m_data->longLongToString(time.msec(), -1, 10, 3, QLocaleData::ZeroPadded)); - break; + + // note: the millisecond component is treated like the decimal part of the seconds + // so ms == 2 is always printed as "002", but ms == 200 can be either "2" or "200" + result.append(m_data->longLongToString(time.msec(), -1, 10, 3, QLocaleData::ZeroPadded)); + if (repeat == 1) { + if (result.endsWith(zero())) + result.chop(1); + if (result.endsWith(zero())) + result.chop(1); } + break; case 't': |