From 4c631c0bf971f0b41eb319cd3c6d5c723055aac6 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 9 Feb 2016 14:19:46 +0100 Subject: [PATCH] Android: add support for custom buttons in native MessageDialog helper New API in QMessageDialogOptions and implementation on Android. Task-number: QTBUG-35545 Change-Id: I59567251199f220862d01ba76979266379eecd86 Reviewed-by: Shawn Rutledge Reviewed-by: Ulf Hermann --- src/gui/kernel/qplatformdialoghelper.cpp | 37 ++++++++++++++++++- src/gui/kernel/qplatformdialoghelper.h | 22 ++++++++++- .../android/qandroidplatformdialoghelpers.cpp | 16 ++++++++ src/widgets/dialogs/qmessagebox.cpp | 23 ++++++++++-- 4 files changed, 91 insertions(+), 7 deletions(-) diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp index b456c1ca31..b787629f6a 100644 --- a/src/gui/kernel/qplatformdialoghelper.cpp +++ b/src/gui/kernel/qplatformdialoghelper.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -786,7 +787,8 @@ class QMessageDialogOptionsPrivate : public QSharedData public: QMessageDialogOptionsPrivate() : icon(QMessageDialogOptions::NoIcon), - buttons(QPlatformDialogHelper::Ok) + buttons(QPlatformDialogHelper::Ok), + nextCustomButtonId(QPlatformDialogHelper::LastButton + 1) {} QString windowTitle; @@ -795,6 +797,8 @@ public: QString informativeText; QString detailedText; QPlatformDialogHelper::StandardButtons buttons; + QVector customButtons; + int nextCustomButtonId; }; QMessageDialogOptions::QMessageDialogOptions(QMessageDialogOptionsPrivate *dd) @@ -886,6 +890,35 @@ QPlatformDialogHelper::StandardButtons QMessageDialogOptions::standardButtons() return d->buttons; } +int QMessageDialogOptions::addButton(const QString &label, QPlatformDialogHelper::ButtonRole role, + void *buttonImpl) +{ + const CustomButton b(d->nextCustomButtonId++, label, role, buttonImpl); + d->customButtons.append(b); + return b.id; +} + +static inline bool operator==(const QMessageDialogOptions::CustomButton &a, + const QMessageDialogOptions::CustomButton &b) { + return a.id == b.id; +} + +void QMessageDialogOptions::removeButton(int id) +{ + d->customButtons.removeOne(CustomButton(id)); +} + +const QVector &QMessageDialogOptions::customButtons() +{ + return d->customButtons; +} + +const QMessageDialogOptions::CustomButton *QMessageDialogOptions::customButton(int id) +{ + int i = d->customButtons.indexOf(CustomButton(id)); + return (i < 0 ? nullptr : &d->customButtons.at(i)); +} + QPlatformDialogHelper::ButtonRole QPlatformDialogHelper::buttonRole(QPlatformDialogHelper::StandardButton button) { switch (button) { diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h index 64b703e524..bfcb658172 100644 --- a/src/gui/kernel/qplatformdialoghelper.h +++ b/src/gui/kernel/qplatformdialoghelper.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -460,6 +460,26 @@ public: void setStandardButtons(QPlatformDialogHelper::StandardButtons buttons); QPlatformDialogHelper::StandardButtons standardButtons() const; + struct CustomButton { + explicit CustomButton( + int id = -1, const QString &label = QString(), + QPlatformDialogHelper::ButtonRole role = QPlatformDialogHelper::InvalidRole, + void *button = nullptr) : + label(label), role(role), id(id), button(button) + {} + + QString label; + QPlatformDialogHelper::ButtonRole role; + int id; + void *button; // strictly internal use only + }; + + int addButton(const QString &label, QPlatformDialogHelper::ButtonRole role, + void *buttonImpl = nullptr); + void removeButton(int id); + const QVector &customButtons(); + const CustomButton *customButton(int id); + private: QMessageDialogOptionsPrivate *d; }; diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp index ced35c4cfa..9218afa7f5 100644 --- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp +++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2018 The Qt Company Ltd. ** Copyright (C) 2013 BogDan Vatra ** Contact: https://www.qt.io/licensing/ ** @@ -117,6 +118,15 @@ bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags void QAndroidPlatformMessageDialogHelper::addButtons(QSharedPointer opt, ButtonRole role) { + for (const QMessageDialogOptions::CustomButton &b : opt->customButtons()) { + if (b.role == role) { + QString label = b.label; + label.remove(QChar('&')); + m_javaMessageDialog.callMethod("addButton", "(ILjava/lang/String;)V", b.id, + QJNIObjectPrivate::fromString(label).object()); + } + } + for (int i = QPlatformDialogHelper::FirstButton; i < QPlatformDialogHelper::LastButton; i<<=1) { StandardButton b = static_cast(i); if (buttonRole(b) == role && (opt->standardButtons() & i)) { @@ -144,6 +154,12 @@ void QAndroidPlatformMessageDialogHelper::dialogResult(int buttonID) QPlatformDialogHelper::StandardButton standardButton = static_cast(buttonID); QPlatformDialogHelper::ButtonRole role = QPlatformDialogHelper::buttonRole(standardButton); + if (buttonID > QPlatformDialogHelper::LastButton) { + const QMessageDialogOptions::CustomButton *custom = options()->customButton(buttonID); + Q_ASSERT(custom); + role = custom->role; + } + emit clicked(standardButton, role); } diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index 6de952a1d3..c9f72da060 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -64,6 +64,7 @@ #include #include #include +#include "private/qabstractbutton_p.h" #include #ifdef Q_OS_WIN @@ -492,9 +493,17 @@ void QMessageBoxPrivate::_q_buttonClicked(QAbstractButton *button) void QMessageBoxPrivate::_q_clicked(QPlatformDialogHelper::StandardButton button, QPlatformDialogHelper::ButtonRole role) { - Q_UNUSED(role); Q_Q(QMessageBox); - q->done(button); + if (button > QPlatformDialogHelper::LastButton) { + // It's a custom button, and the QPushButton in options is just a proxy + // for the button on the platform dialog. Simulate the user clicking it. + clickedButton = static_cast(options->customButton(button)->button); + Q_ASSERT(clickedButton); + clickedButton->click(); + q->done(role); + } else { + q->done(button); + } } /*! @@ -831,6 +840,8 @@ void QMessageBox::addButton(QAbstractButton *button, ButtonRole role) if (!button) return; removeButton(button); + d->options->addButton(button->text(), static_cast(role), + button); d->buttonBox->addButton(button, (QDialogButtonBox::ButtonRole)role); d->customButtonList.append(button); d->autoAddOkButton = false; @@ -2678,7 +2689,11 @@ void QMessageBoxPrivate::helperPrepareShow(QPlatformDialogHelper *) void QMessageBoxPrivate::helperDone(QDialog::DialogCode code, QPlatformDialogHelper *) { Q_Q(QMessageBox); - clickedButton = q->button(QMessageBox::StandardButton(code)); + QAbstractButton *button = q->button(QMessageBox::StandardButton(code)); + // If it was a custom button, a custom ID was used, so we won't get a valid pointer here. + // In that case, clickedButton has already been set in _q_buttonClicked. + if (button) + clickedButton = button; } /*!