Merge branch 'master' of github.com:highfidelity/hifi into bullet-constraints-1

This commit is contained in:
Seth Alves 2017-04-18 11:59:23 -07:00
commit 0807e036e8
32 changed files with 932 additions and 570 deletions

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 50 150" style="enable-background:new 0 0 50 150;" xml:space="preserve">
<style type="text/css">
.st0{fill:#414042;}
@ -8,21 +8,16 @@
.st2{fill:#1398BB;}
.st3{fill:#31D8FF;}
</style>
<g id="Layer_1">
<path class="st0" d="M33.72,85.08l-9.15-9.15l-0.74-0.74l0.74-0.74l9.35-9.35c0.59-0.59,0.59-1.56,0-2.15
c-0.29-0.29-0.67-0.45-1.08-0.45c-0.41,0-0.79,0.16-1.08,0.45L19.52,75.19l12.04,12.04c0.29,0.29,0.67,0.45,1.08,0.45
c0.41,0,0.79-0.16,1.08-0.45C34.31,86.64,34.31,85.67,33.72,85.08z"/>
<path class="st1" d="M33.72,33.45l-9.15-9.15l-0.74-0.74l0.74-0.74l9.35-9.35c0.59-0.59,0.59-1.56,0-2.15
c-0.29-0.29-0.67-0.45-1.08-0.45c-0.41,0-0.79,0.16-1.08,0.45L19.52,23.56L31.56,35.6c0.29,0.29,0.67,0.45,1.08,0.45
c0.41,0,0.79-0.16,1.08-0.45C34.31,35.01,34.31,34.04,33.72,33.45z"/>
<path class="st2" d="M17.99,124.82l12.78,12.78c1,1,2.63,1,3.63,0c1-1,1-2.63,0-3.63l-9.15-9.15l9.35-9.35c1-1,1-2.63,0-3.63
c-1-1-2.63-1-3.63,0L17.99,124.82z"/>
<path class="st3" d="M32.79,112.13c0.41,0,0.79,0.16,1.08,0.45c0.59,0.59,0.59,1.56,0,2.15l-9.35,9.35l-0.74,0.74l0.74,0.74
l9.15,9.15c0.59,0.59,0.59,1.56,0,2.15c-0.29,0.29-0.67,0.45-1.08,0.45c-0.41,0-0.79-0.16-1.08-0.45l-12.04-12.04l12.24-12.24
C32,112.29,32.38,112.13,32.79,112.13 M32.79,111.08c-0.66,0-1.31,0.25-1.82,0.75l-12.98,12.98l12.78,12.78
c0.5,0.5,1.16,0.75,1.82,0.75c0.66,0,1.31-0.25,1.82-0.75c1-1,1-2.63,0-3.63l-9.15-9.15l9.35-9.35c1-1,1-2.63,0-3.63
C34.1,111.34,33.44,111.08,32.79,111.08L32.79,111.08z"/>
</g>
<path class="st0" d="M33.4,87.4L22.1,76.1l-0.9-0.9l0.9-0.9l11.5-11.5c0.7-0.7,0.7-1.9,0-2.7c-0.3-0.3-0.8-0.5-1.3-0.5
s-1,0.2-1.3,0.5L15.9,75.2l14.9,14.9c0.4,0.4,0.8,0.6,1.3,0.6c0.5,0,1-0.2,1.3-0.6C34.2,89.3,34.2,88.2,33.4,87.4z"/>
<path class="st1" d="M33.4,37.1L22.1,25.8l-0.9-0.9l0.9-0.9l11.5-11.5c0.7-0.7,0.7-1.9,0-2.7c-0.3-0.4-0.8-0.6-1.3-0.6
s-1,0.2-1.3,0.6L15.9,24.9l14.9,14.9c0.4,0.4,0.8,0.5,1.3,0.5c0.5,0,1-0.2,1.3-0.5C34.2,39,34.2,37.8,33.4,37.1z"/>
<path class="st2" d="M14.1,124.8l15.8,15.8c1.2,1.2,3.2,1.2,4.5,0c1.2-1.2,1.2-3.2,0-4.5L23,124.8l11.5-11.5c1.2-1.2,1.2-3.2,0-4.5
c-1.2-1.2-3.2-1.2-4.5,0L14.1,124.8z"/>
<path class="st3" d="M32.4,109.2c0.5,0,1,0.2,1.3,0.6c0.7,0.7,0.7,1.9,0,2.7l-11.5,11.5l-0.9,0.9l0.9,0.9l11.3,11.3
c0.7,0.7,0.7,1.9,0,2.7c-0.4,0.4-0.8,0.6-1.3,0.6s-1-0.2-1.3-0.6l-14.9-14.9L31,109.7C31.4,109.4,31.9,109.2,32.4,109.2 M32.4,107.9
c-0.8,0-1.6,0.3-2.2,0.9l-16,16l15.8,15.8c0.6,0.6,1.4,0.9,2.2,0.9s1.6-0.3,2.2-0.9c1.2-1.2,1.2-3.2,0-4.5l-11.3-11.3l11.5-11.6
c1.2-1.2,1.2-3.2,0-4.5C34,108.2,33.2,107.9,32.4,107.9L32.4,107.9z"/>
<g id="Layer_2">
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 50 150" style="enable-background:new 0 0 50 150;" xml:space="preserve">
<style type="text/css">
.st0{fill:#414042;}
@ -8,21 +8,16 @@
.st2{fill:#1398BB;}
.st3{fill:#31D8FF;}
</style>
<g id="Layer_1">
<path class="st0" d="M21.12,62.95c-0.29-0.29-0.67-0.45-1.08-0.45c-0.41,0-0.79,0.16-1.08,0.45c-0.59,0.59-0.59,1.56,0,2.15
l9.35,9.35l0.74,0.74l-0.74,0.74l-9.15,9.15c-0.59,0.59-0.59,1.56,0,2.15c0.29,0.29,0.67,0.45,1.08,0.45
c0.41,0,0.79-0.16,1.08-0.45l12.04-12.04L21.12,62.95z"/>
<path class="st1" d="M21.12,11.32c-0.29-0.29-0.67-0.45-1.08-0.45c-0.41,0-0.79,0.16-1.08,0.45c-0.59,0.59-0.59,1.56,0,2.15
l9.35,9.35l0.74,0.74l-0.74,0.74l-9.15,9.15c-0.59,0.59-0.59,1.56,0,2.15c0.29,0.29,0.67,0.45,1.08,0.45
c0.41,0,0.79-0.16,1.08-0.45l12.04-12.04L21.12,11.32z"/>
<path class="st2" d="M34.9,124.82L22.11,137.6c-1,1-2.63,1-3.63,0c-1-1-1-2.63,0-3.63l9.15-9.15l-9.35-9.35c-1-1-1-2.63,0-3.63
c1-1,2.63-1,3.63,0L34.9,124.82z"/>
<path class="st3" d="M20.1,112.13c0.41,0,0.79,0.16,1.08,0.45l12.24,12.24l-12.04,12.04c-0.29,0.29-0.67,0.45-1.08,0.45
c-0.41,0-0.79-0.16-1.08-0.45c-0.59-0.59-0.59-1.56,0-2.15l9.15-9.15l0.74-0.74l-0.74-0.74l-9.35-9.35c-0.59-0.59-0.59-1.56,0-2.15
C19.31,112.29,19.69,112.13,20.1,112.13 M20.1,111.08c-0.66,0-1.31,0.25-1.82,0.75c-1,1-1,2.63,0,3.63l9.35,9.35l-9.15,9.15
c-1,1-1,2.63,0,3.63c0.5,0.5,1.16,0.75,1.82,0.75s1.31-0.25,1.82-0.75l12.78-12.78l-12.98-12.98
C21.41,111.34,20.76,111.08,20.1,111.08L20.1,111.08z"/>
</g>
<path class="st0" d="M21.1,60.1c-0.4-0.4-0.8-0.5-1.3-0.5s-1,0.2-1.3,0.5c-0.7,0.7-0.7,1.9,0,2.7l11.5,11.5l0.9,0.9l-0.9,0.9
L18.6,87.4c-0.7,0.7-0.7,1.9,0,2.7c0.4,0.3,0.8,0.6,1.3,0.6s1-0.2,1.3-0.6l14.9-14.9L21.1,60.1z"/>
<path class="st1" d="M21.1,9.8c-0.4-0.4-0.8-0.6-1.3-0.6s-1,0.2-1.3,0.6c-0.7,0.7-0.7,1.9,0,2.7L29.9,24l0.9,0.9l-0.9,0.9L18.6,37.1
c-0.7,0.7-0.7,1.9,0,2.7c0.4,0.4,0.8,0.5,1.3,0.5s1-0.2,1.3-0.5l14.9-14.9L21.1,9.8z"/>
<path class="st2" d="M38,124.8l-15.8,15.8c-1.2,1.2-3.2,1.2-4.5,0c-1.2-1.2-1.2-3.2,0-4.5L29,124.8l-11.5-11.5
c-1.2-1.2-1.2-3.2,0-4.5c1.2-1.2,3.2-1.2,4.5,0L38,124.8z"/>
<path class="st3" d="M19.7,109.2c0.5,0,1,0.2,1.3,0.6l15.1,15.1l-14.9,14.9c-0.4,0.4-0.8,0.6-1.3,0.6s-1-0.2-1.3-0.6
c-0.7-0.7-0.7-1.9,0-2.7l11.3-11.3l0.9-0.9l-0.9-0.9l-11.5-11.5c-0.7-0.7-0.7-1.9,0-2.7C18.8,109.4,19.2,109.2,19.7,109.2
M19.7,107.9c-0.8,0-1.6,0.3-2.2,0.9c-1.2,1.2-1.2,3.2,0,4.5L29,124.8l-11.3,11.3c-1.2,1.2-1.2,3.2,0,4.5c0.6,0.6,1.4,0.9,2.2,0.9
s1.6-0.3,2.2-0.9L38,124.8l-16-16C21.4,108.2,20.5,107.9,19.7,107.9L19.7,107.9z"/>
<g id="Layer_2">
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -542,7 +542,7 @@ ScrollingWindow {
Item {
height: parent.height
width: parent.width
HifiControls.Button {
HifiControls.QueuedButton {
id: uploadButton
anchors.right: parent.right
@ -552,22 +552,7 @@ ScrollingWindow {
height: 30
width: 155
onClicked: uploadClickedTimer.running = true
// For some reason trigginer an API that enters
// an internal event loop directly from the button clicked
// trigger below causes the appliction to behave oddly.
// Most likely because the button onClicked handling is never
// completed until the function returns.
// FIXME find a better way of handling the input dialogs that
// doesn't trigger this.
Timer {
id: uploadClickedTimer
interval: 5
repeat: false
running: false
onTriggered: uploadClicked();
}
onClickedQueued: uploadClicked()
}
Item {

View file

@ -0,0 +1,43 @@
//
// QueuedButton.qml
// -- original Button.qml + signal timer workaround --ht
// Created by David Rowe on 16 Feb 2016
// Copyright 2016 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 QtQuick 2.5
import QtQuick.Controls 1.4 as Original
import QtQuick.Controls.Styles 1.4
import "../styles-uit"
import "." as HifiControls
HifiControls.Button {
// FIXME: THIS WORKAROUND MIGRATED/CONSOLIDATED FROM RUNNINGSCRIPTS.QML
// For some reason trigginer an API that enters
// an internal event loop directly from the button clicked
// trigger below causes the appliction to behave oddly.
// Most likely because the button onClicked handling is never
// completed until the function returns.
// FIXME find a better way of handling the input dialogs that
// doesn't trigger this.
// NOTE: dialogs that need to use this workaround can connect via
// onQueuedClicked: ...
// instead of:
// onClicked: ...
signal clickedQueued()
Timer {
id: fromTimer
interval: 5
repeat: false
running: false
onTriggered: clickedQueued()
}
onClicked: fromTimer.running = true
}

View file

@ -0,0 +1,53 @@
//
// TabletWebButton.qml
//
// Created by Dante Ruiz on 2017/4/13
// 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-uit"
Rectangle {
property alias text: label.text
property alias pixelSize: label.font.pixelSize;
property bool selected: false
property bool hovered: false
property bool enabled: false
property int spacing: 2
property var action: function () {}
property string enabledColor: hifi.colors.blueHighlight
property string disabledColor: hifi.colors.blueHighlight
property string highlightColor: hifi.colors.blueHighlight;
width: label.width + 64
height: 32
color: hifi.colors.white
HifiConstants { id: hifi }
RalewaySemiBold {
id: label;
color: enabledColor
font.pixelSize: 15;
anchors {
horizontalCenter: parent.horizontalCenter;
verticalCenter: parent.verticalCenter;
}
}
Rectangle {
id: indicator
width: parent.width
height: selected ? 3 : 1
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
color: hifi.colors.blueHighlight
visible: parent.selected || hovered
}
}

View file

@ -2,97 +2,81 @@ import QtQuick 2.5
import QtQuick.Controls 1.4
import QtWebEngine 1.2
import QtWebChannel 1.0
import HFTabletWebEngineProfile 1.0
import "../controls-uit" as HiFiControls
import "../styles" as HifiStyles
import "../styles-uit"
import HFWebEngineProfile 1.0
import HFTabletWebEngineProfile 1.0
import "../"
import "."
Item {
id: web
HifiConstants { id: hifi }
width: parent.width
height: parent.height
property var parentStackItem: null
property int headerHeight: 38
property int headerHeight: 70
property string url
property string address: url //for compatibility
property alias address: displayUrl.text //for compatibility
property string scriptURL
property alias eventBridge: eventBridgeWrapper.eventBridge
property bool keyboardEnabled: HMD.active
property bool keyboardRaised: false
property bool punctuationMode: false
property bool isDesktop: false
property WebEngineView view: loader.currentView
property int currentPage: -1 // used as a model for repeater
property alias pagesModel: pagesModel
Row {
Rectangle {
id: buttons
HifiConstants { id: hifi }
HifiStyles.HifiConstants { id: hifistyles }
height: headerHeight
spacing: 4
anchors.top: parent.top
anchors.topMargin: 8
anchors.left: parent.left
anchors.leftMargin: 8
HiFiGlyphs {
id: back;
enabled: currentPage >= 0
text: hifi.glyphs.backward
color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText
size: 48
MouseArea { anchors.fill: parent; onClicked: goBack() }
}
HiFiGlyphs {
id: forward;
enabled: currentPage < pagesModel.count - 1
text: hifi.glyphs.forward
color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText
size: 48
MouseArea { anchors.fill: parent; onClicked: goForward() }
}
HiFiGlyphs {
id: reload;
enabled: view != null;
text: (view !== null && view.loading) ? hifi.glyphs.close : hifi.glyphs.reload
color: enabled ? hifistyles.colors.text : hifistyles.colors.disabledText
size: 48
MouseArea { anchors.fill: parent; onClicked: reloadPage(); }
}
}
width: parent.width
height: parent.headerHeight
color: hifi.colors.white
TextField {
id: addressBar
height: 30
anchors.right: parent.right
anchors.rightMargin: 8
anchors.left: buttons.right
anchors.leftMargin: 0
anchors.verticalCenter: buttons.verticalCenter
focus: true
text: address
Component.onCompleted: ScriptDiscoveryService.scriptsModelFilter.filterRegExp = new RegExp("^.*$", "i")
Row {
id: nav
anchors {
top: parent.top
topMargin: 10
horizontalCenter: parent.horizontalCenter
}
spacing: 120
TabletWebButton {
id: back
enabledColor: hifi.colors.baseGray
enabled: false
text: "BACK"
Keys.onPressed: {
switch (event.key) {
case Qt.Key_Enter:
case Qt.Key_Return:
event.accepted = true;
if (text.indexOf("http") != 0) {
text = "http://" + text;
}
//root.hidePermissionsBar();
web.keyboardRaised = false;
gotoPage(text);
break;
MouseArea {
anchors.fill: parent
onClicked: goBack()
hoverEnabled: true
}
}
TabletWebButton {
id: close
enabledColor: hifi.colors.darkGray
text: "CLOSE"
MouseArea {
anchors.fill: parent
onClicked: closeWebEngine()
}
}
}
RalewaySemiBold {
id: displayUrl
color: hifi.colors.baseGray
font.pixelSize: 12
anchors {
top: nav.bottom
horizontalCenter: parent.horizontalCenter;
}
}
}
@ -100,15 +84,30 @@ Item {
ListModel {
id: pagesModel
onCountChanged: {
currentPage = count - 1
currentPage = count - 1;
if (currentPage > 0) {
back.enabledColor = hifi.colors.darkGray;
} else {
back.enabledColor = hifi.colors.baseGray;
}
}
}
function goBack() {
if (currentPage > 0) {
currentPage--;
} else if (parentStackItem) {
if (webview.canGoBack) {
pagesModel.remove(currentPage);
webview.goBack();
} else if (currentPage > 0) {
pagesModel.remove(currentPage);
}
}
function closeWebEngine() {
if (parentStackItem) {
parentStackItem.pop();
} else {
web.visible = false;
}
}
@ -130,18 +129,20 @@ Item {
function urlAppend(url) {
var lurl = decodeURIComponent(url)
if (lurl[lurl.length - 1] !== "/")
if (lurl[lurl.length - 1] !== "/") {
lurl = lurl + "/"
if (currentPage === -1 || pagesModel.get(currentPage).webUrl !== lurl) {
pagesModel.append({webUrl: lurl})
}
if (currentPage === -1 || (pagesModel.get(currentPage).webUrl !== lurl && !timer.running)) {
timer.start();
pagesModel.append({webUrl: lurl});
}
}
onCurrentPageChanged: {
if (currentPage >= 0 && currentPage < pagesModel.count && loader.item !== null) {
loader.item.url = pagesModel.get(currentPage).webUrl
web.url = loader.item.url
web.address = loader.item.url
if (currentPage >= 0 && currentPage < pagesModel.count) {
webview.url = pagesModel.get(currentPage).webUrl;
web.url = webview.url;
web.address = webview.url;
}
}
@ -155,45 +156,110 @@ Item {
property var eventBridge;
}
Loader {
id: loader
Timer {
id: timer
interval: 100
running: false
repeat: false
onTriggered: timer.stop();
}
property WebEngineView currentView: null
WebEngineView {
id: webview
objectName: "webEngineView"
x: 0
y: 0
width: parent.width
height: parent.height - web.headerHeight
asynchronous: true
height: keyboardEnabled && keyboardRaised ? parent.height - keyboard.height - web.headerHeight : parent.height - web.headerHeight
anchors.top: buttons.bottom
active: false
source: "../TabletBrowser.qml"
onStatusChanged: {
if (loader.status === Loader.Ready) {
currentView = item.webView
item.webView.userScriptUrl = web.scriptURL
if (currentPage >= 0) {
//we got something to load already
item.url = pagesModel.get(currentPage).webUrl
web.address = loader.item.url
profile: HFTabletWebEngineProfile {
id: webviewTabletProfile
storageName: "qmlTabletWebEngine"
}
property string userScriptUrl: ""
// creates a global EventBridge object.
WebEngineScript {
id: createGlobalEventBridge
sourceCode: eventBridgeJavaScriptToInject
injectionPoint: WebEngineScript.DocumentCreation
worldId: WebEngineScript.MainWorld
}
// detects when to raise and lower virtual keyboard
WebEngineScript {
id: raiseAndLowerKeyboard
injectionPoint: WebEngineScript.Deferred
sourceUrl: resourceDirectoryUrl + "/html/raiseAndLowerKeyboard.js"
worldId: WebEngineScript.MainWorld
}
// User script.
WebEngineScript {
id: userScript
sourceUrl: webview.userScriptUrl
injectionPoint: WebEngineScript.DocumentReady // DOM ready but page load may not be finished.
worldId: WebEngineScript.MainWorld
}
userScripts: [ createGlobalEventBridge, raiseAndLowerKeyboard, userScript ]
property string newUrl: ""
webChannel.registeredObjects: [eventBridgeWrapper]
Component.onCompleted: {
// Ensure the JS from the web-engine makes it to our logging
webview.javaScriptConsoleMessage.connect(function(level, message, lineNumber, sourceID) {
console.log("Web Entity JS message: " + sourceID + " " + lineNumber + " " + message);
});
webview.profile.httpUserAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36";
web.address = url;
}
onFeaturePermissionRequested: {
grantFeaturePermission(securityOrigin, feature, true);
}
onLoadingChanged: {
keyboardRaised = false;
punctuationMode = false;
keyboard.resetShiftMode(false);
// Required to support clicking on "hifi://" links
if (WebEngineView.LoadStartedStatus == loadRequest.status) {
urlAppend(loadRequest.url.toString())
var url = loadRequest.url.toString();
if (urlHandler.canHandleUrl(url)) {
if (urlHandler.handleUrl(url)) {
root.stop();
}
}
}
}
}
onNewViewRequested: {
request.openIn(webview);
}
}
Component.onCompleted: {
web.isDesktop = (typeof desktop !== "undefined");
address = url;
loader.active = true
}
Keys.onPressed: {
Keys.onPressed: {
switch(event.key) {
case Qt.Key_L:
if (event.modifiers == Qt.ControlModifier) {
event.accepted = true
addressBar.selectAll()
addressBar.forceActiveFocus()
}
break;
case Qt.Key_L:
if (event.modifiers == Qt.ControlModifier) {
event.accepted = true
}
break;
}
}
}

View file

@ -16,7 +16,6 @@ import "../../hifi/tablet/tabletWindows/preferences"
Preference {
id: root
property alias text: dataTextField.text
property alias buttonText: button.text
property alias placeholderText: dataTextField.placeholderText
property var browser;
height: control.height + hifi.dimensions.controlInterlineHeight
@ -58,28 +57,46 @@ Preference {
right: parent.right
bottom: parent.bottom
}
height: Math.max(dataTextField.controlHeight, button.height)
height: dataTextField.controlHeight + bookmarkAvatarButton.height + hifi.dimensions.contentSpacing.y
TextField {
id: dataTextField
label: root.label
placeholderText: root.placeholderText
text: preference.value
label: root.label
colorScheme: dataTextField.acceptableInput ? hifi.colorSchemes.dark : hifi.colorSchemes.light
validator: RegExpValidator {
regExp: /.*\.(?:fst).*\?*/ig
}
anchors {
left: parent.left
right: button.left
rightMargin: hifi.dimensions.contentSpacing.x
bottom: parent.bottom
right: parent.right
bottom: bookmarkAvatarButton.top
bottomMargin: hifi.dimensions.contentSpacing.y
}
colorScheme: hifi.colorSchemes.dark
}
QueuedButton {
id: bookmarkAvatarButton
text: "Bookmark Avatar"
width: 140
visible: dataTextField.acceptableInput
anchors {
left: parent.left
bottom: parent.bottom
rightMargin: hifi.dimensions.contentSpacing.x
}
onClickedQueued: ApplicationInterface.loadAddAvatarBookmarkDialog()
}
Button {
id: button
text: "Browse"
id: browseAvatarsButton
text: "Browse Avatars"
width: 140
anchors {
right: parent.right
verticalCenter: dataTextField.verticalCenter
left: dataTextField.acceptableInput ? bookmarkAvatarButton.right : parent.left
bottom: parent.bottom
leftMargin: dataTextField.acceptableInput ? hifi.dimensions.contentSpacing.x : 0
}
onClicked: {
if (typeof desktop !== "undefined") {
@ -103,5 +120,6 @@ Preference {
eventBridge: tabletRoot.eventBridge
}
}
}
}

View file

@ -219,41 +219,18 @@ ScrollingWindow {
Row {
spacing: hifi.dimensions.contentSpacing.x
HifiControls.Button {
HifiControls.QueuedButton {
text: "from URL"
color: hifi.buttons.black
height: 26
onClicked: fromUrlTimer.running = true
// For some reason trigginer an API that enters
// an internal event loop directly from the button clicked
// trigger below causes the appliction to behave oddly.
// Most likely because the button onClicked handling is never
// completed until the function returns.
// FIXME find a better way of handling the input dialogs that
// doesn't trigger this.
Timer {
id: fromUrlTimer
interval: 5
repeat: false
running: false
onTriggered: ApplicationInterface.loadScriptURLDialog();
}
onClickedQueued: ApplicationInterface.loadScriptURLDialog()
}
HifiControls.Button {
HifiControls.QueuedButton {
text: "from Disk"
color: hifi.buttons.black
height: 26
onClicked: fromDiskTimer.running = true
Timer {
id: fromDiskTimer
interval: 5
repeat: false
running: false
onTriggered: ApplicationInterface.loadDialog();
}
onClickedQueued: ApplicationInterface.loadDialog()
}
HifiControls.Button {

View file

@ -20,8 +20,10 @@ import "../toolbars"
import "../../styles-uit" as HifiStyles
import "../../controls-uit" as HifiControls
// references HMD, AddressManager, AddressBarDialog from root context
StackView {
id: root
id: root;
HifiConstants { id: hifi }
HifiStyles.HifiConstants { id: hifiStyleConstants }
initialItem: addressBarDialog
@ -34,24 +36,16 @@ StackView {
property string metaverseBase: addressBarDialog.metaverseServerUrl + "/api/v1/";
property var tablet: null;
property bool isDesktop: false;
Component { id: tabletStoryCard; TabletStoryCard {} }
Component { id: tabletWebView; TabletWebView {} }
Component.onCompleted: {
root.currentItem.focus = true;
root.currentItem.forceActiveFocus();
addressLine.focus = true;
addressLine.forceActiveFocus();
fillDestinations();
updateLocationText(false);
fillDestinations();
addressLine.focus = !HMD.active;
root.parentChanged.connect(center);
center();
isDesktop = (typeof desktop !== "undefined");
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
if (desktop) {
root.title = "GOTO";
}
}
Component.onDestruction: {
root.parentChanged.disconnect(center);
@ -68,9 +62,9 @@ StackView {
}
function goCard(targetString) {
if (0 !== targetString.indexOf('hifi://')) {
var card = tabletStoryCard.createObject();
card.setUrl(addressBarDialog.metaverseServerUrl + targetString);
card.eventBridge = root.eventBridge;
var card = tabletWebView.createObject();
card.url = addressBarDialog.metaverseServerUrl + targetString;
card.parentStackItem = root;
root.push(card);
return;
}
@ -78,8 +72,6 @@ StackView {
toggleOrGo(true, targetString);
clearAddressLineTimer.start();
}
property bool isCursorVisible: false // Override default cursor visibility.
AddressBarDialog {
@ -102,16 +94,11 @@ StackView {
onMetaverseServerUrlChanged: updateLocationTextTimer.start();
Rectangle {
id: navBar
width: 480
height: 70
width: parent.width
height: 50;
color: hifiStyleConstants.colors.white
anchors {
top: parent.top
right: parent.right
rightMargin: 0
left: parent.left
leftMargin: 0
}
anchors.top: parent.top;
anchors.left: parent.left;
ToolbarButton {
id: homeButton
@ -129,8 +116,14 @@ StackView {
}
ToolbarButton {
id: backArrow;
buttonState: addressBarDialog.backEnabled;
imageURL: "../../../images/backward.svg";
onClicked: addressBarDialog.loadBack();
buttonEnabled: addressBarDialog.backEnabled;
onClicked: {
if (buttonEnabled) {
addressBarDialog.loadBack();
}
}
anchors {
left: homeButton.right
verticalCenter: parent.verticalCenter
@ -138,8 +131,14 @@ StackView {
}
ToolbarButton {
id: forwardArrow;
buttonState: addressBarDialog.forwardEnabled;
imageURL: "../../../images/forward.svg";
onClicked: addressBarDialog.loadForward();
buttonEnabled: addressBarDialog.forwardEnabled;
onClicked: {
if (buttonEnabled) {
addressBarDialog.loadForward();
}
}
anchors {
left: backArrow.right
verticalCenter: parent.verticalCenter
@ -149,85 +148,80 @@ StackView {
Rectangle {
id: addressBar
width: 480
width: parent.width
height: 70
color: hifiStyleConstants.colors.white
anchors {
top: navBar.bottom
right: parent.right
rightMargin: 16
left: parent.left
leftMargin: 16
top: navBar.bottom;
left: parent.left;
}
property int inputAreaHeight: 70
property int inputAreaStep: (height - inputAreaHeight) / 2
HifiStyles.RalewayLight {
id: notice;
font.pixelSize: hifi.fonts.pixelSize * 0.50;
font.pixelSize: hifi.fonts.pixelSize * 0.7;
anchors {
top: parent.top
topMargin: parent.inputAreaStep + 12
left: addressLine.left
right: addressLine.right
top: parent.top;
left: addressLineContainer.left;
right: addressLineContainer.right;
}
}
HifiStyles.FiraSansRegular {
id: location;
anchors {
left: addressLineContainer.left;
leftMargin: 8;
verticalCenter: addressLineContainer.verticalCenter;
}
font.pixelSize: addressLine.font.pixelSize;
color: "gray";
clip: true;
anchors.fill: addressLine;
visible: addressLine.text.length === 0
}
TextInput {
id: addressLine
focus: true
width: addressLineContainer.width - addressLineContainer.anchors.leftMargin - addressLineContainer.anchors.rightMargin;
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
leftMargin: 16
rightMargin: 16
topMargin: parent.inputAreaStep + (2 * hifi.layout.spacing)
bottomMargin: parent.inputAreaStep
left: addressLineContainer.left;
leftMargin: 8;
verticalCenter: addressLineContainer.verticalCenter;
}
font.pixelSize: hifi.fonts.pixelSize * 0.75
cursorVisible: false
onTextChanged: {
filterChoicesByText();
updateLocationText(text.length > 0);
if (!isCursorVisible && text.length > 0) {
isCursorVisible = true;
cursorVisible = true;
}
}
onAccepted: {
addressBarDialog.keyboardEnabled = false;
}
onActiveFocusChanged: {
cursorVisible = isCursorVisible && focus;
}
MouseArea {
// If user clicks in address bar show cursor to indicate ability to enter address.
anchors.fill: parent
onClicked: {
isCursorVisible = true;
parent.cursorVisible = true;
parent.focus = true;
parent.forceActiveFocus();
addressBarDialog.keyboardEnabled = HMD.active
tabletRoot.playButtonClickSound();
}
toggleOrGo();
}
}
Rectangle {
anchors.fill: addressLine
id: addressLineContainer;
height: 40;
anchors {
top: notice.bottom;
topMargin: 2;
left: parent.left;
leftMargin: 16;
right: parent.right;
rightMargin: 16;
}
color: hifiStyleConstants.colors.lightGray
opacity: 0.1
MouseArea {
anchors.fill: parent;
onClicked: {
if (!addressLine.focus || !HMD.active) {
addressLine.focus = true;
addressLine.forceActiveFocus();
addressBarDialog.keyboardEnabled = HMD.active;
}
tabletRoot.playButtonClickSound();
}
}
}
}
Rectangle {
@ -347,13 +341,12 @@ StackView {
Timer {
// Delay clearing address line so as to avoid flicker of "not connected" being displayed after entering an address.
id: clearAddressLineTimer
running: false
interval: 100 // ms
repeat: false
id: clearAddressLineTimer;
running: false;
interval: 100; // ms
repeat: false;
onTriggered: {
addressLine.text = "";
isCursorVisible = false;
}
}
@ -535,7 +528,7 @@ StackView {
function updateLocationText(enteringAddress) {
if (enteringAddress) {
notice.text = "Go to a place, @user, path or network address";
notice.text = "Go To a place, @user, path, or network address:";
notice.color = hifiStyleConstants.colors.baseGrayHighlight;
} else {
notice.text = AddressManager.isConnected ? "Your location:" : "Not Connected";
@ -545,46 +538,14 @@ StackView {
}
}
onVisibleChanged: {
updateLocationText(false);
if (visible) {
addressLine.forceActiveFocus();
fillDestinations();
}
}
function toggleOrGo(fromSuggestions, address) {
if (address !== undefined && address !== "") {
addressBarDialog.loadAddress(address, fromSuggestions)
}
if (addressLine.text !== "") {
addressBarDialog.loadAddress(addressLine.text, fromSuggestions)
}
if (isDesktop) {
tablet.gotoHomeScreen();
} else {
HMD.closeTablet();
}
tabletRoot.shown = false;
}
Keys.onPressed: {
switch (event.key) {
case Qt.Key_Escape:
case Qt.Key_Back:
tabletRoot.shown = false
clearAddressLineTimer.start();
event.accepted = true
break
case Qt.Key_Enter:
case Qt.Key_Return:
toggleOrGo()
clearAddressLineTimer.start();
event.accepted = true
break
addressBarDialog.loadAddress(address, fromSuggestions);
clearAddressLineTimer.start();
} else if (addressLine.text !== "") {
addressBarDialog.loadAddress(addressLine.text, fromSuggestions);
clearAddressLineTimer.start();
}
DialogsManager.hideAddressBar();
}
}

View file

@ -1,46 +0,0 @@
//
// TabletAddressDialog.qml
//
// Created by Dante Ruiz on 2017/04/24
// 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 QtGraphicalEffects 1.0
import "../../controls"
import "../../styles"
import "../../windows"
import "../"
import "../toolbars"
import "../../styles-uit" as HifiStyles
import "../../controls-uit" as HifiControlsUit
import "../../controls" as HifiControls
Rectangle {
id: cardRoot
HifiStyles.HifiConstants { id: hifi }
width: parent.width
height: parent.height
property string address: ""
property alias eventBridge: webview.eventBridge
function setUrl(url) {
cardRoot.address = url;
webview.url = url;
}
HifiControls.TabletWebView {
id: webview
parentStackItem: root
anchors {
top: parent.top
right: parent.right
left: parent.left
bottom: parent.bottom
}
}
}

View file

@ -3,6 +3,8 @@ import QtQuick.Controls 1.4
StateImage {
id: button
property bool buttonEnabled: true
property bool isActive: false
property bool isEntered: false
@ -39,30 +41,37 @@ StateImage {
}
function updateState() {
if (!button.isEntered && !button.isActive) {
buttonState = imageOffOut;
} else if (!button.isEntered && button.isActive) {
buttonState = imageOnOut;
} else if (button.isEntered && !button.isActive) {
buttonState = imageOffIn;
if (buttonEnabled) {
if (!button.isEntered && !button.isActive) {
buttonState = imageOffOut;
} else if (!button.isEntered && button.isActive) {
buttonState = imageOnOut;
} else if (button.isEntered && !button.isActive) {
buttonState = imageOffIn;
} else {
buttonState = imageOnIn;
}
} else {
buttonState = imageOnIn;
buttonState = 0;
}
}
onIsActiveChanged: updateState();
onButtonEnabledChanged: updateState();
Timer {
id: asyncClickSender
interval: 10
repeat: false
running: false
onTriggered: button.clicked();
onTriggered: {
button.clicked();
}
}
MouseArea {
id: mouseArea
hoverEnabled: true
hoverEnabled: buttonEnabled
anchors.fill: parent
onClicked: asyncClickSender.start();
onEntered: {

View file

@ -59,6 +59,7 @@
#include <AssetUpload.h>
#include <AutoUpdater.h>
#include <AudioInjectorManager.h>
#include <AvatarBookmarks.h>
#include <CursorManager.h>
#include <DebugDraw.h>
#include <DeferredLightingEffect.h>
@ -81,6 +82,7 @@
#include <controllers/StateController.h>
#include <UserActivityLoggerScriptingInterface.h>
#include <LogHandler.h>
#include "LocationBookmarks.h"
#include <MainWindow.h>
#include <MappingRequest.h>
#include <MessagesClient.h>
@ -530,6 +532,8 @@ bool setupEssentials(int& argc, char** argv) {
DependencyManager::set<EntityScriptServerLogClient>();
DependencyManager::set<LimitlessVoiceRecognitionScriptingInterface>();
DependencyManager::set<OctreeStatsProvider>(nullptr, qApp->getOcteeSceneStats());
DependencyManager::set<AvatarBookmarks>();
DependencyManager::set<LocationBookmarks>();
return previousSessionCrashed;
}
@ -703,8 +707,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
usleep(USECS_PER_MSEC * 50); // 20hz
}
_bookmarks = new Bookmarks(); // Before setting up the menu
// start the nodeThread so its event loop is running
QThread* nodeThread = new QThread(this);
nodeThread->setObjectName("NodeList Thread");
@ -1420,11 +1422,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
connect(DependencyManager::get<AudioClient>().data(), &AudioClient::mutedByMixer, this, onMutedByMixer);
// Track when the address bar is opened
auto onAddressBarToggled = [this]() {
auto onAddressBarShown = [this]() {
// Record time
UserActivityLogger::getInstance().logAction("opened_address_bar", { { "uptime_ms", _sessionRunTimer.elapsed() } });
};
connect(DependencyManager::get<DialogsManager>().data(), &DialogsManager::addressBarToggled, this, onAddressBarToggled);
connect(DependencyManager::get<DialogsManager>().data(), &DialogsManager::addressBarShown, this, onAddressBarShown);
// Make sure we don't time out during slow operations at startup
updateHeartbeat();
@ -2009,6 +2011,8 @@ void Application::initializeUi() {
rootContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
rootContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
rootContext->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance());
rootContext->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
rootContext->setContextProperty("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
// Caches
rootContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());
@ -5494,6 +5498,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance());
scriptEngine->registerGlobalObject("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
scriptEngine->registerGlobalObject("AudioScope", DependencyManager::get<AudioScope>().data());
scriptEngine->registerGlobalObject("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
scriptEngine->registerGlobalObject("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
// Caches
scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCache>().data());
@ -6359,7 +6365,6 @@ void Application::loadLODToolsDialog() {
} else {
tablet->pushOntoStack("../../hifi/dialogs/TabletLODTools.qml");
}
}
@ -6409,6 +6414,11 @@ void Application::toggleEntityScriptServerLogDialog() {
}
}
void Application::loadAddAvatarBookmarkDialog() const {
auto avatarBookmarks = DependencyManager::get<AvatarBookmarks>();
avatarBookmarks->addBookmark();
}
void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio) {
postLambdaEvent([notify, includeAnimated, aspectRatio, this] {
QMediaPlayer* player = new QMediaPlayer();

View file

@ -52,7 +52,6 @@
#include "avatar/MyAvatar.h"
#include "BandwidthRecorder.h"
#include "Bookmarks.h"
#include "Camera.h"
#include "ConnectionMonitor.h"
#include "gpu/Context.h"
@ -261,7 +260,6 @@ public:
glm::mat4 getEyeProjection(int eye) const;
QRect getDesirableApplicationGeometry() const;
Bookmarks* getBookmarks() const { return _bookmarks; }
virtual bool canAcceptURL(const QString& url) const override;
virtual bool acceptURL(const QString& url, bool defaultUpload = false) override;
@ -330,6 +328,7 @@ public slots:
void toggleEntityScriptServerLogDialog();
void toggleRunningScriptsWidget() const;
Q_INVOKABLE void showAssetServerWidget(QString filePath = "");
Q_INVOKABLE void loadAddAvatarBookmarkDialog() const;
void showDialog(const QString& desktopURL, const QString& tabletURL, const QString& name) const;
@ -599,8 +598,6 @@ private:
bool _aboutToQuit;
Bookmarks* _bookmarks;
bool _notifiedPacketVersionMismatchThisDomain;
QThread _settingsThread;

View file

@ -0,0 +1,81 @@
//
// AvatarBookmarks.cpp
// interface/src
//
// Created by Triplelexx on 23/03/17.
// Copyright 2017 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 <QAction>
#include <QInputDialog>
#include <QMessageBox>
#include <QStandardPaths>
#include <QQmlContext>
#include <Application.h>
#include <OffscreenUi.h>
#include <avatar/AvatarManager.h>
#include "MainWindow.h"
#include "Menu.h"
#include "AvatarBookmarks.h"
#include <QtQuick/QQuickWindow>
AvatarBookmarks::AvatarBookmarks() {
_bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + AVATARBOOKMARKS_FILENAME;
readFromFile();
}
void AvatarBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
// Add menus/actions
auto bookmarkAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkAvatar);
QObject::connect(bookmarkAction, SIGNAL(triggered()), this, SLOT(addBookmark()), Qt::QueuedConnection);
_bookmarksMenu = menu->addMenu(MenuOption::AvatarBookmarks);
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteAvatarBookmark);
QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection);
Bookmarks::setupMenus(menubar, menu);
Bookmarks::sortActions(menubar, _bookmarksMenu);
}
void AvatarBookmarks::changeToBookmarkedAvatar() {
QAction* action = qobject_cast<QAction*>(sender());
const QString& address = action->data().toString();
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
myAvatar->useFullAvatarURL(address);
}
void AvatarBookmarks::addBookmark() {
bool ok = false;
auto bookmarkName = OffscreenUi::getText(OffscreenUi::ICON_PLACEMARK, "Bookmark Avatar", "Name", QString(), &ok);
if (!ok) {
return;
}
bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
if (bookmarkName.length() == 0) {
return;
}
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
const QString& bookmarkAddress = myAvatar->getSkeletonModelURL().toString();
Bookmarks::addBookmarkToFile(bookmarkName, bookmarkAddress);
}
void AvatarBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) {
QAction* changeAction = _bookmarksMenu->newAction();
changeAction->setData(address);
connect(changeAction, SIGNAL(triggered()), this, SLOT(changeToBookmarkedAvatar()));
if (!_isMenuSorted) {
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole);
} else {
// TODO: this is aggressive but other alternatives have proved less fruitful so far.
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole);
Bookmarks::sortActions(menubar, _bookmarksMenu);
}
}

View file

@ -0,0 +1,40 @@
//
// AvatarBookmarks.h
// interface/src
//
// Created by Triplelexx on 23/03/17.
// Copyright 2017 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
//
#ifndef hifi_AvatarBookmarks_h
#define hifi_AvatarBookmarks_h
#include <DependencyManager.h>
#include "Bookmarks.h"
class AvatarBookmarks: public Bookmarks, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
public:
AvatarBookmarks();
void setupMenus(Menu* menubar, MenuWrapper* menu) override;
public slots:
void addBookmark();
protected:
void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override;
private:
const QString AVATARBOOKMARKS_FILENAME = "avatarbookmarks.json";
private slots:
void changeToBookmarkedAvatar();
};
#endif // hifi_AvatarBookmarks_h

View file

@ -11,14 +11,10 @@
#include <QAction>
#include <QDebug>
#include <QJsonObject>
#include <QFile>
#include <QInputDialog>
#include <QJsonDocument>
#include <QMessageBox>
#include <QStandardPaths>
#include <AddressManager.h>
#include <Application.h>
#include <OffscreenUi.h>
@ -27,15 +23,69 @@
#include "InterfaceLogging.h"
#include "Bookmarks.h"
#include <QtQuick/QQuickWindow>
Bookmarks::Bookmarks() :
_isMenuSorted(false)
{
}
const QString Bookmarks::HOME_BOOKMARK = "Home";
void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
// Enable/Disable menus as needed
enableMenuItems(_bookmarks.count() > 0);
// Load Bookmarks
for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it) {
QString bookmarkName = it.key();
QString bookmarkAddress = it.value().toString();
addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress);
}
}
Bookmarks::Bookmarks() {
_bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + BOOKMARKS_FILENAME;
readFromFile();
void Bookmarks::deleteBookmark() {
QStringList bookmarkList;
QList<QAction*> menuItems = _bookmarksMenu->actions();
for (int i = 0; i < menuItems.count(); ++i) {
bookmarkList.append(menuItems[i]->text());
}
bool ok = false;
auto bookmarkName = OffscreenUi::getItem(OffscreenUi::ICON_PLACEMARK, "Delete Bookmark", "Select the bookmark to delete", bookmarkList, 0, false, &ok);
if (!ok) {
return;
}
bookmarkName = bookmarkName.trimmed();
if (bookmarkName.length() == 0) {
return;
}
removeBookmarkFromMenu(Menu::getInstance(), bookmarkName);
remove(bookmarkName);
if (_bookmarksMenu->actions().count() == 0) {
enableMenuItems(false);
}
}
void Bookmarks::addBookmarkToFile(const QString& bookmarkName, const QString& bookmarkAddress) {
Menu* menubar = Menu::getInstance();
if (contains(bookmarkName)) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
auto duplicateBookmarkMessage = offscreenUi->createMessageBox(OffscreenUi::ICON_WARNING, "Duplicate Bookmark",
"The bookmark name you entered already exists in your list.",
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?");
auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage);
if (result != QMessageBox::Yes) {
return;
}
removeBookmarkFromMenu(menubar, bookmarkName);
}
addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress);
insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName.
enableMenuItems(true);
}
void Bookmarks::insert(const QString& name, const QString& address) {
@ -64,6 +114,33 @@ bool Bookmarks::contains(const QString& name) const {
return _bookmarks.contains(name);
}
bool Bookmarks::sortOrder(QAction* a, QAction* b) {
return a->text().toLower().localeAwareCompare(b->text().toLower()) < 0;
}
void Bookmarks::sortActions(Menu* menubar, MenuWrapper* menu) {
QList<QAction*> actions = menu->actions();
qSort(actions.begin(), actions.end(), sortOrder);
for (QAction* action : menu->actions()) {
menu->removeAction(action);
}
for (QAction* action : actions) {
menu->addAction(action);
}
_isMenuSorted = true;
}
int Bookmarks::getMenuItemLocation(QList<QAction*> actions, const QString& name) const {
int menuItemLocation = 0;
for (QAction* action : actions) {
if (name.toLower().localeAwareCompare(action->text().toLower()) < 0) {
menuItemLocation = actions.indexOf(action);
break;
}
}
return menuItemLocation;
}
QString Bookmarks::addressForBookmark(const QString& name) const {
return _bookmarks.value(name).toString();
}
@ -99,108 +176,6 @@ void Bookmarks::persistToFile() {
saveFile.write(data);
}
void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
// Add menus/actions
auto bookmarkAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkLocation);
QObject::connect(bookmarkAction, SIGNAL(triggered()), this, SLOT(bookmarkLocation()), Qt::QueuedConnection);
auto setHomeAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::SetHomeLocation);
QObject::connect(setHomeAction, SIGNAL(triggered()), this, SLOT(setHomeLocation()), Qt::QueuedConnection);
_bookmarksMenu = menu->addMenu(MenuOption::Bookmarks);
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark);
QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection);
// Enable/Disable menus as needed
enableMenuItems(_bookmarks.count() > 0);
// Load bookmarks
for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it ) {
QString bookmarkName = it.key();
QString bookmarkAddress = it.value().toString();
addLocationToMenu(menubar, bookmarkName, bookmarkAddress);
}
}
void Bookmarks::bookmarkLocation() {
bool ok = false;
auto bookmarkName = OffscreenUi::getText(OffscreenUi::ICON_PLACEMARK, "Bookmark Location", "Name", QString(), &ok);
if (!ok) {
return;
}
bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
if (bookmarkName.length() == 0) {
return;
}
auto addressManager = DependencyManager::get<AddressManager>();
QString bookmarkAddress = addressManager->currentAddress().toString();
Menu* menubar = Menu::getInstance();
if (contains(bookmarkName)) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
auto duplicateBookmarkMessage = offscreenUi->createMessageBox(OffscreenUi::ICON_WARNING, "Duplicate Bookmark",
"The bookmark name you entered already exists in your list.",
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?");
auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage);
if (result != QMessageBox::Yes) {
return;
}
removeLocationFromMenu(menubar, bookmarkName);
}
addLocationToMenu(menubar, bookmarkName, bookmarkAddress);
insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName.
enableMenuItems(true);
}
void Bookmarks::setHomeLocation() {
Menu* menubar = Menu::getInstance();
QString bookmarkName = HOME_BOOKMARK;
auto addressManager = DependencyManager::get<AddressManager>();
QString bookmarkAddress = addressManager->currentAddress().toString();
addLocationToMenu(menubar, bookmarkName, bookmarkAddress);
insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName.
enableMenuItems(true);
}
void Bookmarks::teleportToBookmark() {
QAction* action = qobject_cast<QAction*>(sender());
QString address = action->data().toString();
DependencyManager::get<AddressManager>()->handleLookupString(address);
}
void Bookmarks::deleteBookmark() {
QStringList bookmarkList;
QList<QAction*> menuItems = _bookmarksMenu->actions();
for (int i = 0; i < menuItems.count(); i += 1) {
bookmarkList.append(menuItems[i]->text());
}
bool ok = false;
auto bookmarkName = OffscreenUi::getItem(OffscreenUi::ICON_PLACEMARK, "Delete Bookmark", "Select the bookmark to delete", bookmarkList, 0, false, &ok);
if (!ok) {
return;
}
bookmarkName = bookmarkName.trimmed();
if (bookmarkName.length() == 0) {
return;
}
removeLocationFromMenu(Menu::getInstance(), bookmarkName);
remove(bookmarkName);
if (_bookmarksMenu->actions().count() == 0) {
enableMenuItems(false);
}
}
void Bookmarks::enableMenuItems(bool enabled) {
if (_bookmarksMenu) {
_bookmarksMenu->setEnabled(enabled);
@ -210,17 +185,6 @@ void Bookmarks::enableMenuItems(bool enabled) {
}
}
void Bookmarks::addLocationToMenu(Menu* menubar, QString& name, QString& address) {
QAction* teleportAction = _bookmarksMenu->newAction();
teleportAction->setData(address);
connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark()));
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction,
name, 0, QAction::NoRole);
}
void Bookmarks::removeLocationFromMenu(Menu* menubar, QString& name) {
void Bookmarks::removeBookmarkFromMenu(Menu* menubar, const QString& name) {
menubar->removeAction(_bookmarksMenu, name);
}

View file

@ -27,37 +27,35 @@ class Bookmarks: public QObject {
public:
Bookmarks();
void setupMenus(Menu* menubar, MenuWrapper* menu);
virtual void setupMenus(Menu* menubar, MenuWrapper* menu);
QString addressForBookmark(const QString& name) const;
static const QString HOME_BOOKMARK;
protected:
virtual void addBookmarkToFile(const QString& bookmarkName, const QString& bookmarkAddress);
virtual void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) = 0;
void enableMenuItems(bool enabled);
void readFromFile();
void insert(const QString& name, const QString& address); // Overwrites any existing entry with same name.
void sortActions(Menu* menubar, MenuWrapper* menu);
int getMenuItemLocation(QList<QAction*> actions, const QString& name) const;
private slots:
void bookmarkLocation();
void setHomeLocation();
void teleportToBookmark();
void deleteBookmark();
private:
QVariantMap _bookmarks; // { name: address, ... }
QVariantMap _bookmarks; // { name: url, ... }
QPointer<MenuWrapper> _bookmarksMenu;
QPointer<QAction> _deleteBookmarksAction;
const QString BOOKMARKS_FILENAME = "bookmarks.json";
QString _bookmarksFilename;
void insert(const QString& name, const QString& address); // Overwrites any existing entry with same name.
bool _isMenuSorted;
protected slots:
void deleteBookmark();
private:
void remove(const QString& name);
bool contains(const QString& name) const;
static bool sortOrder(QAction* a, QAction* b);
void readFromFile();
void persistToFile();
void enableMenuItems(bool enabled);
void addLocationToMenu(Menu* menubar, QString& name, QString& address);
void removeLocationFromMenu(Menu* menubar, QString& name);
void removeBookmarkFromMenu(Menu* menubar, const QString& name);
};
#endif // hifi_Bookmarks_h
#endif // hifi_Bookmarks_h

View file

@ -0,0 +1,88 @@
//
// LocationBookmarks.cpp
// interface/src
//
// Created by Triplelexx on 23/03/17.
// Copyright 2017 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 <QAction>
#include <QInputDialog>
#include <QMessageBox>
#include <QStandardPaths>
#include <AddressManager.h>
#include <Application.h>
#include <OffscreenUi.h>
#include "MainWindow.h"
#include "Menu.h"
#include "LocationBookmarks.h"
#include <QtQuick/QQuickWindow>
const QString LocationBookmarks::HOME_BOOKMARK = "Home";
LocationBookmarks::LocationBookmarks() {
_bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + LOCATIONBOOKMARKS_FILENAME;
readFromFile();
}
void LocationBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
// Add menus/actions
auto bookmarkAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkLocation);
QObject::connect(bookmarkAction, SIGNAL(triggered()), this, SLOT(addBookmark()), Qt::QueuedConnection);
auto setHomeAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::SetHomeLocation);
QObject::connect(setHomeAction, SIGNAL(triggered()), this, SLOT(setHomeLocation()), Qt::QueuedConnection);
_bookmarksMenu = menu->addMenu(MenuOption::LocationBookmarks);
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark);
QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection);
Bookmarks::setupMenus(menubar, menu);
Bookmarks::sortActions(menubar, _bookmarksMenu);
}
void LocationBookmarks::setHomeLocation() {
auto addressManager = DependencyManager::get<AddressManager>();
QString bookmarkAddress = addressManager->currentAddress().toString();
Bookmarks::addBookmarkToFile(HOME_BOOKMARK, bookmarkAddress);
}
void LocationBookmarks::teleportToBookmark() {
QAction* action = qobject_cast<QAction*>(sender());
QString address = action->data().toString();
DependencyManager::get<AddressManager>()->handleLookupString(address);
}
void LocationBookmarks::addBookmark() {
bool ok = false;
auto bookmarkName = OffscreenUi::getText(OffscreenUi::ICON_PLACEMARK, "Bookmark Location", "Name", QString(), &ok);
if (!ok) {
return;
}
bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
if (bookmarkName.length() == 0) {
return;
}
auto addressManager = DependencyManager::get<AddressManager>();
QString bookmarkAddress = addressManager->currentAddress().toString();
Bookmarks::addBookmarkToFile(bookmarkName, bookmarkAddress);
}
void LocationBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) {
QAction* teleportAction = _bookmarksMenu->newAction();
teleportAction->setData(address);
connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark()));
if (!_isMenuSorted) {
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole);
} else {
// TODO: this is aggressive but other alternatives have proved less fruitful so far.
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole);
Bookmarks::sortActions(menubar, _bookmarksMenu);
}
}

View file

@ -0,0 +1,42 @@
//
// LocationBookmarks.h
// interface/src
//
// Created by Triplelexx on 23/03/17.
// Copyright 2017 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
//
#ifndef hifi_LocationBookmarks_h
#define hifi_LocationBookmarks_h
#include <DependencyManager.h>
#include "Bookmarks.h"
class LocationBookmarks : public Bookmarks, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
public:
LocationBookmarks();
void setupMenus(Menu* menubar, MenuWrapper* menu) override;
static const QString HOME_BOOKMARK;
public slots:
void addBookmark();
protected:
void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override;
private:
const QString LOCATIONBOOKMARKS_FILENAME = "bookmarks.json";
private slots:
void setHomeLocation();
void teleportToBookmark();
};
#endif // hifi_LocationBookmarks_h

View file

@ -32,6 +32,7 @@
#include "assets/ATPAssetMigrator.h"
#include "audio/AudioScope.h"
#include "avatar/AvatarManager.h"
#include "AvatarBookmarks.h"
#include "devices/DdeFaceTracker.h"
#include "devices/Faceshift.h"
#include "MainWindow.h"
@ -40,6 +41,7 @@
#include "ui/DialogsManager.h"
#include "ui/StandAloneJSConsole.h"
#include "InterfaceLogging.h"
#include "LocationBookmarks.h"
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
#include "SpeechRecognizer.h"
@ -194,6 +196,9 @@ Menu::Menu() {
0, // QML Qt::Key_Apostrophe,
qApp, SLOT(resetSensors()));
// Avatar > AvatarBookmarks related menus -- Note: the AvatarBookmarks class adds its own submenus here.
auto avatarBookmarks = DependencyManager::get<AvatarBookmarks>();
avatarBookmarks->setupMenus(this, avatarMenu);
// Display menu ----------------------------------
// FIXME - this is not yet matching Alan's spec because it doesn't have
@ -254,10 +259,11 @@ Menu::Menu() {
// Navigate > Show Address Bar
addActionToQMenuAndActionHash(navigateMenu, MenuOption::AddressBar, Qt::CTRL | Qt::Key_L,
dialogsManager.data(), SLOT(toggleAddressBar()));
dialogsManager.data(), SLOT(showAddressBar()));
// Navigate > Bookmark related menus -- Note: the Bookmark class adds its own submenus here.
qApp->getBookmarks()->setupMenus(this, navigateMenu);
// Navigate > LocationBookmarks related menus -- Note: the LocationBookmarks class adds its own submenus here.
auto locationBookmarks = DependencyManager::get<LocationBookmarks>();
locationBookmarks->setupMenus(this, navigateMenu);
// Navigate > Copy Address [advanced]
auto addressManager = DependencyManager::get<AddressManager>();

View file

@ -47,10 +47,11 @@ namespace MenuOption {
const QString AudioTools = "Show Level Meter";
const QString AutoMuteAudio = "Auto Mute Microphone";
const QString AvatarReceiveStats = "Show Receive Stats";
const QString AvatarBookmarks = "Avatar Bookmarks";
const QString Back = "Back";
const QString BinaryEyelidControl = "Binary Eyelid Control";
const QString BookmarkAvatar = "Bookmark Avatar";
const QString BookmarkLocation = "Bookmark Location";
const QString Bookmarks = "Bookmarks";
const QString CalibrateCamera = "Calibrate Camera";
const QString CameraEntityMode = "Entity Mode";
const QString CenterPlayerInView = "Center Player In View";
@ -78,6 +79,7 @@ namespace MenuOption {
const QString DeadlockInterface = "Deadlock Interface";
const QString DecreaseAvatarSize = "Decrease Avatar Size";
const QString DefaultSkybox = "Default Skybox";
const QString DeleteAvatarBookmark = "Delete Avatar Bookmark...";
const QString DeleteBookmark = "Delete Bookmark...";
const QString DisableActivityLogger = "Disable Activity Logger";
const QString DisableEyelidAdjustment = "Disable Eyelid Adjustment";
@ -89,6 +91,7 @@ namespace MenuOption {
const QString DisplayModelElementChildProxies = "Display Model Element Children";
const QString DisplayModelElementProxy = "Display Model Element Bounds";
const QString DisplayDebugTimingDetails = "Display Timing Details";
const QString LocationBookmarks = "Bookmarks";
const QString DontDoPrecisionPicking = "Don't Do Precision Picking";
const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene";
const QString EchoLocalAudio = "Echo Local Audio";

View file

@ -96,6 +96,14 @@ Avatar::Avatar(RigPointer rig) :
_lastOrientation(),
_worldUpDirection(DEFAULT_UP_DIRECTION),
_moving(false),
_smoothPositionTime(SMOOTH_TIME_POSITION),
_smoothPositionTimer(std::numeric_limits<float>::max()),
_smoothOrientationTime(SMOOTH_TIME_ORIENTATION),
_smoothOrientationTimer(std::numeric_limits<float>::max()),
_smoothPositionInitial(),
_smoothPositionTarget(),
_smoothOrientationInitial(),
_smoothOrientationTarget(),
_initialized(false),
_voiceSphereID(GeometryCache::UNKNOWN_ID)
{
@ -349,6 +357,33 @@ void Avatar::simulate(float deltaTime, bool inView) {
_simulationInViewRate.increment();
}
if (!isMyAvatar()) {
if (_smoothPositionTimer < _smoothPositionTime) {
// Smooth the remote avatar movement.
_smoothPositionTimer += deltaTime;
if (_smoothPositionTimer < _smoothPositionTime) {
AvatarData::setPosition(
lerp(_smoothPositionInitial,
_smoothPositionTarget,
easeInOutQuad(glm::clamp(_smoothPositionTimer / _smoothPositionTime, 0.0f, 1.0f)))
);
updateAttitude();
}
}
if (_smoothOrientationTimer < _smoothOrientationTime) {
// Smooth the remote avatar movement.
_smoothOrientationTimer += deltaTime;
if (_smoothOrientationTimer < _smoothOrientationTime) {
AvatarData::setOrientation(
slerp(_smoothOrientationInitial,
_smoothOrientationTarget,
easeInOutQuad(glm::clamp(_smoothOrientationTimer / _smoothOrientationTime, 0.0f, 1.0f)))
);
updateAttitude();
}
}
}
PerformanceTimer perfTimer("simulate");
{
@ -1361,13 +1396,31 @@ glm::quat Avatar::getUncachedRightPalmRotation() const {
}
void Avatar::setPosition(const glm::vec3& position) {
AvatarData::setPosition(position);
updateAttitude();
if (isMyAvatar()) {
// This is the local avatar, no need to handle any position smoothing.
AvatarData::setPosition(position);
updateAttitude();
return;
}
// Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position.
_smoothPositionInitial = getPosition();
_smoothPositionTarget = position;
_smoothPositionTimer = 0.0f;
}
void Avatar::setOrientation(const glm::quat& orientation) {
AvatarData::setOrientation(orientation);
updateAttitude();
if (isMyAvatar()) {
// This is the local avatar, no need to handle any position smoothing.
AvatarData::setOrientation(orientation);
updateAttitude();
return;
}
// Whether or not there is an existing smoothing going on, just reset the smoothing timer and set the starting position as the avatar's current position, then smooth to the new position.
_smoothOrientationInitial = getOrientation();
_smoothOrientationTarget = orientation;
_smoothOrientationTimer = 0.0f;
}
void Avatar::updatePalms() {

View file

@ -230,6 +230,16 @@ public:
bool hasNewJointData() const { return _hasNewJointData; }
inline float easeInOutQuad(float lerpValue) {
assert(!((lerpValue < 0.0f) || (lerpValue > 1.0f)));
if (lerpValue < 0.5f) {
return (2.0f * lerpValue * lerpValue);
}
return (lerpValue*(4.0f - 2.0f * lerpValue) - 1.0f);
}
public slots:
// FIXME - these should be migrated to use Pose data instead
@ -244,6 +254,9 @@ public slots:
protected:
friend class AvatarManager;
const float SMOOTH_TIME_POSITION = 0.125f;
const float SMOOTH_TIME_ORIENTATION = 0.075f;
virtual const QString& getSessionDisplayNameForTransport() const override { return _empty; } // Save a tiny bit of bandwidth. Mixer won't look at what we send.
QString _empty{};
virtual void maybeUpdateSessionDisplayNameFromTransport(const QString& sessionDisplayName) override { _sessionDisplayName = sessionDisplayName; } // don't use no-op setter!
@ -313,6 +326,15 @@ protected:
RateCounter<> _skeletonModelSimulationRate;
RateCounter<> _jointDataSimulationRate;
// Smoothing data for blending from one position/orientation to another on remote agents.
float _smoothPositionTime;
float _smoothPositionTimer;
float _smoothOrientationTime;
float _smoothOrientationTimer;
glm::vec3 _smoothPositionInitial;
glm::vec3 _smoothPositionTarget;
glm::quat _smoothOrientationInitial;
glm::quat _smoothOrientationTarget;
private:
class AvatarEntityDataHash {

View file

@ -34,9 +34,13 @@ void HFTabletWebEngineRequestInterceptor::interceptRequest(QWebEngineUrlRequestI
QString bearerTokenString = "Bearer " + accountManager->getAccountInfo().getAccessToken().token;
info.setHttpHeader(OAUTH_AUTHORIZATION_HEADER.toLocal8Bit(), bearerTokenString.toLocal8Bit());
}
}
static const QString USER_AGENT = "User-Agent";
QString tokenString = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36";
info.setHttpHeader(USER_AGENT.toLocal8Bit(), tokenString.toLocal8Bit());
static const QString USER_AGENT = "User-Agent";
QString tokenString = "Chrome/48.0 (HighFidelityInterface)";
info.setHttpHeader(USER_AGENT.toLocal8Bit(), tokenString.toLocal8Bit());
} else {
static const QString USER_AGENT = "User-Agent";
QString tokenString = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Mobile Safari/537.36";
info.setHttpHeader(USER_AGENT.toLocal8Bit(), tokenString.toLocal8Bit());
}
}

View file

@ -16,15 +16,24 @@
#include "ui/DialogsManager.h"
DialogsManagerScriptingInterface::DialogsManagerScriptingInterface() {
connect(DependencyManager::get<DialogsManager>().data(), &DialogsManager::addressBarToggled,
this, &DialogsManagerScriptingInterface::addressBarToggled);
connect(DependencyManager::get<DialogsManager>().data(), &DialogsManager::addressBarShown,
this, &DialogsManagerScriptingInterface::addressBarShown);
}
void DialogsManagerScriptingInterface::toggleAddressBar() {
DialogsManagerScriptingInterface* DialogsManagerScriptingInterface::getInstance() {
static DialogsManagerScriptingInterface sharedInstance;
return &sharedInstance;
}
void DialogsManagerScriptingInterface::showAddressBar() {
QMetaObject::invokeMethod(DependencyManager::get<DialogsManager>().data(),
"toggleAddressBar", Qt::QueuedConnection);
"showAddressBar", Qt::QueuedConnection);
}
void DialogsManagerScriptingInterface::hideAddressBar() {
QMetaObject::invokeMethod(DependencyManager::get<DialogsManager>().data(),
"hideAddressBar", Qt::QueuedConnection);
}
void DialogsManagerScriptingInterface::showFeed() {

View file

@ -18,13 +18,14 @@ class DialogsManagerScriptingInterface : public QObject {
Q_OBJECT
public:
DialogsManagerScriptingInterface();
static DialogsManagerScriptingInterface* getInstance();
Q_INVOKABLE void showFeed();
public slots:
void toggleAddressBar();
void showAddressBar();
void hideAddressBar();
signals:
void addressBarToggled();
void addressBarShown(bool visible);
};

View file

@ -17,6 +17,7 @@
#include "DependencyManager.h"
#include "AddressManager.h"
#include "DialogsManager.h"
#include "LocationBookmarks.h"
HIFI_QML_DEF(AddressBarDialog)
@ -52,7 +53,8 @@ void AddressBarDialog::loadAddress(const QString& address, bool fromSuggestions)
void AddressBarDialog::loadHome() {
qDebug() << "Called LoadHome";
QString homeLocation = qApp->getBookmarks()->addressForBookmark(Bookmarks::HOME_BOOKMARK);
auto locationBookmarks = DependencyManager::get<LocationBookmarks>();
QString homeLocation = locationBookmarks->addressForBookmark(LocationBookmarks::HOME_BOOKMARK);
const QString DEFAULT_HOME_LOCATION = "localhost";
if (homeLocation == "") {
homeLocation = DEFAULT_HOME_LOCATION;

View file

@ -46,49 +46,32 @@ void DialogsManager::maybeCreateDialog(QPointer<T>& member) {
}
}
void DialogsManager::toggleAddressBar() {
auto hmd = DependencyManager::get<HMDScriptingInterface>();
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
if (tablet->getToolbarMode()) {
if (tablet->isPathLoaded(TABLET_ADDRESS_DIALOG)) {
tablet->gotoHomeScreen();
emit addressBarToggled();
} else {
tablet->loadQMLSource(TABLET_ADDRESS_DIALOG);
emit addressBarToggled();
}
} else {
if (hmd->getShouldShowTablet()) {
if (tablet->isPathLoaded(TABLET_ADDRESS_DIALOG) && _closeAddressBar) {
tablet->gotoHomeScreen();
hmd->closeTablet();
_closeAddressBar = false;
emit addressBarToggled();
} else {
tablet->loadQMLSource(TABLET_ADDRESS_DIALOG);
_closeAddressBar = true;
emit addressBarToggled();
}
} else {
tablet->loadQMLSource(TABLET_ADDRESS_DIALOG);
hmd->openTablet();
_closeAddressBar = true;
emit addressBarToggled();
}
}
}
void DialogsManager::showAddressBar() {
auto hmd = DependencyManager::get<HMDScriptingInterface>();
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
tablet->loadQMLSource(TABLET_ADDRESS_DIALOG);
if (!tablet->isPathLoaded(TABLET_ADDRESS_DIALOG)) {
tablet->loadQMLSource(TABLET_ADDRESS_DIALOG);
}
if (!hmd->getShouldShowTablet()) {
hmd->openTablet();
}
qApp->setKeyboardFocusOverlay(hmd->getCurrentTabletScreenID());
emit addressBarShown(true);
}
void DialogsManager::hideAddressBar() {
auto hmd = DependencyManager::get<HMDScriptingInterface>();
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
auto tablet = dynamic_cast<TabletProxy*>(tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system"));
if (tablet->isPathLoaded(TABLET_ADDRESS_DIALOG)) {
tablet->gotoHomeScreen();
hmd->closeTablet();
}
qApp->setKeyboardFocusOverlay(UNKNOWN_OVERLAY_ID);
emit addressBarShown(false);
}
void DialogsManager::showFeed() {

View file

@ -41,8 +41,8 @@ public:
void emitAddressBarShown(bool visible) { emit addressBarShown(visible); }
public slots:
void toggleAddressBar();
void showAddressBar();
void hideAddressBar();
void showFeed();
void setDomainConnectionFailureVisibility(bool visible);
void toggleLoginDialog();
@ -57,7 +57,6 @@ public slots:
void showUpdateDialog();
signals:
void addressBarToggled();
void addressBarShown(bool visible);
void setUseFeed(bool useFeed);

View file

@ -40,6 +40,9 @@ void SnapshotUploader::uploadSuccess(QNetworkReply& reply) {
QJsonObject userStoryObject;
QJsonObject detailsObject;
detailsObject.insert("image_url", imageUrl);
if (dataObject.contains("shareable_url")) {
detailsObject.insert("shareable_url", dataObject.value("shareable_url").toString());
}
QString pickledDetails = QJsonDocument(detailsObject).toJson();
userStoryObject.insert("details", pickledDetails);
userStoryObject.insert("thumbnail_url", thumbnailUrl);

View file

@ -198,6 +198,7 @@ void Web3DOverlay::loadSourceURL() {
_webSurface->getRootContext()->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
_webSurface->getRootContext()->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
_webSurface->getRootContext()->setContextProperty("AvatarList", DependencyManager::get<AvatarManager>().data());
_webSurface->getRootContext()->setContextProperty("DialogsManager", DialogsManagerScriptingInterface::getInstance());
_webSurface->getRootContext()->setContextProperty("pathToFonts", "../../");
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface->getRootItem(), _webSurface.data());

View file

@ -41,7 +41,7 @@ public:
Q_INVOKABLE QVector<QUuid> getAvatarIdentifiers();
// Null/Default-constructed QUuids will return MyAvatar
virtual ScriptAvatarData* getAvatar(QUuid avatarID) { return new ScriptAvatarData(getAvatarBySessionID(avatarID)); }
Q_INVOKABLE virtual ScriptAvatarData* getAvatar(QUuid avatarID) { return new ScriptAvatarData(getAvatarBySessionID(avatarID)); }
virtual AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) const { return findAvatar(sessionID); }
int numberOfAvatarsInRange(const glm::vec3& position, float rangeMeters);