diff options
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/global/qcompilerdetection.h | 6 | ||||
-rw-r--r-- | src/corelib/global/qglobal.cpp | 8 | ||||
-rw-r--r-- | src/corelib/global/qglobal.h | 1 | ||||
-rw-r--r-- | src/corelib/global/qsysinfo.h | 8 | ||||
-rw-r--r-- | src/corelib/kernel/qjnihelpers.cpp | 122 | ||||
-rw-r--r-- | src/corelib/kernel/qjnihelpers_p.h | 11 | ||||
-rw-r--r-- | src/corelib/mimetypes/qmimeprovider.cpp | 9 | ||||
-rw-r--r-- | src/corelib/thread/qmutex.h | 6 | ||||
-rw-r--r-- | src/corelib/tools/qsimd_p.h | 3 | ||||
-rw-r--r-- | src/corelib/tools/qstring.h | 3 | ||||
-rw-r--r-- | src/corelib/tools/qstringlist.cpp | 40 | ||||
-rw-r--r-- | src/corelib/tools/qstringlist.h | 7 |
12 files changed, 203 insertions, 21 deletions
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index a48548bc90..a3d816f0c3 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1031,7 +1031,8 @@ // critical definitions. (Reported as Intel Issue ID 6000117277) # define __USE_CONSTEXPR 1 # define __USE_NOEXCEPT 1 -# elif defined(Q_CC_MSVC) && (defined(Q_CC_CLANG) || defined(Q_CC_INTEL)) +# endif +# if defined(Q_CC_MSVC) && defined(Q_CC_CLANG) // Clang and the Intel compiler support more C++ features than the Microsoft compiler // so make sure we don't enable them if the MS headers aren't properly adapted. # ifndef _HAS_CONSTEXPR @@ -1058,7 +1059,8 @@ # ifndef _HAS_VARIADIC_TEMPLATES # undef Q_COMPILER_VARIADIC_TEMPLATES # endif -# elif defined(_LIBCPP_VERSION) +# endif +# if defined(_LIBCPP_VERSION) // libc++ uses __has_feature(cxx_atomic), so disable the feature if the compiler // doesn't support it. That's required for the Intel compiler 14.x or earlier on OS X, for example. # if !__has_feature(cxx_atomic) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index e8b8641191..c78e6f2482 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1179,6 +1179,12 @@ bool qSharedBuild() Q_DECL_NOTHROW \value WV_None Operating system other than Windows. + \omitvalue WV_CE + \omitvalue WV_CENET + \omitvalue WV_CE_5 + \omitvalue WV_CE_6 + \omitvalue WV_CE_based + \sa MacVersion */ @@ -1255,7 +1261,7 @@ bool qSharedBuild() Q_DECL_NOTHROW \macro Q_OS_DARWIN \relates <QtGlobal> - Defined on Darwin-based operating systems such as \macOS, iOS, watchOS, and tvOS. + Defined on Darwin-based operating systems such as \macos, iOS, watchOS, and tvOS. */ /*! diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index f11ec127e0..dd8b6110b3 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -78,6 +78,7 @@ 1: The feature is available */ #define QT_CONFIG(feature) (1/QT_FEATURE_##feature == 1) +#define QT_REQUIRE_CONFIG(feature) Q_STATIC_ASSERT_X(QT_FEATURE_##feature == 1, "Required feature " #feature " for file " __FILE__ " not vailable.") #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) # define QT_NO_UNSHARABLE_CONTAINERS diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h index 5cf8d786cd..cdc186cdcd 100644 --- a/src/corelib/global/qsysinfo.h +++ b/src/corelib/global/qsysinfo.h @@ -110,7 +110,13 @@ public: WV_6_1 = WV_WINDOWS7, WV_6_2 = WV_WINDOWS8, WV_6_3 = WV_WINDOWS8_1, - WV_10_0 = WV_WINDOWS10 + WV_10_0 = WV_WINDOWS10, + + WV_CE = 0x0100, + WV_CENET = 0x0200, + WV_CE_5 = 0x0300, + WV_CE_6 = 0x0400, + WV_CE_based = 0x0f00 }; #if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN) QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const WinVersion WindowsVersion; diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp index 102b835089..6a46f7dd11 100644 --- a/src/corelib/kernel/qjnihelpers.cpp +++ b/src/corelib/kernel/qjnihelpers.cpp @@ -38,14 +38,17 @@ ****************************************************************************/ #include "qjnihelpers_p.h" +#include "qjni_p.h" #include "qmutex.h" #include "qlist.h" #include "qsemaphore.h" #include "qsharedpointer.h" #include "qvector.h" +#include "qthread.h" #include <QtCore/qrunnable.h> #include <deque> +#include <memory> QT_BEGIN_NAMESPACE @@ -60,6 +63,22 @@ static jmethodID g_hideSplashScreenMethodID = Q_NULLPTR; Q_GLOBAL_STATIC(std::deque<QtAndroidPrivate::Runnable>, g_pendingRunnables); Q_GLOBAL_STATIC(QMutex, g_pendingRunnablesMutex); +class PermissionsResultClass : public QObject +{ + Q_OBJECT +public: + PermissionsResultClass(const QtAndroidPrivate::PermissionsResultFunc &func) : m_func(func) {} + Q_INVOKABLE void sendResult(const QtAndroidPrivate::PermissionsHash &result) { m_func(result); } + +private: + QtAndroidPrivate::PermissionsResultFunc m_func; +}; + +typedef QHash<int, QSharedPointer<PermissionsResultClass>> PendingPermissionRequestsHash; +Q_GLOBAL_STATIC(PendingPermissionRequestsHash, g_pendingPermissionRequests); +Q_GLOBAL_STATIC(QMutex, g_pendingPermissionRequestsMutex); +Q_GLOBAL_STATIC(QAtomicInt, g_requestPermissionsRequestCode); + // function called from Java from Android UI thread static void runPendingCppRunnables(JNIEnv */*env*/, jobject /*obj*/) { @@ -81,9 +100,43 @@ namespace { QMutex mutex; QVector<QtAndroidPrivate::GenericMotionEventListener *> listeners; }; + + enum { + PERMISSION_GRANTED = 0 + }; } Q_GLOBAL_STATIC(GenericMotionEventListeners, g_genericMotionEventListeners) +static void sendRequestPermissionsResult(JNIEnv *env, jobject /*obj*/, jint requestCode, + jobjectArray permissions, jintArray grantResults) +{ + g_pendingPermissionRequestsMutex->lock(); + auto it = g_pendingPermissionRequests->find(requestCode); + if (it == g_pendingPermissionRequests->end()) { + g_pendingPermissionRequestsMutex->unlock(); + // show an error or something ? + return; + } + g_pendingPermissionRequestsMutex->unlock(); + + Qt::ConnectionType connection = QThread::currentThread() == it.value()->thread() ? Qt::DirectConnection : Qt::BlockingQueuedConnection; + QtAndroidPrivate::PermissionsHash hash; + const int size = env->GetArrayLength(permissions); + std::unique_ptr<jint[]> results(new jint[size]); + env->GetIntArrayRegion(grantResults, 0, size, results.get()); + for (int i = 0 ; i < size; ++i) { + const auto &permission = QJNIObjectPrivate(env->GetObjectArrayElement(permissions, i)).toString(); + auto value = results[i] == PERMISSION_GRANTED ? + QtAndroidPrivate::PermissionsResult::Granted : + QtAndroidPrivate::PermissionsResult::Denied; + hash[permission] = value; + } + QMetaObject::invokeMethod(it.value().data(), "sendResult", connection, Q_ARG(QtAndroidPrivate::PermissionsHash, hash)); + g_pendingPermissionRequestsMutex->lock(); + g_pendingPermissionRequests->erase(it); + g_pendingPermissionRequestsMutex->unlock(); +} + static jboolean dispatchGenericMotionEvent(JNIEnv *, jclass, jobject event) { jboolean ret = JNI_FALSE; @@ -328,7 +381,8 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env) {"dispatchGenericMotionEvent", "(Landroid/view/MotionEvent;)Z", reinterpret_cast<void *>(dispatchGenericMotionEvent)}, {"dispatchKeyEvent", "(Landroid/view/KeyEvent;)Z", reinterpret_cast<void *>(dispatchKeyEvent)}, {"setNativeActivity", "(Landroid/app/Activity;)V", reinterpret_cast<void *>(setNativeActivity)}, - {"setNativeService", "(Landroid/app/Service;)V", reinterpret_cast<void *>(setNativeService)} + {"setNativeService", "(Landroid/app/Service;)V", reinterpret_cast<void *>(setNativeService)}, + {"sendRequestPermissionsResult", "(I[Ljava/lang/String;[I)V", reinterpret_cast<void *>(sendRequestPermissionsResult)}, }; const bool regOk = (env->RegisterNatives(jQtNative, methods, sizeof(methods) / sizeof(methods[0])) == JNI_OK); @@ -411,6 +465,70 @@ void QtAndroidPrivate::runOnAndroidThreadSync(const QtAndroidPrivate::Runnable & sem->tryAcquire(1, timeoutMs); } +void QtAndroidPrivate::requestPermissions(JNIEnv *env, const QStringList &permissions, const QtAndroidPrivate::PermissionsResultFunc &callbackFunc, bool directCall) +{ + if (androidSdkVersion() < 23 || !activity()) { + QHash<QString, QtAndroidPrivate::PermissionsResult> res; + for (const auto &perm : permissions) + res[perm] = checkPermission(perm); + callbackFunc(res); + return; + } + // Check API 23+ permissions + const int requestCode = (*g_requestPermissionsRequestCode)++; + if (!directCall) { + g_pendingPermissionRequestsMutex->lock(); + (*g_pendingPermissionRequests)[requestCode] = QSharedPointer<PermissionsResultClass>::create(callbackFunc); + g_pendingPermissionRequestsMutex->unlock(); + } + + runOnAndroidThread([permissions, callbackFunc, requestCode, directCall] { + if (directCall) { + g_pendingPermissionRequestsMutex->lock(); + (*g_pendingPermissionRequests)[requestCode] = QSharedPointer<PermissionsResultClass>::create(callbackFunc); + g_pendingPermissionRequestsMutex->unlock(); + } + + QJNIEnvironmentPrivate env; + auto array = env->NewObjectArray(permissions.size(), env->FindClass("java/lang/String"), nullptr); + int index = 0; + for (const auto &perm : permissions) + env->SetObjectArrayElement(array, index++, QJNIObjectPrivate::fromString(perm).object()); + QJNIObjectPrivate(activity()).callMethod<void>("requestPermissions", "([Ljava/lang/String;I)V", array, requestCode); + env->DeleteLocalRef(array); + }, env); +} + +QHash<QString, QtAndroidPrivate::PermissionsResult> QtAndroidPrivate::requestPermissionsSync(JNIEnv *env, const QStringList &permissions, int timeoutMs) +{ + QSharedPointer<QHash<QString, QtAndroidPrivate::PermissionsResult>> res(new QHash<QString, QtAndroidPrivate::PermissionsResult>()); + QSharedPointer<QSemaphore> sem(new QSemaphore); + requestPermissions(env, permissions, [sem, res](const QHash<QString, PermissionsResult> &result){ + *res = result; + sem->release(); + }, true); + sem->tryAcquire(1, timeoutMs); + return *res; +} + +QtAndroidPrivate::PermissionsResult QtAndroidPrivate::checkPermission(const QString &permission) +{ + const auto res = QJNIObjectPrivate::callStaticMethod<jint>("org/qtproject/qt5/android/QtNative", + "checkSelfPermission", + "(Ljava/lang/String;)I", + QJNIObjectPrivate::fromString(permission).object()); + return res == PERMISSION_GRANTED ? PermissionsResult::Granted : PermissionsResult::Denied; +} + +bool QtAndroidPrivate::shouldShowRequestPermissionRationale(const QString &permission) +{ + if (androidSdkVersion() < 23 || !activity()) + return false; + + return QJNIObjectPrivate(activity()).callMethod<jboolean>("shouldShowRequestPermissionRationale", "(Ljava/lang/String;)Z", + QJNIObjectPrivate::fromString(permission).object()); +} + void QtAndroidPrivate::registerGenericMotionEventListener(QtAndroidPrivate::GenericMotionEventListener *listener) { QMutexLocker locker(&g_genericMotionEventListeners()->mutex); @@ -441,3 +559,5 @@ void QtAndroidPrivate::hideSplashScreen(JNIEnv *env) } QT_END_NAMESPACE + +#include "qjnihelpers.moc" diff --git a/src/corelib/kernel/qjnihelpers_p.h b/src/corelib/kernel/qjnihelpers_p.h index 43e2f3af20..478f62a5c7 100644 --- a/src/corelib/kernel/qjnihelpers_p.h +++ b/src/corelib/kernel/qjnihelpers_p.h @@ -58,6 +58,7 @@ QT_BEGIN_NAMESPACE class QRunnable; +class QStringList; namespace QtAndroidPrivate { @@ -97,7 +98,13 @@ namespace QtAndroidPrivate virtual bool handleKeyEvent(jobject event) = 0; }; + enum class PermissionsResult { + Granted, + Denied + }; + typedef QHash<QString, QtAndroidPrivate::PermissionsResult> PermissionsHash; typedef std::function<void()> Runnable; + typedef std::function<void(const PermissionsHash &)> PermissionsResultFunc; Q_CORE_EXPORT jobject activity(); Q_CORE_EXPORT jobject service(); @@ -109,6 +116,10 @@ namespace QtAndroidPrivate Q_CORE_EXPORT void runOnAndroidThread(const Runnable &runnable, JNIEnv *env); Q_CORE_EXPORT void runOnAndroidThreadSync(const Runnable &runnable, JNIEnv *env, int timeoutMs = INT_MAX); Q_CORE_EXPORT void runOnUiThread(QRunnable *runnable, JNIEnv *env); + Q_CORE_EXPORT void requestPermissions(JNIEnv *env, const QStringList &permissions, const PermissionsResultFunc &callbackFunc, bool directCall = false); + Q_CORE_EXPORT QHash<QString, PermissionsResult> requestPermissionsSync(JNIEnv *env, const QStringList &permissions, int timeoutMs = INT_MAX); + Q_CORE_EXPORT PermissionsResult checkPermission(const QString &permission); + Q_CORE_EXPORT bool shouldShowRequestPermissionRationale(const QString &permission); Q_CORE_EXPORT void handleActivityResult(jint requestCode, jint resultCode, jobject data); Q_CORE_EXPORT void registerActivityResultListener(ActivityResultListener *listener); diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index e25eb4272d..a798d9eff6 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -572,10 +572,9 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) const QString file = data.name + QLatin1String(".xml"); // shared-mime-info since 1.3 lowercases the xml files - QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file.toLower()); - if (mimeFiles.isEmpty()) { - mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QString::fromLatin1("mime/") + file); // pre-1.3 - } + QStringList mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/") + file.toLower()); + if (mimeFiles.isEmpty()) + mimeFiles = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QLatin1String("mime/") + file); // pre-1.3 if (mimeFiles.isEmpty()) { qWarning() << "No file found for" << file << ", even though update-mime-info said it would exist.\n" "Either it was just removed, or the directory doesn't have executable permission..." @@ -807,7 +806,7 @@ bool QMimeXMLProvider::load(const QString &fileName, QString *errorMessage) QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { if (errorMessage) - *errorMessage = QString::fromLatin1("Cannot open %1: %2").arg(fileName, file.errorString()); + *errorMessage = QLatin1String("Cannot open ") + fileName + QLatin1String(": ") + file.errorString(); return false; } diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index da8d1704b0..3a0e22e3bd 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -135,8 +135,8 @@ public: template <class Rep, class Period> bool try_lock_for(std::chrono::duration<Rep, Period> duration) { - // § 30.4.1.3.5 [thread.timedmutex.requirements] specifies that a - // duration less than or equal to duration.zero() shall result in a + // N4606 § 30.4.1.3 [thread.timedmutex.requirements]/5 specifies that + // a duration less than or equal to duration.zero() shall result in a // try_lock, unlike QMutex's tryLock with a negative duration which // results in a lock. @@ -150,7 +150,7 @@ public: bool try_lock_until(std::chrono::time_point<Clock, Duration> timePoint) { // Implemented in terms of try_lock_for to honor the similar - // requirement in § 30.4.1.3.12 [thread.timedmutex.requirements] + // requirement in N4606 § 30.4.1.3 [thread.timedmutex.requirements]/12. return try_lock_for(timePoint - Clock::now()); } diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index 9d8695c0f6..2fd4be00a5 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -468,6 +468,9 @@ static inline quint64 qCpuFeatures() #define ALIGNMENT_PROLOGUE_16BYTES(ptr, i, length) \ for (; i < static_cast<int>(qMin(static_cast<quintptr>(length), ((4 - ((reinterpret_cast<quintptr>(ptr) >> 2) & 0x3)) & 0x3))); ++i) +#define ALIGNMENT_PROLOGUE_32BYTES(ptr, i, length) \ + for (; i < static_cast<int>(qMin(static_cast<quintptr>(length), ((8 - ((reinterpret_cast<quintptr>(ptr) >> 2) & 0x7)) & 0x7))); ++i) + QT_END_NAMESPACE #endif // QSIMD_P_H diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index a110c129de..53a28d9278 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -1440,7 +1440,8 @@ public: QStringRef mid(int pos, int n = -1) const Q_REQUIRED_RESULT; void truncate(int pos) Q_DECL_NOTHROW { m_size = qBound(0, pos, m_size); } - void chop(int n) Q_DECL_NOTHROW { + void chop(int n) Q_DECL_NOTHROW + { if (n >= m_size) m_size = 0; else if (n > 0) diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp index eae9e0e5d9..a0b65ea554 100644 --- a/src/corelib/tools/qstringlist.cpp +++ b/src/corelib/tools/qstringlist.cpp @@ -447,6 +447,17 @@ void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegularEx #endif // QT_NO_REGULAREXPRESSION #endif // QT_BOOTSTRAPPED +static int accumulatedSize(const QStringList &list, int seplen) +{ + int result = 0; + if (!list.isEmpty()) { + for (const auto &e : list) + result += e.size() + seplen; + result -= seplen; + } + return result; +} + /*! \fn QString QStringList::join(const QString &separator) const @@ -464,15 +475,9 @@ void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegularEx */ QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, int seplen) { - int totalLength = 0; + const int totalLength = accumulatedSize(*that, seplen); const int size = that->size(); - for (int i = 0; i < size; ++i) - totalLength += that->at(i).size(); - - if(size > 0) - totalLength += seplen * (size - 1); - QString res; if (totalLength == 0) return res; @@ -486,6 +491,27 @@ QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, i } /*! + \fn QString QStringList::join(QLatin1String separator) const + \since 5.8 + \overload join() +*/ +QString QtPrivate::QStringList_join(const QStringList &list, QLatin1String sep) +{ + QString result; + if (!list.isEmpty()) { + result.reserve(accumulatedSize(list, sep.size())); + const auto end = list.end(); + auto it = list.begin(); + result += *it; + while (++it != end) { + result += sep; + result += *it; + } + } + return result; +} + +/*! \fn QStringList QStringList::operator+(const QStringList &other) const Returns a string list that is the concatenation of this string diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h index 87f15528bf..720d7d7419 100644 --- a/src/corelib/tools/qstringlist.h +++ b/src/corelib/tools/qstringlist.h @@ -73,6 +73,7 @@ public: inline int removeDuplicates(); inline QString join(const QString &sep) const; + inline QString join(QLatin1String sep) const; inline QString join(QChar sep) const; inline QStringList filter(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; @@ -159,6 +160,7 @@ namespace QtPrivate { void Q_CORE_EXPORT QStringList_sort(QStringList *that, Qt::CaseSensitivity cs); int Q_CORE_EXPORT QStringList_removeDuplicates(QStringList *that); QString Q_CORE_EXPORT QStringList_join(const QStringList *that, const QChar *sep, int seplen); + Q_CORE_EXPORT QString QStringList_join(const QStringList &list, QLatin1String sep); QStringList Q_CORE_EXPORT QStringList_filter(const QStringList *that, const QString &str, Qt::CaseSensitivity cs); @@ -200,6 +202,11 @@ inline QString QListSpecialMethods<QString>::join(const QString &sep) const return QtPrivate::QStringList_join(self(), sep.constData(), sep.length()); } +QString QListSpecialMethods<QString>::join(QLatin1String sep) const +{ + return QtPrivate::QStringList_join(*self(), sep); +} + inline QString QListSpecialMethods<QString>::join(QChar sep) const { return QtPrivate::QStringList_join(self(), &sep, 1); |