summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/jar/jar.pri1
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java425
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java6
-rw-r--r--src/plugins/platforms/android/src/androidjnimain.cpp4
-rw-r--r--src/plugins/platforms/android/src/qandroidplatformdialoghelpers.cpp223
-rw-r--r--src/plugins/platforms/android/src/qandroidplatformdialoghelpers.h77
-rw-r--r--src/plugins/platforms/android/src/qandroidplatformtheme.cpp18
-rw-r--r--src/plugins/platforms/android/src/qandroidplatformtheme.h3
-rw-r--r--src/plugins/platforms/android/src/src.pri2
-rw-r--r--src/widgets/dialogs/qdialog.cpp24
-rw-r--r--src/widgets/dialogs/qdialog_p.h3
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp4
-rw-r--r--src/widgets/dialogs/qfiledialog_p.h2
-rw-r--r--src/widgets/dialogs/qmessagebox.cpp66
-rw-r--r--src/widgets/dialogs/qmessagebox.h1
15 files changed, 848 insertions, 11 deletions
diff --git a/src/android/jar/jar.pri b/src/android/jar/jar.pri
index 19501d7b29..5906231c73 100644
--- a/src/android/jar/jar.pri
+++ b/src/android/jar/jar.pri
@@ -9,6 +9,7 @@ JAVASOURCES += \
$$PATHPREFIX/QtEditText.java \
$$PATHPREFIX/QtInputConnection.java \
$$PATHPREFIX/QtLayout.java \
+ $$PATHPREFIX/QtMessageDialogHelper.java \
$$PATHPREFIX/QtNative.java \
$$PATHPREFIX/QtNativeLibrariesDir.java \
$$PATHPREFIX/QtSurface.java
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java b/src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java
new file mode 100644
index 0000000000..6ee1304c12
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtMessageDialogHelper.java
@@ -0,0 +1,425 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2013 BogDan Vatra <bogdan@kde.org>
+ ** Contact: http://www.qt-project.org/legal
+ **
+ ** This file is part of the Android port of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and Digia. For licensing terms and
+ ** conditions see http://qt.digia.com/licensing. For further information
+ ** use the contact form at http://qt.digia.com/contact-us.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 2.1 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Digia gives you certain additional
+ ** rights. These rights are described in the Digia Qt LGPL Exception
+ ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+
+package org.qtproject.qt5.android;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.text.ClipboardManager;
+import android.util.TypedValue;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+
+class QtNativeDialogHelper
+{
+ static native void dialogResult(long handler, int buttonID);
+}
+
+class ButtonStruct implements View.OnClickListener
+{
+ ButtonStruct(QtMessageDialogHelper dialog, int id, String text)
+ {
+ m_dialog = dialog;
+ m_id = id;
+ m_text = text;
+ }
+ QtMessageDialogHelper m_dialog;
+ private int m_id;
+ String m_text;
+
+ @Override
+ public void onClick(View view) {
+ QtNativeDialogHelper.dialogResult(m_dialog.handler(), m_id);
+ }
+}
+
+public class QtMessageDialogHelper
+{
+
+ public QtMessageDialogHelper(Activity activity)
+ {
+ m_activity = activity;
+ }
+
+
+ public void setIcon(int icon)
+ {
+ m_icon = icon;
+
+ }
+
+ private Drawable getIconDrawable()
+ {
+ if (m_icon == 0)
+ return null;
+
+ if (Build.VERSION.SDK_INT > 10) {
+ try {
+ TypedValue typedValue = new TypedValue();
+ m_theme.resolveAttribute(Class.forName("android.R$attr").getDeclaredField("alertDialogIcon").getInt(null), typedValue, true);
+ return m_activity.getResources().getDrawable(typedValue.resourceId);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // Information, Warning, Critical, Question
+ switch (m_icon)
+ {
+ case 1: // Information
+ try {
+ return m_activity.getResources().getDrawable(Class.forName("android.R$drawable").getDeclaredField("ic_dialog_info").getInt(null));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ break;
+ case 2: // Warning
+// try {
+// return Class.forName("android.R$drawable").getDeclaredField("stat_sys_warning").getInt(null);
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+// break;
+ case 3: // Critical
+ try {
+ return m_activity.getResources().getDrawable(Class.forName("android.R$drawable").getDeclaredField("ic_dialog_alert").getInt(null));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ break;
+ case 4: // Question
+ try {
+ return m_activity.getResources().getDrawable(Class.forName("android.R$drawable").getDeclaredField("ic_menu_help").getInt(null));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ break;
+ }
+ return null;
+ }
+
+ public void setTile(String title)
+ {
+ m_title = title;
+ }
+
+ public void setText(String text)
+ {
+ m_text = text;
+ }
+
+ public void setInformativeText(String informativeText)
+ {
+ m_informativeText = informativeText;
+ }
+
+ public void setDetailedText(String text)
+ {
+ m_detailedText = text;
+ }
+
+ public void addButton(int id, String text)
+ {
+ if (m_buttonsList == null)
+ m_buttonsList = new ArrayList<ButtonStruct>();
+ m_buttonsList.add(new ButtonStruct(this, id, text));
+ }
+
+ private void setTextAppearance(TextView view, String attr, String style)
+ {
+ try {
+ int[] attrs = (int[]) Class.forName("android.R$styleable").getDeclaredField("TextAppearance").get(null);
+ final TypedArray a = m_theme.obtainStyledAttributes(null,
+ attrs,
+ Class.forName("android.R$attr").getDeclaredField(attr).getInt(null),
+ Class.forName("android.R$style").getDeclaredField(style).getInt(null));
+ final int textSize = a.getDimensionPixelSize(
+ Class.forName("android.R$styleable").getDeclaredField("TextAppearance_textSize").getInt(null), 0);
+ if (textSize != 0)
+ view.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
+
+ final int textColor = a.getColor(
+ Class.forName("android.R$styleable").getDeclaredField("TextAppearance_textColor").getInt(null), 0x3138);
+ if (textColor != 0x3138)
+ view.setTextColor(textColor);
+
+ a.recycle();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private Drawable getStyledDrawable(String drawable) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException
+ {
+ int[] attrs = {Class.forName("android.R$attr").getDeclaredField(drawable).getInt(null)};
+ final TypedArray a = m_theme.obtainStyledAttributes(attrs);
+ Drawable d = a.getDrawable(0);
+ a.recycle();
+ return d;
+ }
+
+
+ public void show(long handler)
+ {
+ m_handler = handler;
+ m_activity.runOnUiThread( new Runnable() {
+ @Override
+ public void run() {
+ if (m_dialog != null && m_dialog.isShowing())
+ m_dialog.dismiss();
+
+ m_dialog = new AlertDialog.Builder(m_activity).create();
+ m_theme = m_dialog.getWindow().getContext().getTheme();
+
+ if (m_title != null)
+ m_dialog.setTitle(m_title);
+ m_dialog.setOnCancelListener( new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialogInterface) {
+ QtNativeDialogHelper.dialogResult(handler(), -1);
+ }
+ });
+ m_dialog.setCancelable(m_buttonsList == null);
+ m_dialog.setCanceledOnTouchOutside(m_buttonsList == null);
+ m_dialog.setIcon(getIconDrawable());
+ ScrollView scrollView = new ScrollView(m_activity);
+ RelativeLayout dialogLayout = new RelativeLayout(m_activity);
+ int id = 1;
+ View lastView = null;
+ View.OnLongClickListener copyText = new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View view) {
+ TextView tv = (TextView)view;
+ if (tv != null) {
+ ClipboardManager cm = (android.text.ClipboardManager) m_activity.getSystemService(Context.CLIPBOARD_SERVICE);
+ cm.setText(tv.getText());
+ }
+ return true;
+ }
+ };
+ if (m_text != null)
+ {
+ TextView view = new TextView(m_activity);
+ view.setId(id++);
+ view.setOnLongClickListener(copyText);
+ view.setLongClickable(true);
+
+ view.setText(m_text);
+ setTextAppearance(view, "textAppearanceMedium", "TextAppearance_Medium");
+
+ RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
+ layout.setMargins(16, 8, 16, 8);
+ layout.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ dialogLayout.addView(view, layout);
+ lastView = view;
+ }
+
+ if (m_informativeText != null)
+ {
+ TextView view= new TextView(m_activity);
+ view.setId(id++);
+ view.setOnLongClickListener(copyText);
+ view.setLongClickable(true);
+
+ view.setText(m_informativeText);
+ setTextAppearance(view, "textAppearanceMedium", "TextAppearance_Medium");
+
+ RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
+ layout.setMargins(16, 8, 16, 8);
+ if (lastView != null)
+ layout.addRule(RelativeLayout.BELOW, lastView.getId());
+ else
+ layout.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ dialogLayout.addView(view, layout);
+ lastView = view;
+ }
+
+ if (m_detailedText != null)
+ {
+ TextView view= new TextView(m_activity);
+ view.setId(id++);
+ view.setOnLongClickListener(copyText);
+ view.setLongClickable(true);
+
+ view.setText(m_detailedText);
+ setTextAppearance(view, "textAppearanceSmall", "TextAppearance_Small");
+
+ RelativeLayout.LayoutParams layout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
+ layout.setMargins(16, 8, 16, 8);
+ if (lastView != null)
+ layout.addRule(RelativeLayout.BELOW, lastView.getId());
+ else
+ layout.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ dialogLayout.addView(view, layout);
+ lastView = view;
+ }
+
+ if (m_buttonsList != null)
+ {
+ LinearLayout buttonsLayout = new LinearLayout(m_activity);
+ buttonsLayout.setOrientation(LinearLayout.HORIZONTAL);
+ buttonsLayout.setId(id++);
+ boolean firstButton = true;
+ for (ButtonStruct button: m_buttonsList)
+ {
+ Button bv;
+ if (Build.VERSION.SDK_INT > 10) {
+ try {
+ bv = new Button(m_activity, null, Class.forName("android.R$attr").getDeclaredField("borderlessButtonStyle").getInt(null));
+ } catch (Exception e) {
+ bv = new Button(m_activity);
+ e.printStackTrace();
+ }
+ } else {
+ bv = new Button(m_activity);
+ }
+
+ bv.setText(button.m_text);
+ bv.setOnClickListener(button);
+ if (!firstButton) // first button
+ {
+ LinearLayout.LayoutParams layout = null;
+ View spacer = new View(m_activity);
+ if (Build.VERSION.SDK_INT > 10) {
+ try {
+ layout = new LinearLayout.LayoutParams(1, RelativeLayout.LayoutParams.MATCH_PARENT);
+ spacer.setBackgroundDrawable(getStyledDrawable("dividerVertical"));
+ buttonsLayout.addView(spacer, layout);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ LinearLayout.LayoutParams layout = null;
+ layout = new LinearLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT, 1.0f);
+ buttonsLayout.addView(bv, layout);
+ firstButton = false;
+ }
+
+ if (Build.VERSION.SDK_INT > 10) {
+ try {
+ View horizontalDevider = new View(m_activity);
+ horizontalDevider.setId(id++);
+ horizontalDevider.setBackgroundDrawable(getStyledDrawable("dividerHorizontal"));
+ RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, 1);
+ relativeParams.setMargins(0, 10, 0, 0);
+ if (lastView != null) {
+ relativeParams.addRule(RelativeLayout.BELOW, lastView.getId());
+ }
+ else
+ relativeParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ dialogLayout.addView(horizontalDevider, relativeParams);
+ lastView = horizontalDevider;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
+ if (lastView != null) {
+ relativeParams.addRule(RelativeLayout.BELOW, lastView.getId());
+ }
+ else
+ relativeParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
+ if (Build.VERSION.SDK_INT < 11)
+ relativeParams.setMargins(2, 12, 2, 4);
+ else
+ relativeParams.setMargins(2, 0, 2, 0);
+ dialogLayout.addView(buttonsLayout, relativeParams);
+ }
+ scrollView.addView(dialogLayout);
+ m_dialog.setView(scrollView);
+ m_dialog.show();
+ }
+ });
+ }
+
+ public void hide()
+ {
+ m_activity.runOnUiThread( new Runnable() {
+ @Override
+ public void run() {
+ if (m_dialog != null && m_dialog.isShowing())
+ m_dialog.dismiss();
+ reset();
+ }
+ });
+ }
+
+ public long handler()
+ {
+ return m_handler;
+ }
+
+ public void reset()
+ {
+ m_icon = 0;
+ m_title = null;
+ m_text = null;
+ m_informativeText = null;
+ m_detailedText = null;
+ m_buttonsList = null;
+ m_dialog = null;
+ m_handler = 0;
+ }
+
+ private Activity m_activity;
+ private int m_icon = 0;
+ private String m_title, m_text, m_informativeText, m_detailedText;
+ private ArrayList<ButtonStruct> m_buttonsList;
+ private AlertDialog m_dialog;
+ private long m_handler = 0;
+ private Resources.Theme m_theme;
+}
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
index 089cf5aa60..7c741edfda 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
@@ -123,13 +123,13 @@ public class QtActivity extends Activity
// and must be separated with "\t"
// e.g "-param1\t-param2=value2\t-param3\tvalue3"
- public String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_STYLE=1\t";
+ public String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_STYLE=1\tQT_USE_ANDROID_NATIVE_DIALOGS=1\t";
// use this variable to add any environment variables to your application.
// the env vars must be separated with "\t"
// e.g. "ENV_VAR1=1\tENV_VAR2=2\t"
// Currently the following vars are used by the android plugin:
- // * QT_USE_ANDROID_NATIVE_STYLE - 1 to use the android widget style if available,
- // note that the android style plugin in Qt 5.1 is not fully functional.
+ // * QT_USE_ANDROID_NATIVE_STYLE - 1 to use the android widget style if available.
+ // * QT_USE_ANDROID_NATIVE_DIALOGS -1 to use the android native dialogs.
public String[] QT_ANDROID_THEMES = null; // A list with all themes that your application want to use.
// The name of the theme must be the same with any theme from
diff --git a/src/plugins/platforms/android/src/androidjnimain.cpp b/src/plugins/platforms/android/src/androidjnimain.cpp
index 3d599b8f8b..3ab4eedb26 100644
--- a/src/plugins/platforms/android/src/androidjnimain.cpp
+++ b/src/plugins/platforms/android/src/androidjnimain.cpp
@@ -59,6 +59,7 @@
#include "androidjniinput.h"
#include "androidjniclipboard.h"
#include "androidjnimenu.h"
+#include "qandroidplatformdialoghelpers.h"
#include "qandroidplatformintegration.h"
#include <QtWidgets/QApplication>
@@ -865,7 +866,8 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
|| !QtAndroidInput::registerNatives(env)
|| !QtAndroidClipboard::registerNatives(env)
|| !QtAndroidMenu::registerNatives(env)
- ) {
+ || !QtAndroidAccessibility::registerNatives(env)
+ || !QtAndroidDialogHelpers::registerNatives(env)) {
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
return -1;
}
diff --git a/src/plugins/platforms/android/src/qandroidplatformdialoghelpers.cpp b/src/plugins/platforms/android/src/qandroidplatformdialoghelpers.cpp
new file mode 100644
index 0000000000..f9eb34751e
--- /dev/null
+++ b/src/plugins/platforms/android/src/qandroidplatformdialoghelpers.cpp
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 BogDan Vatra <bogdan@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QStyle>
+#include "qandroidplatformdialoghelpers.h"
+#include "androidjnimain.h"
+
+namespace QtAndroidDialogHelpers {
+static jclass g_messageDialogHelperClass = 0;
+
+QAndroidPlatformMessageDialogHelper::QAndroidPlatformMessageDialogHelper()
+ :m_buttonId(-1)
+ ,m_javaMessageDialog(g_messageDialogHelperClass, "(Landroid/app/Activity;)V", QtAndroid::activity())
+ ,m_shown(false)
+{
+}
+
+void QAndroidPlatformMessageDialogHelper::exec()
+{
+ if (!m_shown)
+ show(Qt::Dialog, Qt::ApplicationModal, 0);
+ m_loop.exec();
+}
+
+static QString standardButtonText(int sbutton)
+{
+ QString buttonText = 0;
+ switch (sbutton) {
+ case QMessageDialogOptions::Ok:
+ buttonText = QObject::tr("OK");
+ break;
+ case QMessageDialogOptions::Save:
+ buttonText = QObject::tr("Save");
+ break;
+ case QMessageDialogOptions::Open:
+ buttonText = QObject::tr("Open");
+ break;
+ case QMessageDialogOptions::Cancel:
+ buttonText = QObject::tr("Cancel");
+ break;
+ case QMessageDialogOptions::Close:
+ buttonText = QObject::tr("Close");
+ break;
+ case QMessageDialogOptions::Apply:
+ buttonText = QObject::tr("Apply");
+ break;
+ case QMessageDialogOptions::Reset:
+ buttonText = QObject::tr("Reset");
+ break;
+ case QMessageDialogOptions::Help:
+ buttonText = QObject::tr("Help");
+ break;
+ case QMessageDialogOptions::Discard:
+ buttonText = QObject::tr("Discard");
+ break;
+ case QMessageDialogOptions::Yes:
+ buttonText = QObject::tr("Yes");
+ break;
+ case QMessageDialogOptions::YesToAll:
+ buttonText = QObject::tr("Yes to All");
+ break;
+ case QMessageDialogOptions::No:
+ buttonText = QObject::tr("No");
+ break;
+ case QMessageDialogOptions::NoToAll:
+ buttonText = QObject::tr("No to All");
+ break;
+ case QMessageDialogOptions::SaveAll:
+ buttonText = QObject::tr("Save All");
+ break;
+ case QMessageDialogOptions::Abort:
+ buttonText = QObject::tr("Abort");
+ break;
+ case QMessageDialogOptions::Retry:
+ buttonText = QObject::tr("Retry");
+ break;
+ case QMessageDialogOptions::Ignore:
+ buttonText = QObject::tr("Ignore");
+ break;
+ case QMessageDialogOptions::RestoreDefaults:
+ buttonText = QObject::tr("Restore Defaults");
+ break;
+ } // switch
+ return buttonText;
+}
+
+bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags
+ , Qt::WindowModality windowModality
+ , QWindow *parent)
+{
+ Q_UNUSED(windowFlags)
+ Q_UNUSED(windowModality)
+ Q_UNUSED(parent)
+ QSharedPointer<QMessageDialogOptions> opt = options();
+ if (!opt.data())
+ return false;
+
+ m_javaMessageDialog.callMethod<void>("setIcon", "(I)V", opt->icon());
+
+ QString str = opt->windowTitle();
+ if (!str.isEmpty())
+ m_javaMessageDialog.callMethod<void>("setTile", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object());
+
+ str = opt->text();
+ if (!str.isEmpty())
+ m_javaMessageDialog.callMethod<void>("setText", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object());
+
+ str = opt->informativeText();
+ if (!str.isEmpty())
+ m_javaMessageDialog.callMethod<void>("setInformativeText", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object());
+
+ str = opt->detailedText();
+ if (!str.isEmpty())
+ m_javaMessageDialog.callMethod<void>("setDetailedText", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object());
+
+ for (int i = QMessageDialogOptions::FirstButton; i < QMessageDialogOptions::LastButton; i<<=1) {
+ if ( opt->standardButtons() & i )
+ m_javaMessageDialog.callMethod<void>("addButton", "(ILjava/lang/String;)V", i, QJNIObjectPrivate::fromString(standardButtonText(i)).object());
+ }
+
+ m_javaMessageDialog.callMethod<void>("show", "(J)V", jlong(static_cast<QObject*>(this)));
+ m_shown = true;
+ return true;
+}
+
+void QAndroidPlatformMessageDialogHelper::hide()
+{
+ m_javaMessageDialog.callMethod<void>("hide", "()V");
+ m_shown = false;
+}
+
+void QAndroidPlatformMessageDialogHelper::dialogResult(int buttonID)
+{
+ m_buttonId = buttonID;
+ if (m_loop.isRunning())
+ m_loop.exit();
+ if (m_buttonId < 0) {
+ emit reject();
+ return;
+ }
+
+ QMessageDialogOptions::StandardButton standardButton = static_cast<QMessageDialogOptions::StandardButton>(buttonID);
+ QMessageDialogOptions::ButtonRole role = QMessageDialogOptions::buttonRole(standardButton);
+ emit clicked(standardButton, role);
+}
+
+static void dialogResult(JNIEnv * /*env*/, jobject /*thiz*/, jlong handler, int buttonID)
+{
+ QObject *object = reinterpret_cast<QObject *>(handler);
+ QMetaObject::invokeMethod(object, "dialogResult", Qt::QueuedConnection, Q_ARG(int, buttonID));
+}
+
+static JNINativeMethod methods[] = {
+ {"dialogResult", "(JI)V", (void *)dialogResult}
+};
+
+
+#define FIND_AND_CHECK_CLASS(CLASS_NAME) \
+ clazz = env->FindClass(CLASS_NAME); \
+ if (!clazz) { \
+ __android_log_print(ANDROID_LOG_FATAL, QtAndroid::qtTagText(), QtAndroid::classErrorMsgFmt(), CLASS_NAME); \
+ return false; \
+ }
+
+bool registerNatives(JNIEnv *env)
+{
+ jclass clazz = QtAndroid::findClass("org/qtproject/qt5/android/QtMessageDialogHelper", env);
+ if (!clazz) {
+ __android_log_print(ANDROID_LOG_FATAL, QtAndroid::qtTagText(), QtAndroid::classErrorMsgFmt()
+ , "org/qtproject/qt5/android/QtMessageDialogHelper");
+ return false;
+ }
+ g_messageDialogHelperClass = static_cast<jclass>(env->NewGlobalRef(clazz));
+ FIND_AND_CHECK_CLASS("org/qtproject/qt5/android/QtNativeDialogHelper");
+ jclass appClass = static_cast<jclass>(env->NewGlobalRef(clazz));
+
+ if (env->RegisterNatives(appClass, methods, sizeof(methods) / sizeof(methods[0])) < 0) {
+ __android_log_print(ANDROID_LOG_FATAL, "Qt", "RegisterNatives failed");
+ return false;
+ }
+
+ return true;
+}
+}
diff --git a/src/plugins/platforms/android/src/qandroidplatformdialoghelpers.h b/src/plugins/platforms/android/src/qandroidplatformdialoghelpers.h
new file mode 100644
index 0000000000..88ec91d936
--- /dev/null
+++ b/src/plugins/platforms/android/src/qandroidplatformdialoghelpers.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 BogDan Vatra <bogdan@kde.org>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDPLATFORMDIALOGHELPERS_H
+#define QANDROIDPLATFORMDIALOGHELPERS_H
+#include <jni.h>
+#include <qpa/qplatformdialoghelper.h>
+#include <QEventLoop>
+#include <private/qjni_p.h>
+
+namespace QtAndroidDialogHelpers {
+
+class QAndroidPlatformMessageDialogHelper: public QPlatformMessageDialogHelper
+{
+ Q_OBJECT
+public:
+ QAndroidPlatformMessageDialogHelper();
+ void exec();
+ bool show(Qt::WindowFlags windowFlags,
+ Qt::WindowModality windowModality,
+ QWindow *parent);
+ void hide();
+
+public slots:
+ void dialogResult(int buttonID);
+
+private:
+ int m_buttonId;
+ QEventLoop m_loop;
+ QJNIObjectPrivate m_javaMessageDialog;
+ bool m_shown;
+};
+
+
+bool registerNatives(JNIEnv *env);
+
+}
+
+#endif // QANDROIDPLATFORMDIALOGHELPERS_H
diff --git a/src/plugins/platforms/android/src/qandroidplatformtheme.cpp b/src/plugins/platforms/android/src/qandroidplatformtheme.cpp
index 79fbc440fc..0ceac97e35 100644
--- a/src/plugins/platforms/android/src/qandroidplatformtheme.cpp
+++ b/src/plugins/platforms/android/src/qandroidplatformtheme.cpp
@@ -43,6 +43,7 @@
#include "qandroidplatformmenubar.h"
#include "qandroidplatformmenu.h"
#include "qandroidplatformmenuitem.h"
+#include "qandroidplatformdialoghelpers.h"
#include <QVariant>
#include <QFileInfo>
#include <qandroidplatformintegration.h>
@@ -150,3 +151,20 @@ QVariant QAndroidPlatformTheme::themeHint(ThemeHint hint) const
return QPlatformTheme::themeHint(hint);
}
}
+
+bool QAndroidPlatformTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const
+{
+ if (type == MessageDialog)
+ return qgetenv("QT_USE_ANDROID_NATIVE_DIALOGS").toInt() == 1;
+ return false;
+}
+
+QPlatformDialogHelper *QAndroidPlatformTheme::createPlatformDialogHelper(QPlatformTheme::DialogType type) const
+{
+ switch (type) {
+ case MessageDialog:
+ return new QtAndroidDialogHelpers::QAndroidPlatformMessageDialogHelper;
+ default:
+ return 0;
+ }
+}
diff --git a/src/plugins/platforms/android/src/qandroidplatformtheme.h b/src/plugins/platforms/android/src/qandroidplatformtheme.h
index 15d2cb2000..ec259a9b0a 100644
--- a/src/plugins/platforms/android/src/qandroidplatformtheme.h
+++ b/src/plugins/platforms/android/src/qandroidplatformtheme.h
@@ -54,6 +54,9 @@ public:
virtual const QPalette *palette(Palette type = SystemPalette) const;
virtual const QFont *font(Font type = SystemFont) const;
virtual QVariant themeHint(ThemeHint hint) const;
+ virtual bool usePlatformNativeDialog(DialogType type) const;
+ virtual QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const;
+
private:
QAndroidPlatformNativeInterface * m_androidPlatformNativeInterface;
diff --git a/src/plugins/platforms/android/src/src.pri b/src/plugins/platforms/android/src/src.pri
index 6cc41c3e68..9b64e846f7 100644
--- a/src/plugins/platforms/android/src/src.pri
+++ b/src/plugins/platforms/android/src/src.pri
@@ -21,6 +21,7 @@ SOURCES += $$PWD/androidplatformplugin.cpp \
$$PWD/qandroidinputcontext.cpp \
$$PWD/qandroidplatformaccessibility.cpp \
$$PWD/qandroidplatformfontdatabase.cpp \
+ $$PWD/qandroidplatformdialoghelpers.cpp \
$$PWD/qandroidplatformclipboard.cpp \
$$PWD/qandroidplatformtheme.cpp \
$$PWD/qandroidplatformmenubar.cpp \
@@ -41,6 +42,7 @@ HEADERS += $$PWD/qandroidplatformintegration.h \
$$PWD/qandroidplatformaccessibility.h \
$$PWD/qandroidplatformfontdatabase.h \
$$PWD/qandroidplatformclipboard.h \
+ $$PWD/qandroidplatformdialoghelpers.h \
$$PWD/qandroidplatformtheme.h \
$$PWD/qandroidplatformmenubar.h \
$$PWD/qandroidplatformmenu.h \
diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp
index af352e45c6..d498b077fc 100644
--- a/src/widgets/dialogs/qdialog.cpp
+++ b/src/widgets/dialogs/qdialog.cpp
@@ -52,6 +52,8 @@
#include "qwhatsthis.h"
#include "qmenu.h"
#include "qcursor.h"
+#include "qmessagebox.h"
+#include "qerrormessage.h"
#include <qpa/qplatformtheme.h>
#include "private/qdialog_p.h"
#include "private/qguiapplication_p.h"
@@ -75,6 +77,14 @@ static inline int themeDialogType(const QDialog *dialog)
if (qobject_cast<const QFontDialog *>(dialog))
return QPlatformTheme::FontDialog;
#endif
+#ifndef QT_NO_MESSAGEBOX
+ if (qobject_cast<const QMessageBox *>(dialog))
+ return QPlatformTheme::MessageDialog;
+#endif
+#ifndef QT_NO_ERRORMESSAGE
+ if (qobject_cast<const QErrorMessage *>(dialog))
+ return QPlatformTheme::MessageDialog;
+#endif
return -1;
}
@@ -100,6 +110,17 @@ QPlatformDialogHelper *QDialogPrivate::platformHelper() const
return m_platformHelper;
}
+bool QDialogPrivate::canBeNativeDialog() const
+{
+ QDialogPrivate *ncThis = const_cast<QDialogPrivate *>(this);
+ QDialog *dialog = ncThis->q_func();
+ const int type = themeDialogType(dialog);
+ if (type >= 0)
+ return QGuiApplicationPrivate::platformTheme()
+ ->usePlatformNativeDialog(static_cast<QPlatformTheme::DialogType>(type));
+ return false;
+}
+
QWindow *QDialogPrivate::parentWindow() const
{
if (const QWidget *parent = q_func()->nativeParentWidget())
@@ -697,6 +718,9 @@ void QDialog::closeEvent(QCloseEvent *e)
void QDialog::setVisible(bool visible)
{
Q_D(QDialog);
+ if (!testAttribute(Qt::WA_DontShowOnScreen) && d->canBeNativeDialog() && d->setNativeDialogVisible(visible))
+ return;
+
if (visible) {
if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
return;
diff --git a/src/widgets/dialogs/qdialog_p.h b/src/widgets/dialogs/qdialog_p.h
index 5064efa35d..8db1b2a27c 100644
--- a/src/widgets/dialogs/qdialog_p.h
+++ b/src/widgets/dialogs/qdialog_p.h
@@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE
class QSizeGrip;
-class QDialogPrivate : public QWidgetPrivate
+class Q_WIDGETS_EXPORT QDialogPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QDialog)
public:
@@ -113,6 +113,7 @@ public:
bool nativeDialogInUse;
QPlatformDialogHelper *platformHelper() const;
+ virtual bool canBeNativeDialog() const;
private:
virtual void initHelper(QPlatformDialogHelper *) {}
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index cfdc303f21..da026d23a6 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -764,9 +764,9 @@ void QFileDialogPrivate::emitFilesSelected(const QStringList &files)
emit q->fileSelected(files.first());
}
-bool QFileDialogPrivate::canBeNativeDialog()
+bool QFileDialogPrivate::canBeNativeDialog() const
{
- Q_Q(QFileDialog);
+ Q_Q(const QFileDialog);
if (nativeDialogInUse)
return true;
if (q->testAttribute(Qt::WA_DontShowOnScreen))
diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h
index 36336bdbf6..faa721572c 100644
--- a/src/widgets/dialogs/qfiledialog_p.h
+++ b/src/widgets/dialogs/qfiledialog_p.h
@@ -251,7 +251,7 @@ public:
// setVisible_sys returns true if it ends up showing a native
// dialog. Returning false means that a non-native dialog must be
// used instead.
- bool canBeNativeDialog();
+ bool canBeNativeDialog() const;
inline bool usingWidgets() const;
void setDirectory_sys(const QUrl &directory);
diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp
index 9101c568e0..ee2ef409d8 100644
--- a/src/widgets/dialogs/qmessagebox.cpp
+++ b/src/widgets/dialogs/qmessagebox.cpp
@@ -193,7 +193,6 @@ public:
}
};
-
class QMessageBoxPrivate : public QDialogPrivate
{
Q_DECLARE_PUBLIC(QMessageBox)
@@ -204,11 +203,13 @@ public:
detailsText(0),
#endif
compatMode(false), autoAddOkButton(true),
- detectedEscapeButton(0), informativeLabel(0) { }
+ detectedEscapeButton(0), informativeLabel(0),
+ options(new QMessageDialogOptions) { }
void init(const QString &title = QString(), const QString &text = QString());
void setupLayout();
void _q_buttonClicked(QAbstractButton *);
+ void _q_clicked(QMessageDialogOptions::StandardButton button, QMessageDialogOptions::ButtonRole role);
QAbstractButton *findButton(int button0, int button1, int button2, int flags);
void addOldButtons(int button0, int button1, int button2);
@@ -224,7 +225,6 @@ public:
#ifdef Q_OS_WINCE
void hideSpecial();
#endif
-
static int showOldMessageBox(QWidget *parent, QMessageBox::Icon icon,
const QString &title, const QString &text,
int button0, int button1, int button2);
@@ -262,6 +262,11 @@ public:
QPointer<QObject> receiverToDisconnectOnClose;
QByteArray memberToDisconnectOnClose;
QByteArray signalToDisconnectOnClose;
+ QSharedPointer<QMessageDialogOptions> options;
+private:
+ void initHelper(QPlatformDialogHelper *);
+ void helperPrepareShow(QPlatformDialogHelper *);
+ void helperDone(QDialog::DialogCode, QPlatformDialogHelper *);
};
void QMessageBoxPrivate::init(const QString &title, const QString &text)
@@ -519,6 +524,13 @@ void QMessageBoxPrivate::_q_buttonClicked(QAbstractButton *button)
}
}
+void QMessageBoxPrivate::_q_clicked(QMessageDialogOptions::StandardButton button, QMessageDialogOptions::ButtonRole role)
+{
+ Q_UNUSED(role);
+ Q_Q(QMessageBox);
+ q->done(button);
+}
+
/*!
\class QMessageBox
@@ -2682,6 +2694,54 @@ QPixmap QMessageBoxPrivate::standardIcon(QMessageBox::Icon icon, QMessageBox *mb
return QPixmap();
}
+void QMessageBoxPrivate::initHelper(QPlatformDialogHelper *h)
+{
+ Q_Q(QMessageBox);
+ QObject::connect(h, SIGNAL(clicked(QMessageDialogOptions::StandardButton, QMessageDialogOptions::ButtonRole)),
+ q, SLOT(_q_clicked(QMessageDialogOptions::StandardButton, QMessageDialogOptions::ButtonRole)));
+ static_cast<QPlatformMessageDialogHelper *>(h)->setOptions(options);
+}
+
+static QMessageDialogOptions::Icon helperIcon(QMessageBox::Icon i)
+{
+ switch (i) {
+ case QMessageBox::NoIcon:
+ return QMessageDialogOptions::NoIcon;
+ case QMessageBox::Information:
+ return QMessageDialogOptions::Information;
+ case QMessageBox::Warning:
+ return QMessageDialogOptions::Warning;
+ case QMessageBox::Critical:
+ return QMessageDialogOptions::Critical;
+ case QMessageBox::Question:
+ return QMessageDialogOptions::Question;
+ }
+ return QMessageDialogOptions::NoIcon;
+}
+
+static QMessageDialogOptions::StandardButtons helperStandardButtons(QMessageBox * q)
+{
+ QMessageDialogOptions::StandardButtons buttons(int(q->standardButtons()));
+ return buttons;
+}
+
+void QMessageBoxPrivate::helperPrepareShow(QPlatformDialogHelper *)
+{
+ Q_Q(QMessageBox);
+ options->setWindowTitle(q->windowTitle());
+ options->setText(q->text());
+ options->setInformativeText(q->informativeText());
+ options->setDetailedText(q->detailedText());
+ options->setIcon(helperIcon(q->icon()));
+ options->setStandardButtons(helperStandardButtons(q));
+}
+
+void QMessageBoxPrivate::helperDone(QDialog::DialogCode code, QPlatformDialogHelper *)
+{
+ Q_Q(QMessageBox);
+ clickedButton = q->button(QMessageBox::StandardButton(code));
+}
+
/*!
\obsolete
diff --git a/src/widgets/dialogs/qmessagebox.h b/src/widgets/dialogs/qmessagebox.h
index 58be13426c..c5598a8f1d 100644
--- a/src/widgets/dialogs/qmessagebox.h
+++ b/src/widgets/dialogs/qmessagebox.h
@@ -309,6 +309,7 @@ protected:
private:
Q_PRIVATE_SLOT(d_func(), void _q_buttonClicked(QAbstractButton *))
+ Q_PRIVATE_SLOT(d_func(), void _q_clicked(QMessageDialogOptions::StandardButton, QMessageDialogOptions::ButtonRole))
Q_DISABLE_COPY(QMessageBox)
Q_DECLARE_PRIVATE(QMessageBox)