From 313c3cabe41001c19fa1db725db605ec95781cd4 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 5 Jul 2017 13:33:13 +0200 Subject: Prevent qmake to run moc on qobjectdefs.h Change-Id: Ic453c88c36cbeb24f3dc4fa6b6b20aabe5d24e09 Reviewed-by: Oswald Buddenhagen --- src/corelib/kernel/qobjectdefs.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index ea4046df55..cec822ad14 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -206,6 +206,7 @@ private: \ QT_ANNOTATE_CLASS(qt_qgadget, "") \ /*end*/ +/* qmake ignore Q_NAMESPACE */ #define Q_NAMESPACE \ extern const QMetaObject staticMetaObject; \ QT_ANNOTATE_CLASS(qt_qnamespace, "") \ -- cgit v1.2.3 From 7d42293d2fcf466ebf2c99f49b4d15a73947691e Mon Sep 17 00:00:00 2001 From: Michael Winkelmann Date: Wed, 5 Jul 2017 14:43:30 +0200 Subject: QVariant: Print a warning when deserialized user type is unknown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The deserialized user type is now shown to the user to figure which QMetaType registration is missing. Change-Id: I4b7624827e479b1bea67065ce3542183b7355165 Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qvariant.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 17c94e4e9d..f114a84d22 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -2070,6 +2070,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; } } -- cgit v1.2.3 From f065d0f128a09b3faec2a4d3ee6b0952b486e471 Mon Sep 17 00:00:00 2001 From: Stephan Binner Date: Tue, 4 Jul 2017 19:21:36 +0200 Subject: Fix Windows build without features.filesytemiterator Task-number: QTBUG-61671 Change-Id: I65a96ca51efee303602c836e5b0177b1a63d1a7a Reviewed-by: Oswald Buddenhagen --- src/corelib/io/io.pri | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index b0cac59f42..d24c290508 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 += \ -- cgit v1.2.3 From fb13510681952abaf475b5188dd3333503501369 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 2 Jul 2017 15:45:02 -0700 Subject: QFileSystemEngine::fillMetaData: fix apparent use of dangling pointer It's not dangling only because of QFileSystemMetaData's construction: the nativeFilePath() function returns a member variable. Since QByteArray COWs, the pointer that we stored would not be freed. But this was dangerous, since any change to the "entry" variable could cause it to invalidate the member variable and the pointer to become dangling. This line is only as old as this entire file is. Change-Id: I8d96dea9955d4c749b99fffd14cda4d8e2cc5e5b Reviewed-by: Lars Knoll --- src/corelib/io/qfilesystemengine_unix.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index e195afdae9..4ffa6b8972 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -449,15 +449,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; -- cgit v1.2.3 From 08a39ecf332e96444ce6b2fb0502c569935fad6a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 29 Jun 2017 10:38:13 -0700 Subject: QFileSystemEngine/Unix: use fchmod(2) if the file is open This protects against the file having been renamed or deleted. We'll still operate on the open file, regardless the name it may have on the filesystem. Change-Id: I1eba2b016de74620bfc8fffd14cca85cfd672e6d Reviewed-by: Lars Knoll --- src/corelib/io/qfilesystemengine_p.h | 2 ++ src/corelib/io/qfilesystemengine_unix.cpp | 26 ++++++++++++++++++++++++-- src/corelib/io/qfsfileengine_unix.cpp | 7 ++++++- 3 files changed, 32 insertions(+), 3 deletions(-) (limited to 'src/corelib') 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 4ffa6b8972..b26ab2c903 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -659,8 +659,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)) @@ -681,6 +680,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) { @@ -693,6 +699,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/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index e152b035e2..3f4f593d81 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -654,7 +654,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; } -- cgit v1.2.3 From f6ac7379ae0b593a2594d3c06f784109b94a28f0 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 29 Jun 2017 11:17:23 -0700 Subject: QFileSystemEngine::id: use the proper QT_STATBUF/QT_STAT Just in case. Change-Id: I1eba2b016de74620bfc8fffd14ccaa801805ae02 Reviewed-by: Lars Knoll --- src/corelib/io/qfilesystemengine_unix.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index b26ab2c903..90e4faaf50 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -336,8 +336,8 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry) //static QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry) { - struct stat statResult; - if (stat(entry.nativeFilePath().constData(), &statResult)) { + QT_STATBUF statResult; + if (QT_STAT(entry.nativeFilePath().constData(), &statResult)) { qErrnoWarning("stat() failed for '%s'", entry.nativeFilePath().constData()); return QByteArray(); } -- cgit v1.2.3 From e1d7f7dfbc0191f585fde8695d315e3ffb98ccc5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 6 Jul 2017 12:38:31 +0200 Subject: QFileSystemWatcher/Windows: Recreate handle for files QWindowsFileSystemWatcherEngine uses one change notification per directory to watch directories or files within that directory. Adding files and their directories in a sequence caused the value in QWindowsFileSystemWatcherEngineThread::HandleForDirHash to be overwritten. Relax the check for the flags (watcher attributes) to use >= and recreate the change notification of a directory should its flags be insufficient. This triggers when a file is added after its directory since files require more attributes. Task-number: QTBUG-61792 Change-Id: I371a72f1934fa82c53aaf84beb907825031f1c81 Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemwatcher_win.cpp | 47 +++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 9 deletions(-) (limited to 'src/corelib') 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(nativePath.utf16()), + FALSE, flags); + DEBUG() << __FUNCTION__ << nativePath << hex <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; -- cgit v1.2.3 From bcd19b723a4adad4d5f1dbbd35079cc24331dfa8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 30 Sep 2016 11:18:05 -0700 Subject: QLocale: fix handling of milliseconds in string format and document [ChangeLog][QtCore][QLocale] Fixed the conversion of QTime to string form and parsing from string form to always treat the value as the decimal fraction of the seconds component. That is, the string format ".z" produces/parses ".2" for 200 milliseconds and ".002" for 2 milliseconds. Use of "z" or "zzz" is discouraged outside decimal fractions to avoid surprises. Task-number: QTBUG-53565 Change-Id: Ia19de85ad35e4eb7bb95fffd14792caf9b4a5156 Reviewed-by: Edward Welbourne --- src/corelib/tools/qdatetime.cpp | 53 +++++++++++++++++++++++++++-------------- src/corelib/tools/qlocale.cpp | 17 +++++++------ 2 files changed, 45 insertions(+), 25 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index bcdbc5af2a..11c023f762 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -1642,10 +1642,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(). @@ -1991,10 +1995,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 @@ -3895,10 +3903,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 @@ -3912,13 +3924,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 @@ -4918,10 +4931,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 dcdf6b5ed7..ab95f60115 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -2742,14 +2742,17 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDateTime } 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': -- cgit v1.2.3 From 35096261282bfb2d66373d290dfa35b993158bb8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 5 Jul 2017 21:52:52 -0700 Subject: QDeadlineTimer: round milliseconds up instead of down Code like: QElapsedTimer timer; timer.start(); QTest::qWait(30); QVERIFY(timer.elapsed() >= 30); is failing, because qWait sleeps in increments of 10 ms and the last chunk may be off by less than one millisecond, so we end up sleeping too little and thus returning before 30 ms have elapsed. This matches the QElapsedTimer::elapsed() code that rounds down: return nsecsElapsed() / Q_INT64_C(1000000); Task-number: QTBUG-61741 Change-Id: Ic3a088f9f08a4fd7ae91fffd14cea4a91d3f51a8 Reviewed-by: Allan Sandfeld Jensen --- src/corelib/kernel/qdeadlinetimer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') 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); } /*! -- cgit v1.2.3 From 9bec818ccc0c0eddd3029540f65e3be26eae29db Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 13 Jun 2017 09:44:46 -0700 Subject: Use the namespace-mangled symbol for the qt_version_tag group name Doesn't affect our current builds since it's just a marker for the linker on what sections should be merged. Unless you're mixing namespaced and non-namespaced static builds into one executable. Change-Id: Ia53158e207a94bf49489fffd14c7bc294fccf8f9 Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/global/qversiontagging.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') 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" \ -- cgit v1.2.3 From fd95ef765afa3b0fd9996a31546d098465b927fe Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 29 Jun 2017 12:35:01 -0700 Subject: QFile::rename: avoid two stat(2)/CreateFile in a row MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QFileSystemEngine::id() will stat(2)/CreateFile in order to get the ID of the file anyway, so we don't need to use QFile::exists() to check if the destination exists. Instead, rely on id() returning a null value to indicate error. On Windows, it's possible that the calls to either GetFileInformationByHandle or GetFileInformationByHandleEx might fail, but we ignore those. Change-Id: I1eba2b016de74620bfc8fffd14ccaebcbed64419 Reviewed-by: Jędrzej Nowacki --- src/corelib/io/qfile.cpp | 8 +++++--- src/corelib/io/qfilesystemengine_unix.cpp | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 06d706b915..a840307145 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -567,9 +567,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_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 90e4faaf50..c3906c3207 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -338,7 +338,8 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry) { QT_STATBUF statResult; if (QT_STAT(entry.nativeFilePath().constData(), &statResult)) { - qErrnoWarning("stat() failed for '%s'", entry.nativeFilePath().constData()); + if (errno != ENOENT) + qErrnoWarning("stat() failed for '%s'", entry.nativeFilePath().constData()); return QByteArray(); } QByteArray result = QByteArray::number(quint64(statResult.st_dev), 16); -- cgit v1.2.3 From 8d542154a82e4a7b14cffbe46ae493085b9eb4f6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 5 Jul 2017 14:41:11 -0700 Subject: Avoid sharing violation in QFileSystemEngine::id on Windows We can't open a file for reading if the file is open by another process (or by ourselves) without sharing permitted. So ask for no access just so we can get a handle to it. Change-Id: I998653739e1cec2a58a07a6593b6ff87c1d59dd1 Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemengine_win.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index b1e218de9c..e4a7ea4891 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -612,13 +612,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); -- cgit v1.2.3 From 9db09b47000301bc3589278b076abdc111276304 Mon Sep 17 00:00:00 2001 From: Kevin Funk Date: Tue, 4 Jul 2017 11:36:34 +0200 Subject: Fix modernize-use-bool-literals issues Reported by clang-tidy. Skipped fixes in implementation files, only changed headers. Change-Id: I5cfd266b3d4046f90baebc0c538b1b6ab03a02d2 Reviewed-by: Volker Krause Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Marc Mutz Reviewed-by: Thiago Macieira --- src/corelib/global/qcompilerdetection.h | 4 ++-- src/corelib/global/qglobal.h | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src/corelib') 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 0c74ed4a3e..6023cc8564 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -339,10 +339,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: @@ -646,7 +646,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) @@ -654,9 +654,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 @@ -760,10 +760,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 -- cgit v1.2.3 From 1bc5f619ea1cae8cfec2ac53a8206ceb28845c8f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 13 Jun 2017 11:45:59 +0200 Subject: QStorageInfo/Windows: Improve error handling Bail out of QStorageInfoPrivate::doStats() should an error occur and set the ready/valid flags accordingly. Task-number: QTBUG-6039 Change-Id: Id5354b31329d951599ae991aa7edde0515c90514 Reviewed-by: Thiago Macieira --- src/corelib/io/qstorageinfo_win.cpp | 52 ++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 18 deletions(-) (limited to 'src/corelib') 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 #include +#include "qfilesystementry_p.h" + #include 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(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(path.utf16()), - PULARGE_INTEGER(&bytesAvailable), - PULARGE_INTEGER(&bytesTotal), - PULARGE_INTEGER(&bytesFree)); + ready = ::GetDiskFreeSpaceEx(reinterpret_cast(path.utf16()), + PULARGE_INTEGER(&bytesAvailable), + PULARGE_INTEGER(&bytesTotal), + PULARGE_INTEGER(&bytesFree)); ::SetErrorMode(oldmode); } -- cgit v1.2.3 From bb1e5675a5628b72edd32b975e78b7feba366ff9 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 9 Feb 2017 12:12:28 -0500 Subject: cmake: avoid `@var@` expansion in older CMake versions Older versions of CMake expanded `@var@` in CMake code, so this could be expanded at this location rather than the `string(CONFIGURE)` call if `module` were set inadvertently. Instead, hide the literal `@` symbol from CMake, but not from the string. This avoids a CMP0053 warning for projects using Qt5 with a minimum version set lower than 3.1 and silent bugs with projects explicitly setting CMP0053 to OLD. Change-Id: I0e4a86469fdf69b8706387799ab9b17498b8d1ca Reviewed-by: Stephen Kelly Reviewed-by: Oswald Buddenhagen --- src/corelib/Qt5ModuleLocationForInstall.cmake.in | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/corelib') 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) -- cgit v1.2.3 From b3f7bea10525a0b05a61f151f684b63d66488193 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 10 Jul 2017 14:25:48 +0200 Subject: Handle conversion and comparison between qvarianthash and qvariantmap QVariant claims to be able to QVariantHash and QVariantMap, but the actual conversion implementation is missing. Task-number: QTBUG-61471 Change-Id: I0cba74642aa77dc423effed289bc7619922a89eb Reviewed-by: Thiago Macieira --- src/corelib/kernel/qvariant.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index f114a84d22..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") == 0) { *static_cast(result) = *static_cast *>(d->data.shared->ptr); + } else if (d->type == QVariant::Hash) { + QVariantMap *map = static_cast(result); + const QVariantHash *hash = v_cast(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(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") == 0) { *static_cast(result) = *static_cast *>(d->data.shared->ptr); + } else if (d->type == QVariant::Map) { + QVariantHash *hash = static_cast(result); + const QVariantMap *map = v_cast(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(d)->isObject()) -- cgit v1.2.3 From bdca35e8154d6a8cb2232bd32c64c9e0ba3775c4 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 12 Jul 2017 16:00:05 +0200 Subject: Fix documentation of QEvent::LanguageChange propagation The documentation claims that QGuiApplication forwards the top-level windows. However this appears to be a search & replace mistake from the QApplication <> QGuiApplication separation times. Only QApplication forwards the event to top-level widgets and changeEvent() is a virtual method of QWidget. Nothing is implemented for plain QGuiApplication and QWindow. Change-Id: I71b05ecebc90f7c28e150590764438ebaa90e88f Reviewed-by: Michael Brasser --- src/corelib/kernel/qcoreapplication.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 39e7c71a9c..cba279c184 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1896,8 +1896,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 -- cgit v1.2.3 From 627f0a7f7d775ecd263b95dd07fca44bfcb0c5cf Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 3 Jul 2017 13:08:47 +0200 Subject: Doc: Improve documentation about append, prepend The references to the this pointer look somewhat alien in the documentation, because it isn't part of the signature. Rather make the relationship explicit. Change-Id: I6de516e165ea6e9c4ee2898836e9490fbaf4545c Reviewed-by: Thiago Macieira --- src/corelib/tools/qbytearray.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 38df38a32f..0e7365c32b 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -1516,13 +1516,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 @@ -1781,13 +1781,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() */ @@ -1869,13 +1869,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 -- cgit v1.2.3