summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/Qt5ModuleLocationForInstall.cmake.in4
-rw-r--r--src/corelib/global/qcompilerdetection.h4
-rw-r--r--src/corelib/global/qglobal.h14
-rw-r--r--src/corelib/global/qversiontagging.h2
-rw-r--r--src/corelib/io/io.pri5
-rw-r--r--src/corelib/io/qfile.cpp8
-rw-r--r--src/corelib/io/qfilesystemengine_p.h2
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp43
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp6
-rw-r--r--src/corelib/io/qfilesystemwatcher_win.cpp47
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp7
-rw-r--r--src/corelib/io/qstorageinfo_win.cpp52
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp4
-rw-r--r--src/corelib/kernel/qdeadlinetimer.cpp2
-rw-r--r--src/corelib/kernel/qobjectdefs.h1
-rw-r--r--src/corelib/kernel/qvariant.cpp13
-rw-r--r--src/corelib/tools/qbytearray.cpp24
-rw-r--r--src/corelib/tools/qdatetime.cpp53
-rw-r--r--src/corelib/tools/qlocale.cpp17
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':