From 8269b9925b372a09fb24bf1ec7b2e67c1a1e0310 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 20 Apr 2015 17:18:16 -0700 Subject: [PATCH] Adding first pass at message box --- interface/resources/qml/CustomButton.qml | 8 +- interface/resources/qml/MessageDialog.qml | 359 ++++++++++++++++++ interface/resources/qml/images/critical.png | Bin 0 -> 253 bytes .../resources/qml/images/information.png | Bin 0 -> 254 bytes interface/resources/qml/images/question.png | Bin 0 -> 257 bytes interface/resources/qml/images/warning.png | Bin 0 -> 224 bytes interface/src/Application.cpp | 4 +- interface/src/ui/LoginDialog.cpp | 4 +- interface/src/ui/MarketplaceDialog.cpp | 20 - libraries/render-utils/src/MessageDialog.cpp | 142 +++++++ libraries/render-utils/src/MessageDialog.h | 98 +++++ .../render-utils/src/OffscreenQmlDialog.cpp | 24 ++ .../render-utils/src/OffscreenQmlDialog.h | 60 ++- libraries/render-utils/src/OffscreenUi.cpp | 61 +-- libraries/render-utils/src/OffscreenUi.h | 31 +- 15 files changed, 740 insertions(+), 71 deletions(-) create mode 100644 interface/resources/qml/MessageDialog.qml create mode 100644 interface/resources/qml/images/critical.png create mode 100644 interface/resources/qml/images/information.png create mode 100644 interface/resources/qml/images/question.png create mode 100644 interface/resources/qml/images/warning.png create mode 100644 libraries/render-utils/src/MessageDialog.cpp create mode 100644 libraries/render-utils/src/MessageDialog.h diff --git a/interface/resources/qml/CustomButton.qml b/interface/resources/qml/CustomButton.qml index ce57d7ce5e..fb1b544207 100644 --- a/interface/resources/qml/CustomButton.qml +++ b/interface/resources/qml/CustomButton.qml @@ -6,9 +6,13 @@ import QtQuick.Controls.Styles 1.3 Button { SystemPalette { id: myPalette; colorGroup: SystemPalette.Active } text: "Text" - width: 128 - height: 64 style: ButtonStyle { + padding { + top: 8 + left: 12 + right: 12 + bottom: 8 + } background: CustomBorder { anchors.fill: parent } diff --git a/interface/resources/qml/MessageDialog.qml b/interface/resources/qml/MessageDialog.qml new file mode 100644 index 0000000000..f4a360baed --- /dev/null +++ b/interface/resources/qml/MessageDialog.qml @@ -0,0 +1,359 @@ +/***************************************************************************** +** +** 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: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 Hifi 1.0 as Hifi +import QtQuick 2.2 +import QtQuick.Controls 1.2 +import QtQuick.Window 2.1 +import QtQuick.Dialogs 1.2 + +CustomDialog { + id: root + property real spacing: 8 + property real outerSpacing: 16 + + destroyOnCloseButton: true + destroyOnInvisible: true + implicitHeight: content.implicitHeight + outerSpacing * 2 + 48 + implicitWidth: Math.min(200, Math.max(mainText.implicitWidth, content.buttonsRowImplicitWidth) + outerSpacing * 2); + + onImplicitHeightChanged: root.height = implicitHeight + onImplicitWidthChanged: root.width = implicitWidth + + SystemPalette { id: palette } + + function calculateImplicitWidth() { + if (buttons.visibleChildren.length < 2) + return; + var calcWidth = 0; + for (var i = 0; i < buttons.visibleChildren.length; ++i) { + calcWidth += Math.max(100, buttons.visibleChildren[i].implicitWidth) + root.spacing + } + content.buttonsRowImplicitWidth = outerSpacing + calcWidth + 48 + } + + onEnabledChanged: { + if (enabled) { + content.forceActiveFocus(); + } + } + + Hifi.MessageDialog { + id: content + clip: true + anchors.fill: parent + anchors.topMargin: parent.topMargin + root.outerSpacing + anchors.leftMargin: parent.margins + root.outerSpacing + anchors.rightMargin: parent.margins + root.outerSpacing + anchors.bottomMargin: parent.margins + root.outerSpacing + implicitHeight: contentColumn.implicitHeight + outerSpacing * 2 + implicitWidth: Math.max(mainText.implicitWidth, buttonsRowImplicitWidth); + property real buttonsRowImplicitWidth: Screen.pixelDensity * 50 + + Keys.onPressed: { + console.log("Key press at content") + event.accepted = true + if (event.modifiers === Qt.ControlModifier) + switch (event.key) { + case Qt.Key_A: + console.log("Select All") + detailedText.selectAll() + break + case Qt.Key_C: + console.log("Copy") + detailedText.copy() + break + case Qt.Key_Period: + if (Qt.platform.os === "osx") + reject() + break + } else switch (event.key) { + case Qt.Key_Escape: + case Qt.Key_Back: + console.log("Rejecting") + reject() + break + case Qt.Key_Enter: + case Qt.Key_Return: + console.log("Accepting") + accept() + break + } + } + + onImplicitWidthChanged: root.width = implicitWidth + + Component.onCompleted: { + root.title = title + } + + onTitleChanged: { + root.title = title + } + + Column { + id: contentColumn + spacing: root.outerSpacing + anchors { + top: parent.top + left: parent.left + right: parent.right + } + + Item { + width: parent.width + height: Math.max(icon.height, mainText.height + informativeText.height + root.spacing) + Image { + id: icon + source: content.standardIconSource + } + + Text { + id: mainText + anchors { + left: icon.right + leftMargin: root.spacing + right: parent.right + } + text: content.text + font.pointSize: 14 + font.weight: Font.Bold + wrapMode: Text.WordWrap + } + + Text { + id: informativeText + anchors { + left: icon.right + right: parent.right + top: mainText.bottom + leftMargin: root.spacing + topMargin: root.spacing + } + text: content.informativeText + font.pointSize: 14 + wrapMode: Text.WordWrap + } + } + + + Flow { + id: buttons + spacing: root.spacing + layoutDirection: Qt.RightToLeft + width: parent.width + CustomButton { + id: okButton + text: qsTr("OK") + onClicked: content.click(StandardButton.Ok) + visible: content.standardButtons & StandardButton.Ok + } + CustomButton { + id: openButton + text: qsTr("Open") + onClicked: content.click(StandardButton.Open) + visible: content.standardButtons & StandardButton.Open + } + CustomButton { + id: saveButton + text: qsTr("Save") + onClicked: content.click(StandardButton.Save) + visible: content.standardButtons & StandardButton.Save + } + CustomButton { + id: saveAllButton + text: qsTr("Save All") + onClicked: content.click(StandardButton.SaveAll) + visible: content.standardButtons & StandardButton.SaveAll + } + CustomButton { + id: retryButton + text: qsTr("Retry") + onClicked: content.click(StandardButton.Retry) + visible: content.standardButtons & StandardButton.Retry + } + CustomButton { + id: ignoreButton + text: qsTr("Ignore") + onClicked: content.click(StandardButton.Ignore) + visible: content.standardButtons & StandardButton.Ignore + } + CustomButton { + id: applyButton + text: qsTr("Apply") + onClicked: content.click(StandardButton.Apply) + visible: content.standardButtons & StandardButton.Apply + } + CustomButton { + id: yesButton + text: qsTr("Yes") + onClicked: content.click(StandardButton.Yes) + visible: content.standardButtons & StandardButton.Yes + } + CustomButton { + id: yesAllButton + text: qsTr("Yes to All") + onClicked: content.click(StandardButton.YesToAll) + visible: content.standardButtons & StandardButton.YesToAll + } + CustomButton { + id: noButton + text: qsTr("No") + onClicked: content.click(StandardButton.No) + visible: content.standardButtons & StandardButton.No + } + CustomButton { + id: noAllButton + text: qsTr("No to All") + onClicked: content.click(StandardButton.NoToAll) + visible: content.standardButtons & StandardButton.NoToAll + } + CustomButton { + id: discardButton + text: qsTr("Discard") + onClicked: content.click(StandardButton.Discard) + visible: content.standardButtons & StandardButton.Discard + } + CustomButton { + id: resetButton + text: qsTr("Reset") + onClicked: content.click(StandardButton.Reset) + visible: content.standardButtons & StandardButton.Reset + } + CustomButton { + id: restoreDefaultsButton + text: qsTr("Restore Defaults") + onClicked: content.click(StandardButton.RestoreDefaults) + visible: content.standardButtons & StandardButton.RestoreDefaults + } + CustomButton { + id: cancelButton + text: qsTr("Cancel") + onClicked: content.click(StandardButton.Cancel) + visible: content.standardButtons & StandardButton.Cancel + } + CustomButton { + id: abortButton + text: qsTr("Abort") + onClicked: content.click(StandardButton.Abort) + visible: content.standardButtons & StandardButton.Abort + } + CustomButton { + id: closeButton + text: qsTr("Close") + onClicked: content.click(StandardButton.Close) + visible: content.standardButtons & StandardButton.Close + } + CustomButton { + id: moreButton + text: qsTr("Show Details...") + onClicked: content.state = (content.state === "" ? "expanded" : "") + visible: content.detailedText.length > 0 + } + CustomButton { + id: helpButton + text: qsTr("Help") + onClicked: content.click(StandardButton.Help) + visible: content.standardButtons & StandardButton.Help + } + onVisibleChildrenChanged: root.calculateImplicitWidth() + } + } + + Item { + id: details + width: parent.width + implicitHeight: detailedText.implicitHeight + root.spacing + height: 0 + clip: true + + anchors { + left: parent.left + right: parent.right + top: contentColumn.bottom + topMargin: root.spacing + leftMargin: root.outerSpacing + rightMargin: root.outerSpacing + } + + Flickable { + id: flickable + contentHeight: detailedText.height + anchors.fill: parent + anchors.topMargin: root.spacing + anchors.bottomMargin: root.outerSpacing + TextEdit { + id: detailedText + text: content.detailedText + width: details.width + wrapMode: Text.WordWrap + readOnly: true + selectByMouse: true + } + } + } + + states: [ + State { + name: "expanded" + PropertyChanges { + target: details + height: root.height - contentColumn.height - root.spacing - root.outerSpacing + } + PropertyChanges { + target: content + implicitHeight: contentColumn.implicitHeight + root.spacing * 2 + + detailedText.implicitHeight + root.outerSpacing * 2 + } + PropertyChanges { + target: moreButton + text: qsTr("Hide Details") + } + } + ] + +/* + Rectangle { + + } + Component.onCompleted: calculateImplicitWidth() + */ + } +} diff --git a/interface/resources/qml/images/critical.png b/interface/resources/qml/images/critical.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9c5aebf453dd92dba60c48f060b34f0087e02c GIT binary patch literal 253 zcmVkNDWE^AyB8@ZEC00000NkvXXu0mjf DKfYr$ literal 0 HcmV?d00001 diff --git a/interface/resources/qml/images/information.png b/interface/resources/qml/images/information.png new file mode 100644 index 0000000000000000000000000000000000000000..0a2eb87d108d2a24b71559998627570a252ebe69 GIT binary patch literal 254 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I7G?$phQ^Te;|vT8`~f~8uBj!u3?T4-=FFM@ z|NrludHNay0|R48kY6x^!?PP{3=9l&JzX3_G|sP`c#-$80*{Mh+yV`sgwlqP>#QC( z>X#+u7`Xm@Q`=BsWqr<)MUc^=nfrazYu@_ss|q3QYrOu5+ux47bKp#oZChf4k#&aW z_6qNdiK4+zLkc4MIa@Ri#52@3K4zcMoZ;%Na4X>suaM`rgBP8<|7A}r*;L-N)XQ^~ z*Qd}2Q;+ng3Z7t^78=O>`qh(QX^u+vLUu-L1y=d3FMU5VRZj!?kipZ{&t;ucLK6Te CT3=!S literal 0 HcmV?d00001 diff --git a/interface/resources/qml/images/question.png b/interface/resources/qml/images/question.png new file mode 100644 index 0000000000000000000000000000000000000000..2dd92fd7915a09de670b8b6022ddcf02d4cc90e1 GIT binary patch literal 257 zcmV+c0sj7pP)NklQ}7)nBez2^$+jK{Nw%L3xK4m{g6jm}2|@>7z7zk+b}w*O&>f9X*ioevByCmJtfv0xgg* zX&;ac>>nrw_75mp9NLlK=){M}g!K&|3b4W-F*J23VSVK);JN=%IJYXN$un1x$~;9b a#PS7=(1SoC6O>K>0000a literal 0 HcmV?d00001 diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8c93418153..b7ba384a97 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -85,6 +85,7 @@ #include #include #include +#include #include @@ -762,11 +763,10 @@ void Application::initializeUi() { AddressBarDialog::registerType(); LoginDialog::registerType(); MarketplaceDialog::registerType(); + MessageDialog::registerType(); auto offscreenUi = DependencyManager::get(); offscreenUi->create(_glWidget->context()->contextHandle()); - offscreenUi->qmlEngine()->setNetworkAccessManagerFactory(new OAuthFactory()); - offscreenUi->qmlEngine()->networkAccessManager(); offscreenUi->resize(_glWidget->size()); offscreenUi->setProxyWindow(_window->windowHandle()); offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 4df42c0f15..5726818b2d 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -37,7 +37,9 @@ void LoginDialog::toggleAction() { } else { // change the menu item to login loginAction->setText("Login"); - connect(loginAction, &QAction::triggered, &LoginDialog::show); + connect(loginAction, &QAction::triggered, [] { + LoginDialog::show(); + }); } } diff --git a/interface/src/ui/MarketplaceDialog.cpp b/interface/src/ui/MarketplaceDialog.cpp index 34d3414ef4..ed30a2c120 100644 --- a/interface/src/ui/MarketplaceDialog.cpp +++ b/interface/src/ui/MarketplaceDialog.cpp @@ -10,40 +10,20 @@ #include "Application.h" #include "MarketplaceDialog.h" - - -#include - #include "DependencyManager.h" QML_DIALOG_DEF(MarketplaceDialog) MarketplaceDialog::MarketplaceDialog(QQuickItem *parent) : OffscreenQmlDialog(parent) { - this-> } bool MarketplaceDialog::navigationRequested(const QString & url) { qDebug() << url; if (Application::getInstance()->canAcceptURL(url)) { - qDebug() << "Trying to send url to the app"; if (Application::getInstance()->acceptURL(url)) { - qDebug() << "Sent url to the app"; return false; // we handled it, so QWebPage doesn't need to handle it } } return true; } - -//https://metaverse.highfidelity.com/marketplace - -// -//bool DataWebPage::acceptNavigationRequest(QWebFrame* frame, const QNetworkRequest& request, QWebPage::NavigationType type) { -// QString urlString = request.url().toString(); -// if (Application::getInstance()->canAcceptURL(urlString)) { -// if (Application::getInstance()->acceptURL(urlString)) { -// return false; // we handled it, so QWebPage doesn't need to handle it -// } -// } -// return true; -//} \ No newline at end of file diff --git a/libraries/render-utils/src/MessageDialog.cpp b/libraries/render-utils/src/MessageDialog.cpp new file mode 100644 index 0000000000..c16f5653e5 --- /dev/null +++ b/libraries/render-utils/src/MessageDialog.cpp @@ -0,0 +1,142 @@ +// +// +// MessageDialog.cpp +// +// Created by Bradley Austin Davis on 2015/04/14 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "MessageDialog.h" + +QML_DIALOG_DEF(MessageDialog) + + +MessageDialog::MessageDialog(QQuickItem *parent) : OffscreenQmlDialog(parent) { + _buttons = StandardButtons(Ok | Cancel); +} + +MessageDialog::~MessageDialog() { +} + +QString MessageDialog::text() const { + return _text; +} + +QString MessageDialog::informativeText() const { + return _informativeText; +} + +QString MessageDialog::detailedText() const { + return _detailedText; +} + +MessageDialog::Icon MessageDialog::icon() const { + return _icon; +} + +void MessageDialog::setVisible(bool v) { + OffscreenQmlDialog::setVisible(v); +} + +void MessageDialog::setText(const QString &arg) { + if (arg != _text) { + _text = arg; + emit textChanged(); + } +} + +void MessageDialog::setInformativeText(const QString &arg) { + if (arg != _informativeText) { + _informativeText = arg; + emit informativeTextChanged(); + } +} + +void MessageDialog::setDetailedText(const QString &arg) { + if (arg != _detailedText) { + _detailedText = arg; + emit detailedTextChanged(); + } +} + +void MessageDialog::setIcon(MessageDialog::Icon icon) { + if (icon != _icon) { + _icon = icon; + emit iconChanged(); + } +} + +void MessageDialog::setStandardButtons(StandardButtons buttons) { + if (buttons != _buttons) { + _buttons = buttons; + emit standardButtonsChanged(); + } +} + +void MessageDialog::click(StandardButton button) { + click(static_cast(button), + static_cast( + QPlatformDialogHelper::buttonRole(static_cast(button)))); +} + +QUrl MessageDialog::standardIconSource() { + switch (icon()) { + case QMessageDialogOptions::Information: + return QUrl("images/information.png"); + break; + case QMessageDialogOptions::Warning: + return QUrl("images/warning.png"); + break; + case QMessageDialogOptions::Critical: + return QUrl("images/critical.png"); + break; + case QMessageDialogOptions::Question: + return QUrl("images/question.png"); + break; + default: + return QUrl(); + break; + } +} + +MessageDialog::StandardButtons MessageDialog::standardButtons() const { + return _buttons; +} + +MessageDialog::StandardButton MessageDialog::clickedButton() const { + return _clickedButton; +} + +void MessageDialog::click(StandardButton button, QPlatformDialogHelper::ButtonRole) { + _clickedButton = button; + if (_resultCallback) { + _resultCallback(QMessageBox::StandardButton(_clickedButton)); + } + hide(); +} + +void MessageDialog::accept() { + // enter key is treated like OK + if (_clickedButton == NoButton) + _clickedButton = Ok; + if (_resultCallback) { + _resultCallback(QMessageBox::StandardButton(_clickedButton)); + } + OffscreenQmlDialog::accept(); +} + +void MessageDialog::reject() { + // escape key is treated like cancel + if (_clickedButton == NoButton) + _clickedButton = Cancel; + if (_resultCallback) { + _resultCallback(QMessageBox::StandardButton(_clickedButton)); + } + OffscreenQmlDialog::reject(); +} + +void MessageDialog::setResultCallback(OffscreenUi::ButtonCallback callback) { + _resultCallback = callback; +} diff --git a/libraries/render-utils/src/MessageDialog.h b/libraries/render-utils/src/MessageDialog.h new file mode 100644 index 0000000000..8b5a895068 --- /dev/null +++ b/libraries/render-utils/src/MessageDialog.h @@ -0,0 +1,98 @@ +// +// MessageDialog.h +// +// Created by Bradley Austin Davis on 2015/04/14 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#pragma once +#ifndef hifi_MessageDialog_h +#define hifi_MessageDialog_h + +#include "OffscreenQmlDialog.h" +#include <5.4.1/QtGui/qpa/qplatformdialoghelper.h> + +class MessageDialog : public OffscreenQmlDialog +{ + Q_OBJECT + QML_DIALOG_DECL + +private: + Q_ENUMS(Icon) + 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) + +public: + enum Icon { + NoIcon = QMessageDialogOptions::NoIcon, + Information = QMessageDialogOptions::Information, + Warning = QMessageDialogOptions::Warning, + Critical = QMessageDialogOptions::Critical, + Question = QMessageDialogOptions::Question + }; + + + MessageDialog(QQuickItem *parent = 0); + virtual ~MessageDialog(); + + QString text() const; + QString informativeText() const; + QString detailedText() const; + Icon icon() const; + +public slots: + virtual void setVisible(bool v); + void setText(const QString &arg); + void setInformativeText(const QString &arg); + void setDetailedText(const QString &arg); + void setIcon(Icon icon); + void setStandardButtons(StandardButtons buttons); + void setResultCallback(OffscreenUi::ButtonCallback callback); + void click(StandardButton button); + QUrl standardIconSource(); + StandardButtons standardButtons() const; + StandardButton clickedButton() const; + +signals: + void textChanged(); + void informativeTextChanged(); + void detailedTextChanged(); + void iconChanged(); + void standardButtonsChanged(); + void buttonClicked(); + void discard(); + void help(); + void yes(); + void no(); + void apply(); + void reset(); + +protected slots: + virtual void click(StandardButton button, QPlatformDialogHelper::ButtonRole); + virtual void accept(); + virtual void reject(); + +private: + QString _title; + QString _text; + QString _informativeText; + QString _detailedText; + Icon _icon{ Information }; + StandardButtons _buttons; + StandardButton _clickedButton{ NoButton }; + OffscreenUi::ButtonCallback _resultCallback; +}; + +#endif // hifi_MessageDialog_h + + + + diff --git a/libraries/render-utils/src/OffscreenQmlDialog.cpp b/libraries/render-utils/src/OffscreenQmlDialog.cpp index d1e060245d..dbd621ad85 100644 --- a/libraries/render-utils/src/OffscreenQmlDialog.cpp +++ b/libraries/render-utils/src/OffscreenQmlDialog.cpp @@ -13,6 +13,30 @@ OffscreenQmlDialog::OffscreenQmlDialog(QQuickItem* parent) : QQuickItem(parent) { } +OffscreenQmlDialog::~OffscreenQmlDialog() { +} + void OffscreenQmlDialog::hide() { static_cast(parent())->setEnabled(false); } + +QString OffscreenQmlDialog::title() const { + return _title; +} + +void OffscreenQmlDialog::setTitle(const QString &arg) { + if (arg != _title) { + _title = arg; + emit titleChanged(); + } +} + +void OffscreenQmlDialog::accept() { + hide(); + emit accepted(); +} + +void OffscreenQmlDialog::reject() { + hide(); + emit rejected(); +} diff --git a/libraries/render-utils/src/OffscreenQmlDialog.h b/libraries/render-utils/src/OffscreenQmlDialog.h index eca82261c0..c6c95981a6 100644 --- a/libraries/render-utils/src/OffscreenQmlDialog.h +++ b/libraries/render-utils/src/OffscreenQmlDialog.h @@ -13,6 +13,8 @@ #define hifi_OffscreenQmlDialog_h #include +#include <5.4.1/QtGui/qpa/qplatformdialoghelper.h> + #include "OffscreenUi.h" #define QML_DIALOG_DECL \ @@ -21,8 +23,8 @@ private: \ static const QUrl QML; \ public: \ static void registerType(); \ - static void show(); \ - static void toggle(); \ + static void show(std::function f = [](QQmlContext*, QQuickItem*) {}); \ + static void toggle(std::function f = [](QQmlContext*, QQuickItem*) {}); \ private: #define QML_DIALOG_DEF(x) \ @@ -33,24 +35,70 @@ private: qmlRegisterType("Hifi", 1, 0, NAME.toLocal8Bit().constData()); \ } \ \ - void x::show() { \ + void x::show(std::function f) { \ auto offscreenUi = DependencyManager::get(); \ - offscreenUi->show(QML, NAME); \ + offscreenUi->show(QML, NAME, f); \ } \ \ - void x::toggle() { \ + void x::toggle(std::function f) { \ auto offscreenUi = DependencyManager::get(); \ - offscreenUi->toggle(QML, NAME); \ + offscreenUi->toggle(QML, NAME, f); \ } class OffscreenQmlDialog : public QQuickItem { Q_OBJECT + Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) + Q_ENUMS(StandardButton) + Q_FLAGS(StandardButtons) + public: OffscreenQmlDialog(QQuickItem* parent = nullptr); + virtual ~OffscreenQmlDialog(); + + 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) protected: void hide(); + virtual void accept(); + virtual void reject(); + +public: + QString title() const; + void setTitle(const QString &arg); + +signals: + void accepted(); + void rejected(); + void titleChanged(); + +private: + QString _title; + }; +Q_DECLARE_OPERATORS_FOR_FLAGS(OffscreenQmlDialog::StandardButtons) + #endif diff --git a/libraries/render-utils/src/OffscreenUi.cpp b/libraries/render-utils/src/OffscreenUi.cpp index 837affab59..d25d78300a 100644 --- a/libraries/render-utils/src/OffscreenUi.cpp +++ b/libraries/render-utils/src/OffscreenUi.cpp @@ -13,6 +13,7 @@ #include #include #include +#include "MessageDialog.h" // Time between receiving a request to render the offscreen UI actually triggering // the render. Could possibly be increased depending on the framerate we expect to @@ -140,13 +141,15 @@ void OffscreenUi::setBaseUrl(const QUrl& baseUrl) { _qmlEngine->setBaseUrl(baseUrl); } -void OffscreenUi::load(const QUrl& qmlSource, std::function f) { +void OffscreenUi::load(const QUrl& qmlSource, std::function f) { qDebug() << "Loading QML from URL " << qmlSource; _qmlComponent->loadUrl(qmlSource); - if (_qmlComponent->isLoading()) { - connect(_qmlComponent, &QQmlComponent::statusChanged, this, []{}); - } else { - finishQmlLoad(); + if (_qmlComponent->isLoading()) + connect(_qmlComponent, &QQmlComponent::statusChanged, this, [this, f] { + finishQmlLoad(f); + }); + else { + finishQmlLoad(f); } } @@ -163,7 +166,7 @@ void OffscreenUi::requestRender() { } } -void OffscreenUi::finishQmlLoad() { +void OffscreenUi::finishQmlLoad(std::function f) { disconnect(_qmlComponent, &QQmlComponent::statusChanged, this, &OffscreenUi::finishQmlLoad); if (_qmlComponent->isError()) { QList errorList = _qmlComponent->errors(); @@ -197,7 +200,7 @@ void OffscreenUi::finishQmlLoad() { // Make sure we make items focusable (critical for // supporting keyboard shortcuts) newItem->setFlag(QQuickItem::ItemIsFocusScope, true); - + f(_qmlEngine->contextForObject(newItem), newItem); if (!_rootItem) { // The root item is ready. Associate it with the window. _rootItem = newItem; @@ -390,54 +393,62 @@ void OffscreenUi::setProxyWindow(QWindow* window) { _renderControl->_renderWindow = window; } -void OffscreenUi::show(const QUrl& url, const QString& name) { +void OffscreenUi::show(const QUrl& url, const QString& name, std::function f) { QQuickItem* item = _rootItem->findChild(name); // First load? if (!item) { - load(url); + load(url, f); return; } item->setEnabled(true); } -void OffscreenUi::toggle(const QUrl& url, const QString& name) { +void OffscreenUi::toggle(const QUrl& url, const QString& name, std::function f) { QQuickItem* item = _rootItem->findChild(name); // First load? if (!item) { - load(url); + load(url, f); return; } item->setEnabled(!item->isEnabled()); } void OffscreenUi::messageBox(const QString& title, const QString& text, + ButtonCallback callback, QMessageBox::Icon icon, - QMessageBox::StandardButtons buttons, - ButtonCallback f) { + QMessageBox::StandardButtons buttons) { + MessageDialog::show([=](QQmlContext*ctx, QQuickItem*item) { + MessageDialog * pDialog = item->findChild(); + pDialog->setIcon((MessageDialog::Icon)icon); + pDialog->setTitle(title); + pDialog->setText(text); + pDialog->setStandardButtons(MessageDialog::StandardButtons((int)buttons)); + pDialog->setResultCallback(callback); + }); } void OffscreenUi::information(const QString& title, const QString& text, - QMessageBox::StandardButtons buttons, - ButtonCallback callback) { - callback(QMessageBox::information(nullptr, title, text, buttons)); + ButtonCallback callback, + QMessageBox::StandardButtons buttons) { + messageBox(title, text, callback, (QMessageBox::Icon)MessageDialog::Information, buttons); } void OffscreenUi::question(const QString& title, const QString& text, - QMessageBox::StandardButtons buttons, - ButtonCallback callback) { - callback(QMessageBox::question(nullptr, title, text, buttons)); + ButtonCallback callback, + QMessageBox::StandardButtons buttons) { + messageBox(title, text, callback, (QMessageBox::Icon)MessageDialog::Question, buttons); } void OffscreenUi::warning(const QString& title, const QString& text, - QMessageBox::StandardButtons buttons, - ButtonCallback callback) { - callback(QMessageBox::warning(nullptr, title, text, buttons)); + ButtonCallback callback, + QMessageBox::StandardButtons buttons) { + messageBox(title, text, callback, (QMessageBox::Icon)MessageDialog::Warning, buttons); } void OffscreenUi::critical(const QString& title, const QString& text, - QMessageBox::StandardButtons buttons, - ButtonCallback callback) { - callback(QMessageBox::critical(nullptr, title, text, buttons)); + ButtonCallback callback, + QMessageBox::StandardButtons buttons) { + messageBox(title, text, callback, (QMessageBox::Icon)MessageDialog::Critical, buttons); } diff --git a/libraries/render-utils/src/OffscreenUi.h b/libraries/render-utils/src/OffscreenUi.h index c64d0d833c..b2805b2ded 100644 --- a/libraries/render-utils/src/OffscreenUi.h +++ b/libraries/render-utils/src/OffscreenUi.h @@ -59,12 +59,12 @@ public: virtual ~OffscreenUi(); void create(QOpenGLContext* context); void resize(const QSize& size); - void load(const QUrl& qmlSource, std::function f = [](QQmlContext*) {}); - void load(const QString& qmlSourceFile, std::function f = [](QQmlContext*) {}) { + void load(const QUrl& qmlSource, std::function f = [](QQmlContext*, QQuickItem*) {}); + void load(const QString& qmlSourceFile, std::function f = [](QQmlContext*, QQuickItem*) {}) { load(QUrl(qmlSourceFile), f); } - void show(const QUrl& url, const QString& name); - void toggle(const QUrl& url, const QString& name); + void show(const QUrl& url, const QString& name, std::function f = [](QQmlContext*, QQuickItem*) {})); + void toggle(const QUrl& url, const QString& name, std::function f = [](QQmlContext*, QQuickItem*) {})); void setBaseUrl(const QUrl& baseUrl); void addImportPath(const QString& path); QQmlContext* qmlContext(); @@ -86,31 +86,32 @@ public: static ButtonCallback NO_OP_CALLBACK; static void messageBox(const QString& title, const QString& text, + static void messageBox(const QString &title, const QString &text, + ButtonCallback f, QMessageBox::Icon icon, - QMessageBox::StandardButtons buttons, - ButtonCallback f); + QMessageBox::StandardButtons buttons); static void information(const QString& title, const QString& text, - QMessageBox::StandardButtons buttons = QMessageBox::Ok, - ButtonCallback callback = NO_OP_CALLBACK); + ButtonCallback callback = NO_OP_CALLBACK, + QMessageBox::StandardButtons buttons = QMessageBox::Ok); static void question(const QString& title, const QString& text, - QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No), - ButtonCallback callback = [](QMessageBox::StandardButton) {}); + ButtonCallback callback = NO_OP_CALLBACK, + QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No)); static void warning(const QString& title, const QString& text, - QMessageBox::StandardButtons buttons = QMessageBox::Ok, - ButtonCallback callback = [](QMessageBox::StandardButton) {}); + ButtonCallback callback = NO_OP_CALLBACK, + QMessageBox::StandardButtons buttons = QMessageBox::Ok); static void critical(const QString& title, const QString& text, - QMessageBox::StandardButtons buttons = QMessageBox::Ok, - ButtonCallback callback = [](QMessageBox::StandardButton) {}); + ButtonCallback callback = NO_OP_CALLBACK, + QMessageBox::StandardButtons buttons = QMessageBox::Ok); protected: private slots: void updateQuick(); - void finishQmlLoad(); + void finishQmlLoad(std::function f); public slots: void requestUpdate();