diff options
author | Shawn Rutledge <shawn.rutledge@digia.com> | 2014-02-07 16:29:31 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-15 21:52:47 +0100 |
commit | ccb088a6beaff01419ec9325dbd19040f279b6ea (patch) | |
tree | ae1753ab02284a1fd69b30d6086a40b9faf6fc91 | |
parent | f212322a6ecb237d5fb53e56c6dafffb87e45f09 (diff) | |
download | qtquickcontrols-ccb088a6beaff01419ec9325dbd19040f279b6ea.tar.gz |
QtQuick.Dialogs: added Dialog: wrapper for arbitrary content
It provides only a button box, so the application developer can
supply the rest of the dialog contents. This is useful for various
kinds of dialogs that prompt the user for input.
[ChangeLog][QtQuickDialogs][Dialog] Dialog is a new wrapper component
for dialogs with standard buttons and custom content items.
Change-Id: I0434bed5f504820dc0a668cb993a94980f99852a
Reviewed-by: Liang Qi <liang.qi@digia.com>
-rw-r--r-- | examples/quick/dialogs/systemdialogs/CustomDialogs.qml | 262 | ||||
-rw-r--r-- | examples/quick/dialogs/systemdialogs/systemdialogs.pro | 3 | ||||
-rw-r--r-- | examples/quick/dialogs/systemdialogs/systemdialogs.qml | 4 | ||||
-rw-r--r-- | src/dialogs/DefaultDialogWrapper.qml | 162 | ||||
-rw-r--r-- | src/dialogs/dialogs.pro | 5 | ||||
-rw-r--r-- | src/dialogs/plugin.cpp | 14 | ||||
-rw-r--r-- | src/dialogs/qquickabstractdialog.cpp | 27 | ||||
-rw-r--r-- | src/dialogs/qquickabstractdialog_p.h | 31 | ||||
-rw-r--r-- | src/dialogs/qquickabstractmessagedialog.cpp | 2 | ||||
-rw-r--r-- | src/dialogs/qquickabstractmessagedialog_p.h | 37 | ||||
-rw-r--r-- | src/dialogs/qquickdialog.cpp | 271 | ||||
-rw-r--r-- | src/dialogs/qquickdialog_p.h | 127 | ||||
-rw-r--r-- | src/dialogs/qquickdialogassets_p.h | 2 |
13 files changed, 911 insertions, 36 deletions
diff --git a/examples/quick/dialogs/systemdialogs/CustomDialogs.qml b/examples/quick/dialogs/systemdialogs/CustomDialogs.qml new file mode 100644 index 00000000..2a31147e --- /dev/null +++ b/examples/quick/dialogs/systemdialogs/CustomDialogs.qml @@ -0,0 +1,262 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.1 +import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.1 +import QtQuick.Window 2.0 + +Item { + id: root + width: 580 + height: 400 + SystemPalette { id: palette } + clip: true + + //! [dialog] + Dialog { + id: helloDialog + modality: dialogModal.checked ? Qt.WindowModal : Qt.NonModal + title: customizeTitle.checked ? windowTitleField.text : "Hello" + onButtonClicked: console.log("clicked button " + clickedButton) + onAccepted: lastChosen.text = "Accepted " + + (clickedButton == StandardButton.Ok ? "(OK)" : (clickedButton == StandardButton.Retry ? "(Retry)" : "(Ignore)")) + onRejected: lastChosen.text = "Rejected " + + (clickedButton == StandardButton.Close ? "(Close)" : (clickedButton == StandardButton.Abort ? "(Abort)" : "(Cancel)")) + onHelp: lastChosen.text = "Yelped for help!" + onYes: lastChosen.text = (clickedButton == StandardButton.Yes ? "Yeessss!!" : "Yes, now and always") + onNo: lastChosen.text = (clickedButton == StandardButton.No ? "Oh No." : "No, no, a thousand times no!") + onApply: lastChosen.text = "Apply" + onReset: lastChosen.text = "Reset" + + Text { + text: "Hello world!" + } + } + //! [dialog] + + Dialog { + id: spinboxDialog + modality: dialogModal.checked ? Qt.WindowModal : Qt.NonModal + title: customizeTitle.checked ? windowTitleField.text : "Spinbox" + onHelp: { + lastChosen.text = "No help available, sorry. Please answer the question." + visible = true + } + onButtonClicked: { + if (clickedButton === StandardButton.Ok && answer.value == 11.0) + lastChosen.text = "You are correct!" + else + lastChosen.text = "Having failed to give the correct answer, you shall not pass!" + } + + ColumnLayout { + id: column + width: parent ? parent.width : 100 + Text { + text: "<b>What</b> is the average airspeed velocity of an unladen European swallow?" + textFormat: Text.StyledText + Layout.columnSpan: 2 + Layout.fillWidth: true + wrapMode: Text.WordWrap + } + RowLayout { + Layout.alignment: Qt.AlignHCenter + SpinBox { + id: answer + } + Text { + text: "m/s" + Layout.alignment: Qt.AlignBaseline | Qt.AlignLeft + } + } + } + } + + Column { + anchors.fill: parent + anchors.margins: 12 + spacing: 8 + Text { + color: palette.windowText + font.bold: true + text: "Message dialog properties:" + } + CheckBox { + id: dialogModal + text: "Modal" + checked: true + Binding on checked { value: helloDialog.modality != Qt.NonModal } + } + CheckBox { + id: customizeTitle + text: "Window Title" + checked: true + width: parent.width + TextField { + id: windowTitleField + anchors.right: parent.right + text: "Custom Dialog" + width: root.width - customizeTitle.implicitWidth - 30 + } + } + + Flow { + spacing: 8 + width: parent.width + property bool updating: false + function updateButtons(button, checked) { + if (updating) return + updating = true + var buttons = 0 + for (var i = 0; i < children.length; ++i) + if (children[i].checked) + buttons |= children[i].button + if (!buttons) + buttons = StandardButton.Ok + helloDialog.standardButtons = buttons + spinboxDialog.standardButtons = buttons + updating = false + } + + CheckBox { + text: "Help" + property int button: StandardButton.Help + onCheckedChanged: parent.updateButtons(button, checked) + } + + CheckBox { + text: "Abort" + property int button: StandardButton.Abort + onCheckedChanged: parent.updateButtons(button, checked) + } + + CheckBox { + text: "Close" + property int button: StandardButton.Close + onCheckedChanged: parent.updateButtons(button, checked) + } + + CheckBox { + text: "Cancel" + property int button: StandardButton.Cancel + onCheckedChanged: parent.updateButtons(button, checked) + } + + CheckBox { + text: "NoToAll" + property int button: StandardButton.NoToAll + onCheckedChanged: parent.updateButtons(button, checked) + } + + CheckBox { + text: "No" + property int button: StandardButton.No + onCheckedChanged: parent.updateButtons(button, checked) + } + + CheckBox { + text: "YesToAll" + property int button: StandardButton.YesToAll + onCheckedChanged: parent.updateButtons(button, checked) + } + + CheckBox { + text: "Yes" + property int button: StandardButton.Yes + onCheckedChanged: parent.updateButtons(button, checked) + } + + CheckBox { + text: "Ignore" + property int button: StandardButton.Ignore + onCheckedChanged: parent.updateButtons(button, checked) + } + + CheckBox { + text: "Retry" + property int button: StandardButton.Retry + onCheckedChanged: parent.updateButtons(button, checked) + } + + CheckBox { + text: "OK" + checked: true + property int button: StandardButton.Ok + onCheckedChanged: parent.updateButtons(button, checked) + } + + Component.onCompleted: updateButtons() + } + Text { + id: lastChosen + } + } + + Rectangle { + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + height: buttonRow.height * 1.2 + color: Qt.darker(palette.window, 1.1) + border.color: Qt.darker(palette.window, 1.3) + Row { + id: buttonRow + spacing: 6 + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 12 + width: parent.width + Button { + text: "Hello World dialog" + anchors.verticalCenter: parent.verticalCenter + onClicked: helloDialog.open() + } + Button { + text: "Input dialog" + anchors.verticalCenter: parent.verticalCenter + onClicked: spinboxDialog.open() + } + } + } +} diff --git a/examples/quick/dialogs/systemdialogs/systemdialogs.pro b/examples/quick/dialogs/systemdialogs/systemdialogs.pro index fcc61bb8..52ab103c 100644 --- a/examples/quick/dialogs/systemdialogs/systemdialogs.pro +++ b/examples/quick/dialogs/systemdialogs/systemdialogs.pro @@ -10,7 +10,8 @@ OTHER_FILES += \ FileDialogs.qml \ ColorDialogs.qml \ FontDialogs.qml \ - MessageDialogs.qml + MessageDialogs.qml \ + CustomDialogs.qml target.path = $$[QT_INSTALL_EXAMPLES]/quick/dialogs/systemdialogs INSTALLS += target diff --git a/examples/quick/dialogs/systemdialogs/systemdialogs.qml b/examples/quick/dialogs/systemdialogs/systemdialogs.qml index 4b44a1e6..f3372ea0 100644 --- a/examples/quick/dialogs/systemdialogs/systemdialogs.qml +++ b/examples/quick/dialogs/systemdialogs/systemdialogs.qml @@ -67,5 +67,9 @@ ApplicationWindow { title: "Message Dialog" MessageDialogs { anchors.fill:parent } } + Tab { + title: "Custom Dialogs" + CustomDialogs { anchors.fill:parent } + } } } diff --git a/src/dialogs/DefaultDialogWrapper.qml b/src/dialogs/DefaultDialogWrapper.qml new file mode 100644 index 00000000..1a30141e --- /dev/null +++ b/src/dialogs/DefaultDialogWrapper.qml @@ -0,0 +1,162 @@ +/***************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQuick.Dialogs module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +*****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.1 +import QtQuick.Dialogs 1.2 +import QtQuick.Layouts 1.1 +import QtQuick.Window 2.1 +import "qml" + +AbstractDialog { + id: root + default property alias data: contentItem.data + + Rectangle { + id: content + property real spacing: 6 + property real outerSpacing: 12 + property real buttonsRowImplicitWidth: minimumWidth + property bool buttonsInSingleRow: contentItem.width >= buttonsRowImplicitWidth + property real minimumHeight: implicitHeight + property real minimumWidth: Screen.pixelDensity * 50 + implicitHeight: contentItem.implicitHeight + spacing + outerSpacing * 2 + + (buttonsInSingleRow ? moreButton.implicitHeight : moreButton.implicitHeight * 2 + spacing) + implicitWidth: Math.min(Screen.desktopAvailableWidth * 0.9, Math.max( + contentItem.implicitWidth, buttonsRowImplicitWidth, Screen.pixelDensity * 50) + outerSpacing * 2); + color: palette.window + focus: root.visible + Keys.onPressed: { + event.accepted = true + switch (event.key) { + case Qt.Key_Escape: + case Qt.Key_Back: + reject() + break + case Qt.Key_Enter: + case Qt.Key_Return: + accept() + break + } + } + + SystemPalette { id: palette } + + Item { + id: contentItem + anchors { + left: parent.left + right: parent.right + top: parent.top + margins: content.outerSpacing + } + implicitHeight: childrenRect.height + } + + Flow { + id: buttonsLeft + spacing: content.spacing + anchors { + left: parent.left + bottom: content.buttonsInSingleRow ? parent.bottom : buttonsRight.top + margins: content.outerSpacing + } + + Repeater { + model: standardButtonsLeftModel + onCountChanged: calculateImplicitWidth() + Button { + text: standardButtonsLeftModel[index].text + onClicked: root.click(standardButtonsLeftModel[index].standardButton) + } + } + + Button { + id: moreButton + text: "Show Details..." + visible: false + } + } + + Flow { + id: buttonsRight + spacing: content.spacing + layoutDirection: Qt.RightToLeft + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + margins: content.outerSpacing + } + + Repeater { + model: standardButtonsRightModel + onCountChanged: calculateImplicitWidth() + // TODO maybe: insert gaps if the button requires it (destructive buttons only) + Button { + text: standardButtonsRightModel[index].text + onClicked: root.click(standardButtonsRightModel[index].standardButton) + } + } + } + } + function calculateImplicitWidth() { + if (buttonsRight.visibleChildren.length < 2) + return; + var calcWidth = 0; + + function calculateForButton(i, b) { + var buttonWidth = b.implicitWidth; + if (buttonWidth > 0) { + if (i > 0) + buttonWidth += content.spacing + calcWidth += buttonWidth + } + } + + for (var i = 0; i < buttonsRight.visibleChildren.length; ++i) + calculateForButton(i, buttonsRight.visibleChildren[i]) + content.minimumWidth = calcWidth + content.outerSpacing * 2 + for (i = 0; i < buttonsLeft.visibleChildren.length; ++i) + calculateForButton(i, buttonsLeft.visibleChildren[i]) + content.buttonsRowImplicitWidth = calcWidth + content.spacing + } + Component.onCompleted: calculateImplicitWidth() +} diff --git a/src/dialogs/dialogs.pro b/src/dialogs/dialogs.pro index dee9fe36..4ad7888f 100644 --- a/src/dialogs/dialogs.pro +++ b/src/dialogs/dialogs.pro @@ -19,6 +19,7 @@ SOURCES += \ qquickplatformfontdialog.cpp \ qquickfontdialog.cpp \ qquickabstractdialog.cpp \ + qquickdialog.cpp \ plugin.cpp HEADERS += \ @@ -35,7 +36,8 @@ HEADERS += \ qquickabstractfontdialog_p.h \ qquickplatformfontdialog_p.h \ qquickfontdialog_p.h \ - qquickabstractdialog_p.h + qquickabstractdialog_p.h \ + qquickdialog_p.h DIALOGS_QML_FILES += \ DefaultMessageDialog.qml \ @@ -46,6 +48,7 @@ DIALOGS_QML_FILES += \ WidgetColorDialog.qml \ DefaultFontDialog.qml \ WidgetFontDialog.qml \ + DefaultDialogWrapper.qml \ qml/ColorSlider.qml \ qml/DefaultWindowDecoration.qml \ qml/qmldir \ diff --git a/src/dialogs/plugin.cpp b/src/dialogs/plugin.cpp index 4e4c641e..7c8c6bea 100644 --- a/src/dialogs/plugin.cpp +++ b/src/dialogs/plugin.cpp @@ -54,6 +54,7 @@ #include "qquickfontdialog_p.h" #include "qquickabstractfontdialog_p.h" #include "qquickplatformfontdialog_p.h" +#include "qquickdialog_p.h" #include <private/qguiapplication_p.h> #include <qpa/qplatformintegration.h> @@ -162,6 +163,19 @@ public: else #endif registerWidgetOrQmlImplementation<QQuickFontDialog>(widgetsDir, qmlDir, "FontDialog", uri, hasTopLevelWindows, 1, 1); + + // Dialog + { + // @uri QtQuick.Dialogs.AbstractDialog + qmlRegisterType<QQuickDialog>(uri, 1, 2, "AbstractDialog"); // implementation wrapper + QUrl dialogQmlPath = m_useResources ? + QUrl("qrc:/QtQuick/Dialogs/DefaultDialogWrapper.qml") : + QUrl::fromLocalFile(qmlDir.filePath("DefaultDialogWrapper.qml")); +#ifdef DEBUG_REGISTRATION + qDebug() << " registering DefaultDialogWrapper.qml as Dialog; success?" << +#endif + qmlRegisterType(dialogQmlPath, uri, 1, 2, "Dialog"); + } } protected: diff --git a/src/dialogs/qquickabstractdialog.cpp b/src/dialogs/qquickabstractdialog.cpp index 9bb23887..92bad9bf 100644 --- a/src/dialogs/qquickabstractdialog.cpp +++ b/src/dialogs/qquickabstractdialog.cpp @@ -103,7 +103,20 @@ void QQuickAbstractDialog::setVisible(bool v) ((QObject *)win)->setParent(this); // memory management only m_dialogWindow = win; m_contentItem->setParentItem(win->contentItem()); - m_dialogWindow->setMinimumSize(QSize(m_contentItem->implicitWidth(), m_contentItem->implicitHeight())); + QSize minSize = QSize(m_contentItem->implicitWidth(), m_contentItem->implicitHeight()); + QVariant minHeight = m_contentItem->property("minimumHeight"); + if (minHeight.isValid()) { + if (minHeight.toInt() > minSize.height()) + minSize.setHeight(minHeight.toDouble()); + connect(m_contentItem, SIGNAL(minimumHeightChanged()), this, SLOT(minimumHeightChanged())); + } + QVariant minWidth = m_contentItem->property("minimumWidth"); + if (minWidth.isValid()) { + if (minWidth.toInt() > minSize.width()) + minSize.setWidth(minWidth.toInt()); + connect(m_contentItem, SIGNAL(minimumWidthChanged()), this, SLOT(minimumWidthChanged())); + } + m_dialogWindow->setMinimumSize(minSize); connect(win, SIGNAL(widthChanged(int)), this, SLOT(windowGeometryChanged())); connect(win, SIGNAL(heightChanged(int)), this, SLOT(windowGeometryChanged())); } @@ -230,6 +243,18 @@ void QQuickAbstractDialog::windowGeometryChanged() } } +void QQuickAbstractDialog::minimumWidthChanged() +{ + m_dialogWindow->setMinimumWidth(qMax(m_contentItem->implicitWidth(), + m_contentItem->property("minimumWidth").toReal())); +} + +void QQuickAbstractDialog::minimumHeightChanged() +{ + m_dialogWindow->setMinimumHeight(qMax(m_contentItem->implicitHeight(), + m_contentItem->property("minimumHeight").toReal())); +} + QQuickWindow *QQuickAbstractDialog::parentWindow() { QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent()); diff --git a/src/dialogs/qquickabstractdialog_p.h b/src/dialogs/qquickabstractdialog_p.h index 8ffa166c..5a408530 100644 --- a/src/dialogs/qquickabstractdialog_p.h +++ b/src/dialogs/qquickabstractdialog_p.h @@ -63,6 +63,9 @@ QT_BEGIN_NAMESPACE class QQuickAbstractDialog : public QObject { Q_OBJECT + // TODO move the enum to QQuickDialog at the same time that QQuickMessageDialog inherits from it + Q_ENUMS(StandardButton) + Q_FLAGS(StandardButtons) Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibilityChanged) Q_PROPERTY(Qt::WindowModality modality READ modality WRITE setModality NOTIFY modalityChanged) Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) @@ -92,6 +95,30 @@ public: void setQmlImplementation(QObject* obj); bool isWindow() const { return m_hasNativeWindows; } + enum StandardButton { + NoButton = QPlatformDialogHelper::NoButton, + Ok = QPlatformDialogHelper::Ok, + Save = QPlatformDialogHelper::Save, + SaveAll = QPlatformDialogHelper::SaveAll, + Open = QPlatformDialogHelper::Open, + Yes = QPlatformDialogHelper::Yes, + YesToAll = QPlatformDialogHelper::YesToAll, + No = QPlatformDialogHelper::No, + NoToAll = QPlatformDialogHelper::NoToAll, + Abort = QPlatformDialogHelper::Abort, + Retry = QPlatformDialogHelper::Retry, + Ignore = QPlatformDialogHelper::Ignore, + Close = QPlatformDialogHelper::Close, + Cancel = QPlatformDialogHelper::Cancel, + Discard = QPlatformDialogHelper::Discard, + Help = QPlatformDialogHelper::Help, + Apply = QPlatformDialogHelper::Apply, + Reset = QPlatformDialogHelper::Reset, + RestoreDefaults = QPlatformDialogHelper::RestoreDefaults, + NButtons + }; + Q_DECLARE_FLAGS(StandardButtons, StandardButton) + public Q_SLOTS: void open() { setVisible(true); } void close() { setVisible(false); } @@ -114,6 +141,8 @@ protected Q_SLOTS: virtual void reject(); void visibleChanged(bool v); void windowGeometryChanged(); + void minimumWidthChanged(); + void minimumHeightChanged(); protected: virtual QPlatformDialogHelper *helper() = 0; @@ -140,6 +169,8 @@ protected: // variables for pure-QML implementations only Q_DISABLE_COPY(QQuickAbstractDialog) }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickAbstractDialog::StandardButtons) + QT_END_NAMESPACE #endif // QQUICKABSTRACTDIALOG_P_H diff --git a/src/dialogs/qquickabstractmessagedialog.cpp b/src/dialogs/qquickabstractmessagedialog.cpp index 2c24c4ba..ebaed414 100644 --- a/src/dialogs/qquickabstractmessagedialog.cpp +++ b/src/dialogs/qquickabstractmessagedialog.cpp @@ -169,7 +169,7 @@ void QQuickAbstractMessageDialog::click(QPlatformDialogHelper::StandardButton bu } } -void QQuickAbstractMessageDialog::click(QQuickAbstractMessageDialog::StandardButton button) +void QQuickAbstractMessageDialog::click(QQuickAbstractDialog::StandardButton button) { click(static_cast<QPlatformDialogHelper::StandardButton>(button), static_cast<QPlatformDialogHelper::ButtonRole>( diff --git a/src/dialogs/qquickabstractmessagedialog_p.h b/src/dialogs/qquickabstractmessagedialog_p.h index 2afea1dc..3cf8ee47 100644 --- a/src/dialogs/qquickabstractmessagedialog_p.h +++ b/src/dialogs/qquickabstractmessagedialog_p.h @@ -66,16 +66,14 @@ class QQuickAbstractMessageDialog : public QQuickAbstractDialog Q_OBJECT Q_ENUMS(Icon) - Q_ENUMS(StandardButton) - Q_FLAGS(StandardButtons) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QString informativeText READ informativeText WRITE setInformativeText NOTIFY informativeTextChanged) Q_PROPERTY(QString detailedText READ detailedText WRITE setDetailedText NOTIFY detailedTextChanged) Q_PROPERTY(Icon icon READ icon WRITE setIcon NOTIFY iconChanged) Q_PROPERTY(QUrl standardIconSource READ standardIconSource NOTIFY iconChanged) - Q_PROPERTY(StandardButtons standardButtons READ standardButtons WRITE setStandardButtons NOTIFY standardButtonsChanged) - Q_PROPERTY(StandardButton clickedButton READ clickedButton NOTIFY buttonClicked) + Q_PROPERTY(QQuickAbstractDialog::StandardButtons standardButtons READ standardButtons WRITE setStandardButtons NOTIFY standardButtonsChanged) + Q_PROPERTY(QQuickAbstractDialog::StandardButton clickedButton READ clickedButton NOTIFY buttonClicked) public: QQuickAbstractMessageDialog(QObject *parent = 0); @@ -98,29 +96,6 @@ public: QUrl standardIconSource(); - enum StandardButton { - NoButton = QPlatformDialogHelper::NoButton, - Ok = QPlatformDialogHelper::Ok, - Save = QPlatformDialogHelper::Save, - SaveAll = QPlatformDialogHelper::SaveAll, - Open = QPlatformDialogHelper::Open, - Yes = QPlatformDialogHelper::Yes, - YesToAll = QPlatformDialogHelper::YesToAll, - No = QPlatformDialogHelper::No, - NoToAll = QPlatformDialogHelper::NoToAll, - Abort = QPlatformDialogHelper::Abort, - Retry = QPlatformDialogHelper::Retry, - Ignore = QPlatformDialogHelper::Ignore, - Close = QPlatformDialogHelper::Close, - Cancel = QPlatformDialogHelper::Cancel, - Discard = QPlatformDialogHelper::Discard, - Help = QPlatformDialogHelper::Help, - Apply = QPlatformDialogHelper::Apply, - Reset = QPlatformDialogHelper::Reset, - RestoreDefaults = QPlatformDialogHelper::RestoreDefaults - }; - Q_DECLARE_FLAGS(StandardButtons, StandardButton) - StandardButtons standardButtons() const { return static_cast<StandardButtons>(static_cast<int>(m_options->standardButtons())); } StandardButton clickedButton() const { return m_clickedButton; } @@ -133,8 +108,7 @@ public Q_SLOTS: void setDetailedText(const QString &arg); void setIcon(Icon icon); void setStandardButtons(StandardButtons buttons); - void click(QPlatformDialogHelper::StandardButton button, QPlatformDialogHelper::ButtonRole); - void click(QQuickAbstractMessageDialog::StandardButton button); + void click(QQuickAbstractDialog::StandardButton button); Q_SIGNALS: void textChanged(); @@ -151,6 +125,9 @@ Q_SIGNALS: void reset(); protected: + void click(QPlatformDialogHelper::StandardButton button, QPlatformDialogHelper::ButtonRole); + +protected: QPlatformMessageDialogHelper *m_dlgHelper; QSharedPointer<QMessageDialogOptions> m_options; StandardButton m_clickedButton; @@ -158,8 +135,6 @@ protected: Q_DISABLE_COPY(QQuickAbstractMessageDialog) }; -Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickAbstractMessageDialog::StandardButtons) - QT_END_NAMESPACE #endif // QQUICKABSTRACTMESSAGEDIALOG_P_H diff --git a/src/dialogs/qquickdialog.cpp b/src/dialogs/qquickdialog.cpp new file mode 100644 index 00000000..4d47ab3c --- /dev/null +++ b/src/dialogs/qquickdialog.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQuick.Dialogs module 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 "qquickdialog_p.h" +#include <QQuickItem> +#include <private/qguiapplication_p.h> + +QT_BEGIN_NAMESPACE + +/*! + \qmltype Dialog + \instantiates QQuickDialog + \inqmlmodule QtQuick.Dialogs + \ingroup qtquick-visual + \brief A generic QtQuick dialog wrapper with standard buttons + \since 5.3 + + Dialog provides an item with a platform-tailored button box for a dialog. + The \l implementation Item is the default property (the only allowed child + element). +*/ + +/*! + \qmlsignal QtQuick::Dialogs::Dialog::accepted + + This signal is emitted by \l accept(). +*/ + +/*! + \qmlsignal QtQuick::Dialogs::Dialog::rejected + + This signal is emitted by \l reject(). +*/ + +/*! + \class QQuickDialog + \inmodule QtQuick.Dialogs + \internal + + The QQuickDialog class represents a container for arbitrary + dialog contents. + + \since 5.3 +*/ + +/*! + Constructs a dialog wrapper with parent window \a parent. +*/ +QQuickDialog::QQuickDialog(QObject *parent) + : QQuickAbstractDialog(parent) +{ + connect(this, SIGNAL(buttonClicked()), this, SLOT(clicked())); +} + + +/*! + Destroys the dialog wrapper. +*/ +QQuickDialog::~QQuickDialog() +{ +} + +QJSValue QQuickDialog::standardButtonsLeftModel() +{ + updateStandardButtons(); + return m_standardButtonsLeftModel; +} + +QJSValue QQuickDialog::standardButtonsRightModel() +{ + updateStandardButtons(); + return m_standardButtonsRightModel; +} + +void QQuickDialog::updateStandardButtons() +{ + if (m_standardButtonsRightModel.isUndefined()) { + QJSEngine *engine = qmlEngine(this); + // Managed objects so no need to destroy any existing ones + m_standardButtonsLeftModel = engine->newArray(); + m_standardButtonsRightModel = engine->newArray(); + int i = 0; + + QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme(); + QPlatformDialogHelper::ButtonLayout layoutPolicy = + static_cast<QPlatformDialogHelper::ButtonLayout>(theme->themeHint(QPlatformTheme::DialogButtonBoxLayout).toInt()); + const quint32 *buttonLayout = QPlatformDialogHelper::buttonLayout(Qt::Horizontal, layoutPolicy); + QJSValue *model = &m_standardButtonsLeftModel; + for (int r = 0; buttonLayout[r] != QPlatformDialogHelper::EOL; ++r) { + quint32 role = (buttonLayout[r] & ~QPlatformDialogHelper::Reverse); + // Keep implementation in sync with that in QDialogButtonBoxPrivate::layoutButtons() + // to the extent that QtQuick supports the same features + switch (role) { + case QPlatformDialogHelper::Stretch: + model = &m_standardButtonsRightModel; + i = 0; + break; + // TODO maybe: case QPlatformDialogHelper::AlternateRole: + default: { + for (int e = QPlatformDialogHelper::LowestBit; e <= QPlatformDialogHelper::HighestBit; ++e) { + quint32 standardButton = 1 << e; + quint32 standardButtonRole = QPlatformDialogHelper::buttonRole( + static_cast<QPlatformDialogHelper::StandardButton>(standardButton)); + if ((m_enabledButtons & standardButton) && standardButtonRole == role) { + QJSValue o = engine->newObject(); + o.setProperty("text", theme->standardButtonText(standardButton)); + o.setProperty("standardButton", standardButton); + o.setProperty("role", role); + model->setProperty(i++, o); + } + } + } break; + } + } + } +} + +void QQuickDialog::setTitle(const QString &arg) +{ + if (m_title != arg) { + m_title = arg; + emit titleChanged(); + } +} + +void QQuickDialog::setStandardButtons(StandardButtons buttons) +{ + m_enabledButtons = buttons; + m_standardButtonsLeftModel = QJSValue(); + m_standardButtonsRightModel = QJSValue(); + emit standardButtonsChanged(); +} + +/*! + \qmlproperty bool Dialog::visible + + This property holds whether the dialog is visible. By default this is false. +*/ + +/*! + \qmlproperty QObject Dialog::implementation + + The QML object which implements the dialog contents. Should be an \l Item. +*/ + +void QQuickDialog::click(QPlatformDialogHelper::StandardButton button, QPlatformDialogHelper::ButtonRole role) +{ + setVisible(false); + m_clickedButton = static_cast<StandardButton>(button); + emit buttonClicked(); + switch (role) { + case QPlatformDialogHelper::AcceptRole: + emit accept(); + break; + case QPlatformDialogHelper::RejectRole: + emit reject(); + break; + case QPlatformDialogHelper::DestructiveRole: + emit discard(); + break; + case QPlatformDialogHelper::HelpRole: + emit help(); + break; + case QPlatformDialogHelper::YesRole: + emit yes(); + break; + case QPlatformDialogHelper::NoRole: + emit no(); + break; + case QPlatformDialogHelper::ApplyRole: + emit apply(); + break; + case QPlatformDialogHelper::ResetRole: + emit reset(); + break; + default: + qWarning("unhandled MessageDialog button %d with role %ld", button, role); + } +} + +void QQuickDialog::click(QQuickAbstractDialog::StandardButton button) +{ + click(static_cast<QPlatformDialogHelper::StandardButton>(button), + static_cast<QPlatformDialogHelper::ButtonRole>( + QPlatformDialogHelper::buttonRole(static_cast<QPlatformDialogHelper::StandardButton>(button)))); +} + +void QQuickDialog::clicked() { + switch (QPlatformDialogHelper::buttonRole(static_cast<QPlatformDialogHelper::StandardButton>(m_clickedButton))) { + case QPlatformDialogHelper::AcceptRole: + accept(); + break; + case QPlatformDialogHelper::RejectRole: + reject(); + break; + case QPlatformDialogHelper::DestructiveRole: + emit discard(); + break; + case QPlatformDialogHelper::HelpRole: + emit help(); + break; + case QPlatformDialogHelper::YesRole: + emit yes(); + break; + case QPlatformDialogHelper::NoRole: + emit no(); + break; + case QPlatformDialogHelper::ApplyRole: + emit apply(); + break; + case QPlatformDialogHelper::ResetRole: + emit reset(); + break; + default: + qWarning("StandardButton %d has no role", m_clickedButton); + } +} + +void QQuickDialog::accept() { + // enter key is treated like OK + if (m_clickedButton == NoButton) + m_clickedButton = Ok; + QQuickAbstractDialog::accept(); +} + +void QQuickDialog::reject() { + // escape key is treated like cancel + if (m_clickedButton == NoButton) + m_clickedButton = Cancel; + QQuickAbstractDialog::reject(); +} + +QT_END_NAMESPACE diff --git a/src/dialogs/qquickdialog_p.h b/src/dialogs/qquickdialog_p.h new file mode 100644 index 00000000..e9a96612 --- /dev/null +++ b/src/dialogs/qquickdialog_p.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQuick.Dialogs module 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 QQUICKDIALOG_P_H +#define QQUICKDIALOG_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickabstractmessagedialog_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickDialog : public QQuickAbstractDialog +{ + Q_OBJECT + + Q_ENUMS(StandardButton) + Q_FLAGS(StandardButtons) + + Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) + Q_PROPERTY(QQuickAbstractDialog::StandardButtons standardButtons READ standardButtons WRITE setStandardButtons NOTIFY standardButtonsChanged) + Q_PROPERTY(QQuickAbstractDialog::StandardButton clickedButton READ clickedButton NOTIFY buttonClicked) + Q_PROPERTY(QObject* implementation READ qmlImplementation WRITE setQmlImplementation DESIGNABLE false) + Q_PROPERTY(QJSValue standardButtonsLeftModel READ standardButtonsLeftModel NOTIFY standardButtonsChanged) + Q_PROPERTY(QJSValue standardButtonsRightModel READ standardButtonsRightModel NOTIFY standardButtonsChanged) + Q_CLASSINFO("DefaultProperty", "implementation") // Dialog in QML can have only one child + +public: + explicit QQuickDialog(QObject *parent = 0); + ~QQuickDialog(); + + StandardButtons standardButtons() const { return m_enabledButtons; } + StandardButton clickedButton() const { return m_clickedButton; } + QJSValue standardButtonsLeftModel(); + QJSValue standardButtonsRightModel(); + + QString title() const { return m_title; } + +public Q_SLOTS: + virtual void setTitle(const QString &arg); + void setStandardButtons(StandardButtons buttons); + void click(QQuickAbstractDialog::StandardButton button); + +Q_SIGNALS: + void titleChanged(); + void standardButtonsChanged(); + void buttonClicked(); + void discard(); + void help(); + void yes(); + void no(); + void apply(); + void reset(); + +protected: + virtual QPlatformDialogHelper *helper() { return 0; } + void click(QPlatformDialogHelper::StandardButton button, QPlatformDialogHelper::ButtonRole); + +protected Q_SLOTS: + virtual void accept(); + virtual void reject(); + void clicked(); + +private: + void updateStandardButtons(); + +private: + QString m_title; + StandardButton m_clickedButton; + StandardButtons m_enabledButtons; + QJSValue m_standardButtonsLeftModel; + QJSValue m_standardButtonsRightModel; + Q_DISABLE_COPY(QQuickDialog) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickDialog *) + +#endif // QQUICKDIALOG_P_H diff --git a/src/dialogs/qquickdialogassets_p.h b/src/dialogs/qquickdialogassets_p.h index 406b68a6..f06fc412 100644 --- a/src/dialogs/qquickdialogassets_p.h +++ b/src/dialogs/qquickdialogassets_p.h @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE class QQuickStandardButton { Q_GADGET - Q_ENUMS(QQuickAbstractMessageDialog::StandardButton) + Q_ENUMS(QQuickAbstractDialog::StandardButton) }; class QQuickStandardIcon |