summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/global/qcompilerdetection.h6
-rw-r--r--src/corelib/global/qglobal.cpp8
-rw-r--r--src/corelib/global/qglobal.h1
-rw-r--r--src/corelib/global/qsysinfo.h8
-rw-r--r--src/corelib/kernel/qjnihelpers.cpp122
-rw-r--r--src/corelib/kernel/qjnihelpers_p.h11
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp9
-rw-r--r--src/corelib/thread/qmutex.h6
-rw-r--r--src/corelib/tools/qsimd_p.h3
-rw-r--r--src/corelib/tools/qstring.h3
-rw-r--r--src/corelib/tools/qstringlist.cpp40
-rw-r--r--src/corelib/tools/qstringlist.h7
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);