From e41b4c1b7b4bfed4c8ba7af6a86a0842ddfc7ada Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 31 May 2015 20:56:11 -0700 Subject: [PATCH] Add new address bar dialog error message Implemented as a new simple InformationDialog so that can try it out without reworking MessageDialog immediately for all QML UI. --- .../images/address-bar-error-close.svg | 50 ++++++ .../images/address-bar-error-icon.svg | 3 + interface/resources/qml/ErrorDialog.qml | 152 ++++++++++++++++++ interface/src/Application.cpp | 14 +- interface/src/ui/AddressBarDialog.cpp | 6 +- libraries/ui/src/ErrorDialog.cpp | 38 +++++ libraries/ui/src/ErrorDialog.h | 46 ++++++ libraries/ui/src/OffscreenUi.cpp | 10 ++ libraries/ui/src/OffscreenUi.h | 2 + 9 files changed, 311 insertions(+), 10 deletions(-) create mode 100644 interface/resources/images/address-bar-error-close.svg create mode 100644 interface/resources/images/address-bar-error-icon.svg create mode 100644 interface/resources/qml/ErrorDialog.qml create mode 100644 libraries/ui/src/ErrorDialog.cpp create mode 100644 libraries/ui/src/ErrorDialog.h diff --git a/interface/resources/images/address-bar-error-close.svg b/interface/resources/images/address-bar-error-close.svg new file mode 100644 index 0000000000..45a4dd4635 --- /dev/null +++ b/interface/resources/images/address-bar-error-close.svg @@ -0,0 +1,50 @@ + +image/svg+xml \ No newline at end of file diff --git a/interface/resources/images/address-bar-error-icon.svg b/interface/resources/images/address-bar-error-icon.svg new file mode 100644 index 0000000000..f2453fb0d4 --- /dev/null +++ b/interface/resources/images/address-bar-error-icon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/interface/resources/qml/ErrorDialog.qml b/interface/resources/qml/ErrorDialog.qml new file mode 100644 index 0000000000..72b2c24e90 --- /dev/null +++ b/interface/resources/qml/ErrorDialog.qml @@ -0,0 +1,152 @@ +// +// ErrorDialog.qml +// +// Created by David Rowe on 30 May 2015 +// 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 +// + +import Hifi 1.0 as Hifi +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQuick.Dialogs 1.2 +import "controls" +import "styles" + +Item { + id: root + HifiConstants { id: hifi } + + property int animationDuration: hifi.effects.fadeInDuration + property bool destroyOnInvisible: true + + Component.onCompleted: { + enabled = true + } + + onParentChanged: { + if (visible && enabled) { + forceActiveFocus(); + } + } + + implicitWidth: content.implicitWidth + implicitHeight: content.implicitHeight + + x: parent ? parent.width / 2 - width / 2 : 0 + y: parent ? parent.height / 2 - height / 2 : 0 + + Hifi.ErrorDialog { + id: content + + implicitWidth: box.width + implicitHeight: icon.height + hifi.layout.spacing * 2 + + Border { + id: box + + width: 512 + color: "#ebebeb" + radius: 2 + border.width: 1 + border.color: "#000000" + + Image { + id: icon + + source: "../images/address-bar-error-icon.svg" + width: 40 + height: 40 + anchors { + left: parent.left + leftMargin: hifi.layout.spacing + verticalCenter: parent.verticalCenter + } + } + + Text { + id: messageText + + font.pointSize: 10 + font.weight: Font.Bold + + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + + text: content.text + } + + Image { + source: "../images/address-bar-error-close.svg" + width: 20 + height: 20 + anchors { + right: parent.right + rightMargin: hifi.layout.spacing * 2 + verticalCenter: parent.verticalCenter + } + MouseArea { + anchors.fill: parent + onClicked: { + content.accept(); + } + } + } + } + } + + // The UI enables an object, rather than manipulating its visibility, so that we can do animations in both directions. + // Because visibility and enabled are booleans, they cannot be animated. So when enabled is changed, we modify a property + // that can be animated, like scale or opacity, and then when the target animation value is reached, we can modify the + // visibility. + enabled: false + opacity: 1.0 + + onEnabledChanged: { + opacity = enabled ? 1.0 : 0.0 + } + + Behavior on opacity { + // Animate opacity. + NumberAnimation { + duration: animationDuration + easing.type: Easing.OutCubic + } + } + + onOpacityChanged: { + // Once we're transparent, disable the dialog's visibility. + visible = (opacity != 0.0) + } + + onVisibleChanged: { + if (!visible) { + // Some dialogs should be destroyed when they become invisible. + if (destroyOnInvisible) { + destroy() + } + } + } + + Keys.onPressed: { + if (event.modifiers === Qt.ControlModifier) + switch (event.key) { + case Qt.Key_W: + event.accepted = true + content.accept() + break + } else switch (event.key) { + case Qt.Key_Escape: + case Qt.Key_Back: + case Qt.Key_Enter: + case Qt.Key_Return: + event.accepted = true + content.accept() + break + } + } +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 877b5ed931..d43306715a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -55,40 +55,41 @@ #include #include -#include #include +#include #include #include #include #include #include +#include #include #include #include -#include +#include #include #include +#include #include #include #include +#include #include #include -#include #include #include #include #include #include #include +#include #include #include #include #include #include #include -#include -#include -#include +#include #include "Application.h" #include "AudioClient.h" @@ -799,6 +800,7 @@ void Application::initializeGL() { void Application::initializeUi() { AddressBarDialog::registerType(); + ErrorDialog::registerType(); LoginDialog::registerType(); MessageDialog::registerType(); VrMenu::registerType(); diff --git a/interface/src/ui/AddressBarDialog.cpp b/interface/src/ui/AddressBarDialog.cpp index 837702d253..3c3a843586 100644 --- a/interface/src/ui/AddressBarDialog.cpp +++ b/interface/src/ui/AddressBarDialog.cpp @@ -36,12 +36,10 @@ void AddressBarDialog::loadAddress(const QString& address) { } void AddressBarDialog::displayAddressOfflineMessage() { - OffscreenUi::information("Address offline", - "That user or place is currently offline."); + OffscreenUi::error("That user or place is currently offline"); } void AddressBarDialog::displayAddressNotFoundMessage() { - OffscreenUi::information("Address not found", - "There is no address information for that user or place."); + OffscreenUi::error("There is no address information for that user or place"); } diff --git a/libraries/ui/src/ErrorDialog.cpp b/libraries/ui/src/ErrorDialog.cpp new file mode 100644 index 0000000000..ab36ef8d36 --- /dev/null +++ b/libraries/ui/src/ErrorDialog.cpp @@ -0,0 +1,38 @@ +// +// ErrorDialog.cpp +// +// Created by David Rowe on 30 May 2015 +// 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 "ErrorDialog.h" + +HIFI_QML_DEF(ErrorDialog) + +ErrorDialog::ErrorDialog(QQuickItem* parent) : OffscreenQmlDialog(parent) { +} + +ErrorDialog::~ErrorDialog() { +} + +QString ErrorDialog::text() const { + return _text; +} + +void ErrorDialog::setVisible(bool v) { + OffscreenQmlDialog::setVisible(v); +} + +void ErrorDialog::setText(const QString& arg) { + if (arg != _text) { + _text = arg; + emit textChanged(); + } +} + +void ErrorDialog::accept() { + OffscreenQmlDialog::accept(); +} diff --git a/libraries/ui/src/ErrorDialog.h b/libraries/ui/src/ErrorDialog.h new file mode 100644 index 0000000000..665090da1a --- /dev/null +++ b/libraries/ui/src/ErrorDialog.h @@ -0,0 +1,46 @@ +// +// ErrorDialog.h +// +// Created by David Rowe on 30 May 2015 +// 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_ErrorDialog_h +#define hifi_ErrorDialog_h + +#include "OffscreenQmlDialog.h" + +class ErrorDialog : public OffscreenQmlDialog +{ + Q_OBJECT + HIFI_QML_DECL + +private: + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) + +public: + ErrorDialog(QQuickItem* parent = 0); + virtual ~ErrorDialog(); + + QString text() const; + +public slots: + virtual void setVisible(bool v); + void setText(const QString& arg); + +signals: + void textChanged(); + +protected slots: + virtual void accept(); + +private: + QString _text; +}; + +#endif // hifi_ErrorDialog_h diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 449657ca04..d94cad20d2 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -13,6 +13,7 @@ #include #include #include +#include "ErrorDialog.h" #include "MessageDialog.h" @@ -130,6 +131,15 @@ void OffscreenUi::critical(const QString& title, const QString& text, static_cast(MessageDialog::Critical), buttons); } +void OffscreenUi::error(const QString& text) { + ErrorDialog* pDialog{ nullptr }; + ErrorDialog::show([&](QQmlContext* ctx, QObject* item) { + pDialog = item->findChild(); + pDialog->setText(text); + }); + pDialog->setEnabled(true); +} + OffscreenUi::ButtonCallback OffscreenUi::NO_OP_CALLBACK = [](QMessageBox::StandardButton) {}; diff --git a/libraries/ui/src/OffscreenUi.h b/libraries/ui/src/OffscreenUi.h index d3567bbb5e..4d0044e775 100644 --- a/libraries/ui/src/OffscreenUi.h +++ b/libraries/ui/src/OffscreenUi.h @@ -115,6 +115,8 @@ public: static void critical(const QString& title, const QString& text, ButtonCallback callback = NO_OP_CALLBACK, QMessageBox::StandardButtons buttons = QMessageBox::Ok); + + static void error(const QString& text); // Interim dialog in new style }; #endif