mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 07:23:00 +02:00
Merge pull request #11815 from zfox23/commerce_QmlWhitelist
QML Whitelisting + Commerce Integration
This commit is contained in:
commit
297a3df63c
73 changed files with 907 additions and 910 deletions
|
@ -12,8 +12,10 @@ function(JOIN VALUES GLUE OUTPUT)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
|
||||||
set(INTERFACE_QML_QRC ${CMAKE_CURRENT_BINARY_DIR}/qml.qrc)
|
if (NOT DEV_BUILD)
|
||||||
generate_qrc(OUTPUT ${INTERFACE_QML_QRC} PATH ${CMAKE_CURRENT_SOURCE_DIR}/resources GLOBS *.qml *.qss *.js *.html *.ttf *.gif *.svg *.png *.jpg)
|
set(INTERFACE_QML_QRC ${CMAKE_CURRENT_BINARY_DIR}/qml.qrc)
|
||||||
|
generate_qrc(OUTPUT ${INTERFACE_QML_QRC} PATH ${CMAKE_CURRENT_SOURCE_DIR}/resources GLOBS *.qml *.qss *.js *.html *.ttf *.gif *.svg *.png *.jpg)
|
||||||
|
endif()
|
||||||
|
|
||||||
# set a default root dir for each of our optional externals if it was not passed
|
# set a default root dir for each of our optional externals if it was not passed
|
||||||
set(OPTIONAL_EXTERNALS "LeapMotion")
|
set(OPTIONAL_EXTERNALS "LeapMotion")
|
||||||
|
@ -80,7 +82,9 @@ qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}")
|
||||||
# add them to the interface source files
|
# add them to the interface source files
|
||||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}")
|
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${QT_UI_HEADERS}" "${QT_RESOURCES}")
|
||||||
|
|
||||||
|
if (NOT DEV_BUILD)
|
||||||
list(APPEND INTERFACE_SRCS ${INTERFACE_QML_QRC})
|
list(APPEND INTERFACE_SRCS ${INTERFACE_QML_QRC})
|
||||||
|
endif()
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
install(
|
install(
|
||||||
|
|
18
interface/resources/qml/OverlayWindowTest.qml
Normal file
18
interface/resources/qml/OverlayWindowTest.qml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 100
|
||||||
|
height: 100
|
||||||
|
color: "white"
|
||||||
|
Rectangle {
|
||||||
|
width: 10
|
||||||
|
height: 10
|
||||||
|
color: "red"
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
text: OverlayWindowTestString
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,6 @@ Windows.Window {
|
||||||
// Don't destroy on close... otherwise the JS/C++ will have a dangling pointer
|
// Don't destroy on close... otherwise the JS/C++ will have a dangling pointer
|
||||||
destroyOnCloseButton: false
|
destroyOnCloseButton: false
|
||||||
property var source;
|
property var source;
|
||||||
property var component;
|
|
||||||
property var dynamicContent;
|
property var dynamicContent;
|
||||||
|
|
||||||
// Keyboard control properties in case needed by QML content.
|
// Keyboard control properties in case needed by QML content.
|
||||||
|
@ -35,28 +34,9 @@ Windows.Window {
|
||||||
dynamicContent.destroy();
|
dynamicContent.destroy();
|
||||||
dynamicContent = null;
|
dynamicContent = null;
|
||||||
}
|
}
|
||||||
component = Qt.createComponent(source);
|
QmlSurface.load(source, contentHolder, function(newObject) {
|
||||||
console.log("Created component " + component + " from source " + source);
|
dynamicContent = newObject;
|
||||||
}
|
});
|
||||||
|
|
||||||
onComponentChanged: {
|
|
||||||
console.log("Component changed to " + component)
|
|
||||||
populate();
|
|
||||||
}
|
|
||||||
|
|
||||||
function populate() {
|
|
||||||
console.log("Populate called: dynamicContent " + dynamicContent + " component " + component);
|
|
||||||
if (!dynamicContent && component) {
|
|
||||||
if (component.status == Component.Error) {
|
|
||||||
console.log("Error loading component:", component.errorString());
|
|
||||||
} else if (component.status == Component.Ready) {
|
|
||||||
console.log("Building dynamic content");
|
|
||||||
dynamicContent = component.createObject(contentHolder);
|
|
||||||
} else {
|
|
||||||
console.log("Component not yet ready, connecting to status change");
|
|
||||||
component.statusChanged.connect(populate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle message traffic from the script that launched us to the loaded QML
|
// Handle message traffic from the script that launched us to the loaded QML
|
||||||
|
|
|
@ -29,12 +29,12 @@ Original.Button {
|
||||||
|
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
style: ButtonStyle {
|
style: ButtonStyle {
|
||||||
|
|
|
@ -31,12 +31,12 @@ Original.CheckBox {
|
||||||
activeFocusOnPress: true
|
activeFocusOnPress: true
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: doesnt works for QQC1. check with QQC2
|
// TODO: doesnt works for QQC1. check with QQC2
|
||||||
// onHovered: {
|
// onHovered: {
|
||||||
// tabletInterface.playSound(TabletEnums.ButtonHover);
|
// Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
style: CheckBoxStyle {
|
style: CheckBoxStyle {
|
||||||
|
|
|
@ -36,12 +36,12 @@ CheckBox {
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,12 +27,12 @@ Original.Button {
|
||||||
|
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
style: ButtonStyle {
|
style: ButtonStyle {
|
||||||
|
|
|
@ -41,13 +41,13 @@ Item {
|
||||||
|
|
||||||
onContainsMouseChanged: {
|
onContainsMouseChanged: {
|
||||||
if (containsMouse) {
|
if (containsMouse) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
mouse.accepted = true;
|
mouse.accepted = true;
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
|
|
||||||
webEntity.synthesizeKeyPress(glyph);
|
webEntity.synthesizeKeyPress(glyph);
|
||||||
webEntity.synthesizeKeyPress(glyph, mirrorText);
|
webEntity.synthesizeKeyPress(glyph, mirrorText);
|
||||||
|
|
|
@ -30,12 +30,12 @@ Original.RadioButton {
|
||||||
readonly property int checkRadius: 2
|
readonly property int checkRadius: 2
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: doesnt works for QQC1. check with QQC2
|
// TODO: doesnt works for QQC1. check with QQC2
|
||||||
// onHovered: {
|
// onHovered: {
|
||||||
// tabletInterface.playSound(TabletEnums.ButtonHover);
|
// Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
style: RadioButtonStyle {
|
style: RadioButtonStyle {
|
||||||
|
|
|
@ -49,7 +49,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WebEngineView.LoadFailedStatus === loadRequest.status) {
|
if (WebEngineView.LoadFailedStatus === loadRequest.status) {
|
||||||
console.log(" Tablet WebEngineView failed to load url: " + loadRequest.url.toString());
|
console.log("Tablet WebEngineView failed to load url: " + loadRequest.url.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WebEngineView.LoadSucceededStatus === loadRequest.status) {
|
if (WebEngineView.LoadSucceededStatus === loadRequest.status) {
|
||||||
|
|
|
@ -25,13 +25,13 @@ Preference {
|
||||||
id: button
|
id: button
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
preference.trigger();
|
preference.trigger();
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
width: 180
|
width: 180
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
|
|
|
@ -41,12 +41,12 @@ Preference {
|
||||||
id: checkBox
|
id: checkBox
|
||||||
onHoveredChanged: {
|
onHoveredChanged: {
|
||||||
if (hovered) {
|
if (hovered) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
anchors {
|
anchors {
|
||||||
|
|
|
@ -246,12 +246,12 @@ Item {
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
acceptedButtons: Qt.LeftButton;
|
acceptedButtons: Qt.LeftButton;
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
goFunction("hifi://" + hifiUrl);
|
goFunction("hifi://" + hifiUrl);
|
||||||
}
|
}
|
||||||
hoverEnabled: true;
|
hoverEnabled: true;
|
||||||
onEntered: {
|
onEntered: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
hoverThunk();
|
hoverThunk();
|
||||||
}
|
}
|
||||||
onExited: unhoverThunk();
|
onExited: unhoverThunk();
|
||||||
|
@ -269,7 +269,7 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function go() {
|
function go() {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
goFunction(drillDownToPlace ? ("/places/" + placeName) : ("/user_stories/" + storyId));
|
goFunction(drillDownToPlace ? ("/places/" + placeName) : ("/user_stories/" + storyId));
|
||||||
}
|
}
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|
|
@ -45,11 +45,13 @@ OriginalDesktop.Desktop {
|
||||||
Toolbar {
|
Toolbar {
|
||||||
id: sysToolbar;
|
id: sysToolbar;
|
||||||
objectName: "com.highfidelity.interface.toolbar.system";
|
objectName: "com.highfidelity.interface.toolbar.system";
|
||||||
|
property var tablet: Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||||
anchors.horizontalCenter: settings.constrainToolbarToCenterX ? desktop.horizontalCenter : undefined;
|
anchors.horizontalCenter: settings.constrainToolbarToCenterX ? desktop.horizontalCenter : undefined;
|
||||||
// Literal 50 is overwritten by settings from previous session, and sysToolbar.x comes from settings when not constrained.
|
// Literal 50 is overwritten by settings from previous session, and sysToolbar.x comes from settings when not constrained.
|
||||||
x: sysToolbar.x
|
x: sysToolbar.x
|
||||||
y: 50
|
y: 50
|
||||||
shown: true
|
buttonModel: tablet.buttons;
|
||||||
|
shown: tablet.toolbarMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings {
|
Settings {
|
||||||
|
|
|
@ -61,12 +61,12 @@ Rectangle {
|
||||||
scrollGestureEnabled: false;
|
scrollGestureEnabled: false;
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Audio.muted = !Audio.muted;
|
Audio.muted = !Audio.muted;
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
drag.target: dragTarget;
|
drag.target: dragTarget;
|
||||||
onContainsMouseChanged: {
|
onContainsMouseChanged: {
|
||||||
if (containsMouse) {
|
if (containsMouse) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,8 +43,8 @@ Rectangle {
|
||||||
property bool isWearable;
|
property bool isWearable;
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.white;
|
color: hifi.colors.white;
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onWalletStatusResult: {
|
onWalletStatusResult: {
|
||||||
if (walletStatus === 0) {
|
if (walletStatus === 0) {
|
||||||
|
@ -72,7 +72,7 @@ Rectangle {
|
||||||
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
||||||
root.activeView = "needsLogIn";
|
root.activeView = "needsLogIn";
|
||||||
} else {
|
} else {
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemIdChanged: {
|
onItemIdChanged: {
|
||||||
commerce.inventory();
|
Commerce.inventory();
|
||||||
itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg";
|
itemPreviewImage.source = "https://hifi-metaverse.s3-us-west-1.amazonaws.com/marketplace/previews/" + itemId + "/thumbnail/hifi-mp-" + itemId + ".jpg";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
onItemPriceChanged: {
|
onItemPriceChanged: {
|
||||||
commerce.balance();
|
Commerce.balance();
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer {
|
Timer {
|
||||||
|
@ -203,7 +203,7 @@ Rectangle {
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
purchasesReceived = false;
|
purchasesReceived = false;
|
||||||
balanceReceived = false;
|
balanceReceived = false;
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +224,7 @@ Rectangle {
|
||||||
Connections {
|
Connections {
|
||||||
target: GlobalServices
|
target: GlobalServices
|
||||||
onMyUsernameChanged: {
|
onMyUsernameChanged: {
|
||||||
commerce.getLoginStatus();
|
Commerce.getLoginStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,9 +474,9 @@ Rectangle {
|
||||||
if (itemIsJson) {
|
if (itemIsJson) {
|
||||||
buyButton.enabled = false;
|
buyButton.enabled = false;
|
||||||
if (!root.shouldBuyWithControlledFailure) {
|
if (!root.shouldBuyWithControlledFailure) {
|
||||||
commerce.buy(itemId, itemPrice);
|
Commerce.buy(itemId, itemPrice);
|
||||||
} else {
|
} else {
|
||||||
commerce.buy(itemId, itemPrice, true);
|
Commerce.buy(itemId, itemPrice, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (urlHandler.canHandleUrl(itemHref)) {
|
if (urlHandler.canHandleUrl(itemHref)) {
|
||||||
|
@ -940,8 +940,8 @@ Rectangle {
|
||||||
}
|
}
|
||||||
root.balanceReceived = false;
|
root.balanceReceived = false;
|
||||||
root.purchasesReceived = false;
|
root.purchasesReceived = false;
|
||||||
commerce.inventory();
|
Commerce.inventory();
|
||||||
commerce.balance();
|
Commerce.balance();
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -31,14 +31,14 @@ Item {
|
||||||
|
|
||||||
height: mainContainer.height + additionalDropdownHeight;
|
height: mainContainer.height + additionalDropdownHeight;
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onWalletStatusResult: {
|
onWalletStatusResult: {
|
||||||
if (walletStatus === 0) {
|
if (walletStatus === 0) {
|
||||||
sendToParent({method: "needsLogIn"});
|
sendToParent({method: "needsLogIn"});
|
||||||
} else if (walletStatus === 3) {
|
} else if (walletStatus === 3) {
|
||||||
commerce.getSecurityImage();
|
Commerce.getSecurityImage();
|
||||||
} else if (walletStatus > 3) {
|
} else if (walletStatus > 3) {
|
||||||
console.log("ERROR in EmulatedMarketplaceHeader.qml: Unknown wallet status: " + walletStatus);
|
console.log("ERROR in EmulatedMarketplaceHeader.qml: Unknown wallet status: " + walletStatus);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ Item {
|
||||||
if (!isLoggedIn) {
|
if (!isLoggedIn) {
|
||||||
sendToParent({method: "needsLogIn"});
|
sendToParent({method: "needsLogIn"});
|
||||||
} else {
|
} else {
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,13 +61,13 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: GlobalServices
|
target: GlobalServices
|
||||||
onMyUsernameChanged: {
|
onMyUsernameChanged: {
|
||||||
commerce.getLoginStatus();
|
Commerce.getLoginStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,8 @@ Rectangle {
|
||||||
property bool isCertificateInvalid: false;
|
property bool isCertificateInvalid: false;
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.faintGray;
|
color: hifi.colors.faintGray;
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onCertificateInfoResult: {
|
onCertificateInfoResult: {
|
||||||
if (result.status !== 'success') {
|
if (result.status !== 'success') {
|
||||||
|
@ -109,7 +109,7 @@ Rectangle {
|
||||||
|
|
||||||
onCertificateIdChanged: {
|
onCertificateIdChanged: {
|
||||||
if (certificateId !== "") {
|
if (certificateId !== "") {
|
||||||
commerce.certificateInfo(certificateId);
|
Commerce.certificateInfo(certificateId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,8 @@ Rectangle {
|
||||||
property bool isDebuggingFirstUseTutorial: false;
|
property bool isDebuggingFirstUseTutorial: false;
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.white;
|
color: hifi.colors.white;
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onWalletStatusResult: {
|
onWalletStatusResult: {
|
||||||
if (walletStatus === 0) {
|
if (walletStatus === 0) {
|
||||||
|
@ -61,7 +61,7 @@ Rectangle {
|
||||||
root.activeView = "firstUseTutorial";
|
root.activeView = "firstUseTutorial";
|
||||||
} else if (!Settings.getValue("isFirstUseOfPurchases", true) && root.activeView === "initialize") {
|
} else if (!Settings.getValue("isFirstUseOfPurchases", true) && root.activeView === "initialize") {
|
||||||
root.activeView = "purchasesMain";
|
root.activeView = "purchasesMain";
|
||||||
commerce.inventory();
|
Commerce.inventory();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("ERROR in Purchases.qml: Unknown wallet status: " + walletStatus);
|
console.log("ERROR in Purchases.qml: Unknown wallet status: " + walletStatus);
|
||||||
|
@ -72,7 +72,7 @@ Rectangle {
|
||||||
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
||||||
root.activeView = "needsLogIn";
|
root.activeView = "needsLogIn";
|
||||||
} else {
|
} else {
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ Rectangle {
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
securityImageResultReceived = false;
|
securityImageResultReceived = false;
|
||||||
purchasesReceived = false;
|
purchasesReceived = false;
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ Rectangle {
|
||||||
Connections {
|
Connections {
|
||||||
target: GlobalServices
|
target: GlobalServices
|
||||||
onMyUsernameChanged: {
|
onMyUsernameChanged: {
|
||||||
commerce.getLoginStatus();
|
Commerce.getLoginStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ Rectangle {
|
||||||
onSendSignalToParent: {
|
onSendSignalToParent: {
|
||||||
if (msg.method === "authSuccess") {
|
if (msg.method === "authSuccess") {
|
||||||
root.activeView = "initialize";
|
root.activeView = "initialize";
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
} else {
|
} else {
|
||||||
sendToScript(msg);
|
sendToScript(msg);
|
||||||
}
|
}
|
||||||
|
@ -255,7 +255,7 @@ Rectangle {
|
||||||
case 'tutorial_finished':
|
case 'tutorial_finished':
|
||||||
Settings.setValue("isFirstUseOfPurchases", false);
|
Settings.setValue("isFirstUseOfPurchases", false);
|
||||||
root.activeView = "purchasesMain";
|
root.activeView = "purchasesMain";
|
||||||
commerce.inventory();
|
Commerce.inventory();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -595,7 +595,7 @@ Rectangle {
|
||||||
if (root.activeView === "purchasesMain" && !root.pendingInventoryReply) {
|
if (root.activeView === "purchasesMain" && !root.pendingInventoryReply) {
|
||||||
console.log("Refreshing Purchases...");
|
console.log("Refreshing Purchases...");
|
||||||
root.pendingInventoryReply = true;
|
root.pendingInventoryReply = true;
|
||||||
commerce.inventory();
|
Commerce.inventory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ Item {
|
||||||
property string keyFilePath;
|
property string keyFilePath;
|
||||||
property bool showDebugButtons: true;
|
property bool showDebugButtons: true;
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onKeyFilePathIfExistsResult: {
|
onKeyFilePathIfExistsResult: {
|
||||||
root.keyFilePath = path;
|
root.keyFilePath = path;
|
||||||
|
@ -37,7 +37,7 @@ Item {
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
commerce.getKeyFilePathIfExists();
|
Commerce.getKeyFilePathIfExists();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,37 @@ Item {
|
||||||
// Style
|
// Style
|
||||||
color: hifi.colors.blueHighlight;
|
color: hifi.colors.blueHighlight;
|
||||||
}
|
}
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: clearCachedPassphraseButton;
|
||||||
|
visible: root.showDebugButtons;
|
||||||
|
color: hifi.buttons.black;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.top: parent.top;
|
||||||
|
anchors.left: helpTitleText.right;
|
||||||
|
anchors.leftMargin: 20;
|
||||||
|
height: 40;
|
||||||
|
width: 150;
|
||||||
|
text: "DBG: Clear Pass";
|
||||||
|
onClicked: {
|
||||||
|
Commerce.setPassphrase("");
|
||||||
|
sendSignalToWallet({method: 'passphraseReset'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HifiControlsUit.Button {
|
||||||
|
id: resetButton;
|
||||||
|
visible: root.showDebugButtons;
|
||||||
|
color: hifi.buttons.red;
|
||||||
|
colorScheme: hifi.colorSchemes.dark;
|
||||||
|
anchors.top: clearCachedPassphraseButton.top;
|
||||||
|
anchors.left: clearCachedPassphraseButton.right;
|
||||||
|
height: 40;
|
||||||
|
width: 150;
|
||||||
|
text: "DBG: RST Wallet";
|
||||||
|
onClicked: {
|
||||||
|
Commerce.reset();
|
||||||
|
sendSignalToWallet({method: 'walletReset'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ListModel {
|
ListModel {
|
||||||
id: helpModel;
|
id: helpModel;
|
||||||
|
|
|
@ -30,8 +30,8 @@ Item {
|
||||||
source: "images/wallet-bg.jpg";
|
source: "images/wallet-bg.jpg";
|
||||||
}
|
}
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -36,8 +36,8 @@ Item {
|
||||||
source: "images/wallet-bg.jpg";
|
source: "images/wallet-bg.jpg";
|
||||||
}
|
}
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onSecurityImageResult: {
|
onSecurityImageResult: {
|
||||||
titleBarSecurityImage.source = "";
|
titleBarSecurityImage.source = "";
|
||||||
|
@ -210,7 +210,7 @@ Item {
|
||||||
|
|
||||||
onAccepted: {
|
onAccepted: {
|
||||||
submitPassphraseInputButton.enabled = false;
|
submitPassphraseInputButton.enabled = false;
|
||||||
commerce.setPassphrase(passphraseField.text);
|
Commerce.setPassphrase(passphraseField.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ Item {
|
||||||
source: "image://security/securityImage";
|
source: "image://security/securityImage";
|
||||||
cache: false;
|
cache: false;
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
commerce.getSecurityImage();
|
Commerce.getSecurityImage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item {
|
Item {
|
||||||
|
@ -318,7 +318,7 @@ Item {
|
||||||
text: "Submit"
|
text: "Submit"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
submitPassphraseInputButton.enabled = false;
|
submitPassphraseInputButton.enabled = false;
|
||||||
commerce.setPassphrase(passphraseField.text);
|
Commerce.setPassphrase(passphraseField.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,8 @@ Item {
|
||||||
propagateComposedEvents: false;
|
propagateComposedEvents: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
onSecurityImageResult: {
|
onSecurityImageResult: {
|
||||||
passphrasePageSecurityImage.source = "";
|
passphrasePageSecurityImage.source = "";
|
||||||
passphrasePageSecurityImage.source = "image://security/securityImage";
|
passphrasePageSecurityImage.source = "image://security/securityImage";
|
||||||
|
@ -160,7 +160,7 @@ Item {
|
||||||
source: "image://security/securityImage";
|
source: "image://security/securityImage";
|
||||||
cache: false;
|
cache: false;
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
commerce.getSecurityImage();
|
Commerce.getSecurityImage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Item {
|
Item {
|
||||||
|
@ -283,7 +283,7 @@ Item {
|
||||||
passphraseFieldAgain.error = false;
|
passphraseFieldAgain.error = false;
|
||||||
currentPassphraseField.error = false;
|
currentPassphraseField.error = false;
|
||||||
setErrorText("");
|
setErrorText("");
|
||||||
commerce.changePassphrase(currentPassphraseField.text, passphraseField.text);
|
Commerce.changePassphrase(currentPassphraseField.text, passphraseField.text);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ Item {
|
||||||
id: root;
|
id: root;
|
||||||
property string keyFilePath;
|
property string keyFilePath;
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onKeyFilePathIfExistsResult: {
|
onKeyFilePathIfExistsResult: {
|
||||||
root.keyFilePath = path;
|
root.keyFilePath = path;
|
||||||
|
@ -234,7 +234,7 @@ Item {
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
commerce.getKeyFilePathIfExists();
|
Commerce.getKeyFilePathIfExists();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,8 @@ Item {
|
||||||
id: root;
|
id: root;
|
||||||
property bool justSubmitted: false;
|
property bool justSubmitted: false;
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onSecurityImageResult: {
|
onSecurityImageResult: {
|
||||||
securityImageChangePageSecurityImage.source = "";
|
securityImageChangePageSecurityImage.source = "";
|
||||||
|
|
|
@ -25,8 +25,8 @@ Item {
|
||||||
|
|
||||||
id: root;
|
id: root;
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Unavailable"
|
// "Unavailable"
|
||||||
|
|
|
@ -31,13 +31,15 @@ Rectangle {
|
||||||
property bool keyboardRaised: false;
|
property bool keyboardRaised: false;
|
||||||
property bool isPassword: false;
|
property bool isPassword: false;
|
||||||
|
|
||||||
|
anchors.fill: (typeof parent === undefined) ? undefined : parent;
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
anchors.fill: parent;
|
anchors.fill: parent;
|
||||||
source: "images/wallet-bg.jpg";
|
source: "images/wallet-bg.jpg";
|
||||||
}
|
}
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onWalletStatusResult: {
|
onWalletStatusResult: {
|
||||||
if (walletStatus === 0) {
|
if (walletStatus === 0) {
|
||||||
|
@ -47,7 +49,7 @@ Rectangle {
|
||||||
} else if (walletStatus === 1) {
|
} else if (walletStatus === 1) {
|
||||||
if (root.activeView !== "walletSetup") {
|
if (root.activeView !== "walletSetup") {
|
||||||
root.activeView = "walletSetup";
|
root.activeView = "walletSetup";
|
||||||
commerce.resetLocalWalletOnly();
|
Commerce.resetLocalWalletOnly();
|
||||||
var timestamp = new Date();
|
var timestamp = new Date();
|
||||||
walletSetup.startingTimestamp = timestamp;
|
walletSetup.startingTimestamp = timestamp;
|
||||||
walletSetup.setupAttemptID = generateUUID();
|
walletSetup.setupAttemptID = generateUUID();
|
||||||
|
@ -60,8 +62,10 @@ Rectangle {
|
||||||
UserActivityLogger.commercePassphraseEntry("wallet app");
|
UserActivityLogger.commercePassphraseEntry("wallet app");
|
||||||
}
|
}
|
||||||
} else if (walletStatus === 3) {
|
} else if (walletStatus === 3) {
|
||||||
root.activeView = "walletHome";
|
if (root.activeView !== "walletSetup") {
|
||||||
commerce.getSecurityImage();
|
root.activeView = "walletHome";
|
||||||
|
Commerce.getSecurityImage();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("ERROR in Wallet.qml: Unknown wallet status: " + walletStatus);
|
console.log("ERROR in Wallet.qml: Unknown wallet status: " + walletStatus);
|
||||||
}
|
}
|
||||||
|
@ -71,7 +75,7 @@ Rectangle {
|
||||||
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
if (!isLoggedIn && root.activeView !== "needsLogIn") {
|
||||||
root.activeView = "needsLogIn";
|
root.activeView = "needsLogIn";
|
||||||
} else if (isLoggedIn) {
|
} else if (isLoggedIn) {
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,7 +181,7 @@ Rectangle {
|
||||||
if (msg.method === 'walletSetup_finished') {
|
if (msg.method === 'walletSetup_finished') {
|
||||||
if (msg.referrer === '' || msg.referrer === 'marketplace cta') {
|
if (msg.referrer === '' || msg.referrer === 'marketplace cta') {
|
||||||
root.activeView = "initialize";
|
root.activeView = "initialize";
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
} else if (msg.referrer === 'purchases') {
|
} else if (msg.referrer === 'purchases') {
|
||||||
sendToScript({method: 'goToPurchases'});
|
sendToScript({method: 'goToPurchases'});
|
||||||
} else {
|
} else {
|
||||||
|
@ -206,17 +210,19 @@ Rectangle {
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
onSendSignalToWallet: {
|
onSendSignalToWallet: {
|
||||||
if (msg.method === 'walletSetup_raiseKeyboard') {
|
if (passphraseChange.visible) {
|
||||||
root.keyboardRaised = true;
|
if (msg.method === 'walletSetup_raiseKeyboard') {
|
||||||
root.isPassword = msg.isPasswordField;
|
root.keyboardRaised = true;
|
||||||
} else if (msg.method === 'walletSetup_lowerKeyboard') {
|
root.isPassword = msg.isPasswordField;
|
||||||
root.keyboardRaised = false;
|
} else if (msg.method === 'walletSetup_lowerKeyboard') {
|
||||||
} else if (msg.method === 'walletSecurity_changePassphraseCancelled') {
|
root.keyboardRaised = false;
|
||||||
root.activeView = "security";
|
} else if (msg.method === 'walletSecurity_changePassphraseCancelled') {
|
||||||
} else if (msg.method === 'walletSecurity_changePassphraseSuccess') {
|
root.activeView = "security";
|
||||||
root.activeView = "security";
|
} else if (msg.method === 'walletSecurity_changePassphraseSuccess') {
|
||||||
} else {
|
root.activeView = "security";
|
||||||
sendToScript(msg);
|
} else {
|
||||||
|
sendToScript(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,7 +263,7 @@ Rectangle {
|
||||||
color: hifi.colors.baseGray;
|
color: hifi.colors.baseGray;
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +284,7 @@ Rectangle {
|
||||||
Connections {
|
Connections {
|
||||||
target: GlobalServices
|
target: GlobalServices
|
||||||
onMyUsernameChanged: {
|
onMyUsernameChanged: {
|
||||||
commerce.getLoginStatus();
|
Commerce.getLoginStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,7 +298,7 @@ Rectangle {
|
||||||
Connections {
|
Connections {
|
||||||
onSendSignalToParent: {
|
onSendSignalToParent: {
|
||||||
if (msg.method === "authSuccess") {
|
if (msg.method === "authSuccess") {
|
||||||
commerce.getWalletStatus();
|
Commerce.getWalletStatus();
|
||||||
} else {
|
} else {
|
||||||
sendToScript(msg);
|
sendToScript(msg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,8 @@ Item {
|
||||||
property bool historyReceived: false;
|
property bool historyReceived: false;
|
||||||
property int pendingCount: 0;
|
property int pendingCount: 0;
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onBalanceResult : {
|
onBalanceResult : {
|
||||||
balanceText.text = result.data.balance;
|
balanceText.text = result.data.balance;
|
||||||
|
@ -135,8 +135,8 @@ Item {
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
historyReceived = false;
|
historyReceived = false;
|
||||||
commerce.balance();
|
Commerce.balance();
|
||||||
commerce.history();
|
Commerce.history();
|
||||||
} else {
|
} else {
|
||||||
refreshTimer.stop();
|
refreshTimer.stop();
|
||||||
}
|
}
|
||||||
|
@ -165,8 +165,8 @@ Item {
|
||||||
interval: 4000;
|
interval: 4000;
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
console.log("Refreshing Wallet Home...");
|
console.log("Refreshing Wallet Home...");
|
||||||
commerce.balance();
|
Commerce.balance();
|
||||||
commerce.history();
|
Commerce.history();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,8 @@ Item {
|
||||||
source: "images/wallet-bg.jpg";
|
source: "images/wallet-bg.jpg";
|
||||||
}
|
}
|
||||||
|
|
||||||
Hifi.QmlCommerce {
|
Connections {
|
||||||
id: commerce;
|
target: Commerce;
|
||||||
|
|
||||||
onSecurityImageResult: {
|
onSecurityImageResult: {
|
||||||
if (!exists && root.lastPage === "step_2") {
|
if (!exists && root.lastPage === "step_2") {
|
||||||
|
@ -366,7 +366,7 @@ Item {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.lastPage = "step_2";
|
root.lastPage = "step_2";
|
||||||
var securityImagePath = securityImageSelection.getImagePathFromImageID(securityImageSelection.getSelectedImageIndex())
|
var securityImagePath = securityImageSelection.getImagePathFromImageID(securityImageSelection.getSelectedImageIndex())
|
||||||
commerce.chooseSecurityImage(securityImagePath);
|
Commerce.chooseSecurityImage(securityImagePath);
|
||||||
root.activeView = "step_3";
|
root.activeView = "step_3";
|
||||||
passphraseSelection.clearPassphraseFields();
|
passphraseSelection.clearPassphraseFields();
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ Item {
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
commerce.getWalletAuthenticatedStatus();
|
Commerce.getWalletAuthenticatedStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -535,7 +535,7 @@ Item {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (passphraseSelection.validateAndSubmitPassphrase()) {
|
if (passphraseSelection.validateAndSubmitPassphrase()) {
|
||||||
root.lastPage = "step_3";
|
root.lastPage = "step_3";
|
||||||
commerce.generateKeyPair();
|
Commerce.generateKeyPair();
|
||||||
root.activeView = "step_4";
|
root.activeView = "step_4";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -668,7 +668,7 @@ Item {
|
||||||
|
|
||||||
onVisibleChanged: {
|
onVisibleChanged: {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
commerce.getKeyFilePathIfExists();
|
Commerce.getKeyFilePathIfExists();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,11 +123,11 @@ Item {
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
enabled: true
|
enabled: true
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
newEntityButton.clicked();
|
newEntityButton.clicked();
|
||||||
}
|
}
|
||||||
onEntered: {
|
onEntered: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
newEntityButton.state = "hover state";
|
newEntityButton.state = "hover state";
|
||||||
}
|
}
|
||||||
onExited: {
|
onExited: {
|
||||||
|
|
|
@ -1,261 +0,0 @@
|
||||||
import QtQuick 2.5
|
|
||||||
import QtGraphicalEffects 1.0
|
|
||||||
import QtQuick.Layouts 1.3
|
|
||||||
|
|
||||||
import "../../styles-uit"
|
|
||||||
import "../audio" as HifiAudio
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: tablet
|
|
||||||
objectName: "tablet"
|
|
||||||
property int rowIndex: 6 // by default
|
|
||||||
property int columnIndex: 1 // point to 'go to location'
|
|
||||||
property int count: (flowMain.children.length - 1)
|
|
||||||
|
|
||||||
// used to look up a button by its uuid
|
|
||||||
function findButtonIndex(uuid) {
|
|
||||||
if (!uuid) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i in flowMain.children) {
|
|
||||||
var child = flowMain.children[i];
|
|
||||||
if (child.uuid === uuid) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortButtons() {
|
|
||||||
var children = [];
|
|
||||||
for (var i = 0; i < flowMain.children.length; i++) {
|
|
||||||
children[i] = flowMain.children[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
children.sort(function (a, b) {
|
|
||||||
if (a.sortOrder === b.sortOrder) {
|
|
||||||
// subsort by stableOrder, because JS sort is not stable in qml.
|
|
||||||
return a.stableOrder - b.stableOrder;
|
|
||||||
} else {
|
|
||||||
return a.sortOrder - b.sortOrder;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
flowMain.children = children;
|
|
||||||
}
|
|
||||||
|
|
||||||
// called by C++ code when a button should be added to the tablet
|
|
||||||
function addButtonProxy(properties) {
|
|
||||||
var component = Qt.createComponent("TabletButton.qml");
|
|
||||||
var button = component.createObject(flowMain);
|
|
||||||
|
|
||||||
// copy all properites to button
|
|
||||||
var keys = Object.keys(properties).forEach(function (key) {
|
|
||||||
button[key] = properties[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
// pass a reference to the tabletRoot object to the button.
|
|
||||||
if (tabletRoot) {
|
|
||||||
button.tabletRoot = tabletRoot;
|
|
||||||
} else {
|
|
||||||
button.tabletRoot = parent.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
sortButtons();
|
|
||||||
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
// called by C++ code when a button should be removed from the tablet
|
|
||||||
function removeButtonProxy(properties) {
|
|
||||||
var index = findButtonIndex(properties.uuid);
|
|
||||||
if (index < 0) {
|
|
||||||
console.log("Warning: Tablet.qml could not find button with uuid = " + properties.uuid);
|
|
||||||
} else {
|
|
||||||
flowMain.children[index].destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: bgTopBar
|
|
||||||
height: 90
|
|
||||||
|
|
||||||
anchors {
|
|
||||||
top: parent.top
|
|
||||||
topMargin: 0
|
|
||||||
left: parent.left
|
|
||||||
leftMargin: 0
|
|
||||||
right: parent.right
|
|
||||||
rightMargin: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
gradient: Gradient {
|
|
||||||
GradientStop {
|
|
||||||
position: 0
|
|
||||||
color: "#2b2b2b"
|
|
||||||
}
|
|
||||||
|
|
||||||
GradientStop {
|
|
||||||
position: 1
|
|
||||||
color: "#1e1e1e"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HifiAudio.MicBar {
|
|
||||||
anchors {
|
|
||||||
left: parent.left
|
|
||||||
leftMargin: 30
|
|
||||||
verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
width: 150
|
|
||||||
height: 50
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: 30
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
RalewaySemiBold {
|
|
||||||
text: Account.loggedIn ? qsTr("Log out") : qsTr("Log in")
|
|
||||||
horizontalAlignment: Text.AlignRight
|
|
||||||
anchors.right: parent.right
|
|
||||||
font.pixelSize: 20
|
|
||||||
color: "#afafaf"
|
|
||||||
}
|
|
||||||
|
|
||||||
RalewaySemiBold {
|
|
||||||
visible: Account.loggedIn
|
|
||||||
height: Account.loggedIn ? parent.height/2 - parent.spacing/2 : 0
|
|
||||||
text: Account.loggedIn ? "[" + tabletRoot.usernameShort + "]" : ""
|
|
||||||
horizontalAlignment: Text.AlignRight
|
|
||||||
anchors.right: parent.right
|
|
||||||
font.pixelSize: 20
|
|
||||||
color: "#afafaf"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: {
|
|
||||||
if (!Account.loggedIn) {
|
|
||||||
DialogsManager.showLoginDialog()
|
|
||||||
} else {
|
|
||||||
Account.logOut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: bgMain
|
|
||||||
gradient: Gradient {
|
|
||||||
GradientStop {
|
|
||||||
position: 0
|
|
||||||
color: "#2b2b2b"
|
|
||||||
}
|
|
||||||
|
|
||||||
GradientStop {
|
|
||||||
position: 1
|
|
||||||
color: "#0f212e"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.bottomMargin: 0
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: 0
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: 0
|
|
||||||
anchors.top: bgTopBar.bottom
|
|
||||||
anchors.topMargin: 0
|
|
||||||
|
|
||||||
Flickable {
|
|
||||||
id: flickable
|
|
||||||
width: parent.width
|
|
||||||
height: parent.height
|
|
||||||
contentWidth: parent.width
|
|
||||||
contentHeight: flowMain.childrenRect.height + flowMain.anchors.topMargin + flowMain.anchors.bottomMargin + flowMain.spacing
|
|
||||||
clip: true
|
|
||||||
Flow {
|
|
||||||
id: flowMain
|
|
||||||
spacing: 16
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: 30
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.leftMargin: 30
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.bottomMargin: 30
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.topMargin: 30
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setCurrentItemState(state) {
|
|
||||||
var index = rowIndex + columnIndex;
|
|
||||||
|
|
||||||
if (index >= 0 && index <= count ) {
|
|
||||||
flowMain.children[index].state = state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function nextItem() {
|
|
||||||
setCurrentItemState("base state");
|
|
||||||
var nextColumnIndex = (columnIndex + 3 + 1) % 3;
|
|
||||||
var nextIndex = rowIndex + nextColumnIndex;
|
|
||||||
if(nextIndex <= count) {
|
|
||||||
columnIndex = nextColumnIndex;
|
|
||||||
};
|
|
||||||
setCurrentItemState("hover state");
|
|
||||||
}
|
|
||||||
|
|
||||||
function previousItem() {
|
|
||||||
setCurrentItemState("base state");
|
|
||||||
var prevIndex = (columnIndex + 3 - 1) % 3;
|
|
||||||
if((rowIndex + prevIndex) <= count){
|
|
||||||
columnIndex = prevIndex;
|
|
||||||
}
|
|
||||||
setCurrentItemState("hover state");
|
|
||||||
}
|
|
||||||
|
|
||||||
function upItem() {
|
|
||||||
setCurrentItemState("base state");
|
|
||||||
rowIndex = rowIndex - 3;
|
|
||||||
if (rowIndex < 0 ) {
|
|
||||||
rowIndex = (count - (count % 3));
|
|
||||||
var index = rowIndex + columnIndex;
|
|
||||||
if(index > count) {
|
|
||||||
rowIndex = rowIndex - 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setCurrentItemState("hover state");
|
|
||||||
}
|
|
||||||
|
|
||||||
function downItem() {
|
|
||||||
setCurrentItemState("base state");
|
|
||||||
rowIndex = rowIndex + 3;
|
|
||||||
var index = rowIndex + columnIndex;
|
|
||||||
if (index > count ) {
|
|
||||||
rowIndex = 0;
|
|
||||||
}
|
|
||||||
setCurrentItemState("hover state");
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectItem() {
|
|
||||||
flowMain.children[rowIndex + columnIndex].clicked();
|
|
||||||
if (tabletRoot) {
|
|
||||||
tabletRoot.playButtonClickSound();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onRightPressed: nextItem();
|
|
||||||
Keys.onLeftPressed: previousItem();
|
|
||||||
Keys.onDownPressed: downItem();
|
|
||||||
Keys.onUpPressed: upItem();
|
|
||||||
Keys.onReturnPressed: selectItem();
|
|
||||||
}
|
|
|
@ -123,7 +123,6 @@ Item {
|
||||||
enabled: true
|
enabled: true
|
||||||
preventStealing: true
|
preventStealing: true
|
||||||
onClicked: {
|
onClicked: {
|
||||||
console.log("Tablet Button Clicked!");
|
|
||||||
if (tabletButton.inDebugMode) {
|
if (tabletButton.inDebugMode) {
|
||||||
if (tabletButton.isActive) {
|
if (tabletButton.isActive) {
|
||||||
tabletButton.isActive = false;
|
tabletButton.isActive = false;
|
||||||
|
@ -133,12 +132,12 @@ Item {
|
||||||
}
|
}
|
||||||
tabletButton.clicked();
|
tabletButton.clicked();
|
||||||
if (tabletRoot) {
|
if (tabletRoot) {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onEntered: {
|
onEntered: {
|
||||||
tabletButton.isEntered = true;
|
tabletButton.isEntered = true;
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
|
|
||||||
if (tabletButton.isActive) {
|
if (tabletButton.isActive) {
|
||||||
tabletButton.state = "hover active state";
|
tabletButton.state = "hover active state";
|
||||||
|
|
159
interface/resources/qml/hifi/tablet/TabletHome.qml
Normal file
159
interface/resources/qml/hifi/tablet/TabletHome.qml
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
import QtQuick 2.5
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
|
||||||
|
import "."
|
||||||
|
import "../../styles-uit"
|
||||||
|
import "../audio" as HifiAudio
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: tablet
|
||||||
|
objectName: "tablet"
|
||||||
|
property var tabletProxy: Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: bgTopBar
|
||||||
|
height: 90
|
||||||
|
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop {
|
||||||
|
position: 0
|
||||||
|
color: "#2b2b2b"
|
||||||
|
}
|
||||||
|
|
||||||
|
GradientStop {
|
||||||
|
position: 1
|
||||||
|
color: "#1e1e1e"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HifiAudio.MicBar {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: 30
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
width: 150
|
||||||
|
height: 50
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 30
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
RalewaySemiBold {
|
||||||
|
text: Account.loggedIn ? qsTr("Log out") : qsTr("Log in")
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
anchors.right: parent.right
|
||||||
|
font.pixelSize: 20
|
||||||
|
color: "#afafaf"
|
||||||
|
}
|
||||||
|
|
||||||
|
RalewaySemiBold {
|
||||||
|
visible: Account.loggedIn
|
||||||
|
height: Account.loggedIn ? parent.height/2 - parent.spacing/2 : 0
|
||||||
|
text: Account.loggedIn ? "[" + tabletRoot.usernameShort + "]" : ""
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
anchors.right: parent.right
|
||||||
|
font.pixelSize: 20
|
||||||
|
color: "#afafaf"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
if (!Account.loggedIn) {
|
||||||
|
DialogsManager.showLoginDialog()
|
||||||
|
} else {
|
||||||
|
Account.logOut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: bgMain
|
||||||
|
clip: true
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop {
|
||||||
|
position: 0
|
||||||
|
color: "#2b2b2b"
|
||||||
|
}
|
||||||
|
|
||||||
|
GradientStop {
|
||||||
|
position: 1
|
||||||
|
color: "#0f212e"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: bgTopBar.bottom
|
||||||
|
|
||||||
|
GridView {
|
||||||
|
id: flickable
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 15
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
width: cellWidth * 3
|
||||||
|
cellHeight: 145
|
||||||
|
cellWidth: 145
|
||||||
|
model: tabletProxy.buttons
|
||||||
|
delegate: Item {
|
||||||
|
width: flickable.cellWidth
|
||||||
|
height: flickable.cellHeight
|
||||||
|
property var proxy: modelData
|
||||||
|
|
||||||
|
TabletButton {
|
||||||
|
id: tabletButton
|
||||||
|
anchors.centerIn: parent
|
||||||
|
onClicked: modelData.clicked()
|
||||||
|
state: wrapper.GridView.isCurrentItem ? "hover state" : "base state"
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: modelData;
|
||||||
|
onPropertiesChanged: {
|
||||||
|
updateProperties();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: updateProperties()
|
||||||
|
|
||||||
|
function updateProperties() {
|
||||||
|
var keys = Object.keys(modelData.properties).forEach(function (key) {
|
||||||
|
if (tabletButton[key] !== modelData.properties[key]) {
|
||||||
|
tabletButton[key] = modelData.properties[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onRightPressed: flickable.moveCurrentIndexRight();
|
||||||
|
Keys.onLeftPressed: flickable.moveCurrentIndexLeft();
|
||||||
|
Keys.onDownPressed: flickable.moveCurrentIndexDown();
|
||||||
|
Keys.onUpPressed: flickable.moveCurrentIndexUp();
|
||||||
|
Keys.onReturnPressed: {
|
||||||
|
if (flickable.currentItem) {
|
||||||
|
flickable.currentItem.proxy.clicked();
|
||||||
|
if (tabletRoot) {
|
||||||
|
tabletRoot.playButtonClickSound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -77,12 +77,12 @@ FocusScope {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: {
|
onEntered: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonHover);
|
Tablet.playSound(TabletEnums.ButtonHover);
|
||||||
listView.currentIndex = index
|
listView.currentIndex = index
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabletInterface.playSound(TabletEnums.ButtonClick);
|
Tablet.playSound(TabletEnums.ButtonClick);
|
||||||
root.selected(item);
|
root.selected(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,37 +68,36 @@ Item {
|
||||||
|
|
||||||
function loadSource(url) {
|
function loadSource(url) {
|
||||||
tabletApps.clear();
|
tabletApps.clear();
|
||||||
loader.source = ""; // make sure we load the qml fresh each time.
|
|
||||||
loader.source = url;
|
|
||||||
tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""});
|
tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""});
|
||||||
|
loader.load(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadQMLOnTop(url) {
|
function loadQMLOnTop(url) {
|
||||||
tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""});
|
tabletApps.append({"appUrl": url, "isWebUrl": false, "scriptUrl": "", "appWebUrl": ""});
|
||||||
loader.source = "";
|
loader.load(tabletApps.get(currentApp).appUrl, function(){
|
||||||
loader.source = tabletApps.get(currentApp).appUrl;
|
if (loader.item.hasOwnProperty("gotoPreviousApp")) {
|
||||||
if (loader.item.hasOwnProperty("gotoPreviousApp")) {
|
loader.item.gotoPreviousApp = true;
|
||||||
loader.item.gotoPreviousApp = true;
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadWebOnTop(url, injectJavaScriptUrl) {
|
function loadWebContent(source, url, injectJavaScriptUrl) {
|
||||||
tabletApps.append({"appUrl": loader.source, "isWebUrl": true, "scriptUrl": injectJavaScriptUrl, "appWebUrl": url});
|
tabletApps.append({"appUrl": source, "isWebUrl": true, "scriptUrl": injectJavaScriptUrl, "appWebUrl": url});
|
||||||
loader.item.url = tabletApps.get(currentApp).appWebUrl;
|
loader.load(source, function() {
|
||||||
loader.item.scriptUrl = tabletApps.get(currentApp).scriptUrl;
|
loader.item.scriptURL = injectJavaScriptUrl;
|
||||||
if (loader.item.hasOwnProperty("gotoPreviousApp")) {
|
loader.item.url = url;
|
||||||
loader.item.gotoPreviousApp = true;
|
if (loader.item.hasOwnProperty("gotoPreviousApp")) {
|
||||||
}
|
loader.item.gotoPreviousApp = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadWebBase() {
|
function loadWebBase(url, injectJavaScriptUrl) {
|
||||||
loader.source = "";
|
loadWebContent("hifi/tablet/TabletWebView.qml", url, injectJavaScriptUrl);
|
||||||
loader.source = "TabletWebView.qml";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadTabletWebBase() {
|
function loadTabletWebBase(url, injectJavaScriptUrl) {
|
||||||
loader.source = "";
|
loadWebContent("hifi/tablet/BlocksWebView.qml", url, injectJavaScriptUrl);
|
||||||
loader.source = "./BlocksWebView.qml";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function returnToPreviousApp() {
|
function returnToPreviousApp() {
|
||||||
|
@ -110,7 +109,7 @@ Item {
|
||||||
loadSource("TabletWebView.qml");
|
loadSource("TabletWebView.qml");
|
||||||
loadWebUrl(webUrl, scriptUrl);
|
loadWebUrl(webUrl, scriptUrl);
|
||||||
} else {
|
} else {
|
||||||
loader.source = tabletApps.get(currentApp).appUrl;
|
loader.load(tabletApps.get(currentApp).appUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,47 +172,79 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
// Hook up callback for clara.io download from the marketplace.
|
||||||
id: loader
|
Connections {
|
||||||
objectName: "loader"
|
id: eventBridgeConnection
|
||||||
asynchronous: false
|
target: eventBridge
|
||||||
|
onWebEventReceived: {
|
||||||
width: parent.width
|
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
|
||||||
height: parent.height
|
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
|
||||||
|
|
||||||
// Hook up callback for clara.io download from the marketplace.
|
|
||||||
Connections {
|
|
||||||
id: eventBridgeConnection
|
|
||||||
target: eventBridge
|
|
||||||
onWebEventReceived: {
|
|
||||||
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
|
|
||||||
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoaded: {
|
|
||||||
if (loader.item.hasOwnProperty("sendToScript")) {
|
|
||||||
loader.item.sendToScript.connect(tabletRoot.sendToScript);
|
|
||||||
}
|
|
||||||
if (loader.item.hasOwnProperty("setRootMenu")) {
|
|
||||||
loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu);
|
|
||||||
}
|
|
||||||
loader.item.forceActiveFocus();
|
|
||||||
|
|
||||||
if (openModal) {
|
|
||||||
openModal.canceled();
|
|
||||||
openModal.destroy();
|
|
||||||
openModal = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (openBrowser) {
|
|
||||||
openBrowser.destroy();
|
|
||||||
openBrowser = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: loader
|
||||||
|
objectName: "loader";
|
||||||
|
anchors.fill: parent;
|
||||||
|
property string source: "";
|
||||||
|
property var item: null;
|
||||||
|
signal loaded;
|
||||||
|
|
||||||
|
onWidthChanged: {
|
||||||
|
if (loader.item) {
|
||||||
|
loader.item.width = loader.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onHeightChanged: {
|
||||||
|
if (loader.item) {
|
||||||
|
loader.item.height = loader.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function load(newSource, callback) {
|
||||||
|
if (loader.source == newSource) {
|
||||||
|
loader.loaded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loader.item) {
|
||||||
|
loader.item.destroy();
|
||||||
|
loader.item = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
QmlSurface.load(newSource, loader, function(newItem) {
|
||||||
|
loader.item = newItem;
|
||||||
|
loader.item.width = loader.width;
|
||||||
|
loader.item.height = loader.height;
|
||||||
|
loader.loaded();
|
||||||
|
if (loader.item.hasOwnProperty("sendToScript")) {
|
||||||
|
loader.item.sendToScript.connect(tabletRoot.sendToScript);
|
||||||
|
}
|
||||||
|
if (loader.item.hasOwnProperty("setRootMenu")) {
|
||||||
|
loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu);
|
||||||
|
}
|
||||||
|
loader.item.forceActiveFocus();
|
||||||
|
|
||||||
|
if (openModal) {
|
||||||
|
openModal.canceled();
|
||||||
|
openModal.destroy();
|
||||||
|
openModal = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openBrowser) {
|
||||||
|
openBrowser.destroy();
|
||||||
|
openBrowser = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
width: 480
|
width: 480
|
||||||
height: 706
|
height: 706
|
||||||
|
|
||||||
|
|
|
@ -59,26 +59,25 @@ Windows.ScrollingWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadSource(url) {
|
function loadSource(url) {
|
||||||
loader.source = ""; // make sure we load the qml fresh each time.
|
loader.load(url)
|
||||||
loader.source = url;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadWebBase() {
|
function loadWebContent(source, url, injectJavaScriptUrl) {
|
||||||
loader.source = "";
|
loader.load(source, function() {
|
||||||
loader.source = "WindowWebView.qml";
|
loader.item.scriptURL = injectJavaScriptUrl;
|
||||||
|
loader.item.url = url;
|
||||||
|
if (loader.item.hasOwnProperty("closeButtonVisible")) {
|
||||||
|
loader.item.closeButtonVisible = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadTabletWebBase() {
|
function loadWebBase(url, injectJavaScriptUrl) {
|
||||||
loader.source = "";
|
loadWebContent("hifi/tablet/TabletWebView.qml", url, injectJavaScriptUrl);
|
||||||
loader.source = "./BlocksWebView.qml";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadWebUrl(url, injectedJavaScriptUrl) {
|
function loadTabletWebBase(url, injectJavaScriptUrl) {
|
||||||
loader.item.url = url;
|
loadWebContent("hifi/tablet/BlocksWebView.qml", url, injectJavaScriptUrl);
|
||||||
loader.item.scriptURL = injectedJavaScriptUrl;
|
|
||||||
if (loader.item.hasOwnProperty("closeButtonVisible")) {
|
|
||||||
loader.item.closeButtonVisible = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// used to send a message from qml to interface script.
|
// used to send a message from qml to interface script.
|
||||||
|
@ -111,38 +110,68 @@ Windows.ScrollingWindow {
|
||||||
username = newUsername;
|
username = newUsername;
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader {
|
// Hook up callback for clara.io download from the marketplace.
|
||||||
|
Connections {
|
||||||
|
id: eventBridgeConnection
|
||||||
|
target: eventBridge
|
||||||
|
onWebEventReceived: {
|
||||||
|
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
|
||||||
|
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
id: loader
|
id: loader
|
||||||
objectName: "loader"
|
objectName: "loader";
|
||||||
asynchronous: false
|
property string source: "";
|
||||||
|
property var item: null;
|
||||||
|
|
||||||
height: pane.scrollHeight
|
height: pane.scrollHeight
|
||||||
width: pane.contentWidth
|
width: pane.contentWidth
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
|
signal loaded;
|
||||||
// Hook up callback for clara.io download from the marketplace.
|
|
||||||
Connections {
|
onWidthChanged: {
|
||||||
id: eventBridgeConnection
|
if (loader.item) {
|
||||||
target: eventBridge
|
loader.item.width = loader.width;
|
||||||
onWebEventReceived: {
|
|
||||||
if (message.slice(0, 17) === "CLARA.IO DOWNLOAD") {
|
|
||||||
ApplicationInterface.addAssetToWorldFromURL(message.slice(18));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoaded: {
|
onHeightChanged: {
|
||||||
if (loader.item.hasOwnProperty("sendToScript")) {
|
if (loader.item) {
|
||||||
loader.item.sendToScript.connect(tabletRoot.sendToScript);
|
loader.item.height = loader.height;
|
||||||
}
|
}
|
||||||
if (loader.item.hasOwnProperty("setRootMenu")) {
|
}
|
||||||
loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu);
|
|
||||||
|
function load(newSource, callback) {
|
||||||
|
if (loader.item) {
|
||||||
|
loader.item.destroy();
|
||||||
|
loader.item = null;
|
||||||
}
|
}
|
||||||
loader.item.forceActiveFocus();
|
|
||||||
|
QmlSurface.load(newSource, loader, function(newItem) {
|
||||||
|
loader.item = newItem;
|
||||||
|
loader.item.width = loader.width;
|
||||||
|
loader.item.height = loader.height;
|
||||||
|
loader.loaded();
|
||||||
|
if (loader.item.hasOwnProperty("sendToScript")) {
|
||||||
|
loader.item.sendToScript.connect(tabletRoot.sendToScript);
|
||||||
|
}
|
||||||
|
if (loader.item.hasOwnProperty("setRootMenu")) {
|
||||||
|
loader.item.setRootMenu(tabletRoot.rootMenu, tabletRoot.subMenu);
|
||||||
|
}
|
||||||
|
loader.item.forceActiveFocus();
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
implicitWidth: 480
|
implicitWidth: 480
|
||||||
implicitHeight: 706
|
implicitHeight: 706
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ Window {
|
||||||
horizontalSpacers: horizontal
|
horizontalSpacers: horizontal
|
||||||
verticalSpacers: !horizontal
|
verticalSpacers: !horizontal
|
||||||
}
|
}
|
||||||
|
property var tabletProxy;
|
||||||
|
property var buttonModel: ListModel {}
|
||||||
hideBackground: true
|
hideBackground: true
|
||||||
resizable: false
|
resizable: false
|
||||||
destroyOnCloseButton: false
|
destroyOnCloseButton: false
|
||||||
|
@ -23,24 +25,32 @@ Window {
|
||||||
activator: Item {}
|
activator: Item {}
|
||||||
property bool horizontal: true
|
property bool horizontal: true
|
||||||
property real buttonSize: 50;
|
property real buttonSize: 50;
|
||||||
property var buttons: []
|
|
||||||
property var container: horizontal ? row : column
|
|
||||||
|
|
||||||
Settings {
|
Settings {
|
||||||
category: "toolbar/" + window.objectName
|
category: "toolbar/" + window.objectName
|
||||||
property alias x: window.x
|
property alias x: window.x
|
||||||
property alias y: window.y
|
property alias y: window.y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: buttonComponent
|
||||||
|
ToolbarButton {
|
||||||
|
id: toolbarButton
|
||||||
|
property var proxy: modelData;
|
||||||
|
onClicked: proxy.clicked()
|
||||||
|
Component.onCompleted: updateProperties()
|
||||||
|
|
||||||
onHorizontalChanged: {
|
Connections {
|
||||||
var newParent = horizontal ? row : column;
|
target: proxy;
|
||||||
for (var i in buttons) {
|
onPropertiesChanged: updateProperties();
|
||||||
var child = buttons[i];
|
}
|
||||||
child.parent = newParent;
|
|
||||||
if (horizontal) {
|
function updateProperties() {
|
||||||
child.y = 0
|
Object.keys(proxy.properties).forEach(function (key) {
|
||||||
} else {
|
if (toolbarButton[key] !== proxy.properties[key]) {
|
||||||
child.x = 0
|
toolbarButton[key] = proxy.properties[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,97 +62,22 @@ Window {
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: row
|
id: row
|
||||||
|
visible: window.horizontal
|
||||||
spacing: 6
|
spacing: 6
|
||||||
|
Repeater {
|
||||||
|
model: buttonModel
|
||||||
|
delegate: buttonComponent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: column
|
id: column
|
||||||
|
visible: !window.horizontal
|
||||||
spacing: 6
|
spacing: 6
|
||||||
}
|
Repeater {
|
||||||
|
model: buttonModel
|
||||||
Component { id: toolbarButtonBuilder; ToolbarButton { } }
|
delegate: buttonComponent
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function findButtonIndex(name) {
|
|
||||||
if (!name) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i in buttons) {
|
|
||||||
var child = buttons[i];
|
|
||||||
if (child.objectName === name) {
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findButton(name) {
|
|
||||||
var index = findButtonIndex(name);
|
|
||||||
if (index < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return buttons[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortButtons() {
|
|
||||||
var children = [];
|
|
||||||
for (var i = 0; i < container.children.length; i++) {
|
|
||||||
children[i] = container.children[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
children.sort(function (a, b) {
|
|
||||||
if (a.sortOrder === b.sortOrder) {
|
|
||||||
// subsort by stableOrder, because JS sort is not stable in qml.
|
|
||||||
return a.stableOrder - b.stableOrder;
|
|
||||||
} else {
|
|
||||||
return a.sortOrder - b.sortOrder;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
container.children = children;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addButton(properties) {
|
|
||||||
properties = properties || {}
|
|
||||||
|
|
||||||
// If a name is specified, then check if there's an existing button with that name
|
|
||||||
// and return it if so. This will allow multiple clients to listen to a single button,
|
|
||||||
// and allow scripts to be idempotent so they don't duplicate buttons if they're reloaded
|
|
||||||
var result = findButton(properties.objectName);
|
|
||||||
if (result) {
|
|
||||||
for (var property in properties) {
|
|
||||||
result[property] = properties[property];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
properties.toolbar = this;
|
|
||||||
properties.opacity = 0;
|
|
||||||
result = toolbarButtonBuilder.createObject(container, properties);
|
|
||||||
buttons.push(result);
|
|
||||||
|
|
||||||
result.opacity = 1;
|
|
||||||
|
|
||||||
sortButtons();
|
|
||||||
|
|
||||||
fadeIn(null);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeButton(name) {
|
|
||||||
var index = findButtonIndex(name);
|
|
||||||
if (index < -1) {
|
|
||||||
console.warn("Tried to remove non-existent button " + name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
buttons[index].destroy();
|
|
||||||
buttons.splice(index, 1);
|
|
||||||
|
|
||||||
if (buttons.length === 0) {
|
|
||||||
fadeOut(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,8 @@ StateImage {
|
||||||
property string activeHoverIcon: button.activeIcon
|
property string activeHoverIcon: button.activeIcon
|
||||||
|
|
||||||
property int sortOrder: 100
|
property int sortOrder: 100
|
||||||
property int stableSortOrder: 0
|
property int stableOrder: 0
|
||||||
|
property var uuid;
|
||||||
|
|
||||||
signal clicked()
|
signal clicked()
|
||||||
|
|
||||||
|
|
|
@ -2248,27 +2248,65 @@ extern void setupPreferences();
|
||||||
void Application::initializeUi() {
|
void Application::initializeUi() {
|
||||||
// Make sure all QML surfaces share the main thread GL context
|
// Make sure all QML surfaces share the main thread GL context
|
||||||
OffscreenQmlSurface::setSharedContext(_offscreenContext->getContext());
|
OffscreenQmlSurface::setSharedContext(_offscreenContext->getContext());
|
||||||
|
OffscreenQmlSurface::addWhitelistContextHandler(QUrl{ "OverlayWindowTest.qml" },
|
||||||
|
[](QQmlContext* context) {
|
||||||
|
qDebug() << "Whitelist OverlayWindow worked";
|
||||||
|
context->setContextProperty("OverlayWindowTestString", "TestWorked");
|
||||||
|
});
|
||||||
|
OffscreenQmlSurface::addWhitelistContextHandler(QUrl{ "hifi/audio/Audio.qml" },
|
||||||
|
[](QQmlContext* context) {
|
||||||
|
qDebug() << "QQQ" << __FUNCTION__ << "Whitelist Audio worked";
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
AddressBarDialog::registerType();
|
AddressBarDialog::registerType();
|
||||||
ErrorDialog::registerType();
|
ErrorDialog::registerType();
|
||||||
LoginDialog::registerType();
|
LoginDialog::registerType();
|
||||||
Tooltip::registerType();
|
Tooltip::registerType();
|
||||||
UpdateDialog::registerType();
|
UpdateDialog::registerType();
|
||||||
QmlCommerce::registerType();
|
QmlContextCallback callback = [](QQmlContext* context) {
|
||||||
|
context->setContextProperty("Commerce", new QmlCommerce());
|
||||||
|
};
|
||||||
|
OffscreenQmlSurface::addWhitelistContextHandler({
|
||||||
|
QUrl{ "hifi/commerce/checkout/Checkout.qml" },
|
||||||
|
QUrl{ "hifi/commerce/common/CommerceLightbox.qml" },
|
||||||
|
QUrl{ "hifi/commerce/common/EmulatedMarketplaceHeader.qml" },
|
||||||
|
QUrl{ "hifi/commerce/common/FirstUseTutorial.qml" },
|
||||||
|
QUrl{ "hifi/commerce/common/SortableListModel.qml" },
|
||||||
|
QUrl{ "hifi/commerce/inspectionCertificate/InspectionCertificate.qml" },
|
||||||
|
QUrl{ "hifi/commerce/purchases/PurchasedItem.qml" },
|
||||||
|
QUrl{ "hifi/commerce/purchases/Purchases.qml" },
|
||||||
|
QUrl{ "hifi/commerce/wallet/Help.qml" },
|
||||||
|
QUrl{ "hifi/commerce/wallet/NeedsLogIn.qml" },
|
||||||
|
QUrl{ "hifi/commerce/wallet/PassphraseChange.qml" },
|
||||||
|
QUrl{ "hifi/commerce/wallet/PassphraseModal.qml" },
|
||||||
|
QUrl{ "hifi/commerce/wallet/PassphraseSelection.qml" },
|
||||||
|
QUrl{ "hifi/commerce/wallet/Security.qml" },
|
||||||
|
QUrl{ "hifi/commerce/wallet/SecurityImageChange.qml" },
|
||||||
|
QUrl{ "hifi/commerce/wallet/SecurityImageModel.qml" },
|
||||||
|
QUrl{ "hifi/commerce/wallet/SecurityImageSelection.qml" },
|
||||||
|
QUrl{ "hifi/commerce/wallet/SendMoney.qml" },
|
||||||
|
QUrl{ "hifi/commerce/wallet/Wallet.qml" },
|
||||||
|
QUrl{ "hifi/commerce/wallet/WalletHome.qml" },
|
||||||
|
QUrl{ "hifi/commerce/wallet/WalletSetup.qml" },
|
||||||
|
}, callback);
|
||||||
qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem");
|
qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem");
|
||||||
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
|
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
|
||||||
qmlRegisterType<WebBrowserSuggestionsEngine>("HifiWeb", 1, 0, "WebBrowserSuggestionsEngine");
|
qmlRegisterType<WebBrowserSuggestionsEngine>("HifiWeb", 1, 0, "WebBrowserSuggestionsEngine");
|
||||||
|
|
||||||
|
{
|
||||||
|
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||||
|
tabletScriptingInterface->getTablet(SYSTEM_TABLET);
|
||||||
|
}
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
offscreenUi->create();
|
offscreenUi->create();
|
||||||
|
|
||||||
auto surfaceContext = offscreenUi->getSurfaceContext();
|
auto surfaceContext = offscreenUi->getSurfaceContext();
|
||||||
|
|
||||||
offscreenUi->setProxyWindow(_window->windowHandle());
|
offscreenUi->setProxyWindow(_window->windowHandle());
|
||||||
offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
|
|
||||||
// OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to
|
// OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to
|
||||||
// support the window management and scripting proxies for VR use
|
// support the window management and scripting proxies for VR use
|
||||||
offscreenUi->createDesktop(QString("qrc:///qml/hifi/Desktop.qml"));
|
offscreenUi->createDesktop(QString("hifi/Desktop.qml"));
|
||||||
|
|
||||||
// FIXME either expose so that dialogs can set this themselves or
|
// FIXME either expose so that dialogs can set this themselves or
|
||||||
// do better detection in the offscreen UI of what has focus
|
// do better detection in the offscreen UI of what has focus
|
||||||
|
@ -2336,9 +2374,6 @@ void Application::initializeUi() {
|
||||||
surfaceContext->setContextProperty("InputConfiguration", DependencyManager::get<InputConfiguration>().data());
|
surfaceContext->setContextProperty("InputConfiguration", DependencyManager::get<InputConfiguration>().data());
|
||||||
|
|
||||||
surfaceContext->setContextProperty("Account", AccountScriptingInterface::getInstance());
|
surfaceContext->setContextProperty("Account", AccountScriptingInterface::getInstance());
|
||||||
surfaceContext->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
|
||||||
// Tablet inteference with Tablet.qml. Need to avoid this in QML space
|
|
||||||
surfaceContext->setContextProperty("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
|
|
||||||
surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
|
surfaceContext->setContextProperty("DialogsManager", _dialogsManagerScriptingInterface);
|
||||||
surfaceContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
|
surfaceContext->setContextProperty("GlobalServices", GlobalServicesScriptingInterface::getInstance());
|
||||||
surfaceContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
|
surfaceContext->setContextProperty("FaceTracker", DependencyManager::get<DdeFaceTracker>().data());
|
||||||
|
@ -5836,9 +5871,9 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe
|
||||||
qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue<TabletProxy>, wrapperFromScriptValue<TabletProxy>);
|
qScriptRegisterMetaType(scriptEngine.data(), wrapperToScriptValue<TabletProxy>, wrapperFromScriptValue<TabletProxy>);
|
||||||
qScriptRegisterMetaType(scriptEngine.data(),
|
qScriptRegisterMetaType(scriptEngine.data(),
|
||||||
wrapperToScriptValue<TabletButtonProxy>, wrapperFromScriptValue<TabletButtonProxy>);
|
wrapperToScriptValue<TabletButtonProxy>, wrapperFromScriptValue<TabletButtonProxy>);
|
||||||
// Tablet inteference with Tablet.qml. Need to avoid this in QML space
|
|
||||||
scriptEngine->registerGlobalObject("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
|
|
||||||
scriptEngine->registerGlobalObject("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
scriptEngine->registerGlobalObject("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
||||||
|
// FIXME remove these deprecated names for the tablet scripting interface
|
||||||
|
scriptEngine->registerGlobalObject("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
|
||||||
|
|
||||||
auto toolbarScriptingInterface = DependencyManager::get<ToolbarScriptingInterface>().data();
|
auto toolbarScriptingInterface = DependencyManager::get<ToolbarScriptingInterface>().data();
|
||||||
DependencyManager::get<TabletScriptingInterface>().data()->setToolbarScriptingInterface(toolbarScriptingInterface);
|
DependencyManager::get<TabletScriptingInterface>().data()->setToolbarScriptingInterface(toolbarScriptingInterface);
|
||||||
|
@ -7245,13 +7280,17 @@ void Application::updateDisplayMode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
auto desktop = offscreenUi->getDesktop();
|
||||||
|
|
||||||
// Make the switch atomic from the perspective of other threads
|
// Make the switch atomic from the perspective of other threads
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(_displayPluginLock);
|
std::unique_lock<std::mutex> lock(_displayPluginLock);
|
||||||
// Tell the desktop to no reposition (which requires plugin info), until we have set the new plugin, below.
|
bool wasRepositionLocked = false;
|
||||||
bool wasRepositionLocked = offscreenUi->getDesktop()->property("repositionLocked").toBool();
|
if (desktop) {
|
||||||
offscreenUi->getDesktop()->setProperty("repositionLocked", true);
|
// Tell the desktop to no reposition (which requires plugin info), until we have set the new plugin, below.
|
||||||
|
wasRepositionLocked = offscreenUi->getDesktop()->property("repositionLocked").toBool();
|
||||||
|
offscreenUi->getDesktop()->setProperty("repositionLocked", true);
|
||||||
|
}
|
||||||
|
|
||||||
if (_displayPlugin) {
|
if (_displayPlugin) {
|
||||||
disconnect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent);
|
disconnect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent);
|
||||||
|
@ -7297,7 +7336,6 @@ void Application::updateDisplayMode() {
|
||||||
getApplicationCompositor().setDisplayPlugin(newDisplayPlugin);
|
getApplicationCompositor().setDisplayPlugin(newDisplayPlugin);
|
||||||
_displayPlugin = newDisplayPlugin;
|
_displayPlugin = newDisplayPlugin;
|
||||||
connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent, Qt::DirectConnection);
|
connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent, Qt::DirectConnection);
|
||||||
auto desktop = offscreenUi->getDesktop();
|
|
||||||
if (desktop) {
|
if (desktop) {
|
||||||
desktop->setProperty("repositionLocked", wasRepositionLocked);
|
desktop->setProperty("repositionLocked", wasRepositionLocked);
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,7 @@ Menu::Menu() {
|
||||||
auto action = addActionToQMenuAndActionHash(editMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J);
|
auto action = addActionToQMenuAndActionHash(editMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J);
|
||||||
connect(action, &QAction::triggered, [] {
|
connect(action, &QAction::triggered, [] {
|
||||||
static const QUrl widgetUrl("hifi/dialogs/RunningScripts.qml");
|
static const QUrl widgetUrl("hifi/dialogs/RunningScripts.qml");
|
||||||
static const QUrl tabletUrl("../../hifi/dialogs/TabletRunningScripts.qml");
|
static const QUrl tabletUrl("hifi/dialogs/TabletRunningScripts.qml");
|
||||||
static const QString name("RunningScripts");
|
static const QString name("RunningScripts");
|
||||||
qApp->showDialog(widgetUrl, tabletUrl, name);
|
qApp->showDialog(widgetUrl, tabletUrl, name);
|
||||||
});
|
});
|
||||||
|
@ -338,7 +338,7 @@ Menu::Menu() {
|
||||||
connect(action, &QAction::triggered, [] {
|
connect(action, &QAction::triggered, [] {
|
||||||
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
|
auto tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
|
||||||
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||||
tablet->loadQMLSource("ControllerSettings.qml");
|
tablet->loadQMLSource("hifi/tablet/ControllerSettings.qml");
|
||||||
|
|
||||||
if (!hmd->getShouldShowTablet()) {
|
if (!hmd->getShouldShowTablet()) {
|
||||||
hmd->toggleShouldShowTablet();
|
hmd->toggleShouldShowTablet();
|
||||||
|
|
|
@ -16,9 +16,7 @@
|
||||||
#include "Wallet.h"
|
#include "Wallet.h"
|
||||||
#include <AccountManager.h>
|
#include <AccountManager.h>
|
||||||
|
|
||||||
HIFI_QML_DEF(QmlCommerce)
|
QmlCommerce::QmlCommerce() {
|
||||||
|
|
||||||
QmlCommerce::QmlCommerce(QQuickItem* parent) : OffscreenQmlDialog(parent) {
|
|
||||||
auto ledger = DependencyManager::get<Ledger>();
|
auto ledger = DependencyManager::get<Ledger>();
|
||||||
auto wallet = DependencyManager::get<Wallet>();
|
auto wallet = DependencyManager::get<Wallet>();
|
||||||
connect(ledger.data(), &Ledger::buyResult, this, &QmlCommerce::buyResult);
|
connect(ledger.data(), &Ledger::buyResult, this, &QmlCommerce::buyResult);
|
||||||
|
|
|
@ -16,16 +16,14 @@
|
||||||
#define hifi_QmlCommerce_h
|
#define hifi_QmlCommerce_h
|
||||||
|
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <OffscreenQmlDialog.h>
|
|
||||||
|
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
|
|
||||||
class QmlCommerce : public OffscreenQmlDialog {
|
class QmlCommerce : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
HIFI_QML_DECL
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QmlCommerce(QQuickItem* parent = nullptr);
|
QmlCommerce();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void walletStatusResult(uint walletStatus);
|
void walletStatusResult(uint walletStatus);
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
#include "scripting/HMDScriptingInterface.h"
|
#include "scripting/HMDScriptingInterface.h"
|
||||||
|
|
||||||
static const QVariant TABLET_ADDRESS_DIALOG = "TabletAddressDialog.qml";
|
static const QVariant TABLET_ADDRESS_DIALOG = "hifi/tablet/TabletAddressDialog.qml";
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void DialogsManager::maybeCreateDialog(QPointer<T>& member) {
|
void DialogsManager::maybeCreateDialog(QPointer<T>& member) {
|
||||||
if (!member) {
|
if (!member) {
|
||||||
|
@ -91,7 +91,7 @@ void DialogsManager::setDomainConnectionFailureVisibility(bool visible) {
|
||||||
ConnectionFailureDialog::hide();
|
ConnectionFailureDialog::hide();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
static const QUrl url("../../dialogs/TabletConnectionFailureDialog.qml");
|
static const QUrl url("dialogs/TabletConnectionFailureDialog.qml");
|
||||||
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
auto hmd = DependencyManager::get<HMDScriptingInterface>();
|
||||||
if (visible) {
|
if (visible) {
|
||||||
tablet->initialScreen(url);
|
tablet->initialScreen(url);
|
||||||
|
|
|
@ -46,7 +46,7 @@ void LoginDialog::showWithSelection()
|
||||||
if (tablet->getToolbarMode()) {
|
if (tablet->getToolbarMode()) {
|
||||||
LoginDialog::show();
|
LoginDialog::show();
|
||||||
} else {
|
} else {
|
||||||
static const QUrl url("../../dialogs/TabletLoginDialog.qml");
|
static const QUrl url("dialogs/TabletLoginDialog.qml");
|
||||||
tablet->initialScreen(url);
|
tablet->initialScreen(url);
|
||||||
if (!hmd->getShouldShowTablet()) {
|
if (!hmd->getShouldShowTablet()) {
|
||||||
hmd->openTablet();
|
hmd->openTablet();
|
||||||
|
|
|
@ -266,7 +266,7 @@ void ContextOverlayInterface::contextOverlays_hoverLeaveEntity(const EntityItemI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const QString INSPECTION_CERTIFICATE_QML_PATH = qApp->applicationDirPath() + "../../../qml/hifi/commerce/inspectionCertificate/InspectionCertificate.qml";
|
static const QString INSPECTION_CERTIFICATE_QML_PATH = "hifi/commerce/inspectionCertificate/InspectionCertificate.qml";
|
||||||
void ContextOverlayInterface::openInspectionCertificate() {
|
void ContextOverlayInterface::openInspectionCertificate() {
|
||||||
// lets open the tablet to the inspection certificate QML
|
// lets open the tablet to the inspection certificate QML
|
||||||
if (!_currentEntityWithContextOverlay.isNull() && _entityMarketplaceID.length() > 0) {
|
if (!_currentEntityWithContextOverlay.isNull() && _entityMarketplaceID.length() > 0) {
|
||||||
|
|
|
@ -200,7 +200,6 @@ void Web3DOverlay::setupQmlSurface() {
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("fileDialogHelper", new FileDialogHelper());
|
_webSurface->getSurfaceContext()->setContextProperty("fileDialogHelper", new FileDialogHelper());
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
|
_webSurface->getSurfaceContext()->setContextProperty("MyAvatar", DependencyManager::get<AvatarManager>()->getMyAvatar().get());
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
|
_webSurface->getSurfaceContext()->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
|
_webSurface->getSurfaceContext()->setContextProperty("Assets", DependencyManager::get<AssetMappingsScriptingInterface>().data());
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
|
_webSurface->getSurfaceContext()->setContextProperty("LODManager", DependencyManager::get<LODManager>().data());
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("OctreeStats", DependencyManager::get<OctreeStatsProvider>().data());
|
_webSurface->getSurfaceContext()->setContextProperty("OctreeStats", DependencyManager::get<OctreeStatsProvider>().data());
|
||||||
|
@ -220,9 +219,6 @@ void Web3DOverlay::setupQmlSurface() {
|
||||||
|
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../");
|
_webSurface->getSurfaceContext()->setContextProperty("pathToFonts", "../../");
|
||||||
|
|
||||||
// Tablet inteference with Tablet.qml. Need to avoid this in QML space
|
|
||||||
_webSurface->getSurfaceContext()->setContextProperty("tabletInterface", DependencyManager::get<TabletScriptingInterface>().data());
|
|
||||||
|
|
||||||
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data());
|
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", _webSurface.data());
|
||||||
// mark the TabletProxy object as cpp ownership.
|
// mark the TabletProxy object as cpp ownership.
|
||||||
QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");
|
QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
using namespace render;
|
using namespace render;
|
||||||
using namespace render::entities;
|
using namespace render::entities;
|
||||||
|
|
||||||
|
static const QString WEB_ENTITY_QML = "controls/WebEntityView.qml";
|
||||||
|
|
||||||
const float METERS_TO_INCHES = 39.3701f;
|
const float METERS_TO_INCHES = 39.3701f;
|
||||||
static uint32_t _currentWebCount{ 0 };
|
static uint32_t _currentWebCount{ 0 };
|
||||||
// Don't allow more than 100 concurrent web views
|
// Don't allow more than 100 concurrent web views
|
||||||
|
@ -218,6 +220,7 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) {
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
|
// FIXME use the surface cache instead of explicit creation
|
||||||
_webSurface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface(), deleter);
|
_webSurface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface(), deleter);
|
||||||
_webSurface->create();
|
_webSurface->create();
|
||||||
}
|
}
|
||||||
|
@ -291,7 +294,6 @@ void WebEntityRenderer::loadSourceURL() {
|
||||||
if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" ||
|
if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" ||
|
||||||
_lastSourceUrl.toLower().endsWith(".htm") || _lastSourceUrl.toLower().endsWith(".html")) {
|
_lastSourceUrl.toLower().endsWith(".htm") || _lastSourceUrl.toLower().endsWith(".html")) {
|
||||||
_contentType = htmlContent;
|
_contentType = htmlContent;
|
||||||
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "qml/controls/"));
|
|
||||||
|
|
||||||
// We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS.
|
// We special case YouTube URLs since we know they are videos that we should play with at least 30 FPS.
|
||||||
if (sourceUrl.host().endsWith("youtube.com", Qt::CaseInsensitive)) {
|
if (sourceUrl.host().endsWith("youtube.com", Qt::CaseInsensitive)) {
|
||||||
|
@ -300,12 +302,11 @@ void WebEntityRenderer::loadSourceURL() {
|
||||||
_webSurface->setMaxFps(DEFAULT_MAX_FPS);
|
_webSurface->setMaxFps(DEFAULT_MAX_FPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
_webSurface->load("WebEntityView.qml", [this](QQmlContext* context, QObject* item) {
|
_webSurface->load("controls/WebEntityView.qml", [this](QQmlContext* context, QObject* item) {
|
||||||
item->setProperty("url", _lastSourceUrl);
|
item->setProperty("url", _lastSourceUrl);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
_contentType = qmlContent;
|
_contentType = qmlContent;
|
||||||
_webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath()));
|
|
||||||
_webSurface->load(_lastSourceUrl);
|
_webSurface->load(_lastSourceUrl);
|
||||||
if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") {
|
if (_webSurface->getRootItem() && _webSurface->getRootItem()->objectName() == "tabletRoot") {
|
||||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||||
|
|
|
@ -217,8 +217,6 @@ gpu::TexturePointer TextureCache::cacheTextureByHash(const std::string& hash, co
|
||||||
if (!result) {
|
if (!result) {
|
||||||
_texturesByHashes[hash] = texture;
|
_texturesByHashes[hash] = texture;
|
||||||
result = texture;
|
result = texture;
|
||||||
} else {
|
|
||||||
qCWarning(modelnetworking) << "QQQ Swapping out texture with previous live texture in hash " << hash.c_str();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -9,10 +9,6 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define _USE_MATH_DEFINES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
|
@ -30,9 +30,30 @@ QString TEMP_DIR_FORMAT { "%1-%2-%3" };
|
||||||
|
|
||||||
const QString& PathUtils::resourcesPath() {
|
const QString& PathUtils::resourcesPath() {
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/../Resources/";
|
static const QString staticResourcePath = QCoreApplication::applicationDirPath() + "/../Resources/";
|
||||||
#else
|
#else
|
||||||
static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/resources/";
|
static const QString staticResourcePath = QCoreApplication::applicationDirPath() + "/resources/";
|
||||||
|
#endif
|
||||||
|
return staticResourcePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEV_BUILD
|
||||||
|
const QString& PathUtils::projectRootPath() {
|
||||||
|
static QString sourceFolder;
|
||||||
|
static std::once_flag once;
|
||||||
|
std::call_once(once, [&] {
|
||||||
|
QDir thisDir = QFileInfo(__FILE__).absoluteDir();
|
||||||
|
sourceFolder = QDir::cleanPath(thisDir.absoluteFilePath("../../../"));
|
||||||
|
});
|
||||||
|
return sourceFolder;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const QString& PathUtils::qmlBasePath() {
|
||||||
|
#ifdef DEV_BUILD
|
||||||
|
static const QString staticResourcePath = QUrl::fromLocalFile(projectRootPath() + "/interface/resources/qml/").toString();
|
||||||
|
#else
|
||||||
|
static const QString staticResourcePath = "qrc:///qml/";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return staticResourcePath;
|
return staticResourcePath;
|
||||||
|
|
|
@ -34,6 +34,10 @@ class PathUtils : public QObject, public Dependency {
|
||||||
Q_PROPERTY(QUrl defaultScripts READ defaultScriptsLocation CONSTANT)
|
Q_PROPERTY(QUrl defaultScripts READ defaultScriptsLocation CONSTANT)
|
||||||
public:
|
public:
|
||||||
static const QString& resourcesPath();
|
static const QString& resourcesPath();
|
||||||
|
static const QString& qmlBasePath();
|
||||||
|
#ifdef DEV_BUILD
|
||||||
|
static const QString& projectRootPath();
|
||||||
|
#endif
|
||||||
|
|
||||||
static QString getAppDataPath();
|
static QString getAppDataPath();
|
||||||
static QString getAppLocalDataPath();
|
static QString getAppLocalDataPath();
|
||||||
|
|
|
@ -134,9 +134,6 @@ void OffscreenUi::create() {
|
||||||
myContext->setContextProperty("OffscreenUi", this);
|
myContext->setContextProperty("OffscreenUi", this);
|
||||||
myContext->setContextProperty("offscreenFlags", offscreenFlags = new OffscreenFlags());
|
myContext->setContextProperty("offscreenFlags", offscreenFlags = new OffscreenFlags());
|
||||||
myContext->setContextProperty("fileDialogHelper", new FileDialogHelper());
|
myContext->setContextProperty("fileDialogHelper", new FileDialogHelper());
|
||||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
|
||||||
TabletProxy* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");
|
|
||||||
myContext->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenUi::show(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f) {
|
void OffscreenUi::show(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f) {
|
||||||
|
|
|
@ -61,8 +61,9 @@ QVariantMap QmlWindowClass::parseArguments(QScriptContext* context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl url { properties[SOURCE_PROPERTY].toString() };
|
QUrl url { properties[SOURCE_PROPERTY].toString() };
|
||||||
|
// If the passed URL doesn't correspond to a known scheme, assume it's a local file path
|
||||||
if (url.scheme() != "http" && url.scheme() != "https" && url.scheme() != "file" && url.scheme() != "about" &&
|
if (url.scheme() != "http" && url.scheme() != "https" && url.scheme() != "file" && url.scheme() != "about" &&
|
||||||
url.scheme() != "atp") {
|
url.scheme() != "atp" && url.scheme() != "qrc") {
|
||||||
properties[SOURCE_PROPERTY] = QUrl::fromLocalFile(url.toString()).toString();
|
properties[SOURCE_PROPERTY] = QUrl::fromLocalFile(url.toString()).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
#include "types/HFWebEngineProfile.h"
|
#include "types/HFWebEngineProfile.h"
|
||||||
#include "types/SoundEffect.h"
|
#include "types/SoundEffect.h"
|
||||||
|
|
||||||
|
#include "TabletScriptingInterface.h"
|
||||||
|
#include "ToolbarScriptingInterface.h"
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(trace_render_qml, "trace.render.qml")
|
Q_LOGGING_CATEGORY(trace_render_qml, "trace.render.qml")
|
||||||
|
@ -65,7 +67,10 @@ public:
|
||||||
|
|
||||||
void addWhitelistContextHandler(const std::initializer_list<QUrl>& urls, const QmlContextCallback& callback) {
|
void addWhitelistContextHandler(const std::initializer_list<QUrl>& urls, const QmlContextCallback& callback) {
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
for (const auto& url : urls) {
|
for (auto url : urls) {
|
||||||
|
if (url.isRelative()) {
|
||||||
|
url = QUrl(PathUtils::qmlBasePath() + url.toString());
|
||||||
|
}
|
||||||
_callbacks[url].push_back(callback);
|
_callbacks[url].push_back(callback);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -102,7 +107,7 @@ void OffscreenQmlSurface::addWhitelistContextHandler(const std::initializer_list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QmlContextCallback OffscreenQmlSurface::DEFAULT_CONTEXT_CALLBACK = [](QQmlContext*, QObject*) {};
|
QmlContextObjectCallback OffscreenQmlSurface::DEFAULT_CONTEXT_CALLBACK = [](QQmlContext*, QQuickItem*) {};
|
||||||
|
|
||||||
struct TextureSet {
|
struct TextureSet {
|
||||||
// The number of surfaces with this size
|
// The number of surfaces with this size
|
||||||
|
@ -443,6 +448,15 @@ void initializeQmlEngine(QQmlEngine* engine, QQuickWindow* window) {
|
||||||
rootContext->setContextProperty("FileTypeProfile", new FileTypeProfile(rootContext));
|
rootContext->setContextProperty("FileTypeProfile", new FileTypeProfile(rootContext));
|
||||||
rootContext->setContextProperty("HFWebEngineProfile", new HFWebEngineProfile(rootContext));
|
rootContext->setContextProperty("HFWebEngineProfile", new HFWebEngineProfile(rootContext));
|
||||||
rootContext->setContextProperty("Paths", DependencyManager::get<PathUtils>().data());
|
rootContext->setContextProperty("Paths", DependencyManager::get<PathUtils>().data());
|
||||||
|
static std::once_flag once;
|
||||||
|
std::call_once(once, [&] {
|
||||||
|
qRegisterMetaType<TabletProxy*>();
|
||||||
|
qRegisterMetaType<TabletButtonProxy*>();
|
||||||
|
});
|
||||||
|
rootContext->setContextProperty("Tablet", DependencyManager::get<TabletScriptingInterface>().data());
|
||||||
|
rootContext->setContextProperty("Toolbars", DependencyManager::get<ToolbarScriptingInterface>().data());
|
||||||
|
TabletProxy* tablet = DependencyManager::get<TabletScriptingInterface>()->getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
engine->setObjectOwnership(tablet, QQmlEngine::CppOwnership);
|
||||||
}
|
}
|
||||||
|
|
||||||
QQmlEngine* acquireEngine(QQuickWindow* window) {
|
QQmlEngine* acquireEngine(QQuickWindow* window) {
|
||||||
|
@ -659,10 +673,11 @@ void OffscreenQmlSurface::create() {
|
||||||
auto qmlEngine = acquireEngine(_quickWindow);
|
auto qmlEngine = acquireEngine(_quickWindow);
|
||||||
|
|
||||||
_qmlContext = new QQmlContext(qmlEngine->rootContext());
|
_qmlContext = new QQmlContext(qmlEngine->rootContext());
|
||||||
|
_qmlContext->setBaseUrl(QUrl{ PathUtils::qmlBasePath() });
|
||||||
_qmlContext->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow()));
|
_qmlContext->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow()));
|
||||||
_qmlContext->setContextProperty("eventBridge", this);
|
_qmlContext->setContextProperty("eventBridge", this);
|
||||||
_qmlContext->setContextProperty("webEntity", this);
|
_qmlContext->setContextProperty("webEntity", this);
|
||||||
|
_qmlContext->setContextProperty("QmlSurface", this);
|
||||||
|
|
||||||
// FIXME Compatibility mechanism for existing HTML and JS that uses eventBridgeWrapper
|
// FIXME Compatibility mechanism for existing HTML and JS that uses eventBridgeWrapper
|
||||||
// Find a way to flag older scripts using this mechanism and wanr that this is deprecated
|
// Find a way to flag older scripts using this mechanism and wanr that this is deprecated
|
||||||
|
@ -801,55 +816,70 @@ QQuickItem* OffscreenQmlSurface::getRootItem() {
|
||||||
return _rootItem;
|
return _rootItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenQmlSurface::setBaseUrl(const QUrl& baseUrl) {
|
QQmlContext* OffscreenQmlSurface::contextForUrl(const QUrl& qmlSource, QQuickItem* parent, bool forceNewContext) {
|
||||||
_qmlContext->setBaseUrl(baseUrl);
|
// Get any whitelist functionality
|
||||||
|
QList<QmlContextCallback> callbacks = getQmlWhitelist()->getCallbacksForUrl(qmlSource);
|
||||||
|
// If we have whitelisted content, we must load a new context
|
||||||
|
forceNewContext |= !callbacks.empty();
|
||||||
|
|
||||||
|
QQmlContext* targetContext = parent ? QQmlEngine::contextForObject(parent) : _qmlContext;
|
||||||
|
if (!targetContext) {
|
||||||
|
targetContext = _qmlContext;
|
||||||
|
}
|
||||||
|
if (_rootItem && forceNewContext) {
|
||||||
|
targetContext = new QQmlContext(targetContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& callback : callbacks) {
|
||||||
|
callback(targetContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, const QmlContextCallback& onQmlLoadedCallback) {
|
void OffscreenQmlSurface::load(const QUrl& qmlSource, QQuickItem* parent, const QJSValue& callback) {
|
||||||
|
loadInternal(qmlSource, false, parent, [callback](QQmlContext* context, QQuickItem* newItem) {
|
||||||
|
QJSValue(callback).call(QJSValueList() << context->engine()->newQObject(newItem));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, const QmlContextObjectCallback& onQmlLoadedCallback) {
|
||||||
|
loadInternal(qmlSource, createNewContext, nullptr, onQmlLoadedCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OffscreenQmlSurface::loadInternal(const QUrl& qmlSource, bool createNewContext, QQuickItem* parent, const QmlContextObjectCallback& onQmlLoadedCallback) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
qCWarning(uiLogging) << "Called load on a non-surface thread";
|
qCWarning(uiLogging) << "Called load on a non-surface thread";
|
||||||
}
|
}
|
||||||
// Synchronous loading may take a while; restart the deadlock timer
|
// Synchronous loading may take a while; restart the deadlock timer
|
||||||
QMetaObject::invokeMethod(qApp, "updateHeartbeat", Qt::DirectConnection);
|
QMetaObject::invokeMethod(qApp, "updateHeartbeat", Qt::DirectConnection);
|
||||||
|
|
||||||
// Get any whitelist functionality
|
|
||||||
QList<QmlContextCallback> callbacks = getQmlWhitelist()->getCallbacksForUrl(qmlSource);
|
|
||||||
// If we have whitelisted content, we must load a new context
|
|
||||||
createNewContext |= !callbacks.empty();
|
|
||||||
callbacks.push_back(onQmlLoadedCallback);
|
|
||||||
|
|
||||||
QQmlContext* targetContext = _qmlContext;
|
|
||||||
if (_rootItem && createNewContext) {
|
|
||||||
targetContext = new QQmlContext(targetContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// FIXME eliminate loading of relative file paths for QML
|
|
||||||
QUrl finalQmlSource = qmlSource;
|
QUrl finalQmlSource = qmlSource;
|
||||||
if ((qmlSource.isRelative() && !qmlSource.isEmpty()) || qmlSource.scheme() == QLatin1String("file")) {
|
if ((qmlSource.isRelative() && !qmlSource.isEmpty()) || qmlSource.scheme() == QLatin1String("file")) {
|
||||||
finalQmlSource = _qmlContext->resolvedUrl(qmlSource);
|
finalQmlSource = _qmlContext->resolvedUrl(qmlSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto targetContext = contextForUrl(finalQmlSource, parent, createNewContext);
|
||||||
auto qmlComponent = new QQmlComponent(_qmlContext->engine(), finalQmlSource, QQmlComponent::PreferSynchronous);
|
auto qmlComponent = new QQmlComponent(_qmlContext->engine(), finalQmlSource, QQmlComponent::PreferSynchronous);
|
||||||
if (qmlComponent->isLoading()) {
|
if (qmlComponent->isLoading()) {
|
||||||
connect(qmlComponent, &QQmlComponent::statusChanged, this, [=](QQmlComponent::Status) {
|
connect(qmlComponent, &QQmlComponent::statusChanged, this, [=](QQmlComponent::Status) {
|
||||||
finishQmlLoad(qmlComponent, targetContext, callbacks);
|
finishQmlLoad(qmlComponent, targetContext, parent, onQmlLoadedCallback);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
finishQmlLoad(qmlComponent, targetContext, callbacks);
|
finishQmlLoad(qmlComponent, targetContext, parent, onQmlLoadedCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, const QmlContextCallback& onQmlLoadedCallback) {
|
void OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback) {
|
||||||
load(qmlSource, true, onQmlLoadedCallback);
|
load(qmlSource, true, onQmlLoadedCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenQmlSurface::load(const QUrl& qmlSource, const QmlContextCallback& onQmlLoadedCallback) {
|
void OffscreenQmlSurface::load(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback) {
|
||||||
load(qmlSource, false, onQmlLoadedCallback);
|
load(qmlSource, false, onQmlLoadedCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenQmlSurface::load(const QString& qmlSourceFile, const QmlContextCallback& onQmlLoadedCallback) {
|
void OffscreenQmlSurface::load(const QString& qmlSourceFile, const QmlContextObjectCallback& onQmlLoadedCallback) {
|
||||||
return load(QUrl(qmlSourceFile), onQmlLoadedCallback);
|
return load(QUrl(qmlSourceFile), onQmlLoadedCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -857,7 +887,8 @@ void OffscreenQmlSurface::clearCache() {
|
||||||
_qmlContext->engine()->clearComponentCache();
|
_qmlContext->engine()->clearComponentCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, const QList<QmlContextCallback>& callbacks) {
|
|
||||||
|
void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, QQuickItem* parent, const QmlContextObjectCallback& callback) {
|
||||||
disconnect(qmlComponent, &QQmlComponent::statusChanged, this, 0);
|
disconnect(qmlComponent, &QQmlComponent::statusChanged, this, 0);
|
||||||
if (qmlComponent->isError()) {
|
if (qmlComponent->isError()) {
|
||||||
for (const auto& error : qmlComponent->errors()) {
|
for (const auto& error : qmlComponent->errors()) {
|
||||||
|
@ -879,6 +910,22 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!newObject) {
|
||||||
|
if (!_rootItem) {
|
||||||
|
qFatal("Could not load object as root item");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qCWarning(uiLogging) << "Unable to load QML item";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject* eventBridge = qmlContext->contextProperty("eventBridge").value<QObject*>();
|
||||||
|
if (qmlContext != _qmlContext && eventBridge && eventBridge != this) {
|
||||||
|
// FIXME Compatibility mechanism for existing HTML and JS that uses eventBridgeWrapper
|
||||||
|
// Find a way to flag older scripts using this mechanism and wanr that this is deprecated
|
||||||
|
qmlContext->setContextProperty("eventBridgeWrapper", new EventBridgeWrapper(eventBridge, qmlContext));
|
||||||
|
}
|
||||||
|
|
||||||
qmlContext->engine()->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
qmlContext->engine()->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
||||||
|
|
||||||
// All quick items should be focusable
|
// All quick items should be focusable
|
||||||
|
@ -889,41 +936,30 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext
|
||||||
newItem->setFlag(QQuickItem::ItemIsFocusScope, true);
|
newItem->setFlag(QQuickItem::ItemIsFocusScope, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Make sure we will call callback for this codepath
|
// Make sure we will call callback for this codepath
|
||||||
// Call this before qmlComponent->completeCreate() otherwise ghost window appears
|
// Call this before qmlComponent->completeCreate() otherwise ghost window appears
|
||||||
if (newItem && _rootItem) {
|
// If we already have a root, just set a couple of flags and the ancestry
|
||||||
for (const auto& callback : callbacks) {
|
if (_rootItem) {
|
||||||
callback(qmlContext, newObject);
|
callback(qmlContext, newItem);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QObject* eventBridge = qmlContext->contextProperty("eventBridge").value<QObject*>();
|
if (!parent) {
|
||||||
if (qmlContext != _qmlContext && eventBridge && eventBridge != this) {
|
parent = _rootItem;
|
||||||
// FIXME Compatibility mechanism for existing HTML and JS that uses eventBridgeWrapper
|
}
|
||||||
// Find a way to flag older scripts using this mechanism and wanr that this is deprecated
|
// Allow child windows to be destroyed from JS
|
||||||
qmlContext->setContextProperty("eventBridgeWrapper", new EventBridgeWrapper(eventBridge, qmlContext));
|
QQmlEngine::setObjectOwnership(newObject, QQmlEngine::JavaScriptOwnership);
|
||||||
|
newObject->setParent(parent);
|
||||||
|
newItem->setParentItem(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
qmlComponent->completeCreate();
|
qmlComponent->completeCreate();
|
||||||
qmlComponent->deleteLater();
|
qmlComponent->deleteLater();
|
||||||
|
|
||||||
// If we already have a root, just set a couple of flags and the ancestry
|
if (_rootItem) {
|
||||||
if (newItem && _rootItem) {
|
|
||||||
// Allow child windows to be destroyed from JS
|
|
||||||
QQmlEngine::setObjectOwnership(newObject, QQmlEngine::JavaScriptOwnership);
|
|
||||||
newObject->setParent(_rootItem);
|
|
||||||
if (newItem) {
|
|
||||||
newItem->setParentItem(_rootItem);
|
|
||||||
}
|
|
||||||
QMetaObject::invokeMethod(this, "forceQmlAudioOutputDeviceUpdate", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(this, "forceQmlAudioOutputDeviceUpdate", Qt::QueuedConnection);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newItem) {
|
|
||||||
qFatal("Could not load object as root item");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant)));
|
connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant)));
|
||||||
|
|
||||||
// The root item is ready. Associate it with the window.
|
// The root item is ready. Associate it with the window.
|
||||||
|
@ -931,11 +967,16 @@ void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext
|
||||||
_rootItem->setParentItem(_quickWindow->contentItem());
|
_rootItem->setParentItem(_quickWindow->contentItem());
|
||||||
_rootItem->setSize(_quickWindow->renderTargetSize());
|
_rootItem->setSize(_quickWindow->renderTargetSize());
|
||||||
|
|
||||||
// Call this callback after rootitem is set, otherwise VrMenu wont work
|
if (_rootItem->objectName() == "tabletRoot") {
|
||||||
for (const auto& callback : callbacks) {
|
_qmlContext->setContextProperty("tabletRoot", QVariant::fromValue(_rootItem));
|
||||||
callback(qmlContext, newObject);
|
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||||
|
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", this);
|
||||||
|
QObject* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");
|
||||||
|
_qmlContext->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership);
|
||||||
}
|
}
|
||||||
QMetaObject::invokeMethod(this, "forceQmlAudioOutputDeviceUpdate", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(this, "forceQmlAudioOutputDeviceUpdate", Qt::QueuedConnection);
|
||||||
|
// Call this callback after rootitem is set, otherwise VrMenu wont work
|
||||||
|
callback(qmlContext, newItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenQmlSurface::updateQuick() {
|
void OffscreenQmlSurface::updateQuick() {
|
||||||
|
|
|
@ -33,12 +33,14 @@ class QQmlContext;
|
||||||
class QQmlComponent;
|
class QQmlComponent;
|
||||||
class QQuickWindow;
|
class QQuickWindow;
|
||||||
class QQuickItem;
|
class QQuickItem;
|
||||||
|
class QJSValue;
|
||||||
|
|
||||||
// GPU resources are typically buffered for one copy being used by the renderer,
|
// GPU resources are typically buffered for one copy being used by the renderer,
|
||||||
// one copy in flight, and one copy being used by the receiver
|
// one copy in flight, and one copy being used by the receiver
|
||||||
#define GPU_RESOURCE_BUFFER_SIZE 3
|
#define GPU_RESOURCE_BUFFER_SIZE 3
|
||||||
|
|
||||||
using QmlContextCallback = std::function<void(QQmlContext*, QObject*)>;
|
using QmlContextCallback = std::function<void(QQmlContext*)>;
|
||||||
|
using QmlContextObjectCallback = std::function<void(QQmlContext*, QQuickItem*)>;
|
||||||
|
|
||||||
class OffscreenQmlSurface : public QObject, public QEnableSharedFromThis<OffscreenQmlSurface> {
|
class OffscreenQmlSurface : public QObject, public QEnableSharedFromThis<OffscreenQmlSurface> {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -46,7 +48,7 @@ class OffscreenQmlSurface : public QObject, public QEnableSharedFromThis<Offscre
|
||||||
public:
|
public:
|
||||||
static void setSharedContext(QOpenGLContext* context);
|
static void setSharedContext(QOpenGLContext* context);
|
||||||
|
|
||||||
static QmlContextCallback DEFAULT_CONTEXT_CALLBACK;
|
static QmlContextObjectCallback DEFAULT_CONTEXT_CALLBACK;
|
||||||
static void addWhitelistContextHandler(const std::initializer_list<QUrl>& urls, const QmlContextCallback& callback);
|
static void addWhitelistContextHandler(const std::initializer_list<QUrl>& urls, const QmlContextCallback& callback);
|
||||||
static void addWhitelistContextHandler(const QUrl& url, const QmlContextCallback& callback) { addWhitelistContextHandler({ { url } }, callback); };
|
static void addWhitelistContextHandler(const QUrl& url, const QmlContextCallback& callback) { addWhitelistContextHandler({ { url } }, callback); };
|
||||||
|
|
||||||
|
@ -59,10 +61,15 @@ public:
|
||||||
void resize(const QSize& size, bool forceResize = false);
|
void resize(const QSize& size, bool forceResize = false);
|
||||||
QSize size() const;
|
QSize size() const;
|
||||||
|
|
||||||
Q_INVOKABLE void load(const QUrl& qmlSource, bool createNewContext, const QmlContextCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK);
|
// Usable from QML code as QmlSurface.load(url, parent, function(newItem){ ... })
|
||||||
Q_INVOKABLE void loadInNewContext(const QUrl& qmlSource, const QmlContextCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK);
|
Q_INVOKABLE void load(const QUrl& qmlSource, QQuickItem* parent, const QJSValue& callback);
|
||||||
Q_INVOKABLE void load(const QUrl& qmlSource, const QmlContextCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK);
|
|
||||||
Q_INVOKABLE void load(const QString& qmlSourceFile, const QmlContextCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK);
|
// For C++ use
|
||||||
|
Q_INVOKABLE void load(const QUrl& qmlSource, bool createNewContext, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK);
|
||||||
|
Q_INVOKABLE void loadInNewContext(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK);
|
||||||
|
Q_INVOKABLE void load(const QUrl& qmlSource, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK);
|
||||||
|
Q_INVOKABLE void load(const QString& qmlSourceFile, const QmlContextObjectCallback& onQmlLoadedCallback = DEFAULT_CONTEXT_CALLBACK);
|
||||||
|
|
||||||
void clearCache();
|
void clearCache();
|
||||||
void setMaxFps(uint8_t maxFps) { _maxFps = maxFps; }
|
void setMaxFps(uint8_t maxFps) { _maxFps = maxFps; }
|
||||||
// Optional values for event handling
|
// Optional values for event handling
|
||||||
|
@ -77,7 +84,6 @@ public:
|
||||||
bool isPaused() const;
|
bool isPaused() const;
|
||||||
bool getCleaned() { return _isCleaned; }
|
bool getCleaned() { return _isCleaned; }
|
||||||
|
|
||||||
void setBaseUrl(const QUrl& baseUrl);
|
|
||||||
QQuickItem* getRootItem();
|
QQuickItem* getRootItem();
|
||||||
QQuickWindow* getWindow();
|
QQuickWindow* getWindow();
|
||||||
QObject* getEventHandler();
|
QObject* getEventHandler();
|
||||||
|
@ -142,13 +148,13 @@ protected:
|
||||||
private:
|
private:
|
||||||
static QOpenGLContext* getSharedContext();
|
static QOpenGLContext* getSharedContext();
|
||||||
|
|
||||||
void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, const QList<QmlContextCallback>& callbacks);
|
QQmlContext* contextForUrl(const QUrl& url, QQuickItem* parent, bool forceNewContext = false);
|
||||||
|
void loadInternal(const QUrl& qmlSource, bool createNewContext, QQuickItem* parent, const QmlContextObjectCallback& onQmlLoadedCallback);
|
||||||
|
void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, QQuickItem* parent, const QmlContextObjectCallback& onQmlLoadedCallback);
|
||||||
QPointF mapWindowToUi(const QPointF& sourcePosition, QObject* sourceObject);
|
QPointF mapWindowToUi(const QPointF& sourcePosition, QObject* sourceObject);
|
||||||
void setupFbo();
|
|
||||||
bool allowNewFrame(uint8_t fps);
|
bool allowNewFrame(uint8_t fps);
|
||||||
void render();
|
void render();
|
||||||
void cleanup();
|
void cleanup();
|
||||||
QJsonObject getGLContextData();
|
|
||||||
void disconnectAudioOutputTimer();
|
void disconnectAudioOutputTimer();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
|
@ -45,7 +45,6 @@ void OffscreenQmlSurfaceCache::release(const QString& rootSource, const QSharedP
|
||||||
QSharedPointer<OffscreenQmlSurface> OffscreenQmlSurfaceCache::buildSurface(const QString& rootSource) {
|
QSharedPointer<OffscreenQmlSurface> OffscreenQmlSurfaceCache::buildSurface(const QString& rootSource) {
|
||||||
auto surface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface());
|
auto surface = QSharedPointer<OffscreenQmlSurface>(new OffscreenQmlSurface());
|
||||||
surface->create();
|
surface->create();
|
||||||
surface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
|
|
||||||
surface->load(rootSource);
|
surface->load(rootSource);
|
||||||
surface->resize(QSize(100, 100));
|
surface->resize(QSize(100, 100));
|
||||||
return surface;
|
return surface;
|
||||||
|
|
|
@ -32,6 +32,14 @@ const QString SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system";
|
||||||
const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
|
const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
|
||||||
const QString TabletScriptingInterface::QML = "hifi/tablet/TabletRoot.qml";
|
const QString TabletScriptingInterface::QML = "hifi/tablet/TabletRoot.qml";
|
||||||
|
|
||||||
|
static QString getUsername() {
|
||||||
|
QString username = "Unknown user";
|
||||||
|
auto accountManager = DependencyManager::get<AccountManager>();
|
||||||
|
if (accountManager->isLoggedIn()) {
|
||||||
|
username = accountManager->getAccountInfo().getUsername();
|
||||||
|
}
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
static Setting::Handle<QStringList> tabletSoundsButtonClick("TabletSounds", QStringList { "/sounds/Button06.wav",
|
static Setting::Handle<QStringList> tabletSoundsButtonClick("TabletSounds", QStringList { "/sounds/Button06.wav",
|
||||||
"/sounds/Button04.wav",
|
"/sounds/Button04.wav",
|
||||||
|
@ -39,6 +47,51 @@ static Setting::Handle<QStringList> tabletSoundsButtonClick("TabletSounds", QStr
|
||||||
"/sounds/Tab01.wav",
|
"/sounds/Tab01.wav",
|
||||||
"/sounds/Tab02.wav" });
|
"/sounds/Tab02.wav" });
|
||||||
|
|
||||||
|
TabletButtonListModel::TabletButtonListModel() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TabletButtonListModel::~TabletButtonListModel() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ButtonDeviceRole {
|
||||||
|
ButtonProxyRole = Qt::UserRole,
|
||||||
|
};
|
||||||
|
|
||||||
|
QHash<int, QByteArray> TabletButtonListModel::_roles{
|
||||||
|
{ ButtonProxyRole, "buttonProxy" },
|
||||||
|
};
|
||||||
|
|
||||||
|
Qt::ItemFlags TabletButtonListModel::_flags{ Qt::ItemIsSelectable | Qt::ItemIsEnabled };
|
||||||
|
|
||||||
|
QVariant TabletButtonListModel::data(const QModelIndex& index, int role) const {
|
||||||
|
if (!index.isValid() || index.row() >= rowCount() || role != ButtonProxyRole) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant::fromValue(_buttons.at(index.row()).data());
|
||||||
|
}
|
||||||
|
|
||||||
|
TabletButtonProxy* TabletButtonListModel::addButton(const QVariant& properties) {
|
||||||
|
auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap()));
|
||||||
|
beginResetModel();
|
||||||
|
_buttons.push_back(tabletButtonProxy);
|
||||||
|
endResetModel();
|
||||||
|
return tabletButtonProxy.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabletButtonListModel::removeButton(TabletButtonProxy* button) {
|
||||||
|
auto itr = std::find(_buttons.begin(), _buttons.end(), button);
|
||||||
|
if (itr == _buttons.end()) {
|
||||||
|
qCWarning(uiLogging) << "TabletProxy::removeButton() could not find button " << button;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
beginResetModel();
|
||||||
|
_buttons.erase(itr);
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
TabletScriptingInterface::TabletScriptingInterface() {
|
TabletScriptingInterface::TabletScriptingInterface() {
|
||||||
qmlRegisterType<TabletScriptingInterface>("TabletScriptingInterface", 1, 0, "TabletEnums");
|
qmlRegisterType<TabletScriptingInterface>("TabletScriptingInterface", 1, 0, "TabletEnums");
|
||||||
}
|
}
|
||||||
|
@ -210,9 +263,9 @@ QObject* TabletScriptingInterface::getFlags() {
|
||||||
// TabletProxy
|
// TabletProxy
|
||||||
//
|
//
|
||||||
|
|
||||||
static const char* TABLET_SOURCE_URL = "Tablet.qml";
|
static const char* TABLET_HOME_SOURCE_URL = "hifi/tablet/TabletHome.qml";
|
||||||
static const char* WEB_VIEW_SOURCE_URL = "TabletWebView.qml";
|
static const char* WEB_VIEW_SOURCE_URL = "hifi/tablet/TabletWebView.qml";
|
||||||
static const char* VRMENU_SOURCE_URL = "TabletMenu.qml";
|
static const char* VRMENU_SOURCE_URL = "hifi/tablet/TabletMenu.qml";
|
||||||
|
|
||||||
class TabletRootWindow : public QmlWindowClass {
|
class TabletRootWindow : public QmlWindowClass {
|
||||||
virtual QString qmlSource() const override { return "hifi/tablet/WindowRoot.qml"; }
|
virtual QString qmlSource() const override { return "hifi/tablet/WindowRoot.qml"; }
|
||||||
|
@ -247,9 +300,6 @@ void TabletProxy::setToolbarMode(bool toolbarMode) {
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
|
||||||
if (toolbarMode) {
|
if (toolbarMode) {
|
||||||
removeButtonsFromHomeScreen();
|
|
||||||
addButtonsToToolbar();
|
|
||||||
|
|
||||||
// create new desktop window
|
// create new desktop window
|
||||||
auto tabletRootWindow = new TabletRootWindow();
|
auto tabletRootWindow = new TabletRootWindow();
|
||||||
tabletRootWindow->initQml(QVariantMap());
|
tabletRootWindow->initQml(QVariantMap());
|
||||||
|
@ -264,11 +314,7 @@ void TabletProxy::setToolbarMode(bool toolbarMode) {
|
||||||
// forward qml surface events to interface js
|
// forward qml surface events to interface js
|
||||||
connect(tabletRootWindow, &QmlWindowClass::fromQml, this, &TabletProxy::fromQml);
|
connect(tabletRootWindow, &QmlWindowClass::fromQml, this, &TabletProxy::fromQml);
|
||||||
} else {
|
} else {
|
||||||
removeButtonsFromToolbar();
|
if (_currentPathLoaded != TABLET_HOME_SOURCE_URL) {
|
||||||
|
|
||||||
if (_currentPathLoaded == TABLET_SOURCE_URL) {
|
|
||||||
addButtonsToHomeScreen();
|
|
||||||
} else {
|
|
||||||
loadHomeScreen(true);
|
loadHomeScreen(true);
|
||||||
}
|
}
|
||||||
//check if running scripts window opened and save it for reopen in Tablet
|
//check if running scripts window opened and save it for reopen in Tablet
|
||||||
|
@ -282,40 +328,8 @@ void TabletProxy::setToolbarMode(bool toolbarMode) {
|
||||||
_desktopWindow = nullptr;
|
_desktopWindow = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void addButtonProxyToQmlTablet(QQuickItem* qmlTablet, TabletButtonProxy* buttonProxy) {
|
emit toolbarModeChanged();
|
||||||
Q_ASSERT(QThread::currentThread() == qApp->thread());
|
|
||||||
if (buttonProxy == NULL){
|
|
||||||
qCCritical(uiLogging) << "TabletScriptingInterface addButtonProxyToQmlTablet buttonProxy is NULL";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant resultVar;
|
|
||||||
bool hasResult = QMetaObject::invokeMethod(qmlTablet, "addButtonProxy", Qt::DirectConnection,
|
|
||||||
Q_RETURN_ARG(QVariant, resultVar), Q_ARG(QVariant, buttonProxy->getProperties()));
|
|
||||||
if (!hasResult) {
|
|
||||||
qCWarning(uiLogging) << "TabletScriptingInterface addButtonProxyToQmlTablet has no result";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QObject* qmlButton = qvariant_cast<QObject *>(resultVar);
|
|
||||||
if (!qmlButton) {
|
|
||||||
qCWarning(uiLogging) << "TabletScriptingInterface addButtonProxyToQmlTablet result not a QObject";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
QObject::connect(qmlButton, SIGNAL(clicked()), buttonProxy, SLOT(clickedSlot()));
|
|
||||||
buttonProxy->setQmlButton(qobject_cast<QQuickItem*>(qmlButton));
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString getUsername() {
|
|
||||||
QString username = "Unknown user";
|
|
||||||
auto accountManager = DependencyManager::get<AccountManager>();
|
|
||||||
if (accountManager->isLoggedIn()) {
|
|
||||||
return accountManager->getAccountInfo().getUsername();
|
|
||||||
} else {
|
|
||||||
return "Unknown user";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabletProxy::initialScreen(const QVariant& url) {
|
void TabletProxy::initialScreen(const QVariant& url) {
|
||||||
|
@ -363,7 +377,7 @@ void TabletProxy::onTabletShown() {
|
||||||
static_cast<TabletScriptingInterface*>(parent())->playSound(TabletScriptingInterface::TabletOpen);
|
static_cast<TabletScriptingInterface*>(parent())->playSound(TabletScriptingInterface::TabletOpen);
|
||||||
if (_showRunningScripts) {
|
if (_showRunningScripts) {
|
||||||
_showRunningScripts = false;
|
_showRunningScripts = false;
|
||||||
pushOntoStack("../../hifi/dialogs/TabletRunningScripts.qml");
|
pushOntoStack("hifi/dialogs/TabletRunningScripts.qml");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,10 +411,7 @@ void TabletProxy::setQmlTabletRoot(OffscreenQmlSurface* qmlOffscreenSurface) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (_toolbarMode) {
|
if (_toolbarMode) {
|
||||||
// if someone creates the tablet in toolbar mode, make sure to display the home screen on the tablet.
|
QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_HOME_SOURCE_URL)));
|
||||||
auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader");
|
|
||||||
QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen()));
|
|
||||||
QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_SOURCE_URL)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// force to the tablet to go to the homescreen
|
// force to the tablet to go to the homescreen
|
||||||
|
@ -436,7 +447,6 @@ void TabletProxy::setQmlTabletRoot(OffscreenQmlSurface* qmlOffscreenSurface) {
|
||||||
QMetaObject::invokeMethod(_qmlTabletRoot, "setShown", Q_ARG(const QVariant&, QVariant(true)));
|
QMetaObject::invokeMethod(_qmlTabletRoot, "setShown", Q_ARG(const QVariant&, QVariant(true)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
removeButtonsFromHomeScreen();
|
|
||||||
_state = State::Uninitialized;
|
_state = State::Uninitialized;
|
||||||
emit screenChanged(QVariant("Closed"), QVariant(""));
|
emit screenChanged(QVariant("Closed"), QVariant(""));
|
||||||
_currentPathLoaded = "";
|
_currentPathLoaded = "";
|
||||||
|
@ -465,7 +475,6 @@ void TabletProxy::gotoMenuScreen(const QString& submenu) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root) {
|
if (root) {
|
||||||
removeButtonsFromHomeScreen();
|
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
QObject* menu = offscreenUi->getRootMenu();
|
QObject* menu = offscreenUi->getRootMenu();
|
||||||
QMetaObject::invokeMethod(root, "setMenuProperties", Q_ARG(QVariant, QVariant::fromValue(menu)), Q_ARG(const QVariant&, QVariant(submenu)));
|
QMetaObject::invokeMethod(root, "setMenuProperties", Q_ARG(QVariant, QVariant::fromValue(menu)), Q_ARG(const QVariant&, QVariant(submenu)));
|
||||||
|
@ -539,7 +548,6 @@ void TabletProxy::loadQMLSource(const QVariant& path, bool resizable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root) {
|
if (root) {
|
||||||
removeButtonsFromHomeScreen(); //works only in Tablet
|
|
||||||
QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, path));
|
QMetaObject::invokeMethod(root, "loadSource", Q_ARG(const QVariant&, path));
|
||||||
_state = State::QML;
|
_state = State::QML;
|
||||||
if (path != _currentPathLoaded) {
|
if (path != _currentPathLoaded) {
|
||||||
|
@ -621,9 +629,7 @@ void TabletProxy::loadHomeScreen(bool forceOntoHomeScreen) {
|
||||||
|
|
||||||
if ((_state != State::Home && _state != State::Uninitialized) || forceOntoHomeScreen) {
|
if ((_state != State::Home && _state != State::Uninitialized) || forceOntoHomeScreen) {
|
||||||
if (!_toolbarMode && _qmlTabletRoot) {
|
if (!_toolbarMode && _qmlTabletRoot) {
|
||||||
auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader");
|
QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_HOME_SOURCE_URL)));
|
||||||
QObject::connect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen()));
|
|
||||||
QMetaObject::invokeMethod(_qmlTabletRoot, "loadSource", Q_ARG(const QVariant&, QVariant(TABLET_SOURCE_URL)));
|
|
||||||
QMetaObject::invokeMethod(_qmlTabletRoot, "playButtonClickSound");
|
QMetaObject::invokeMethod(_qmlTabletRoot, "playButtonClickSound");
|
||||||
} else if (_toolbarMode && _desktopWindow) {
|
} else if (_toolbarMode && _desktopWindow) {
|
||||||
// close desktop window
|
// close desktop window
|
||||||
|
@ -632,8 +638,8 @@ void TabletProxy::loadHomeScreen(bool forceOntoHomeScreen) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_state = State::Home;
|
_state = State::Home;
|
||||||
emit screenChanged(QVariant("Home"), QVariant(TABLET_SOURCE_URL));
|
emit screenChanged(QVariant("Home"), QVariant(TABLET_HOME_SOURCE_URL));
|
||||||
_currentPathLoaded = TABLET_SOURCE_URL;
|
_currentPathLoaded = TABLET_HOME_SOURCE_URL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,17 +689,18 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root) {
|
if (root) {
|
||||||
removeButtonsFromHomeScreen();
|
|
||||||
if (loadOtherBase) {
|
if (loadOtherBase) {
|
||||||
QMetaObject::invokeMethod(root, "loadTabletWebBase");
|
QMetaObject::invokeMethod(root, "loadTabletWebBase", Q_ARG(const QVariant&, QVariant(url)), Q_ARG(const QVariant&, QVariant(injectedJavaScriptUrl)));
|
||||||
} else {
|
} else {
|
||||||
QMetaObject::invokeMethod(root, "loadWebBase");
|
QMetaObject::invokeMethod(root, "loadWebBase", Q_ARG(const QVariant&, QVariant(url)), Q_ARG(const QVariant&, QVariant(injectedJavaScriptUrl)));
|
||||||
}
|
}
|
||||||
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
|
QMetaObject::invokeMethod(root, "setShown", Q_ARG(const QVariant&, QVariant(true)));
|
||||||
if (_toolbarMode && _desktopWindow) {
|
if (_toolbarMode && _desktopWindow) {
|
||||||
QMetaObject::invokeMethod(root, "setResizable", Q_ARG(const QVariant&, QVariant(false)));
|
QMetaObject::invokeMethod(root, "setResizable", Q_ARG(const QVariant&, QVariant(false)));
|
||||||
}
|
}
|
||||||
QMetaObject::invokeMethod(root, "loadWebUrl", Q_ARG(const QVariant&, QVariant(url)), Q_ARG(const QVariant&, QVariant(injectedJavaScriptUrl)));
|
_state = State::Web;
|
||||||
|
emit screenChanged(QVariant("Web"), QVariant(url));
|
||||||
|
_currentPathLoaded = QVariant(url);
|
||||||
} else {
|
} else {
|
||||||
// tablet is not initialized yet, save information and load when
|
// tablet is not initialized yet, save information and load when
|
||||||
// the tablet root is set
|
// the tablet root is set
|
||||||
|
@ -702,10 +709,8 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS
|
||||||
_initialWebPathParams.first = injectedJavaScriptUrl;
|
_initialWebPathParams.first = injectedJavaScriptUrl;
|
||||||
_initialWebPathParams.second = loadOtherBase;
|
_initialWebPathParams.second = loadOtherBase;
|
||||||
_initialScreen = true;
|
_initialScreen = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
_state = State::Web;
|
|
||||||
emit screenChanged(QVariant("Web"), QVariant(url));
|
|
||||||
_currentPathLoaded = QVariant(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TabletButtonProxy* TabletProxy::addButton(const QVariant& properties) {
|
TabletButtonProxy* TabletProxy::addButton(const QVariant& properties) {
|
||||||
|
@ -715,24 +720,7 @@ TabletButtonProxy* TabletProxy::addButton(const QVariant& properties) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap()));
|
return _buttons.addButton(properties);
|
||||||
_tabletButtonProxies.push_back(tabletButtonProxy);
|
|
||||||
if (!_toolbarMode && _qmlTabletRoot) {
|
|
||||||
auto tablet = getQmlTablet();
|
|
||||||
if (tablet) {
|
|
||||||
addButtonProxyToQmlTablet(tablet, tabletButtonProxy.data());
|
|
||||||
} else {
|
|
||||||
qCCritical(uiLogging) << "Could not find tablet in TabletRoot.qml";
|
|
||||||
}
|
|
||||||
} else if (_toolbarMode) {
|
|
||||||
auto toolbarProxy = DependencyManager::get<TabletScriptingInterface>()->getSystemToolbarProxy();
|
|
||||||
if (toolbarProxy) {
|
|
||||||
// copy properties from tablet button proxy to toolbar button proxy.
|
|
||||||
auto toolbarButtonProxy = toolbarProxy->addButton(tabletButtonProxy->getProperties());
|
|
||||||
tabletButtonProxy->setToolbarButtonProxy(toolbarButtonProxy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tabletButtonProxy.data();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TabletProxy::onHomeScreen() {
|
bool TabletProxy::onHomeScreen() {
|
||||||
|
@ -751,35 +739,7 @@ void TabletProxy::removeButton(TabletButtonProxy* tabletButtonProxy) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tablet = getQmlTablet();
|
_buttons.removeButton(tabletButtonProxy);
|
||||||
if (!tablet) {
|
|
||||||
qCCritical(uiLogging) << "Could not find tablet in TabletRoot.qml";
|
|
||||||
}
|
|
||||||
|
|
||||||
QSharedPointer<TabletButtonProxy> buttonProxy;
|
|
||||||
{
|
|
||||||
auto iter = std::find(_tabletButtonProxies.begin(), _tabletButtonProxies.end(), tabletButtonProxy);
|
|
||||||
if (iter == _tabletButtonProxies.end()) {
|
|
||||||
qCWarning(uiLogging) << "TabletProxy::removeButton() could not find button " << tabletButtonProxy;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
buttonProxy = *iter;
|
|
||||||
_tabletButtonProxies.erase(iter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_toolbarMode && _qmlTabletRoot) {
|
|
||||||
buttonProxy->setQmlButton(nullptr);
|
|
||||||
if (tablet) {
|
|
||||||
QMetaObject::invokeMethod(tablet, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, buttonProxy->getProperties()));
|
|
||||||
}
|
|
||||||
} else if (_toolbarMode) {
|
|
||||||
auto toolbarProxy = DependencyManager::get<TabletScriptingInterface>()->getSystemToolbarProxy();
|
|
||||||
// remove button from toolbarProxy
|
|
||||||
if (toolbarProxy) {
|
|
||||||
toolbarProxy->removeButton(buttonProxy->getUuid().toString());
|
|
||||||
buttonProxy->setToolbarButtonProxy(nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabletProxy::emitScriptEvent(const QVariant& msg) {
|
void TabletProxy::emitScriptEvent(const QVariant& msg) {
|
||||||
|
@ -808,57 +768,16 @@ void TabletProxy::sendToQml(const QVariant& msg) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabletProxy::addButtonsToHomeScreen() {
|
|
||||||
auto tablet = getQmlTablet();
|
|
||||||
if (!tablet || _toolbarMode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (auto& buttonProxy : _tabletButtonProxies) {
|
|
||||||
addButtonProxyToQmlTablet(tablet, buttonProxy.data());
|
|
||||||
}
|
|
||||||
auto loader = _qmlTabletRoot->findChild<QQuickItem*>("loader");
|
|
||||||
QObject::disconnect(loader, SIGNAL(loaded()), this, SLOT(addButtonsToHomeScreen()));
|
|
||||||
}
|
|
||||||
|
|
||||||
OffscreenQmlSurface* TabletProxy::getTabletSurface() {
|
OffscreenQmlSurface* TabletProxy::getTabletSurface() {
|
||||||
return _qmlOffscreenSurface;
|
return _qmlOffscreenSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabletProxy::removeButtonsFromHomeScreen() {
|
|
||||||
auto tablet = getQmlTablet();
|
|
||||||
for (auto& buttonProxy : _tabletButtonProxies) {
|
|
||||||
if (tablet) {
|
|
||||||
QMetaObject::invokeMethod(tablet, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, buttonProxy->getProperties()));
|
|
||||||
}
|
|
||||||
buttonProxy->setQmlButton(nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabletProxy::desktopWindowClosed() {
|
void TabletProxy::desktopWindowClosed() {
|
||||||
gotoHomeScreen();
|
gotoHomeScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabletProxy::addButtonsToToolbar() {
|
|
||||||
Q_ASSERT(QThread::currentThread() == thread());
|
|
||||||
ToolbarProxy* toolbarProxy = DependencyManager::get<TabletScriptingInterface>()->getSystemToolbarProxy();
|
|
||||||
for (auto& buttonProxy : _tabletButtonProxies) {
|
|
||||||
// copy properties from tablet button proxy to toolbar button proxy.
|
|
||||||
buttonProxy->setToolbarButtonProxy(toolbarProxy->addButton(buttonProxy->getProperties()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// make the toolbar visible
|
|
||||||
toolbarProxy->writeProperty("visible", QVariant(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabletProxy::removeButtonsFromToolbar() {
|
|
||||||
Q_ASSERT(QThread::currentThread() == thread());
|
|
||||||
ToolbarProxy* toolbarProxy = DependencyManager::get<TabletScriptingInterface>()->getSystemToolbarProxy();
|
|
||||||
for (auto& buttonProxy : _tabletButtonProxies) {
|
|
||||||
// remove button from toolbarProxy
|
|
||||||
toolbarProxy->removeButton(buttonProxy->getUuid().toString());
|
|
||||||
buttonProxy->setToolbarButtonProxy(nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QQuickItem* TabletProxy::getQmlTablet() const {
|
QQuickItem* TabletProxy::getQmlTablet() const {
|
||||||
if (!_qmlTabletRoot) {
|
if (!_qmlTabletRoot) {
|
||||||
|
@ -928,25 +847,6 @@ TabletButtonProxy::~TabletButtonProxy() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabletButtonProxy::setQmlButton(QQuickItem* qmlButton) {
|
|
||||||
Q_ASSERT(QThread::currentThread() == qApp->thread());
|
|
||||||
if (_qmlButton) {
|
|
||||||
QObject::disconnect(_qmlButton, &QQuickItem::destroyed, this, nullptr);
|
|
||||||
}
|
|
||||||
_qmlButton = qmlButton;
|
|
||||||
if (_qmlButton) {
|
|
||||||
QObject::connect(_qmlButton, &QQuickItem::destroyed, this, [this] { _qmlButton = nullptr; });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabletButtonProxy::setToolbarButtonProxy(QObject* toolbarButtonProxy) {
|
|
||||||
Q_ASSERT(QThread::currentThread() == thread());
|
|
||||||
_toolbarButtonProxy = toolbarButtonProxy;
|
|
||||||
if (_toolbarButtonProxy) {
|
|
||||||
QObject::connect(_toolbarButtonProxy, SIGNAL(clicked()), this, SLOT(clickedSlot()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap TabletButtonProxy::getProperties() {
|
QVariantMap TabletButtonProxy::getProperties() {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QVariantMap result;
|
QVariantMap result;
|
||||||
|
@ -963,20 +863,19 @@ void TabletButtonProxy::editProperties(const QVariantMap& properties) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
QVariantMap::const_iterator iter = properties.constBegin();
|
QVariantMap::const_iterator iter = properties.constBegin();
|
||||||
while (iter != properties.constEnd()) {
|
while (iter != properties.constEnd()) {
|
||||||
const auto& key = iter.key();
|
const auto& key = iter.key();
|
||||||
const auto& value = iter.value();
|
const auto& value = iter.value();
|
||||||
if (!_properties.contains(key) || _properties[key] != value) {
|
if (!_properties.contains(key) || _properties[key] != value) {
|
||||||
_properties[iter.key()] = iter.value();
|
_properties[key] = value;
|
||||||
if (_qmlButton) {
|
changed = true;
|
||||||
QMetaObject::invokeMethod(_qmlButton, "changeProperty", Qt::AutoConnection, Q_ARG(QVariant, QVariant(iter.key())), Q_ARG(QVariant, iter.value()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
++iter;
|
++iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_toolbarButtonProxy) {
|
if (changed) {
|
||||||
QMetaObject::invokeMethod(_toolbarButtonProxy, "editProperties", Qt::AutoConnection, Q_ARG(QVariantMap, properties));
|
emit propertiesChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,13 +12,16 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QVariant>
|
#include <QtCore/QUuid>
|
||||||
|
#include <QtCore/QVariant>
|
||||||
|
#include <QtCore/QAbstractListModel>
|
||||||
|
|
||||||
#include <QtScript/QScriptValue>
|
#include <QtScript/QScriptValue>
|
||||||
#include <QScriptEngine>
|
#include <QtScript/QScriptEngine>
|
||||||
#include <QScriptValueIterator>
|
#include <QtScript/QScriptValueIterator>
|
||||||
#include <QQuickItem>
|
|
||||||
#include <QUuid>
|
#include <QtQuick/QQuickItem>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
@ -90,6 +93,31 @@ protected:
|
||||||
bool _toolbarMode { false };
|
bool _toolbarMode { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class TabletButtonListModel : public QAbstractListModel {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
TabletButtonListModel();
|
||||||
|
~TabletButtonListModel();
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex& parent = QModelIndex()) const override { Q_UNUSED(parent); return (int)_buttons.size(); }
|
||||||
|
QHash<int, QByteArray> roleNames() const override { return _roles; }
|
||||||
|
Qt::ItemFlags flags(const QModelIndex& index) const override { return _flags; }
|
||||||
|
QVariant data(const QModelIndex& index, int role) const override;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class TabletProxy;
|
||||||
|
TabletButtonProxy* addButton(const QVariant& properties);
|
||||||
|
void removeButton(TabletButtonProxy* button);
|
||||||
|
using List = std::list<QSharedPointer<TabletButtonProxy>>;
|
||||||
|
static QHash<int, QByteArray> _roles;
|
||||||
|
static Qt::ItemFlags _flags;
|
||||||
|
std::vector<QSharedPointer<TabletButtonProxy>> _buttons;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(TabletButtonListModel*);
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* @class TabletProxy
|
* @class TabletProxy
|
||||||
* @property name {string} READ_ONLY: name of this tablet
|
* @property name {string} READ_ONLY: name of this tablet
|
||||||
|
@ -99,9 +127,10 @@ protected:
|
||||||
class TabletProxy : public QObject {
|
class TabletProxy : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QString name READ getName)
|
Q_PROPERTY(QString name READ getName)
|
||||||
Q_PROPERTY(bool toolbarMode READ getToolbarMode WRITE setToolbarMode)
|
Q_PROPERTY(bool toolbarMode READ getToolbarMode WRITE setToolbarMode NOTIFY toolbarModeChanged)
|
||||||
Q_PROPERTY(bool landscape READ getLandscape WRITE setLandscape)
|
Q_PROPERTY(bool landscape READ getLandscape WRITE setLandscape)
|
||||||
Q_PROPERTY(bool tabletShown MEMBER _tabletShown NOTIFY tabletShownChanged)
|
Q_PROPERTY(bool tabletShown MEMBER _tabletShown NOTIFY tabletShownChanged)
|
||||||
|
Q_PROPERTY(TabletButtonListModel* buttons READ getButtons CONSTANT)
|
||||||
public:
|
public:
|
||||||
TabletProxy(QObject* parent, const QString& name);
|
TabletProxy(QObject* parent, const QString& name);
|
||||||
~TabletProxy();
|
~TabletProxy();
|
||||||
|
@ -204,6 +233,7 @@ public:
|
||||||
|
|
||||||
QQuickItem* getQmlMenu() const;
|
QQuickItem* getQmlMenu() const;
|
||||||
|
|
||||||
|
TabletButtonListModel* getButtons() { return &_buttons; }
|
||||||
signals:
|
signals:
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Signaled when this tablet receives an event from the html/js embedded in the tablet
|
* Signaled when this tablet receives an event from the html/js embedded in the tablet
|
||||||
|
@ -236,21 +266,19 @@ signals:
|
||||||
*/
|
*/
|
||||||
void tabletShownChanged();
|
void tabletShownChanged();
|
||||||
|
|
||||||
|
void toolbarModeChanged();
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void addButtonsToHomeScreen();
|
|
||||||
void desktopWindowClosed();
|
void desktopWindowClosed();
|
||||||
void emitWebEvent(const QVariant& msg);
|
void emitWebEvent(const QVariant& msg);
|
||||||
void onTabletShown();
|
void onTabletShown();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void removeButtonsFromHomeScreen();
|
|
||||||
void loadHomeScreen(bool forceOntoHomeScreen);
|
void loadHomeScreen(bool forceOntoHomeScreen);
|
||||||
void addButtonsToToolbar();
|
|
||||||
void removeButtonsFromToolbar();
|
|
||||||
|
|
||||||
bool _initialScreen { false };
|
bool _initialScreen { false };
|
||||||
QVariant _currentPathLoaded { "" };
|
QVariant _currentPathLoaded { "" };
|
||||||
QString _name;
|
QString _name;
|
||||||
std::vector<QSharedPointer<TabletButtonProxy>> _tabletButtonProxies;
|
|
||||||
QQuickItem* _qmlTabletRoot { nullptr };
|
QQuickItem* _qmlTabletRoot { nullptr };
|
||||||
OffscreenQmlSurface* _qmlOffscreenSurface { nullptr };
|
OffscreenQmlSurface* _qmlOffscreenSurface { nullptr };
|
||||||
QmlWindowClass* _desktopWindow { nullptr };
|
QmlWindowClass* _desktopWindow { nullptr };
|
||||||
|
@ -263,6 +291,8 @@ protected:
|
||||||
std::pair<QVariant, bool> _initialWebPathParams;
|
std::pair<QVariant, bool> _initialWebPathParams;
|
||||||
bool _landscape { false };
|
bool _landscape { false };
|
||||||
bool _showRunningScripts { false };
|
bool _showRunningScripts { false };
|
||||||
|
|
||||||
|
TabletButtonListModel _buttons;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(TabletProxy*);
|
Q_DECLARE_METATYPE(TabletProxy*);
|
||||||
|
@ -274,13 +304,11 @@ Q_DECLARE_METATYPE(TabletProxy*);
|
||||||
class TabletButtonProxy : public QObject {
|
class TabletButtonProxy : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QUuid uuid READ getUuid)
|
Q_PROPERTY(QUuid uuid READ getUuid)
|
||||||
|
Q_PROPERTY(QVariantMap properties READ getProperties NOTIFY propertiesChanged)
|
||||||
public:
|
public:
|
||||||
TabletButtonProxy(const QVariantMap& properties);
|
TabletButtonProxy(const QVariantMap& properties);
|
||||||
~TabletButtonProxy();
|
~TabletButtonProxy();
|
||||||
|
|
||||||
void setQmlButton(QQuickItem* qmlButton);
|
|
||||||
void setToolbarButtonProxy(QObject* toolbarButtonProxy);
|
|
||||||
|
|
||||||
QUuid getUuid() const { return _uuid; }
|
QUuid getUuid() const { return _uuid; }
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
@ -297,9 +325,6 @@ public:
|
||||||
*/
|
*/
|
||||||
Q_INVOKABLE void editProperties(const QVariantMap& properties);
|
Q_INVOKABLE void editProperties(const QVariantMap& properties);
|
||||||
|
|
||||||
public slots:
|
|
||||||
void clickedSlot() { emit clicked(); }
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Signaled when this button has been clicked on by the user.
|
* Signaled when this button has been clicked on by the user.
|
||||||
|
@ -307,12 +332,11 @@ signals:
|
||||||
* @returns {Signal}
|
* @returns {Signal}
|
||||||
*/
|
*/
|
||||||
void clicked();
|
void clicked();
|
||||||
|
void propertiesChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QUuid _uuid;
|
QUuid _uuid;
|
||||||
int _stableOrder;
|
int _stableOrder;
|
||||||
QQuickItem* _qmlButton { nullptr };
|
|
||||||
QObject* _toolbarButtonProxy { nullptr };
|
|
||||||
QVariantMap _properties;
|
QVariantMap _properties;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -234,7 +234,7 @@
|
||||||
|
|
||||||
Recorder.setUp();
|
Recorder.setUp();
|
||||||
|
|
||||||
// Tablet/toolbar button.
|
// tablet/toolbar button.
|
||||||
button = tablet.addButton({
|
button = tablet.addButton({
|
||||||
icon: APP_ICON_INACTIVE,
|
icon: APP_ICON_INACTIVE,
|
||||||
activeIcon: APP_ICON_ACTIVE,
|
activeIcon: APP_ICON_ACTIVE,
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
tablet.gotoHomeScreen();
|
tablet.gotoHomeScreen();
|
||||||
onRecordingScreen = false;
|
onRecordingScreen = false;
|
||||||
} else {
|
} else {
|
||||||
tablet.loadQMLSource("InputRecorder.qml");
|
tablet.loadQMLSource("hifi/tablet/InputRecorder.qml");
|
||||||
onRecordingScreen = true;
|
onRecordingScreen = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
print("Launching web window");
|
print("Launching web window");
|
||||||
qmlWindow = new OverlayWindow({
|
qmlWindow = new OverlayWindow({
|
||||||
title: 'Test Qml',
|
title: 'Test Qml',
|
||||||
source: "https://s3.amazonaws.com/DreamingContent/qml/content.qml",
|
source: "qrc:///qml/OverlayWindowTest.qml",
|
||||||
height: 240,
|
height: 240,
|
||||||
width: 320,
|
width: 320,
|
||||||
toolWindow: false,
|
toolWindow: false,
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
var TABLET_BUTTON_NAME = "AUDIO";
|
var TABLET_BUTTON_NAME = "AUDIO";
|
||||||
var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png";
|
var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png";
|
||||||
var AUDIO_QML_SOURCE = "../audio/Audio.qml";
|
var AUDIO_QML_SOURCE = "hifi/audio/Audio.qml";
|
||||||
|
|
||||||
var MUTE_ICONS = {
|
var MUTE_ICONS = {
|
||||||
icon: "icons/tablet-icons/mic-mute-i.svg",
|
icon: "icons/tablet-icons/mic-mute-i.svg",
|
||||||
|
|
|
@ -26,8 +26,8 @@
|
||||||
// Relevant Variables:
|
// Relevant Variables:
|
||||||
// -WALLET_QML_SOURCE: The path to the Wallet QML
|
// -WALLET_QML_SOURCE: The path to the Wallet QML
|
||||||
// -onWalletScreen: true/false depending on whether we're looking at the app.
|
// -onWalletScreen: true/false depending on whether we're looking at the app.
|
||||||
var WALLET_QML_SOURCE = Script.resourcesPath() + "qml/hifi/commerce/wallet/Wallet.qml";
|
var WALLET_QML_SOURCE = "hifi/commerce/wallet/Wallet.qml";
|
||||||
var MARKETPLACE_PURCHASES_QML_PATH = Script.resourcesPath() + "qml/hifi/commerce/purchases/Purchases.qml";
|
var MARKETPLACE_PURCHASES_QML_PATH = "hifi/commerce/purchases/Purchases.qml";
|
||||||
var onWalletScreen = false;
|
var onWalletScreen = false;
|
||||||
function onButtonClicked() {
|
function onButtonClicked() {
|
||||||
if (!tablet) {
|
if (!tablet) {
|
||||||
|
|
|
@ -427,7 +427,7 @@ var toolBar = (function () {
|
||||||
});
|
});
|
||||||
createButton = activeButton;
|
createButton = activeButton;
|
||||||
tablet.screenChanged.connect(function (type, url) {
|
tablet.screenChanged.connect(function (type, url) {
|
||||||
if (isActive && (type !== "QML" || url !== "Edit.qml")) {
|
if (isActive && (type !== "QML" || url !== "hifi/tablet/Edit.qml")) {
|
||||||
that.setActive(false)
|
that.setActive(false)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -656,7 +656,7 @@ var toolBar = (function () {
|
||||||
selectionDisplay.triggerMapping.disable();
|
selectionDisplay.triggerMapping.disable();
|
||||||
tablet.landscape = false;
|
tablet.landscape = false;
|
||||||
} else {
|
} else {
|
||||||
tablet.loadQMLSource("Edit.qml", true);
|
tablet.loadQMLSource("hifi/tablet/Edit.qml", true);
|
||||||
UserActivityLogger.enabledEdit();
|
UserActivityLogger.enabledEdit();
|
||||||
entityListTool.setVisible(true);
|
entityListTool.setVisible(true);
|
||||||
gridTool.setVisible(true);
|
gridTool.setVisible(true);
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
var buttonName = "Settings";
|
var buttonName = "Settings";
|
||||||
var toolBar = null;
|
var toolBar = null;
|
||||||
var tablet = null;
|
var tablet = null;
|
||||||
var settings = "TabletGeneralPreferences.qml"
|
var settings = "hifi/tablet/TabletGeneralPreferences.qml"
|
||||||
function onClicked(){
|
function onClicked(){
|
||||||
if (tablet) {
|
if (tablet) {
|
||||||
tablet.loadQMLSource(settings);
|
tablet.loadQMLSource(settings);
|
||||||
|
|
|
@ -10,7 +10,7 @@ openLoginWindow = function openLoginWindow() {
|
||||||
|| (!HMD.active && Settings.getValue("desktopTabletBecomesToolbar", true))) {
|
|| (!HMD.active && Settings.getValue("desktopTabletBecomesToolbar", true))) {
|
||||||
Menu.triggerOption("Login / Sign Up");
|
Menu.triggerOption("Login / Sign Up");
|
||||||
} else {
|
} else {
|
||||||
tablet.loadQMLOnTop("../../dialogs/TabletLoginDialog.qml");
|
tablet.loadQMLOnTop("dialogs/TabletLoginDialog.qml");
|
||||||
HMD.openTablet();
|
HMD.openTablet();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,10 +23,9 @@ var selectionDisplay = null; // for gridTool.js to ignore
|
||||||
var MARKETPLACE_URL_INITIAL = MARKETPLACE_URL + "?"; // Append "?" to signal injected script that it's the initial page.
|
var MARKETPLACE_URL_INITIAL = MARKETPLACE_URL + "?"; // Append "?" to signal injected script that it's the initial page.
|
||||||
var MARKETPLACES_URL = Script.resolvePath("../html/marketplaces.html");
|
var MARKETPLACES_URL = Script.resolvePath("../html/marketplaces.html");
|
||||||
var MARKETPLACES_INJECT_SCRIPT_URL = Script.resolvePath("../html/js/marketplacesInject.js");
|
var MARKETPLACES_INJECT_SCRIPT_URL = Script.resolvePath("../html/js/marketplacesInject.js");
|
||||||
var MARKETPLACE_CHECKOUT_QML_PATH_BASE = "qml/hifi/commerce/checkout/Checkout.qml";
|
var MARKETPLACE_CHECKOUT_QML_PATH = "hifi/commerce/checkout/Checkout.qml";
|
||||||
var MARKETPLACE_CHECKOUT_QML_PATH = Script.resourcesPath() + MARKETPLACE_CHECKOUT_QML_PATH_BASE;
|
var MARKETPLACE_PURCHASES_QML_PATH = "hifi/commerce/purchases/Purchases.qml";
|
||||||
var MARKETPLACE_PURCHASES_QML_PATH = Script.resourcesPath() + "qml/hifi/commerce/purchases/Purchases.qml";
|
var MARKETPLACE_WALLET_QML_PATH = "hifi/commerce/wallet/Wallet.qml";
|
||||||
var MARKETPLACE_WALLET_QML_PATH = Script.resourcesPath() + "qml/hifi/commerce/wallet/Wallet.qml";
|
|
||||||
var MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH = "commerce/inspectionCertificate/InspectionCertificate.qml";
|
var MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH = "commerce/inspectionCertificate/InspectionCertificate.qml";
|
||||||
|
|
||||||
var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png";
|
var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-with-home-button.fbx/tablet-with-home-button.fbm/button-root.png";
|
||||||
|
@ -114,7 +113,7 @@ var selectionDisplay = null; // for gridTool.js to ignore
|
||||||
function onScreenChanged(type, url) {
|
function onScreenChanged(type, url) {
|
||||||
onMarketplaceScreen = type === "Web" && url.indexOf(MARKETPLACE_URL) !== -1;
|
onMarketplaceScreen = type === "Web" && url.indexOf(MARKETPLACE_URL) !== -1;
|
||||||
onWalletScreen = url.indexOf(MARKETPLACE_WALLET_QML_PATH) !== -1;
|
onWalletScreen = url.indexOf(MARKETPLACE_WALLET_QML_PATH) !== -1;
|
||||||
onCommerceScreen = type === "QML" && (url.indexOf(MARKETPLACE_CHECKOUT_QML_PATH_BASE) !== -1 || url === MARKETPLACE_PURCHASES_QML_PATH
|
onCommerceScreen = type === "QML" && (url.indexOf(MARKETPLACE_CHECKOUT_QML_PATH) !== -1 || url === MARKETPLACE_PURCHASES_QML_PATH
|
||||||
|| url.indexOf(MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH) !== -1);
|
|| url.indexOf(MARKETPLACE_INSPECTIONCERTIFICATE_QML_PATH) !== -1);
|
||||||
wireEventBridge(onMarketplaceScreen || onCommerceScreen || onWalletScreen);
|
wireEventBridge(onMarketplaceScreen || onCommerceScreen || onWalletScreen);
|
||||||
|
|
||||||
|
@ -492,7 +491,7 @@ var selectionDisplay = null; // for gridTool.js to ignore
|
||||||
Menu.setIsOptionChecked("Disable Preview", isHmdPreviewDisabled);
|
Menu.setIsOptionChecked("Disable Preview", isHmdPreviewDisabled);
|
||||||
break;
|
break;
|
||||||
case 'purchases_openGoTo':
|
case 'purchases_openGoTo':
|
||||||
tablet.loadQMLSource("TabletAddressDialog.qml");
|
tablet.loadQMLSource("hifi/tablet/TabletAddressDialog.qml");
|
||||||
break;
|
break;
|
||||||
case 'purchases_itemCertificateClicked':
|
case 'purchases_itemCertificateClicked':
|
||||||
setCertificateInfo("", message.itemCertificateId);
|
setCertificateInfo("", message.itemCertificateId);
|
||||||
|
|
|
@ -40,7 +40,7 @@ var HOVER_TEXTURES = {
|
||||||
var UNSELECTED_COLOR = { red: 0x1F, green: 0xC6, blue: 0xA6};
|
var UNSELECTED_COLOR = { red: 0x1F, green: 0xC6, blue: 0xA6};
|
||||||
var SELECTED_COLOR = {red: 0xF3, green: 0x91, blue: 0x29};
|
var SELECTED_COLOR = {red: 0xF3, green: 0x91, blue: 0x29};
|
||||||
var HOVER_COLOR = {red: 0xD0, green: 0xD0, blue: 0xD0}; // almost white for now
|
var HOVER_COLOR = {red: 0xD0, green: 0xD0, blue: 0xD0}; // almost white for now
|
||||||
var PAL_QML_SOURCE = "../Pal.qml";
|
var PAL_QML_SOURCE = "hifi/Pal.qml";
|
||||||
var conserveResources = true;
|
var conserveResources = true;
|
||||||
|
|
||||||
Script.include("/~/system/libraries/controllers.js");
|
Script.include("/~/system/libraries/controllers.js");
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
print('tablet-goto.js:', [].map.call(arguments, JSON.stringify));
|
print('tablet-goto.js:', [].map.call(arguments, JSON.stringify));
|
||||||
}
|
}
|
||||||
|
|
||||||
var gotoQmlSource = "TabletAddressDialog.qml";
|
var gotoQmlSource = "hifi/tablet/TabletAddressDialog.qml";
|
||||||
var buttonName = "GOTO";
|
var buttonName = "GOTO";
|
||||||
var onGotoScreen = false;
|
var onGotoScreen = false;
|
||||||
var shouldActivateButton = false;
|
var shouldActivateButton = false;
|
||||||
|
|
27
tests/shared/src/PathUtilsTests.cpp
Normal file
27
tests/shared/src/PathUtilsTests.cpp
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2017/11/08
|
||||||
|
// Copyright 2013-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 "PathUtilsTests.h"
|
||||||
|
|
||||||
|
#include <QtTest/QtTest>
|
||||||
|
|
||||||
|
#include <PathUtils.h>
|
||||||
|
|
||||||
|
QTEST_MAIN(PathUtilsTests)
|
||||||
|
|
||||||
|
void PathUtilsTests::testPathUtils() {
|
||||||
|
QString result = PathUtils::qmlBasePath();
|
||||||
|
#if DEV_BUILD
|
||||||
|
QVERIFY(result.startsWith("file:///"));
|
||||||
|
#else
|
||||||
|
QVERIFY(result.startsWith("qrc:///"));
|
||||||
|
#endif
|
||||||
|
QVERIFY(result.endsWith("/"));
|
||||||
|
}
|
||||||
|
|
20
tests/shared/src/PathUtilsTests.h
Normal file
20
tests/shared/src/PathUtilsTests.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2017/11/08
|
||||||
|
// Copyright 2013-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_PathUtilsTests_h
|
||||||
|
#define hifi_PathUtilsTests_h
|
||||||
|
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
|
||||||
|
class PathUtilsTests : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
private slots:
|
||||||
|
void testPathUtils();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_PathUtilsTests_h
|
|
@ -24,7 +24,7 @@
|
||||||
if (onSkyboxChangerScreen) {
|
if (onSkyboxChangerScreen) {
|
||||||
tablet.gotoHomeScreen();
|
tablet.gotoHomeScreen();
|
||||||
} else {
|
} else {
|
||||||
tablet.loadQMLSource("../SkyboxChanger.qml");
|
tablet.loadQMLSource("hifi/SkyboxChanger.qml");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -393,7 +393,7 @@
|
||||||
// Relevant Variables:
|
// Relevant Variables:
|
||||||
// -SPECTATOR_CAMERA_QML_SOURCE: The path to the SpectatorCamera QML
|
// -SPECTATOR_CAMERA_QML_SOURCE: The path to the SpectatorCamera QML
|
||||||
// -onSpectatorCameraScreen: true/false depending on whether we're looking at the spectator camera app.
|
// -onSpectatorCameraScreen: true/false depending on whether we're looking at the spectator camera app.
|
||||||
var SPECTATOR_CAMERA_QML_SOURCE = Script.resourcesPath() + "qml/hifi/SpectatorCamera.qml";
|
var SPECTATOR_CAMERA_QML_SOURCE = "hifi/SpectatorCamera.qml";
|
||||||
var onSpectatorCameraScreen = false;
|
var onSpectatorCameraScreen = false;
|
||||||
function onTabletButtonClicked() {
|
function onTabletButtonClicked() {
|
||||||
if (!tablet) {
|
if (!tablet) {
|
||||||
|
|
Loading…
Reference in a new issue