diff --git a/interface/resources/images/hifi-logo-blackish.svg b/interface/resources/images/hifi-logo-blackish.svg
new file mode 100644
index 0000000000..60bfb3d418
--- /dev/null
+++ b/interface/resources/images/hifi-logo-blackish.svg
@@ -0,0 +1,123 @@
+
+
+
+
\ No newline at end of file
diff --git a/interface/resources/images/login-close.svg b/interface/resources/images/login-close.svg
new file mode 100644
index 0000000000..2fb10c241b
--- /dev/null
+++ b/interface/resources/images/login-close.svg
@@ -0,0 +1,55 @@
+
+
\ No newline at end of file
diff --git a/interface/resources/images/login-password.svg b/interface/resources/images/login-password.svg
new file mode 100644
index 0000000000..98d86f6d8a
--- /dev/null
+++ b/interface/resources/images/login-password.svg
@@ -0,0 +1,58 @@
+
+
\ No newline at end of file
diff --git a/interface/resources/images/login-username.svg b/interface/resources/images/login-username.svg
new file mode 100644
index 0000000000..a40dd91cf7
--- /dev/null
+++ b/interface/resources/images/login-username.svg
@@ -0,0 +1,51 @@
+
+
\ No newline at end of file
diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml
index 91e05d020d..3377b20d87 100644
--- a/interface/resources/qml/AddressBarDialog.qml
+++ b/interface/resources/qml/AddressBarDialog.qml
@@ -9,18 +9,16 @@
//
import Hifi 1.0
-import QtQuick 2.3
-import QtQuick.Controls 1.2
+import QtQuick 2.4
import "controls"
import "styles"
-Item {
+DialogContainer {
id: root
HifiConstants { id: hifi }
objectName: "AddressBarDialog"
- property int animationDuration: hifi.effects.fadeInDuration
property bool destroyOnInvisible: false
property real scale: 1.25 // Make this dialog a little larger than normal
@@ -101,47 +99,16 @@ Item {
}
}
- // 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: 0.0
-
onEnabledChanged: {
- opacity = enabled ? 1.0 : 0.0
if (enabled) {
- addressLine.forceActiveFocus();
+ addressLine.forceActiveFocus()
}
}
- 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) {
- reset()
-
- // Some dialogs should be destroyed when they become invisible.
- if (destroyOnInvisible) {
- destroy()
- }
+ addressLine.text = ""
}
-
- }
-
- function reset() {
- addressLine.text = ""
}
function toggleOrGo() {
@@ -152,21 +119,18 @@ Item {
}
}
- Keys.onEscapePressed: {
- enabled = false
- }
-
Keys.onPressed: {
- switch(event.key) {
- case Qt.Key_W:
- if (event.modifiers == Qt.ControlModifier) {
- event.accepted = true
- enabled = false
- }
+ switch (event.key) {
+ case Qt.Key_Escape:
+ case Qt.Key_Back:
+ enabled = false
+ event.accepted = true
+ break
+ case Qt.Key_Enter:
+ case Qt.Key_Return:
+ toggleOrGo()
+ event.accepted = true
break
}
}
-
- Keys.onReturnPressed: toggleOrGo()
- Keys.onEnterPressed: toggleOrGo()
}
diff --git a/interface/resources/qml/Browser.qml b/interface/resources/qml/Browser.qml
index 55a0a6a461..947bf739fc 100644
--- a/interface/resources/qml/Browser.qml
+++ b/interface/resources/qml/Browser.qml
@@ -4,7 +4,7 @@ import QtWebKit 3.0
import "controls"
import "styles"
-Dialog {
+VrDialog {
id: root
HifiConstants { id: hifi }
title: "Browser"
diff --git a/interface/resources/qml/ErrorDialog.qml b/interface/resources/qml/ErrorDialog.qml
index c0f8132f14..76d9111d97 100644
--- a/interface/resources/qml/ErrorDialog.qml
+++ b/interface/resources/qml/ErrorDialog.qml
@@ -8,27 +8,22 @@
// 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 Hifi 1.0
+import QtQuick 2.4
import "controls"
import "styles"
-Item {
+DialogContainer {
id: root
HifiConstants { id: hifi }
- property int animationDuration: hifi.effects.fadeInDuration
- property bool destroyOnInvisible: true
-
Component.onCompleted: {
enabled = true
}
onParentChanged: {
if (visible && enabled) {
- forceActiveFocus();
+ forceActiveFocus()
}
}
@@ -38,7 +33,7 @@ Item {
x: parent ? parent.width / 2 - width / 2 : 0
y: parent ? parent.height / 2 - height / 2 : 0
- Hifi.ErrorDialog {
+ ErrorDialog {
id: content
implicitWidth: box.width
@@ -69,7 +64,7 @@ Item {
Text {
id: messageText
- font.pointSize: 10
+ font.pixelSize: hifi.fonts.pixelSize * 0.6
font.weight: Font.Bold
anchors {
@@ -91,55 +86,17 @@ Item {
}
MouseArea {
anchors.fill: parent
+ cursorShape: "PointingHandCursor"
onClicked: {
- content.accept();
+ 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: 0.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) {
+ switch (event.key) {
case Qt.Key_Escape:
case Qt.Key_Back:
case Qt.Key_Enter:
diff --git a/interface/resources/qml/InfoView.qml b/interface/resources/qml/InfoView.qml
index 6b49e6f0c7..012f04f1fd 100644
--- a/interface/resources/qml/InfoView.qml
+++ b/interface/resources/qml/InfoView.qml
@@ -5,7 +5,7 @@ import QtQuick.Controls.Styles 1.3
import QtWebKit 3.0
import "controls"
-Dialog {
+VrDialog {
id: root
width: 800
height: 800
diff --git a/interface/resources/qml/LoginDialog.qml b/interface/resources/qml/LoginDialog.qml
index 5653dfc7a1..8d5267f7f8 100644
--- a/interface/resources/qml/LoginDialog.qml
+++ b/interface/resources/qml/LoginDialog.qml
@@ -1,78 +1,173 @@
+//
+// LoginDialog.qml
+//
+// Created by David Rowe on 3 Jun 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
-import QtQuick 2.3
-import QtQuick.Controls.Styles 1.3
+import QtQuick 2.4
import "controls"
import "styles"
-Dialog {
+DialogContainer {
+ id: root
HifiConstants { id: hifi }
- title: "Login"
+
objectName: "LoginDialog"
- height: 512
- width: 384
- onVisibleChanged: {
- if (!visible) {
- reset()
- }
- }
+ property bool destroyOnInvisible: false
- onEnabledChanged: {
- if (enabled) {
- username.forceActiveFocus();
- }
- }
+ implicitWidth: loginDialog.implicitWidth
+ implicitHeight: loginDialog.implicitHeight
- function reset() {
- username.text = ""
- password.text = ""
- loginDialog.statusText = ""
- }
+ x: parent ? parent.width / 2 - width / 2 : 0
+ y: parent ? parent.height / 2 - height / 2 : 0
+ property int maximumX: parent ? parent.width - width : 0
+ property int maximumY: parent ? parent.height - height : 0
LoginDialog {
id: loginDialog
- anchors.fill: parent
- anchors.margins: parent.margins
- anchors.topMargin: parent.topMargin
- Column {
- anchors.topMargin: 8
- anchors.right: parent.right
- anchors.rightMargin: 0
- anchors.left: parent.left
- anchors.top: parent.top
- spacing: 8
- Image {
- height: 64
- anchors.horizontalCenter: parent.horizontalCenter
- width: 64
- source: "../images/hifi-logo.svg"
+ implicitWidth: backgroundRectangle.width
+ implicitHeight: backgroundRectangle.height
+
+ readonly property int inputWidth: 500
+ readonly property int inputHeight: 60
+ readonly property int borderWidth: 30
+ readonly property int closeMargin: 16
+ readonly property real tan30: 0.577 // tan(30°)
+ readonly property int inputSpacing: 16
+ property int maximumX: parent ? parent.width - width : 0
+ property int maximumY: parent ? parent.height - height : 0
+
+ Rectangle {
+ id: backgroundRectangle
+ width: loginDialog.inputWidth + loginDialog.borderWidth * 2
+ height: loginDialog.inputHeight * 6 + loginDialog.closeMargin * 2
+ radius: loginDialog.closeMargin * 2
+
+ color: "#2c86b1"
+ opacity: 0.85
+
+ MouseArea {
+ width: parent.width
+ height: parent.height
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ verticalCenter: parent.verticalCenter
+ }
+ drag {
+ target: root
+ minimumX: 0
+ minimumY: 0
+ maximumX: root.parent ? root.maximumX : 0
+ maximumY: root.parent ? root.maximumY : 0
+ }
+ }
+ }
+
+ Image {
+ id: closeIcon
+ source: "../images/login-close.svg"
+ width: 20
+ height: 20
+ anchors {
+ top: backgroundRectangle.top
+ right: backgroundRectangle.right
+ topMargin: loginDialog.closeMargin
+ rightMargin: loginDialog.closeMargin
}
- Border {
- width: 304
- height: 64
- anchors.horizontalCenter: parent.horizontalCenter
+ MouseArea {
+ anchors.fill: parent
+ cursorShape: "PointingHandCursor"
+ onClicked: {
+ root.enabled = false
+ }
+ }
+ }
+
+ Column {
+ id: mainContent
+ width: loginDialog.inputWidth
+ spacing: loginDialog.inputSpacing
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ verticalCenter: parent.verticalCenter
+ }
+
+ Item {
+ // Offset content down a little
+ width: loginDialog.inputWidth
+ height: loginDialog.closeMargin
+ }
+
+ Rectangle {
+ width: loginDialog.inputWidth
+ height: loginDialog.inputHeight
+ radius: height / 2
+ color: "#ebebeb"
+
+ Image {
+ source: "../images/login-username.svg"
+ width: loginDialog.inputHeight * 0.65
+ height: width
+ anchors {
+ verticalCenter: parent.verticalCenter
+ left: parent.left
+ leftMargin: loginDialog.inputHeight / 4
+ }
+ }
+
TextInput {
id: username
- anchors.fill: parent
- helperText: "Username or Email"
- anchors.margins: 8
+ anchors {
+ fill: parent
+ leftMargin: loginDialog.inputHeight
+ rightMargin: loginDialog.inputHeight / 2
+ }
+
+ helperText: "username or email"
+ color: hifi.colors.text
+
KeyNavigation.tab: password
KeyNavigation.backtab: password
}
}
- Border {
- width: 304
- height: 64
- anchors.horizontalCenter: parent.horizontalCenter
+ Rectangle {
+ width: loginDialog.inputWidth
+ height: loginDialog.inputHeight
+ radius: height / 2
+ color: "#ebebeb"
+
+ Image {
+ source: "../images/login-password.svg"
+ width: loginDialog.inputHeight * 0.65
+ height: width
+ anchors {
+ verticalCenter: parent.verticalCenter
+ left: parent.left
+ leftMargin: loginDialog.inputHeight / 4
+ }
+ }
+
TextInput {
id: password
- anchors.fill: parent
+ anchors {
+ fill: parent
+ leftMargin: loginDialog.inputHeight
+ rightMargin: loginDialog.inputHeight / 2
+ }
+
+ helperText: "password"
echoMode: TextInput.Password
- helperText: "Password"
- anchors.margins: 8
+ color: hifi.colors.text
+
KeyNavigation.tab: username
KeyNavigation.backtab: username
onFocusChanged: {
@@ -83,102 +178,176 @@ Dialog {
}
}
- Text {
- anchors.horizontalCenter: parent.horizontalCenter
- textFormat: Text.StyledText
- width: parent.width
- height: 96
- wrapMode: Text.WordWrap
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- text: loginDialog.statusText
- }
- }
+ Item {
+ width: loginDialog.inputWidth
+ height: loginDialog.inputHeight / 2
- Column {
- anchors.bottomMargin: 5
- anchors.right: parent.right
- anchors.rightMargin: 0
- anchors.left: parent.left
- anchors.bottom: parent.bottom
+ Text {
+ id: messageText
+
+ visible: loginDialog.statusText != "" && loginDialog.statusText != "Logging in..."
+
+ width: loginDialog.inputWidth
+ height: loginDialog.inputHeight / 2
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+
+ text: loginDialog.statusText
+ color: "white"
+ }
+
+ Row {
+ id: messageSpinner
+
+ visible: loginDialog.statusText == "Logging in..."
+ onVisibleChanged: visible ? messageSpinnerAnimation.restart() : messageSpinnerAnimation.stop()
+
+ spacing: 24
+ anchors {
+ verticalCenter: parent.verticalCenter
+ horizontalCenter: parent.horizontalCenter
+ }
+
+ Rectangle {
+ id: spinner1
+ width: 10
+ height: 10
+ color: "#ebebeb"
+ opacity: 0.05
+ }
+
+ Rectangle {
+ id: spinner2
+ width: 10
+ height: 10
+ color: "#ebebeb"
+ opacity: 0.05
+ }
+
+ Rectangle {
+ id: spinner3
+ width: 10
+ height: 10
+ color: "#ebebeb"
+ opacity: 0.05
+ }
+
+ SequentialAnimation {
+ id: messageSpinnerAnimation
+ running: messageSpinner.visible
+ loops: Animation.Infinite
+ NumberAnimation { target: spinner1; property: "opacity"; to: 1.0; duration: 1000 }
+ NumberAnimation { target: spinner2; property: "opacity"; to: 1.0; duration: 1000 }
+ NumberAnimation { target: spinner3; property: "opacity"; to: 1.0; duration: 1000 }
+ NumberAnimation { target: spinner1; property: "opacity"; to: 0.05; duration: 0 }
+ NumberAnimation { target: spinner2; property: "opacity"; to: 0.05; duration: 0 }
+ NumberAnimation { target: spinner3; property: "opacity"; to: 0.05; duration: 0 }
+ }
+ }
+ }
Rectangle {
- width: 192
- height: 64
- anchors.horizontalCenter: parent.horizontalCenter
- color: hifi.colors.hifiBlue
- border.width: 0
- radius: 10
+ width: loginDialog.inputWidth
+ height: loginDialog.inputHeight
+ radius: height / 2
+ color: "#353535"
+
+ TextInput {
+ anchors.fill: parent
+ text: "Login"
+ color: "white"
+ horizontalAlignment: Text.AlignHCenter
+ }
MouseArea {
- anchors.bottom: parent.bottom
- anchors.bottomMargin: 0
- anchors.top: parent.top
- anchors.right: parent.right
- anchors.left: parent.left
+ anchors.fill: parent
+ cursorShape: "PointingHandCursor"
onClicked: {
loginDialog.login(username.text, password.text)
}
}
+ }
- Row {
- anchors.centerIn: parent
+ Row {
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ Text {
+ text: "Password?"
+ font.pixelSize: hifi.fonts.pixelSize * 0.8
+ font.underline: true
+ color: "#e0e0e0"
+ width: loginDialog.inputHeight * 4
+ horizontalAlignment: Text.AlignRight
anchors.verticalCenter: parent.verticalCenter
- spacing: 8
+
+ MouseArea {
+ anchors.fill: parent
+ cursorShape: "PointingHandCursor"
+ onClicked: {
+ loginDialog.openUrl(loginDialog.rootUrl + "/users/password/new")
+ }
+ }
+ }
+
+ Item {
+ width: loginDialog.inputHeight + loginDialog.inputSpacing * 2
+ height: loginDialog.inputHeight
+
Image {
- id: loginIcon
- height: 32
- width: 32
- source: "../images/login.svg"
- }
- Text {
- text: "Login"
- color: "white"
- width: 64
- height: parent.height
+ id: hifiIcon
+ source: "../images/hifi-logo-blackish.svg"
+ width: loginDialog.inputHeight
+ height: width
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ verticalCenter: parent.verticalCenter
+ }
}
}
- }
+ Text {
+ text: "Register"
+ font.pixelSize: hifi.fonts.pixelSize * 0.8
+ font.underline: true
+ color: "#e0e0e0"
+ width: loginDialog.inputHeight * 4
+ horizontalAlignment: Text.AlignLeft
+ anchors.verticalCenter: parent.verticalCenter
- Text {
- width: parent.width
- height: 24
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- text:"Create Account"
- font.pointSize: 12
- font.bold: true
- color: hifi.colors.hifiBlue
-
- MouseArea {
- anchors.fill: parent
- onClicked: {
- loginDialog.openUrl(loginDialog.rootUrl + "/signup")
- }
- }
- }
-
- Text {
- width: parent.width
- height: 24
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- font.pointSize: 12
- text: "Recover Password"
- color: hifi.colors.hifiBlue
-
- MouseArea {
- anchors.fill: parent
- onClicked: {
- loginDialog.openUrl(loginDialog.rootUrl + "/users/password/new")
+ MouseArea {
+ anchors.fill: parent
+ cursorShape: "PointingHandCursor"
+ onClicked: {
+ loginDialog.openUrl(loginDialog.rootUrl + "/signup")
+ }
}
}
}
}
}
+
+ onOpacityChanged: {
+ // Set focus once animation is completed so that focus is set at start-up when not logged in
+ if (opacity == 1.0) {
+ username.forceActiveFocus()
+ }
+ }
+
+ onVisibleChanged: {
+ if (!visible) {
+ username.text = ""
+ password.text = ""
+ loginDialog.statusText = ""
+ }
+ }
+
Keys.onPressed: {
- switch(event.key) {
+ switch (event.key) {
+ case Qt.Key_Escape:
+ case Qt.Key_Back:
+ enabled = false
+ event.accepted = true
+ break
case Qt.Key_Enter:
case Qt.Key_Return:
if (username.activeFocus) {
@@ -192,7 +361,7 @@ Dialog {
loginDialog.login(username.text, password.text)
}
}
- break;
+ break
}
}
}
diff --git a/interface/resources/qml/MarketplaceDialog.qml b/interface/resources/qml/MarketplaceDialog.qml
index 58bb3e6183..946f32e84a 100644
--- a/interface/resources/qml/MarketplaceDialog.qml
+++ b/interface/resources/qml/MarketplaceDialog.qml
@@ -5,7 +5,7 @@ import QtQuick.Controls.Styles 1.3
import QtWebKit 3.0
import "controls"
-Dialog {
+VrDialog {
title: "Test Dlg"
id: testDialog
objectName: "Browser"
diff --git a/interface/resources/qml/MessageDialog.qml b/interface/resources/qml/MessageDialog.qml
index dd410b8070..e8b01df9d0 100644
--- a/interface/resources/qml/MessageDialog.qml
+++ b/interface/resources/qml/MessageDialog.qml
@@ -5,7 +5,7 @@ import QtQuick.Dialogs 1.2
import "controls"
import "styles"
-Dialog {
+VrDialog {
id: root
HifiConstants { id: hifi }
property real spacing: hifi.layout.spacing
diff --git a/interface/resources/qml/TestDialog.qml b/interface/resources/qml/TestDialog.qml
index 15bd790c22..e6675b7282 100644
--- a/interface/resources/qml/TestDialog.qml
+++ b/interface/resources/qml/TestDialog.qml
@@ -3,7 +3,7 @@ import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.3
import "controls"
-Dialog {
+VrDialog {
title: "Test Dialog"
id: testDialog
objectName: "TestDialog"
diff --git a/interface/resources/qml/controls/DialogContainer.qml b/interface/resources/qml/controls/DialogContainer.qml
new file mode 100644
index 0000000000..4aa4e45d67
--- /dev/null
+++ b/interface/resources/qml/controls/DialogContainer.qml
@@ -0,0 +1,65 @@
+//
+// DialogCommon.qml
+//
+// Created by David Rowe on 3 Jun 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
+import QtQuick 2.4
+import "../styles"
+
+Item {
+ id: root
+
+ property bool destroyOnInvisible: true
+
+
+ // 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: 0.0
+
+ onEnabledChanged: {
+ opacity = enabled ? 1.0 : 0.0
+ }
+
+ Behavior on opacity {
+ // Animate opacity.
+ NumberAnimation {
+ duration: hifi.effects.fadeInDuration
+ 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: {
+ switch(event.key) {
+ case Qt.Key_W:
+ if (event.modifiers == Qt.ControlModifier) {
+ enabled = false
+ event.accepted = true
+ }
+ break
+ }
+ }
+}
diff --git a/interface/resources/qml/controls/Dialog.qml b/interface/resources/qml/controls/VrDialog.qml
similarity index 100%
rename from interface/resources/qml/controls/Dialog.qml
rename to interface/resources/qml/controls/VrDialog.qml
diff --git a/interface/resources/qml/styles/HifiConstants.qml b/interface/resources/qml/styles/HifiConstants.qml
index fa556f2083..c232b993d1 100644
--- a/interface/resources/qml/styles/HifiConstants.qml
+++ b/interface/resources/qml/styles/HifiConstants.qml
@@ -13,10 +13,9 @@ Item {
readonly property color hifiBlue: "#0e7077"
readonly property color window: sysPalette.window
readonly property color dialogBackground: sysPalette.window
- //readonly property color dialogBackground: "#00000000"
readonly property color inputBackground: "white"
readonly property color background: sysPalette.dark
- readonly property color text: sysPalette.text
+ readonly property color text: "#202020"
readonly property color disabledText: "gray"
readonly property color hintText: "gray" // A bit darker than sysPalette.dark so that it is visible on the DK2
readonly property color light: sysPalette.light
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 3ee470cc17..a957768d72 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -477,7 +477,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
addressManager->setPositionGetter(getPositionForPath);
addressManager->setOrientationGetter(getOrientationForPath);
- connect(addressManager.data(), &AddressManager::rootPlaceNameChanged, this, &Application::updateWindowTitle);
+ connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle);
connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress);
#ifdef _WIN32
@@ -3656,7 +3656,7 @@ void Application::updateWindowTitle(){
QString connectionStatus = nodeList->getDomainHandler().isConnected() ? "" : " (NOT CONNECTED) ";
QString username = AccountManager::getInstance().getAccountInfo().getUsername();
- QString currentPlaceName = DependencyManager::get()->getRootPlaceName();
+ QString currentPlaceName = DependencyManager::get()->getHost();
if (currentPlaceName.isEmpty()) {
currentPlaceName = nodeList->getDomainHandler().getHostname();
diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp
index b452f153f0..196ba5d29e 100644
--- a/interface/src/ui/LoginDialog.cpp
+++ b/interface/src/ui/LoginDialog.cpp
@@ -1,6 +1,6 @@
//
-//
// LoginDialog.cpp
+// interface/src/ui
//
// Created by Bradley Austin Davis on 2015/04/14
// Copyright 2015 High Fidelity, Inc.
@@ -8,16 +8,22 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
+
#include "LoginDialog.h"
-#include "DependencyManager.h"
-#include "AccountManager.h"
-#include "Menu.h"
+#include
+
#include
+#include "AccountManager.h"
+#include "DependencyManager.h"
+#include "Menu.h"
+
HIFI_QML_DEF(LoginDialog)
-LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent), _rootUrl(NetworkingConstants::METAVERSE_SERVER_URL.toString()) {
+LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent),
+ _rootUrl(NetworkingConstants::METAVERSE_SERVER_URL.toString())
+{
connect(&AccountManager::getInstance(), &AccountManager::loginComplete,
this, &LoginDialog::handleLoginCompleted);
connect(&AccountManager::getInstance(), &AccountManager::loginFailed,
@@ -48,7 +54,7 @@ void LoginDialog::handleLoginCompleted(const QUrl&) {
}
void LoginDialog::handleLoginFailed() {
- setStatusText("Invalid username or password.< / font>");
+ setStatusText("Invalid username or password");
}
void LoginDialog::setStatusText(const QString& statusText) {
@@ -68,10 +74,11 @@ QString LoginDialog::rootUrl() const {
void LoginDialog::login(const QString& username, const QString& password) {
qDebug() << "Attempting to login " << username;
- setStatusText("Authenticating...");
+ setStatusText("Logging in...");
AccountManager::getInstance().requestAccessToken(username, password);
}
void LoginDialog::openUrl(const QString& url) {
qDebug() << url;
+ QDesktopServices::openUrl(url);
}
diff --git a/interface/src/ui/LoginDialog.h b/interface/src/ui/LoginDialog.h
index e9ae0a1c16..50c820aa07 100644
--- a/interface/src/ui/LoginDialog.h
+++ b/interface/src/ui/LoginDialog.h
@@ -1,5 +1,6 @@
//
// LoginDialog.h
+// interface/src/ui
//
// Created by Bradley Austin Davis on 2015/04/14
// Copyright 2015 High Fidelity, Inc.
@@ -9,6 +10,7 @@
//
#pragma once
+
#ifndef hifi_LoginDialog_h
#define hifi_LoginDialog_h
diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp
index 3c6b7bd3f5..a86ce78655 100644
--- a/libraries/networking/src/AddressManager.cpp
+++ b/libraries/networking/src/AddressManager.cpp
@@ -30,7 +30,7 @@ const QString SETTINGS_CURRENT_ADDRESS_KEY = "address";
Setting::Handle currentAddressHandle(QStringList() << ADDRESS_MANAGER_SETTINGS_GROUP << "address", DEFAULT_HIFI_ADDRESS);
AddressManager::AddressManager() :
- _rootPlaceName(),
+ _host(),
_rootPlaceID(),
_positionGetter(NULL),
_orientationGetter(NULL)
@@ -45,7 +45,7 @@ const QUrl AddressManager::currentAddress() const {
QUrl hifiURL;
hifiURL.setScheme(HIFI_URL_SCHEME);
- hifiURL.setHost(_rootPlaceName);
+ hifiURL.setHost(_host);
hifiURL.setPath(currentPath());
return hifiURL;
@@ -123,6 +123,10 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl) {
+ (lookupUrl.port() == -1 ? "" : ":" + QString::number(lookupUrl.port())))) {
// we may have a path that defines a relative viewpoint - if so we should jump to that now
handlePath(lookupUrl.path());
+ } else if (handleDomainID(lookupUrl.host())){
+ // no place name - this is probably a domain ID
+ // try to look up the domain ID on the metaverse API
+ attemptDomainIDLookup(lookupUrl.host(), lookupUrl.path());
} else {
// wasn't an address - lookup the place name
// we may have a path that defines a relative viewpoint - pass that through the lookup so we can go to it after
@@ -161,11 +165,18 @@ void AddressManager::handleLookupString(const QString& lookupString) {
}
}
+const QString DATA_OBJECT_DOMAIN_KEY = "domain";
+
+
void AddressManager::handleAPIResponse(QNetworkReply& requestReply) {
QJsonObject responseObject = QJsonDocument::fromJson(requestReply.readAll()).object();
QJsonObject dataObject = responseObject["data"].toObject();
- goToAddressFromObject(dataObject.toVariantMap(), requestReply);
+ if (!dataObject.isEmpty()) {
+ goToAddressFromObject(dataObject.toVariantMap(), requestReply);
+ } else if (responseObject.contains(DATA_OBJECT_DOMAIN_KEY)) {
+ goToAddressFromObject(responseObject.toVariantMap(), requestReply);
+ }
emit lookupResultsFinished();
}
@@ -180,6 +191,8 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
QVariantMap locationMap;
if (dataObject.contains(DATA_OBJECT_PLACE_KEY)) {
locationMap = dataObject[DATA_OBJECT_PLACE_KEY].toMap();
+ } else if (dataObject.contains(DATA_OBJECT_DOMAIN_KEY)) {
+ locationMap = dataObject;
} else {
locationMap = dataObject[DATA_OBJECT_USER_LOCATION_KEY].toMap();
}
@@ -206,6 +219,10 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
DependencyManager::get()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::HandleAddress);
+ const QString DOMAIN_ID_KEY = "id";
+ QString domainIDString = domainObject[DOMAIN_ID_KEY].toString();
+ QUuid domainID(domainIDString);
+
if (domainObject.contains(DOMAIN_NETWORK_ADDRESS_KEY)) {
QString domainHostname = domainObject[DOMAIN_NETWORK_ADDRESS_KEY].toString();
@@ -219,10 +236,6 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
} else {
QString iceServerAddress = domainObject[DOMAIN_ICE_SERVER_ADDRESS_KEY].toString();
- const QString DOMAIN_ID_KEY = "id";
- QString domainIDString = domainObject[DOMAIN_ID_KEY].toString();
- QUuid domainID(domainIDString);
-
qCDebug(networking) << "Possible domain change required to connect to domain with ID" << domainID
<< "via ice-server at" << iceServerAddress;
@@ -235,8 +248,12 @@ void AddressManager::goToAddressFromObject(const QVariantMap& dataObject, const
// set our current root place name to the name that came back
const QString PLACE_NAME_KEY = "name";
- QString newRootPlaceName = rootMap[PLACE_NAME_KEY].toString();
- setRootPlaceName(newRootPlaceName);
+ QString placeName = rootMap[PLACE_NAME_KEY].toString();
+ if (!placeName.isEmpty()) {
+ setHost(placeName);
+ } else {
+ setHost(domainIDString);
+ }
// check if we had a path to override the path returned
QString overridePath = reply.property(OVERRIDE_PATH_KEY).toString();
@@ -304,6 +321,24 @@ void AddressManager::attemptPlaceNameLookup(const QString& lookupString, const Q
QByteArray(), NULL, requestParams);
}
+const QString GET_DOMAIN_ID = "/api/v1/domains/%1";
+
+void AddressManager::attemptDomainIDLookup(const QString& lookupString, const QString& overridePath) {
+ // assume this is a domain ID and see if we can get any info on it
+ QString domainID = QUrl::toPercentEncoding(lookupString);
+
+ QVariantMap requestParams;
+ if (!overridePath.isEmpty()) {
+ requestParams.insert(OVERRIDE_PATH_KEY, overridePath);
+ }
+
+ AccountManager::getInstance().sendRequest(GET_DOMAIN_ID.arg(domainID),
+ AccountManagerAuth::None,
+ QNetworkAccessManager::GetOperation,
+ apiCallbackParameters(),
+ QByteArray(), NULL, requestParams);
+}
+
bool AddressManager::handleNetworkAddress(const QString& lookupString) {
const QString IP_ADDRESS_REGEX_STRING = "^((?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}"
"(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))(?::(\\d{1,5}))?$";
@@ -335,7 +370,7 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) {
quint16 domainPort = DEFAULT_DOMAIN_SERVER_PORT;
if (!hostnameRegex.cap(2).isEmpty()) {
- domainPort = (qint16) hostnameRegex.cap(2).toInt();
+ domainPort = (qint16)hostnameRegex.cap(2).toInt();
}
emit lookupResultsFinished();
@@ -347,6 +382,14 @@ bool AddressManager::handleNetworkAddress(const QString& lookupString) {
return false;
}
+bool AddressManager::handleDomainID(const QString& host) {
+ const QString UUID_REGEX_STRING = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
+
+ QRegExp domainIDRegex(UUID_REGEX_STRING, Qt::CaseInsensitive);
+
+ return (domainIDRegex.indexIn(host) != -1);
+}
+
void AddressManager::handlePath(const QString& path) {
if (!handleViewpoint(path)) {
qCDebug(networking) << "User entered path could not be handled as a viewpoint - " << path <<
@@ -422,16 +465,16 @@ bool AddressManager::handleUsername(const QString& lookupString) {
return false;
}
-void AddressManager::setRootPlaceName(const QString& rootPlaceName) {
- if (rootPlaceName != _rootPlaceName) {
- _rootPlaceName = rootPlaceName;
- emit rootPlaceNameChanged(_rootPlaceName);
+void AddressManager::setHost(const QString& host) {
+ if (host != _host) {
+ _host = host;
+ emit hostChanged(_host);
}
}
void AddressManager::setDomainInfo(const QString& hostname, quint16 port) {
- _rootPlaceName = hostname;
+ _host = hostname;
_rootPlaceID = QUuid();
qCDebug(networking) << "Possible domain change required to connect to domain at" << hostname << "on" << port;
diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h
index 5831d62603..2b587a9bd7 100644
--- a/libraries/networking/src/AddressManager.h
+++ b/libraries/networking/src/AddressManager.h
@@ -35,7 +35,7 @@ class AddressManager : public QObject, public Dependency {
Q_PROPERTY(bool isConnected READ isConnected)
Q_PROPERTY(QUrl href READ currentAddress)
Q_PROPERTY(QString protocol READ getProtocol)
- Q_PROPERTY(QString hostname READ getRootPlaceName)
+ Q_PROPERTY(QString hostname READ getHost)
Q_PROPERTY(QString pathname READ currentPath)
public:
bool isConnected();
@@ -46,10 +46,11 @@ public:
const QUuid& getRootPlaceID() const { return _rootPlaceID; }
- const QString& getRootPlaceName() const { return _rootPlaceName; }
- void setRootPlaceName(const QString& rootPlaceName);
+ const QString& getHost() const { return _host; }
+ void setHost(const QString& host);
void attemptPlaceNameLookup(const QString& lookupString, const QString& overridePath = QString());
+ void attemptDomainIDLookup(const QString& lookupString, const QString& overridePath = QString());
void setPositionGetter(PositionGetter positionGetter) { _positionGetter = positionGetter; }
void setOrientationGetter(OrientationGetter orientationGetter) { _orientationGetter = orientationGetter; }
@@ -78,7 +79,7 @@ signals:
bool hasOrientationChange, const glm::quat& newOrientation,
bool shouldFaceLocation);
void pathChangeRequired(const QString& newPath);
- void rootPlaceNameChanged(const QString& newRootPlaceName);
+ void hostChanged(const QString& newHost);
protected:
AddressManager();
private slots:
@@ -95,8 +96,9 @@ private:
void handlePath(const QString& path);
bool handleViewpoint(const QString& viewpointString, bool shouldFace = false);
bool handleUsername(const QString& lookupString);
+ bool handleDomainID(const QString& host);
- QString _rootPlaceName;
+ QString _host;
QUuid _rootPlaceID;
PositionGetter _positionGetter;
OrientationGetter _orientationGetter;