Android native message dialog
Change-Id: Ief8c3ce3b8683c6960f046245844c1835a327d51 Reviewed-by: Shawn Rutledge <shawn.rutledge@digia.com>
This commit is contained in:
parent
315ba388f3
commit
ef6544ee27
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 \
|
||||
|
@ -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"
|
||||
@ -74,6 +76,14 @@ static inline int themeDialogType(const QDialog *dialog)
|
||||
#ifndef QT_NO_FONTDIALOG
|
||||
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;
|
||||
|
@ -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 *) {}
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user