diff options
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/doc/src/external-resources.qdoc | 30 | ||||
-rw-r--r-- | src/corelib/doc/src/includes/android-content-uri-limitations.qdocinc | 13 | ||||
-rw-r--r-- | src/corelib/doc/src/io.qdoc | 2 | ||||
-rw-r--r-- | src/corelib/io/qabstractfileengine_p.h | 2 | ||||
-rw-r--r-- | src/corelib/io/qbuffer.cpp | 4 | ||||
-rw-r--r-- | src/corelib/io/qdir.cpp | 19 | ||||
-rw-r--r-- | src/corelib/io/qfile.cpp | 5 | ||||
-rw-r--r-- | src/corelib/io/qfiledevice.cpp | 5 | ||||
-rw-r--r-- | src/corelib/io/qfileinfo.cpp | 22 | ||||
-rw-r--r-- | src/corelib/io/qfilesystemengine_unix.cpp | 13 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_mac.mm | 8 | ||||
-rw-r--r-- | src/corelib/text/qlocale_win.cpp | 14 | ||||
-rw-r--r-- | src/corelib/text/qstring.h | 5 | ||||
-rw-r--r-- | src/corelib/thread/qthreadpool.cpp | 4 | ||||
-rw-r--r-- | src/corelib/time/qtimezone.cpp | 14 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer.cpp | 49 | ||||
-rw-r--r-- | src/corelib/tools/qsharedpointer.h | 10 | ||||
-rw-r--r-- | src/corelib/tools/qtools_p.h | 11 | ||||
-rw-r--r-- | src/corelib/tools/qvarlengtharray.h | 29 |
19 files changed, 216 insertions, 43 deletions
diff --git a/src/corelib/doc/src/external-resources.qdoc b/src/corelib/doc/src/external-resources.qdoc index f16a21d521..0096bca948 100644 --- a/src/corelib/doc/src/external-resources.qdoc +++ b/src/corelib/doc/src/external-resources.qdoc @@ -65,3 +65,33 @@ \externalpage http://marcmutz.wordpress.com/effective-qt/containers/ \title Understand the Qt Containers */ + +/*! + \externalpage https://developer.android.com/training/data-storage/shared/documents-files + \title Android: Access documents and other files from shared storage +*/ + +/*! + \externalpage https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile#getParentFile() + \title Android: DocumentFile.getParentFile() +*/ + +/*! + \externalpage https://developer.android.com/guide/topics/providers/content-provider-basics#ContentURIs + \title Android: Content URIs +*/ + +/*! + \externalpage https://developer.android.com/training/data-storage#scoped-storage + \title Android: Scoped storage +*/ + +/*! + \externalpage https://developer.android.com/training/data-storage/use-cases + \title Android: storage best practices +*/ + +/*! + \externalpage https://developer.android.com/reference/android/provider/MediaStore + \title Android: MediaStore +*/ diff --git a/src/corelib/doc/src/includes/android-content-uri-limitations.qdocinc b/src/corelib/doc/src/includes/android-content-uri-limitations.qdocinc new file mode 100644 index 0000000000..f08086407e --- /dev/null +++ b/src/corelib/doc/src/includes/android-content-uri-limitations.qdocinc @@ -0,0 +1,13 @@ +On Android, some limitations apply when dealing with +\l {Android: Content URIs}{content URIs}: +\list + \li Access permissions might be needed by prompting the user through the + \l QFileDialog which implements + \l {Access documents and other files from shared storage}{Android's native file picker}. + \li Aim to follow the \l {Android: Scoped storage}{Scoped storage} guidelines, + such as using app specific directories instead of other public external directories. + For more information, also see + \l {Android: storage best practices}{storage best practices}. + \li Due to the design of Qt APIs (e.g. QFile), it's not possible to fully + integrate the latter APIs with Android's \l {Android: MediaStore}{MediaStore} APIs. +\endlist diff --git a/src/corelib/doc/src/io.qdoc b/src/corelib/doc/src/io.qdoc index a1bbc623a1..6315a069aa 100644 --- a/src/corelib/doc/src/io.qdoc +++ b/src/corelib/doc/src/io.qdoc @@ -34,7 +34,7 @@ network handling. These \l{Qt Core} classes are used to handle input and output to and from - external devices, processes, files etc. as well as manipulating files and + external devices, processes, files etc., as well as manipulating files and directories. */ diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h index c88b66c7ce..37b7b822fd 100644 --- a/src/corelib/io/qabstractfileengine_p.h +++ b/src/corelib/io/qabstractfileengine_p.h @@ -237,7 +237,7 @@ public: virtual QString currentFileName() const = 0; virtual QFileInfo currentFileInfo() const; - QString currentFilePath() const; + virtual QString currentFilePath() const; protected: enum EntryInfoType { diff --git a/src/corelib/io/qbuffer.cpp b/src/corelib/io/qbuffer.cpp index 5c562623e2..8771ac3764 100644 --- a/src/corelib/io/qbuffer.cpp +++ b/src/corelib/io/qbuffer.cpp @@ -319,6 +319,10 @@ void QBuffer::setData(const QByteArray &data) /*! \reimp + + Unlike QFile, opening a QBuffer QIODevice::WriteOnly does not truncate it. + However, pos() is set to 0. Use QIODevice::Append or QIODevice::Truncate to + change either behavior. */ bool QBuffer::open(OpenMode flags) { diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 7a3e68a19a..b89e665d20 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -554,6 +554,10 @@ inline void QDirPrivate::initFileEngine() \snippet qdir-listfiles/main.cpp 0 + \section1 Platform Specific Issues + + \include android-content-uri-limitations.qdocinc + \sa QFileInfo, QFile, QFileDialog, QCoreApplication::applicationDirPath(), {Find Files Example} */ @@ -673,8 +677,12 @@ QString QDir::path() const QString QDir::absolutePath() const { const QDirPrivate* d = d_ptr.constData(); - d->resolveAbsoluteEntry(); - return d->absoluteDirEntry.filePath(); + if (!d->fileEngine) { + d->resolveAbsoluteEntry(); + return d->absoluteDirEntry.filePath(); + } + + return d->fileEngine->fileName(QAbstractFileEngine::AbsoluteName); } /*! @@ -717,7 +725,9 @@ QString QDir::canonicalPath() const QString QDir::dirName() const { const QDirPrivate* d = d_ptr.constData(); - return d->dirEntry.fileName(); + if (!d_ptr->fileEngine) + return d->dirEntry.fileName(); + return d->fileEngine->fileName(QAbstractFileEngine::BaseName); } @@ -1037,6 +1047,9 @@ bool QDir::cd(const QString &dirName) otherwise returns \c false. Note that the logical cdUp() operation is not performed if the new directory does not exist. + \note On Android, this is not supported for content URIs. For more information, + see \l {Android: DocumentFile.getParentFile()}{DocumentFile.getParentFile()}. + \sa cd(), isReadable(), exists(), path() */ bool QDir::cdUp() diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 14ce49da56..3bf6ddbc41 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -229,6 +229,8 @@ QAbstractFileEngine *QFilePrivate::engine() const function mostly useless for NTFS volumes. It may still be of use for USB sticks that use VFAT file systems. POSIX ACLs are not manipulated, either. + \include android-content-uri-limitations.qdocinc + \sa QTextStream, QDataStream, QFileInfo, QDir, {The Qt Resource System} */ @@ -961,6 +963,9 @@ QFile::copy(const QString &fileName, const QString &newName) \note In \l{QIODevice::}{WriteOnly} or \l{QIODevice::}{ReadWrite} mode, if the relevant file does not already exist, this function will try to create a new file before opening it. + On Android, it's expected to have access permission to the parent + of the file name, otherwise, it won't be possible to create this + non-existing file. \sa QIODevice::OpenMode, setFileName() */ diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp index b0aba3193c..d70b9f1c73 100644 --- a/src/corelib/io/qfiledevice.cpp +++ b/src/corelib/io/qfiledevice.cpp @@ -148,6 +148,11 @@ void QFileDevicePrivate::setError(QFileDevice::FileError err, int errNum) decrementing \c qt_ntfs_permission_lookup by 1. \snippet ntfsp.cpp 1 + + \note Since this is a non-atomic global variable, it is only safe + to increment or decrement \c qt_ntfs_permission_lookup before any + threads other than the main thread have started or after every thread + other than the main thread has ended. */ //************* QFileDevice diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index e73a6f4946..b5f5003f93 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -294,6 +294,11 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) \snippet ntfsp.cpp 1 + \note Since this is a non-atomic global variable, it is only safe + to increment or decrement \c qt_ntfs_permission_lookup before any + threads other than the main thread have started or after every thread + other than the main thread has ended. + \section1 Performance Issues Some of QFileInfo's functions query the file system, but for @@ -312,6 +317,10 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) off a QFileInfo's caching and force it to access the file system every time you request information from it call setCaching(false). + \section1 Platform Specific Issues + + \include android-content-uri-limitations.qdocinc + \sa QDir, QFile */ @@ -767,7 +776,9 @@ QString QFileInfo::fileName() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return QLatin1String(""); - return d->fileEntry.fileName(); + if (!d->fileEngine) + return d->fileEntry.fileName(); + return d->fileEngine->fileName(QAbstractFileEngine::BaseName); } /*! @@ -811,7 +822,9 @@ QString QFileInfo::baseName() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return QLatin1String(""); - return d->fileEntry.baseName(); + if (!d->fileEngine) + return d->fileEntry.baseName(); + return QFileSystemEntry(d->fileEngine->fileName(QAbstractFileEngine::BaseName)).baseName(); } /*! @@ -830,7 +843,10 @@ QString QFileInfo::completeBaseName() const Q_D(const QFileInfo); if (d->isDefaultConstructed) return QLatin1String(""); - return d->fileEntry.completeBaseName(); + if (!d->fileEngine) + return d->fileEntry.completeBaseName(); + const QString fileEngineBaseName = d->fileEngine->fileName(QAbstractFileEngine::BaseName); + return QFileSystemEntry(fileEngineBaseName).completeBaseName(); } /*! diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 42739097f2..01aed7ad14 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -44,6 +44,7 @@ #include "qfile.h" #include "qstorageinfo.h" #include "qtextstream.h" +#include "qurl.h" #include <QtCore/qoperatingsystemversion.h> #include <QtCore/private/qcore_unix_p.h> @@ -1392,6 +1393,16 @@ bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source, const QString targetPath = trashDir.filePath(filesDir) + uniqueTrashedName; const QFileSystemEntry target(targetPath); + QString infoPath; + const QStorageInfo storageInfo(sourcePath); + if (storageInfo.isValid() && storageInfo.rootPath() != rootPath() && storageInfo != QStorageInfo(QDir::home())) { + infoPath = sourcePath.mid(storageInfo.rootPath().length()); + if (infoPath.front() == u'/') + infoPath = infoPath.mid(1); + } else { + infoPath = sourcePath; + } + /* We might fail to rename if source and target are on different file systems. In that case, we don't try further, i.e. copying and removing the original @@ -1408,7 +1419,7 @@ bool QFileSystemEngine::moveFileToTrash(const QFileSystemEntry &source, out.setCodec("UTF-8"); #endif out << "[Trash Info]" << Qt::endl; - out << "Path=" << sourcePath << Qt::endl; + out << "Path=" << QUrl::toPercentEncoding(infoPath, "/") << Qt::endl; out << "DeletionDate=" << QDateTime::currentDateTime().toString(QLatin1String("yyyy-MM-ddThh:mm:ss")) << Qt::endl; infoFile.close(); diff --git a/src/corelib/kernel/qcore_mac.mm b/src/corelib/kernel/qcore_mac.mm index 99ad4ce666..0b64deff4b 100644 --- a/src/corelib/kernel/qcore_mac.mm +++ b/src/corelib/kernel/qcore_mac.mm @@ -606,6 +606,14 @@ void qt_apple_check_os_version() const NSOperatingSystemVersion required = (NSOperatingSystemVersion){ version / 10000, version / 100 % 100, version % 100}; const NSOperatingSystemVersion current = NSProcessInfo.processInfo.operatingSystemVersion; + +#if defined(Q_OS_MACOS) + // Check for compatibility version, in which case we can't do a + // comparison to the deployment target, which might be e.g. 11.0 + if (current.majorVersion == 10 && current.minorVersion >= 16) + return; // FIXME: Find a way to detect the real OS version +#endif + if (![NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:required]) { NSDictionary *plist = NSBundle.mainBundle.infoDictionary; NSString *applicationName = plist[@"CFBundleDisplayName"]; diff --git a/src/corelib/text/qlocale_win.cpp b/src/corelib/text/qlocale_win.cpp index ce060cbe9a..9d9cefecba 100644 --- a/src/corelib/text/qlocale_win.cpp +++ b/src/corelib/text/qlocale_win.cpp @@ -489,15 +489,17 @@ QVariant QSystemLocalePrivate::toString(QTime time, QLocale::FormatType type) DWORD flags = 0; // keep the same conditional as timeFormat() above - if (type == QLocale::ShortFormat) - flags = TIME_NOSECONDS; + const QString format = type == QLocale::ShortFormat + ? getLocaleInfo(LOCALE_SSHORTTIME) + : QString(); + auto formatStr = reinterpret_cast<const wchar_t *>(format.isEmpty() ? nullptr : format.utf16()); wchar_t buf[255]; - if (getTimeFormat(flags, &st, NULL, buf, 255)) { - QString format = QString::fromWCharArray(buf); + if (getTimeFormat(flags, &st, formatStr, buf, int(std::size(buf)))) { + QString text = QString::fromWCharArray(buf); if (substitution() == SAlways) - substituteDigits(format); - return format; + substituteDigits(text); + return text; } return QString(); } diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h index 0fdab96e28..5bec5dffbe 100644 --- a/src/corelib/text/qstring.h +++ b/src/corelib/text/qstring.h @@ -361,14 +361,11 @@ public: #endif private: template <typename T> - struct is_convertible_to_view_or_qstring_helper + struct is_convertible_to_view_or_qstring : std::integral_constant<bool, std::is_convertible<T, QString>::value || std::is_convertible<T, QStringView>::value || std::is_convertible<T, QLatin1String>::value> {}; - template <typename T> - struct is_convertible_to_view_or_qstring - : is_convertible_to_view_or_qstring_helper<typename std::decay<T>::type> {}; public: template <typename...Args> Q_REQUIRED_RESULT diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index cdeb077233..5b1e4f4c33 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -602,8 +602,12 @@ bool QThreadPool::tryStart(std::function<void()> functionToRun) return false; QRunnable *runnable = QRunnable::create(std::move(functionToRun)); + Q_ASSERT(runnable->ref == 0); + ++runnable->ref; if (d->tryStart(runnable)) return true; + --runnable->ref; + Q_ASSERT(runnable->ref == 0); delete runnable; return false; } diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp index 0309e43e52..3d451696a1 100644 --- a/src/corelib/time/qtimezone.cpp +++ b/src/corelib/time/qtimezone.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 John Layt <jlayt@kde.org> +** Copyright (C) 2020 John Layt <jlayt@kde.org> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -975,9 +975,15 @@ QList<QByteArray> QTimeZone::windowsIdToIanaIds(const QByteArray &windowsId, } #ifndef QT_NO_DATASTREAM +// Invalid, as an IANA ID: too long, starts with - and has other invalid characters in it +static inline QString invalidId() { return QStringLiteral("-No Time Zone Specified!"); } + QDataStream &operator<<(QDataStream &ds, const QTimeZone &tz) { - tz.d->serialize(ds); + if (tz.isValid()) + tz.d->serialize(ds); + else + ds << invalidId(); return ds; } @@ -985,7 +991,9 @@ QDataStream &operator>>(QDataStream &ds, QTimeZone &tz) { QString ianaId; ds >> ianaId; - if (ianaId == QLatin1String("OffsetFromUtc")) { + if (ianaId == invalidId()) { + tz = QTimeZone(); + } else if (ianaId == QLatin1String("OffsetFromUtc")) { int utcOffset; QString name; QString abbreviation; diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index 7becff8700..bc7a5f80d7 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -479,6 +479,46 @@ */ /*! + \fn template <class T> QSharedPointer<T>::QSharedPointer(QSharedPointer &&other) + + Move-constructs a QSharedPointer instance, making it point at the same + object that \a other was pointing to. + + \since 5.4 +*/ + +/*! + \fn template <class T> QSharedPointer<T>::operator=(QSharedPointer &&other) + + Move-assigns \a other to this QSharedPointer instance. + + \since 5.0 +*/ + +/*! + \fn template <class T> template <class X> QSharedPointer<T>::QSharedPointer(QSharedPointer<X> &&other) + + Move-constructs a QSharedPointer instance, making it point at the same + object that \a other was pointing to. + + This constructor participates in overload resolution only if \c{X*} + implicitly converts to \c{T*}. + + \since 5.6 +*/ + +/*! + \fn template <class T> template <class X> QSharedPointer<T>::operator=(QSharedPointer<X> &&other) + + Move-assigns \a other to this QSharedPointer instance. + + This assignment operator participates in overload resolution only if \c{X*} + implicitly converts to \c{T*}. + + \since 5.6 +*/ + +/*! \fn template <class T> QSharedPointer<T>::QSharedPointer(const QWeakPointer<T> &other) Creates a QSharedPointer by promoting the weak reference \a other @@ -932,6 +972,15 @@ */ /*! + \fn template <class T> qHash(const QSharedPointer<T> &key, size_t seed) + \relates QSharedPointer + + Returns the hash value for \a key, using \a seed to seed the calculation. + + \since 5.0 +*/ + +/*! \fn template <class T> template <class X> bool operator==(const QSharedPointer<T> &ptr1, const QSharedPointer<X> &ptr2) \relates QSharedPointer diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h index 5d47369687..72e48d8a16 100644 --- a/src/corelib/tools/qsharedpointer.h +++ b/src/corelib/tools/qsharedpointer.h @@ -82,7 +82,12 @@ public: QSharedPointer<T> &operator=(const QSharedPointer<T> &other); QSharedPointer<T> &operator=(const QWeakPointer<T> &other); - void swap(QSharedPointer<T> &other); + template <class X> + QSharedPointer(QSharedPointer<X> && other) noexcept; + template <class X> + QSharedPointer &operator=(QSharedPointer<X> && other) noexcept; + + void swap(QSharedPointer<T> &other) noexcept; QWeakPointer<T> toWeakRef() const; @@ -104,6 +109,9 @@ public: }; template <class T> +size_t qHash(const QSharedPointer<T> &key, size_t seed = 0) noexcept; + +template <class T> class QWeakPointer { public: diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h index d48318b474..ca52b15870 100644 --- a/src/corelib/tools/qtools_p.h +++ b/src/corelib/tools/qtools_p.h @@ -84,6 +84,17 @@ Q_DECL_CONSTEXPR inline int fromOct(uint c) noexcept { return ((c >= '0') && (c <= '7')) ? int(c - '0') : -1; } + +constexpr inline char toAsciiLower(char ch) noexcept +{ + return (ch >= 'A' && ch <= 'Z') ? ch - 'A' + 'a' : ch; +} + +constexpr inline char toAsciiUpper(char ch) noexcept +{ + return (ch >= 'a' && ch <= 'z') ? ch - 'a' + 'A' : ch; +} + } // We typically need an extra bit for qNextPowerOfTwo when determining the next allocation size. diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index d8c229dea8..4b7e277187 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -475,28 +475,17 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA { Q_ASSERT_X(isValidIterator(before), "QVarLengthArray::insert", "The specified const_iterator argument 'before' is invalid"); - int offset = int(before - ptr); - reserve(s + 1); - if (!QTypeInfo<T>::isRelocatable) { - T *b = ptr + offset; - T *i = ptr + s; - T *j = i + 1; - // The new end-element needs to be constructed, the rest must be move assigned - if (i != b) { - new (--j) T(std::move(*--i)); - while (i != b) - *--j = std::move(*--i); - *b = std::move(t); - } else { - new (b) T(std::move(t)); - } + const int offset = int(before - ptr); + append(std::move(t)); + const auto b = begin() + offset; + const auto e = end(); + if (QTypeInfo<T>::isRelocatable) { + auto cast = [](T *p) { return reinterpret_cast<uchar*>(p); }; + std::rotate(cast(b), cast(e - 1), cast(e)); } else { - T *b = ptr + offset; - memmove(static_cast<void *>(b + 1), static_cast<const void *>(b), (s - offset) * sizeof(T)); - new (b) T(std::move(t)); + std::rotate(b, e - 1, e); } - s += 1; - return ptr + offset; + return b; } template <class T, int Prealloc> |