diff options
author | Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> | 2014-11-24 13:37:06 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> | 2014-11-24 13:39:13 +0100 |
commit | 34aba4724f196e34ed02cf50073f41968f119bb6 (patch) | |
tree | 0ebdfcabda989ab76ee6de53c6461553c7a767a5 /src/plugins/platforms/android | |
parent | b86b2a742afae118bf974c82ba966ddb0cae4afb (diff) | |
parent | b1cf07f495e10c93e53651ac03e46ebdaea0a97e (diff) |
Merge remote-tracking branch 'origin/5.4' into dev
Conflicts:
src/corelib/io/qiodevice.cpp
src/plugins/bearer/linux_common/qofonoservice_linux.cpp
src/plugins/bearer/linux_common/qofonoservice_linux_p.h
src/plugins/platforms/android/qandroidplatformtheme.cpp
src/tools/bootstrap/bootstrap.pro
src/widgets/styles/qmacstyle_mac.mm
Change-Id: Ia02aab6c4598ce74e9c30bb4666d5e2ef000f99b
Diffstat (limited to 'src/plugins/platforms/android')
11 files changed, 350 insertions, 139 deletions
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 536415339f..62da60ab92 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -48,10 +48,6 @@ using namespace QtAndroid; namespace QtAndroidInput { - static jmethodID m_showSoftwareKeyboardMethodID = 0; - static jmethodID m_resetSoftwareKeyboardMethodID = 0; - static jmethodID m_hideSoftwareKeyboardMethodID = 0; - static jmethodID m_updateSelectionMethodID = 0; static bool m_ignoreMouseEvents = false; static bool m_softwareKeyboardVisible = false; @@ -62,30 +58,28 @@ namespace QtAndroidInput void updateSelection(int selStart, int selEnd, int candidatesStart, int candidatesEnd) { - AttachedJNIEnv env; - if (!env.jniEnv) - return; - #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << ">>> UPDATESELECTION" << selStart << selEnd << candidatesStart << candidatesEnd; #endif - env.jniEnv->CallStaticVoidMethod(applicationClass(), m_updateSelectionMethodID, - selStart, selEnd, candidatesStart, candidatesEnd); + QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), + "updateSelection", + "(IIII)V", + selStart, + selEnd, + candidatesStart, + candidatesEnd); } void showSoftwareKeyboard(int left, int top, int width, int height, int inputHints) { - AttachedJNIEnv env; - if (!env.jniEnv) - return; - - env.jniEnv->CallStaticVoidMethod(applicationClass(), - m_showSoftwareKeyboardMethodID, - left, - top, - width, - height, - inputHints); + QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), + "showSoftwareKeyboard", + "(IIIII)V", + left, + top, + width, + height, + inputHints); #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ SHOWSOFTWAREKEYBOARD" << left << top << width << height << inputHints; #endif @@ -93,11 +87,7 @@ namespace QtAndroidInput void resetSoftwareKeyboard() { - AttachedJNIEnv env; - if (!env.jniEnv) - return; - - env.jniEnv->CallStaticVoidMethod(applicationClass(), m_resetSoftwareKeyboardMethodID); + QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "resetSoftwareKeyboard"); #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ RESETSOFTWAREKEYBOARD"; #endif @@ -105,11 +95,7 @@ namespace QtAndroidInput void hideSoftwareKeyboard() { - AttachedJNIEnv env; - if (!env.jniEnv) - return; - - env.jniEnv->CallStaticVoidMethod(applicationClass(), m_hideSoftwareKeyboardMethodID); + QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "hideSoftwareKeyboard"); #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ HIDESOFTWAREKEYBOARD"; #endif @@ -722,13 +708,6 @@ namespace QtAndroidInput {"keyboardVisibilityChanged", "(Z)V", (void *)keyboardVisibilityChanged} }; -#define GET_AND_CHECK_STATIC_METHOD(VAR, CLASS, METHOD_NAME, METHOD_SIGNATURE) \ - VAR = env->GetStaticMethodID(CLASS, METHOD_NAME, METHOD_SIGNATURE); \ - if (!VAR) { \ - __android_log_print(ANDROID_LOG_FATAL, qtTagText(), methodErrorMsgFmt(), METHOD_NAME, METHOD_SIGNATURE); \ - return false; \ - } - bool registerNatives(JNIEnv *env) { jclass appClass = QtAndroid::applicationClass(); @@ -738,10 +717,6 @@ namespace QtAndroidInput return false; } - GET_AND_CHECK_STATIC_METHOD(m_showSoftwareKeyboardMethodID, appClass, "showSoftwareKeyboard", "(IIIII)V"); - GET_AND_CHECK_STATIC_METHOD(m_resetSoftwareKeyboardMethodID, appClass, "resetSoftwareKeyboard", "()V"); - GET_AND_CHECK_STATIC_METHOD(m_hideSoftwareKeyboardMethodID, appClass, "hideSoftwareKeyboard", "()V"); - GET_AND_CHECK_STATIC_METHOD(m_updateSelectionMethodID, appClass, "updateSelection", "(IIII)V"); return true; } } diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 235e004904..df0a8c56cb 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -80,7 +80,6 @@ static jmethodID m_createBitmapMethodID = Q_NULLPTR; static jobject m_ARGB_8888_BitmapConfigValue = Q_NULLPTR; static jobject m_RGB_565_BitmapConfigValue = Q_NULLPTR; -jmethodID m_setFullScreenMethodID = Q_NULLPTR; static bool m_statusBarShowing = true; static jclass m_bitmapDrawableClass = Q_NULLPTR; @@ -182,13 +181,7 @@ namespace QtAndroid if (m_statusBarShowing) return; - QtAndroid::AttachedJNIEnv env; - if (!env.jniEnv) { - qWarning("Failed to get JNI Environment."); - return; - } - - env.jniEnv->CallStaticVoidMethod(m_applicationClass, m_setFullScreenMethodID, false); + QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "setFullScreen", "(Z)V", false); m_statusBarShowing = true; } @@ -197,13 +190,7 @@ namespace QtAndroid if (!m_statusBarShowing) return; - QtAndroid::AttachedJNIEnv env; - if (!env.jniEnv) { - qWarning("Failed to get JNI Environment."); - return; - } - - env.jniEnv->CallStaticVoidMethod(m_applicationClass, m_setFullScreenMethodID, true); + QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "setFullScreen", "(Z)V", true); m_statusBarShowing = false; } @@ -453,16 +440,9 @@ static void *startMainMethod(void */*data*/) if (res < 0) qWarning() << "dlclose failed:" << dlerror(); } - m_mainLibraryHnd = Q_NULLPTR; - m_main = Q_NULLPTR; - QtAndroid::AttachedJNIEnv env; - if (!env.jniEnv) - return 0; - if (m_applicationClass) { - jmethodID quitApp = env.jniEnv->GetStaticMethodID(m_applicationClass, "quitApp", "()V"); - env.jniEnv->CallStaticVoidMethod(m_applicationClass, quitApp); - } + if (m_applicationClass) + QJNIObjectPrivate::callStaticMethod<void>(m_applicationClass, "quitApp", "()V"); return 0; } @@ -723,7 +703,6 @@ static int registerNatives(JNIEnv *env) jclass clazz; FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/QtNative"); m_applicationClass = static_cast<jclass>(env->NewGlobalRef(clazz)); - GET_AND_CHECK_STATIC_METHOD(m_setFullScreenMethodID, m_applicationClass, "setFullScreen", "(Z)V"); if (env->RegisterNatives(m_applicationClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) { __android_log_print(ANDROID_LOG_FATAL,"Qt", "RegisterNatives failed"); diff --git a/src/plugins/platforms/android/androidjnimain.h b/src/plugins/platforms/android/androidjnimain.h index 01330ce283..8cf9274857 100644 --- a/src/plugins/platforms/android/androidjnimain.h +++ b/src/plugins/platforms/android/androidjnimain.h @@ -85,29 +85,6 @@ namespace QtAndroid jobject createBitmap(int width, int height, QImage::Format format, JNIEnv *env); jobject createBitmapDrawable(jobject bitmap, JNIEnv *env = 0); - struct AttachedJNIEnv - { - AttachedJNIEnv() - { - attached = false; - if (QtAndroid::javaVM()->GetEnv((void**)&jniEnv, JNI_VERSION_1_6) < 0) { - if (QtAndroid::javaVM()->AttachCurrentThread(&jniEnv, NULL) < 0) { - __android_log_print(ANDROID_LOG_ERROR, "Qt", "AttachCurrentThread failed"); - jniEnv = Q_NULLPTR; - return; - } - attached = true; - } - } - - ~AttachedJNIEnv() - { - if (attached) - QtAndroid::javaVM()->DetachCurrentThread(); - } - bool attached; - JNIEnv *jniEnv; - }; const char *classErrorMsgFmt(); const char *methodErrorMsgFmt(); const char *qtTagText(); diff --git a/src/plugins/platforms/android/androidjnimenu.cpp b/src/plugins/platforms/android/androidjnimenu.cpp index 1251bbf193..36c349f6b4 100644 --- a/src/plugins/platforms/android/androidjnimenu.cpp +++ b/src/plugins/platforms/android/androidjnimenu.cpp @@ -44,6 +44,7 @@ #include <QSet> #include <QWindow> #include <QtCore/private/qjnihelpers_p.h> +#include <QtCore/private/qjni_p.h> QT_BEGIN_NAMESPACE @@ -61,9 +62,6 @@ namespace QtAndroidMenu static QMutex menuBarMutex(QMutex::Recursive); static jmethodID openContextMenuMethodID = 0; - static jmethodID closeContextMenuMethodID = 0; - static jmethodID resetOptionsMenuMethodID = 0; - static jmethodID openOptionsMenuMethodID = 0; static jmethodID clearMenuMethodID = 0; static jmethodID addMenuItemMethodID = 0; @@ -78,16 +76,12 @@ namespace QtAndroidMenu void resetMenuBar() { - AttachedJNIEnv env; - if (env.jniEnv) - env.jniEnv->CallStaticVoidMethod(applicationClass(), resetOptionsMenuMethodID); + QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "resetOptionsMenu"); } void openOptionsMenu() { - AttachedJNIEnv env; - if (env.jniEnv) - env.jniEnv->CallStaticVoidMethod(applicationClass(), openOptionsMenuMethodID); + QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "openOptionsMenu"); } void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect, JNIEnv *env) @@ -103,22 +97,14 @@ namespace QtAndroidMenu visibleMenu = menu; menu->aboutToShow(); - if (env) { - env->CallStaticVoidMethod(applicationClass(), openContextMenuMethodID, anchorRect.x(), anchorRect.y(), anchorRect.width(), anchorRect.height()); - } else { - AttachedJNIEnv aenv; - if (aenv.jniEnv) - aenv.jniEnv->CallStaticVoidMethod(applicationClass(), openContextMenuMethodID, anchorRect.x(), anchorRect.y(), anchorRect.width(), anchorRect.height()); - } + env->CallStaticVoidMethod(applicationClass(), openContextMenuMethodID, anchorRect.x(), anchorRect.y(), anchorRect.width(), anchorRect.height()); } void hideContextMenu(QAndroidPlatformMenu *menu) { QMutexLocker lock(&visibleMenuMutex); if (visibleMenu == menu) { - AttachedJNIEnv env; - if (env.jniEnv) - env.jniEnv->CallStaticVoidMethod(applicationClass(), closeContextMenuMethodID); + QJNIObjectPrivate::callStaticMethod<void>(applicationClass(), "closeContextMenu"); pendingContextMenus.clear(); } else { pendingContextMenus.removeOne(menu); @@ -430,9 +416,6 @@ namespace QtAndroidMenu } GET_AND_CHECK_STATIC_METHOD(openContextMenuMethodID, appClass, "openContextMenu", "(IIII)V"); - GET_AND_CHECK_STATIC_METHOD(closeContextMenuMethodID, appClass, "closeContextMenu", "()V"); - GET_AND_CHECK_STATIC_METHOD(resetOptionsMenuMethodID, appClass, "resetOptionsMenu", "()V"); - GET_AND_CHECK_STATIC_METHOD(openOptionsMenuMethodID, appClass, "openOptionsMenu", "()V"); jclass clazz; FIND_AND_CHECK_CLASS("android/view/Menu"); diff --git a/src/plugins/platforms/android/androidjnimenu.h b/src/plugins/platforms/android/androidjnimenu.h index c54eb37f37..f85db9ff86 100644 --- a/src/plugins/platforms/android/androidjnimenu.h +++ b/src/plugins/platforms/android/androidjnimenu.h @@ -50,7 +50,7 @@ namespace QtAndroidMenu { // Menu support void openOptionsMenu(); - void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect, JNIEnv *env = 0); + void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect, JNIEnv *env); void hideContextMenu(QAndroidPlatformMenu *menu); void syncMenu(QAndroidPlatformMenu *menu); void androidPlatformMenuDestroyed(QAndroidPlatformMenu *menu); diff --git a/src/plugins/platforms/android/qandroidplatformclipboard.cpp b/src/plugins/platforms/android/qandroidplatformclipboard.cpp index fb73db8455..2605ec9901 100644 --- a/src/plugins/platforms/android/qandroidplatformclipboard.cpp +++ b/src/plugins/platforms/android/qandroidplatformclipboard.cpp @@ -44,6 +44,7 @@ QAndroidPlatformClipboard::QAndroidPlatformClipboard() QMimeData *QAndroidPlatformClipboard::mimeData(QClipboard::Mode mode) { + Q_UNUSED(mode); Q_ASSERT(supportsMode(mode)); m_mimeData.setText(QtAndroidClipboard::hasClipboardText() ? QtAndroidClipboard::clipboardText() @@ -53,8 +54,8 @@ QMimeData *QAndroidPlatformClipboard::mimeData(QClipboard::Mode mode) void QAndroidPlatformClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) { - Q_ASSERT(supportsMode(mode)); - QtAndroidClipboard::setClipboardText(data != 0 && data->hasText() ? data->text() : QString()); + if (supportsMode(mode)) + QtAndroidClipboard::setClipboardText(data != 0 && data->hasText() ? data->text() : QString()); if (data != 0) data->deleteLater(); } diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 8a3a958d3b..07bdf95bf4 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -78,10 +78,24 @@ void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteA return QtAndroid::javaVM(); if (resource == "QtActivity") return QtAndroid::activity(); - if (resource == "AndroidStylePalettes") - return &m_palettes; - if (resource == "AndroidStyleFonts") - return &m_fonts; + if (resource == "AndroidStyleData") { + if (m_androidStyle) + return &m_androidStyle->m_styleData; + else + return Q_NULLPTR; + } + if (resource == "AndroidStandardPalette") { + if (m_androidStyle) + return &m_androidStyle->m_standardPalette; + else + return Q_NULLPTR; + } + if (resource == "AndroidQWidgetFonts") { + if (m_androidStyle) + return &m_androidStyle->m_QWidgetsFonts; + else + return Q_NULLPTR; + } if (resource == "AndroidDeviceName") { static QString deviceName = QtAndroid::deviceName(); return &deviceName; diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h index 13c98442e9..7b4ab08847 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/qandroidplatformintegration.h @@ -44,6 +44,8 @@ #include "qandroidplatformscreen.h" +#include <memory> + QT_BEGIN_NAMESPACE class QDesktopWidget; @@ -51,12 +53,12 @@ class QAndroidPlatformServices; class QAndroidSystemLocale; class QPlatformAccessibility; +struct AndroidStyle; class QAndroidPlatformNativeInterface: public QPlatformNativeInterface { public: void *nativeResourceForIntegration(const QByteArray &resource); - QHash<int, QPalette> m_palettes; - QHash<int, QFont> m_fonts; + std::shared_ptr<AndroidStyle> m_androidStyle; }; class QAndroidPlatformIntegration : public QPlatformIntegration diff --git a/src/plugins/platforms/android/qandroidplatformmenu.cpp b/src/plugins/platforms/android/qandroidplatformmenu.cpp index f3505fac3c..8f992f6bea 100644 --- a/src/plugins/platforms/android/qandroidplatformmenu.cpp +++ b/src/plugins/platforms/android/qandroidplatformmenu.cpp @@ -34,6 +34,7 @@ #include "qandroidplatformmenu.h" #include "qandroidplatformmenuitem.h" #include "androidjnimenu.h" +#include <QtCore/private/qjni_p.h> QT_BEGIN_NAMESPACE @@ -140,7 +141,7 @@ void QAndroidPlatformMenu::showPopup(const QWindow *parentWindow, const QRect &t Q_UNUSED(parentWindow); Q_UNUSED(item); setVisible(true); - QtAndroidMenu::showContextMenu(this, targetRect); + QtAndroidMenu::showContextMenu(this, targetRect, QJNIEnvironmentPrivate()); } QPlatformMenuItem *QAndroidPlatformMenu::menuItemAt(int position) const diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp index 914de9d270..b955cff44d 100644 --- a/src/plugins/platforms/android/qandroidplatformtheme.cpp +++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp @@ -37,17 +37,281 @@ #include "qandroidplatformmenu.h" #include "qandroidplatformmenuitem.h" #include "qandroidplatformdialoghelpers.h" -#include <QVariant> -#include <QFileInfo> + #include <QCoreApplication> +#include <QDebug> +#include <QFileInfo> +#include <QJsonDocument> +#include <QVariant> + #include <private/qguiapplication_p.h> #include <qandroidplatformintegration.h> QT_BEGIN_NAMESPACE +namespace { + const int textStyle_bold = 1; + const int textStyle_italic = 2; + + const int typeface_sans = 1; + const int typeface_serif = 2; + const int typeface_monospace = 3; +} + +static int fontType(const QString &androidControl) +{ + if (androidControl == QLatin1String("defaultStyle")) + return QPlatformTheme::SystemFont; + if (androidControl == QLatin1String("textViewStyle")) + return QPlatformTheme::LabelFont; + else if (androidControl == QLatin1String("buttonStyle")) + return QPlatformTheme::PushButtonFont; + else if (androidControl == QLatin1String("checkboxStyle")) + return QPlatformTheme::CheckBoxFont; + else if (androidControl == QLatin1String("radioButtonStyle")) + return QPlatformTheme::RadioButtonFont; + else if (androidControl == QLatin1String("simple_list_item_single_choice")) + return QPlatformTheme::ItemViewFont; + else if (androidControl == QLatin1String("simple_spinner_dropdown_item")) + return QPlatformTheme::ComboMenuItemFont; + else if (androidControl == QLatin1String("spinnerStyle")) + return QPlatformTheme::ComboLineEditFont; + else if (androidControl == QLatin1String("simple_list_item")) + return QPlatformTheme::ListViewFont; + return -1; +} + +static int paletteType(const QString &androidControl) +{ + if (androidControl == QLatin1String("defaultStyle")) + return QPlatformTheme::SystemPalette; + if (androidControl == QLatin1String("textViewStyle")) + return QPlatformTheme::LabelPalette; + else if (androidControl == QLatin1String("buttonStyle")) + return QPlatformTheme::ButtonPalette; + else if (androidControl == QLatin1String("checkboxStyle")) + return QPlatformTheme::CheckBoxPalette; + else if (androidControl == QLatin1String("radioButtonStyle")) + return QPlatformTheme::RadioButtonPalette; + else if (androidControl == QLatin1String("simple_list_item_single_choice")) + return QPlatformTheme::ItemViewPalette; + else if (androidControl == QLatin1String("editTextStyle")) + return QPlatformTheme::TextLineEditPalette; + else if (androidControl == QLatin1String("spinnerStyle")) + return QPlatformTheme::ComboBoxPalette; + return -1; +} + +static void setPaletteColor(const QVariantMap &object, + QPalette &palette, + QPalette::ColorRole role) +{ + // QPalette::Active -> ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET + palette.setColor(QPalette::Active, + role, + QRgb(object.value(QLatin1String("ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET")).toInt())); + + // QPalette::Inactive -> ENABLED_STATE_SET + palette.setColor(QPalette::Inactive, + role, + QRgb(object.value(QLatin1String("ENABLED_STATE_SET")).toInt())); + + // QPalette::Disabled -> EMPTY_STATE_SET + palette.setColor(QPalette::Disabled, + role, + QRgb(object.value(QLatin1String("EMPTY_STATE_SET")).toInt())); + + palette.setColor(QPalette::Current, role, palette.color(QPalette::Active, role)); + + if (role == QPalette::WindowText) { + // QPalette::BrightText -> PRESSED + // QPalette::Active -> PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET + palette.setColor(QPalette::Active, + QPalette::BrightText, + QRgb(object.value(QLatin1String("PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET")).toInt())); + + // QPalette::Inactive -> PRESSED_ENABLED_STATE_SET + palette.setColor(QPalette::Inactive, + QPalette::BrightText, + QRgb(object.value(QLatin1String("PRESSED_ENABLED_STATE_SET")).toInt())); + + // QPalette::Disabled -> PRESSED_STATE_SET + palette.setColor(QPalette::Disabled, + QPalette::BrightText, + QRgb(object.value(QLatin1String("PRESSED_STATE_SET")).toInt())); + + palette.setColor(QPalette::Current, QPalette::BrightText, palette.color(QPalette::Active, QPalette::BrightText)); + + // QPalette::HighlightedText -> SELECTED + // QPalette::Active -> ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET + palette.setColor(QPalette::Active, + QPalette::HighlightedText, + QRgb(object.value(QLatin1String("ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET")).toInt())); + + // QPalette::Inactive -> ENABLED_SELECTED_STATE_SET + palette.setColor(QPalette::Inactive, + QPalette::HighlightedText, + QRgb(object.value(QLatin1String("ENABLED_SELECTED_STATE_SET")).toInt())); + + // QPalette::Disabled -> SELECTED_STATE_SET + palette.setColor(QPalette::Disabled, + QPalette::HighlightedText, + QRgb(object.value(QLatin1String("SELECTED_STATE_SET")).toInt())); + + palette.setColor(QPalette::Current, + QPalette::HighlightedText, + palette.color(QPalette::Active, QPalette::HighlightedText)); + + // Same colors for Text + palette.setColor(QPalette::Active, QPalette::Text, palette.color(QPalette::Active, role)); + palette.setColor(QPalette::Inactive, QPalette::Text, palette.color(QPalette::Inactive, role)); + palette.setColor(QPalette::Disabled, QPalette::Text, palette.color(QPalette::Disabled, role)); + palette.setColor(QPalette::Current, QPalette::Text, palette.color(QPalette::Current, role)); + + // And for ButtonText + palette.setColor(QPalette::Active, QPalette::ButtonText, palette.color(QPalette::Active, role)); + palette.setColor(QPalette::Inactive, QPalette::ButtonText, palette.color(QPalette::Inactive, role)); + palette.setColor(QPalette::Disabled, QPalette::ButtonText, palette.color(QPalette::Disabled, role)); + palette.setColor(QPalette::Current, QPalette::ButtonText, palette.color(QPalette::Current, role)); + } +} + +static std::shared_ptr<AndroidStyle> loadAndroidStyle(QPalette *defaultPalette) +{ + QString stylePath(QLatin1String(qgetenv("MINISTRO_ANDROID_STYLE_PATH"))); + const QLatin1Char slashChar('/'); + if (!stylePath.isEmpty() && !stylePath.endsWith(slashChar)) + stylePath += slashChar; + + QString androidTheme = QLatin1String(qgetenv("QT_ANDROID_THEME")); + if (!androidTheme.isEmpty() && !androidTheme.endsWith(slashChar)) + androidTheme += slashChar; + + if (stylePath.isEmpty()) { + stylePath = QLatin1String("/data/data/org.kde.necessitas.ministro/files/dl/style/") + + QLatin1String(qgetenv("QT_ANDROID_THEME_DISPLAY_DPI")) + slashChar; + } + Q_ASSERT(!stylePath.isEmpty()); + + if (!androidTheme.isEmpty() && QFileInfo(stylePath + androidTheme + QLatin1String("style.json")).exists()) + stylePath += androidTheme; + + QFile f(stylePath + QLatin1String("style.json")); + if (!f.open(QIODevice::ReadOnly)) + return std::shared_ptr<AndroidStyle>(); + + QJsonParseError error; + QJsonDocument document = QJsonDocument::fromJson(f.readAll(), &error); + if (document.isNull()) { + qCritical() << error.errorString(); + return std::shared_ptr<AndroidStyle>(); + } + + if (!document.isObject()) { + qCritical() << "Style.json does not contain a valid style."; + return std::shared_ptr<AndroidStyle>(); + } + std::shared_ptr<AndroidStyle> style(new AndroidStyle); + style->m_styleData = document.object(); + for (QJsonObject::const_iterator objectIterator = style->m_styleData.constBegin(); + objectIterator != style->m_styleData.constEnd(); + ++objectIterator) { + QString key = objectIterator.key(); + QJsonValue value = objectIterator.value(); + if (!value.isObject()) { + qWarning("Style.json structure is unrecognized."); + continue; + } + QJsonObject item = value.toObject(); + QJsonObject::const_iterator attributeIterator = item.find(QLatin1String("qtClass")); + QByteArray qtClassName; + if (attributeIterator != item.constEnd()) { + // The item has palette and font information for a specific Qt Class (e.g. QWidget, QPushButton, etc.) + qtClassName = attributeIterator.value().toString().toLatin1(); + } + const int ft = fontType(key); + if (ft > -1 || !qtClassName.isEmpty()) { + // Extract font information + QFont font; + + // Font size (in pixels) + attributeIterator = item.find(QLatin1String("TextAppearance_textSize")); + if (attributeIterator != item.constEnd()) + font.setPixelSize(int(attributeIterator.value().toDouble())); + + // Font style + attributeIterator = item.find(QLatin1String("TextAppearance_textStyle")); + if (attributeIterator != item.constEnd()) { + const int style = int(attributeIterator.value().toDouble()); + font.setBold(style & textStyle_bold); + font.setItalic(style & textStyle_italic); + } + + // Font typeface + attributeIterator = item.find(QLatin1String("TextAppearance_typeface")); + if (attributeIterator != item.constEnd()) { + QFont::StyleHint styleHint = QFont::AnyStyle; + switch (int(attributeIterator.value().toDouble())) { + case typeface_sans: + styleHint = QFont::SansSerif; + break; + case typeface_serif: + styleHint = QFont::Serif; + break; + case typeface_monospace: + styleHint = QFont::Monospace; + break; + } + font.setStyleHint(styleHint, QFont::PreferMatch); + } + if (!qtClassName.isEmpty()) + style->m_QWidgetsFonts.insert(qtClassName, font); + + if (ft > -1) { + style->m_fonts.insert(ft, font); + if (ft == QPlatformTheme::SystemFont) + QGuiApplication::setFont(font); + } + // Extract font information + } + + const int pt = paletteType(key); + if (pt > -1 || !qtClassName.isEmpty()) { + // Extract palette information + QPalette palette; + attributeIterator = item.find(QLatin1String("defaultTextColorPrimary")); + if (attributeIterator != item.constEnd()) + palette.setColor(QPalette::WindowText, QRgb(int(attributeIterator.value().toDouble()))); + + attributeIterator = item.find(QLatin1String("defaultBackgroundColor")); + if (attributeIterator != item.constEnd()) + palette.setColor(QPalette::Background, QRgb(int(attributeIterator.value().toDouble()))); + + attributeIterator = item.find(QLatin1String("TextAppearance_textColor")); + if (attributeIterator != item.constEnd()) + setPaletteColor(attributeIterator.value().toObject().toVariantMap(), palette, QPalette::WindowText); + + attributeIterator = item.find(QLatin1String("TextAppearance_textColorLink")); + if (attributeIterator != item.constEnd()) + setPaletteColor(attributeIterator.value().toObject().toVariantMap(), palette, QPalette::Link); + + attributeIterator = item.find(QLatin1String("TextAppearance_textColorHighlight")); + if (attributeIterator != item.constEnd()) + palette.setColor(QPalette::Highlight, QRgb(int(attributeIterator.value().toDouble()))); + + if (pt == QPlatformTheme::SystemPalette) + *defaultPalette = style->m_standardPalette = palette; + + if (pt > -1) + style->m_palettes.insert(pt, palette); + // Extract palette information + } + } + return style; +} + QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *androidPlatformNativeInterface) { - m_androidPlatformNativeInterface = androidPlatformNativeInterface; QColor background(229, 229, 229); QColor light = background.lighter(150); QColor mid(background.darker(130)); @@ -80,6 +344,9 @@ QAndroidPlatformTheme::QAndroidPlatformTheme(QAndroidPlatformNativeInterface *an m_defaultPalette.setBrush(QPalette::Active, QPalette::Highlight, highlight); m_defaultPalette.setBrush(QPalette::Inactive, QPalette::Highlight, highlight); m_defaultPalette.setBrush(QPalette::Disabled, QPalette::Highlight, highlight.lighter(150)); + m_androidStyleData = loadAndroidStyle(&m_defaultPalette); + QGuiApplication::setPalette(m_defaultPalette); + androidPlatformNativeInterface->m_androidStyle = m_androidStyleData; } QPlatformMenuBar *QAndroidPlatformTheme::createPlatformMenuBar() const @@ -132,9 +399,11 @@ static inline int paletteType(QPlatformTheme::Palette type) const QPalette *QAndroidPlatformTheme::palette(Palette type) const { - QHash<int, QPalette>::const_iterator it = m_androidPlatformNativeInterface->m_palettes.find(paletteType(type)); - if (it != m_androidPlatformNativeInterface->m_palettes.end()) - return &(it.value()); + if (m_androidStyleData) { + auto it = m_androidStyleData->m_palettes.find(paletteType(type)); + if (it != m_androidStyleData->m_palettes.end()) + return &(it.value()); + } return &m_defaultPalette; } @@ -154,9 +423,11 @@ static inline int fontType(QPlatformTheme::Font type) const QFont *QAndroidPlatformTheme::font(Font type) const { - QHash<int, QFont>::const_iterator it = m_androidPlatformNativeInterface->m_fonts.find(fontType(type)); - if (it != m_androidPlatformNativeInterface->m_fonts.end()) - return &(it.value()); + if (m_androidStyleData) { + auto it = m_androidStyleData->m_fonts.find(fontType(type)); + if (it != m_androidStyleData->m_fonts.end()) + return &(it.value()); + } // default in case the style has not set a font static QFont systemFont("Roboto", 14.0 * 100 / 72); // keep default size the same after changing from 100 dpi to 72 dpi @@ -165,18 +436,12 @@ const QFont *QAndroidPlatformTheme::font(Font type) const return 0; } -static const QLatin1String STYLES_PATH("/data/data/org.kde.necessitas.ministro/files/dl/style/"); -static const QLatin1String STYLE_FILE("/style.json"); - QVariant QAndroidPlatformTheme::themeHint(ThemeHint hint) const { switch (hint) { case StyleNames: if (qEnvironmentVariableIntValue("QT_USE_ANDROID_NATIVE_STYLE") - && (!qgetenv("MINISTRO_ANDROID_STYLE_PATH").isEmpty() - || QFileInfo(STYLES_PATH - + QLatin1String(qgetenv("QT_ANDROID_THEME_DISPLAY_DPI")) - + STYLE_FILE).exists())) { + && m_androidStyleData) { return QStringList("android"); } return QStringList("fusion"); diff --git a/src/plugins/platforms/android/qandroidplatformtheme.h b/src/plugins/platforms/android/qandroidplatformtheme.h index 01611bf9d4..334e86ad7a 100644 --- a/src/plugins/platforms/android/qandroidplatformtheme.h +++ b/src/plugins/platforms/android/qandroidplatformtheme.h @@ -37,8 +37,22 @@ #include <qpa/qplatformtheme.h> #include <QtGui/qpalette.h> +#include <QJsonObject> + +#include <memory> + QT_BEGIN_NAMESPACE +struct AndroidStyle +{ + QJsonObject m_styleData; + QPalette m_standardPalette; + QHash<int, QPalette> m_palettes; + QHash<int, QFont> m_fonts; + QHash<QByteArray, QFont> m_QWidgetsFonts; + QHash<QByteArray, QFont> m_QWidgetsPalettes; +}; + class QAndroidPlatformNativeInterface; class QAndroidPlatformTheme: public QPlatformTheme { @@ -57,7 +71,7 @@ public: private: - QAndroidPlatformNativeInterface * m_androidPlatformNativeInterface; + std::shared_ptr<AndroidStyle> m_androidStyleData; QPalette m_defaultPalette; }; |