mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 08:04:01 +02:00
Merge branch 'feature/qml_whitelist_tablet' of https://github.com/jherico/hifi into commerce_QmlWhitelist
This commit is contained in:
commit
5290ee3b4e
15 changed files with 268 additions and 322 deletions
|
@ -307,7 +307,6 @@ table .headers + .headers td {
|
|||
margin-right: 20px;
|
||||
}
|
||||
|
||||
#visit-domain-link,
|
||||
.blue-link {
|
||||
font-size: 14px;
|
||||
text-decoration-line: underline;
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
<li><a href="/settings/">Settings</a></li>
|
||||
</ul>
|
||||
<ul class="nav navbar-right navbar-nav">
|
||||
<li><a id="visit-domain-link" target="_blank" style="display: none;">Visit domain in VR</a></li>
|
||||
<li><a id="visit-domain-link" class="blue-link" target="_blank" style="display: none;">Visit domain in VR</a></li>
|
||||
<li><a href="#" id="restart-server"><span class="glyphicon glyphicon-refresh"></span> Restart</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -31,6 +31,12 @@ label {
|
|||
color: #373A3C;
|
||||
}
|
||||
|
||||
.wizard-link {
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
color: #2F80ED;
|
||||
}
|
||||
|
||||
#admin-row {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
|
@ -84,6 +90,14 @@ label {
|
|||
height: 169px;
|
||||
}
|
||||
|
||||
#visit-domain-row {
|
||||
margin-bottom: 68px;
|
||||
#congratulation-text {
|
||||
margin-bottom: 59px;
|
||||
}
|
||||
|
||||
#visit-domain-checkbox {
|
||||
margin-bottom: 23px;
|
||||
}
|
||||
|
||||
#visit-domain-checkbox label {
|
||||
margin: 0 0;
|
||||
}
|
||||
|
|
|
@ -60,8 +60,7 @@
|
|||
</div>
|
||||
<div id="admin-row" class="row">
|
||||
<p class="col-md-6">
|
||||
<span id="admin-description" class="step-info"><b>Add your High Fidelity username</b> and any other usernames to grant administrator privileges.</span>
|
||||
<span class='glyphicon glyphicon-info-sign' data-toggle="tooltip" title="Users who will have all the permissions for this domain."></span>
|
||||
<span class="step-info"><span id="admin-description"><b>Add your High Fidelity username</b> and any other usernames</span> to grant <span class='wizard-link' data-toggle="tooltip" title="Users who will have all the permissions for this domain.">administrator privileges</span></span>
|
||||
</p>
|
||||
<div class="col-md-6">
|
||||
<input id="admin-usernames" type="text" class="form-control">
|
||||
|
@ -78,7 +77,7 @@
|
|||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<p id="connect-question" class="step-info">
|
||||
Who can connect to your domain?
|
||||
Who can <a href='#' class='wizard-link perms-link'>connect</a> to your domain?
|
||||
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='You can set this to allow a user to connect to this domain.'></span>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -87,25 +86,21 @@
|
|||
<p class="col-md-2">
|
||||
<label>
|
||||
<input id="connect-none" name="connect-radio" type="radio" value="none" checked> None
|
||||
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='Only the admins of this domain'></span>
|
||||
</label>
|
||||
</p>
|
||||
<p class="col-md-3">
|
||||
<label>
|
||||
<input id="connect-friends" name="connect-radio" type="radio" value="friends"> Friends
|
||||
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='Users who are your Friends in High Fidelity'></span>
|
||||
</label>
|
||||
</p>
|
||||
<p class="col-md-5">
|
||||
<label>
|
||||
<input id="connect-logged-in" name="connect-radio" type="radio" value="logged-in"> Users logged in to High Fidelity
|
||||
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='Users who are currently logged into High Fidelity'></span>
|
||||
<input id="connect-logged-in" name="connect-radio" type="radio" value="logged-in"> Users logged into High Fidelity
|
||||
</label>
|
||||
</p>
|
||||
<p class="col-md-2">
|
||||
<label>
|
||||
<input id="connect-everyone" name="connect-radio" type="radio" value="everyone"> Everyone
|
||||
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title="Users who aren't logged into High Fidelity"></span>
|
||||
</label>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -113,7 +108,7 @@
|
|||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<p class="step-info">
|
||||
Who can rez items in your domain?
|
||||
Who can <a href='#' class='wizard-link perms-link'>rez items</a> in your domain?
|
||||
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='You can set this to allow a user to create entities in this domain.'></span>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -122,33 +117,32 @@
|
|||
<p class="col-md-2">
|
||||
<label>
|
||||
<input id="rez-none" name="rez-radio" type="radio" value="none" checked> None
|
||||
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='Only the admins of this domain'></span>
|
||||
</label>
|
||||
</p>
|
||||
<p class="col-md-3">
|
||||
<label>
|
||||
<input id="rez-friends" name="rez-radio" type="radio" value="friends"> Friends
|
||||
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='Users who are your Friends in High Fidelity'></span>
|
||||
<input id="rez-friends" name="rez-radio" type="radio" value="friends" disabled> Friends
|
||||
</label>
|
||||
</p>
|
||||
<p class="col-md-5">
|
||||
<label>
|
||||
<input id="rez-logged-in" name="rez-radio" type="radio" value="logged-in"> Users logged in to High Fidelity
|
||||
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title='Users who are currently logged into High Fidelity'></span>
|
||||
<input id="rez-logged-in" name="rez-radio" type="radio" value="logged-in" disabled> Users logged into High Fidelity
|
||||
</label>
|
||||
</p>
|
||||
<p class="col-md-2">
|
||||
<label>
|
||||
<input id="rez-everyone" name="rez-radio" type="radio" value="everyone"> Everyone
|
||||
<span class='glyphicon glyphicon-info-sign' data-toggle='tooltip' title="Users who aren't logged into High Fidelity"></span>
|
||||
<input id="rez-everyone" name="rez-radio" type="radio" value="everyone" disabled> Everyone
|
||||
</label>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-md-offset-9">
|
||||
<dd class="col-md-3">
|
||||
<button type="button" class="btn btn-md btn-block btn-default back-button">Back</button>
|
||||
</dd>
|
||||
<dd class="col-md-3 col-md-offset-6">
|
||||
<button id="save-permissions" type="button" class="btn btn-md btn-block btn-primary">Next</button>
|
||||
</div>
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -188,35 +182,37 @@
|
|||
</dl>
|
||||
|
||||
<dl class="row">
|
||||
<dd class="col-md-3 col-md-offset-9">
|
||||
<dd class="col-md-3">
|
||||
<button type="button" class="btn btn-md btn-block btn-default back-button">Back</button>
|
||||
</dd>
|
||||
<dd class="col-md-3 col-md-offset-6">
|
||||
<button id="save-username-password" type="button" class="btn btn-md btn-block btn-primary">Finish</button>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div class="wizard-step cloud-only col-md-7 col-centered" style="display: none;">
|
||||
<div class="wizard-step cloud-only col-xs-12 col-sm-12 col-md-9 col-lg-7 col-centered" style="display: none;">
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-centered">
|
||||
<div class="col-xs-12" align="center">
|
||||
<img id="checkmark-image" src="../images/checkmark.svg">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="congratulation-text" class="row">
|
||||
<div class="col-xs-12">
|
||||
<p class="step-info">Congratulations! You have successfully setup and configured your cloud hosted domain.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="visit-domain-row" class="row">
|
||||
<div class="col-md-12">
|
||||
<label><input id="go-to-domain" class="form-check-input" type="checkbox"> Visit domain in VR now</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<dl class="row">
|
||||
<dd class="col-md-5 col-md-offset-7">
|
||||
<button id="explore-settings" type="button" class="btn btn-md btn-block btn-primary">Explore all domain server settings</button>
|
||||
</dd>
|
||||
<div class="col-xs-12">
|
||||
<div class="pull-right">
|
||||
<div id="visit-domain-checkbox">
|
||||
<label><input id="go-to-domain" class="form-check-input" type="checkbox"> Visit domain in VR now</label>
|
||||
</div>
|
||||
<button id="explore-settings" type="button" class="btn btn-md btn-primary">Explore all domain server settings</button>
|
||||
</div>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ var Metaverse = {
|
|||
accessToken: null
|
||||
}
|
||||
|
||||
var currentStepNumber;
|
||||
|
||||
$(document).ready(function(){
|
||||
Strings.ADD_PLACE_NOT_CONNECTED_MESSAGE = "You must have an access token to query your High Fidelity places.<br><br>" +
|
||||
"Please go back and connect your account.";
|
||||
|
@ -9,6 +11,22 @@ $(document).ready(function(){
|
|||
$('#connect-account-btn').attr('href', URLs.METAVERSE_URL + "/user/tokens/new?for_domain_server=true");
|
||||
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
$('.perms-link').on('click', function() {
|
||||
var modal_body = '<div>';
|
||||
modal_body += '<b>None</b> - No one will have permissions. Only you and the users your have given administrator privileges to will have permissions.</br></br>';
|
||||
modal_body += '<b>Friends</b> - Users who are your Friends in High Fidelity.</br></br>';
|
||||
modal_body += '<b>Users logged into High Fidelity</b> - Users who are currently logged into High Fidelity.</br></br>';
|
||||
modal_body += '<b>Everyone</b> - Anyone who uses High Fidelity.';
|
||||
modal_body += '</div>';
|
||||
|
||||
dialog = bootbox.dialog({
|
||||
title: "User definition",
|
||||
message: modal_body,
|
||||
closeButton: true
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
$('body').on('click', '.next-button', function() {
|
||||
goToNextStep();
|
||||
|
@ -56,6 +74,36 @@ $(document).ready(function(){
|
|||
exploreSettings();
|
||||
});
|
||||
|
||||
$('input[type=radio][name=connect-radio]').change(function() {
|
||||
var inputs = $('input[type=radio][name=rez-radio]');
|
||||
var disabled = [];
|
||||
|
||||
switch (this.value) {
|
||||
case 'none':
|
||||
disabled = inputs.splice(1);
|
||||
break;
|
||||
case 'friends':
|
||||
disabled = inputs.splice(2);
|
||||
break;
|
||||
case 'logged-in':
|
||||
disabled = inputs.splice(3);
|
||||
break;
|
||||
case 'everyone':
|
||||
disabled = inputs.splice(4);
|
||||
break;
|
||||
}
|
||||
|
||||
$.each(inputs, function() {
|
||||
$(this).prop('disabled', false);
|
||||
});
|
||||
$.each(disabled, function() {
|
||||
if ($(this).prop('checked')) {
|
||||
$(inputs.last()).prop('checked', true);
|
||||
}
|
||||
$(this).prop('disabled', true);
|
||||
});
|
||||
});
|
||||
|
||||
reloadSettings(function(success) {
|
||||
if (success) {
|
||||
getDomainFromAPI();
|
||||
|
@ -73,12 +121,12 @@ $(document).ready(function(){
|
|||
});
|
||||
|
||||
function setupWizardSteps() {
|
||||
var stepsCompleted = Settings.data.values.wizard.steps_completed;
|
||||
currentStepNumber = Settings.data.values.wizard.steps_completed;
|
||||
var steps = null;
|
||||
|
||||
if (Settings.data.values.wizard.cloud_domain) {
|
||||
$('.desktop-only').remove();
|
||||
$('.wizard-step').find('.back-button').hide();
|
||||
$('.wizard-step:first').find('.back-button').hide();
|
||||
|
||||
steps = $('.wizard-step');
|
||||
$(steps).each(function(i) {
|
||||
|
@ -86,7 +134,7 @@ function setupWizardSteps() {
|
|||
});
|
||||
|
||||
$('#permissions-description').html('You <span id="username-display"></span>have been assigned administrator privileges to this domain.');
|
||||
$('#admin-description').html('Add more High Fidelity usernames to grant administrator privileges.');
|
||||
$('#admin-description').html('Add more High Fidelity usernames');
|
||||
} else {
|
||||
$('.cloud-only').remove();
|
||||
$('#save-permissions').text("Finish");
|
||||
|
@ -96,12 +144,12 @@ function setupWizardSteps() {
|
|||
$(this).children(".step-title").text("Step " + (i + 1) + " of " + steps.length);
|
||||
});
|
||||
|
||||
if (stepsCompleted == 0) {
|
||||
if (currentStepNumber == 0) {
|
||||
$('#skip-wizard-button').show();
|
||||
}
|
||||
}
|
||||
|
||||
var currentStep = steps[stepsCompleted];
|
||||
var currentStep = steps[currentStepNumber];
|
||||
$(currentStep).show();
|
||||
}
|
||||
|
||||
|
@ -204,7 +252,7 @@ function goToNextStep() {
|
|||
currentStep.hide();
|
||||
nextStep.show();
|
||||
|
||||
var currentStepNumber = parseInt(Settings.data.values.wizard.steps_completed) + 1;
|
||||
currentStepNumber += 1;
|
||||
|
||||
postSettings({
|
||||
"wizard": {
|
||||
|
@ -233,7 +281,7 @@ function goToPreviousStep() {
|
|||
currentStep.hide();
|
||||
previousStep.show();
|
||||
|
||||
var currentStepNumber = parseInt(Settings.data.values.wizard.steps_completed) - 1;
|
||||
currentStepNumber -= 1;
|
||||
|
||||
postSettings({
|
||||
"wizard": {
|
||||
|
@ -439,7 +487,7 @@ function saveUsernamePassword() {
|
|||
return;
|
||||
}
|
||||
|
||||
var currentStepNumber = parseInt(Settings.data.values.wizard.steps_completed) + 1;
|
||||
currentStepNumber += 1;
|
||||
|
||||
var formJSON = {
|
||||
"security": {
|
||||
|
|
|
@ -45,11 +45,13 @@ OriginalDesktop.Desktop {
|
|||
Toolbar {
|
||||
id: sysToolbar;
|
||||
objectName: "com.highfidelity.interface.toolbar.system";
|
||||
property var tablet: Tablets.getTablet("com.highfidelity.interface.tablet.system");
|
||||
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.
|
||||
x: sysToolbar.x
|
||||
y: 50
|
||||
shown: true
|
||||
buttonModel: tablet.buttons;
|
||||
shown: tablet.toolbarMode;
|
||||
}
|
||||
|
||||
Settings {
|
||||
|
|
|
@ -113,21 +113,6 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
titleBarText.text = "Certificate";
|
||||
popText.text = "PROOF OF PURCHASE";
|
||||
root.certificateId = "";
|
||||
root.itemName = "--";
|
||||
root.itemOwner = "--";
|
||||
root.itemEdition = "--";
|
||||
root.dateOfPurchase = "--";
|
||||
root.marketplaceUrl = "";
|
||||
root.isMyCert = false;
|
||||
errorText.text = "";
|
||||
}
|
||||
}
|
||||
|
||||
// This object is always used in a popup.
|
||||
// This MouseArea is used to prevent a user from being
|
||||
// able to click on a button/mouseArea underneath the popup.
|
||||
|
@ -420,6 +405,18 @@ Rectangle {
|
|||
case 'inspectionCertificate_setCertificateId':
|
||||
root.certificateId = message.certificateId;
|
||||
break;
|
||||
case 'inspectionCertificate_resetCert':
|
||||
titleBarText.text = "Certificate";
|
||||
popText.text = "PROOF OF PURCHASE";
|
||||
root.certificateId = "";
|
||||
root.itemName = "--";
|
||||
root.itemOwner = "--";
|
||||
root.itemEdition = "--";
|
||||
root.dateOfPurchase = "--";
|
||||
root.marketplaceUrl = "";
|
||||
root.isMyCert = false;
|
||||
errorText.text = "";
|
||||
break;
|
||||
default:
|
||||
console.log('Unrecognized message from marketplaces.js:', JSON.stringify(message));
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ Window {
|
|||
horizontalSpacers: horizontal
|
||||
verticalSpacers: !horizontal
|
||||
}
|
||||
property var tabletProxy;
|
||||
property var buttonModel: ListModel {}
|
||||
hideBackground: true
|
||||
resizable: false
|
||||
destroyOnCloseButton: false
|
||||
|
@ -23,24 +25,32 @@ Window {
|
|||
activator: Item {}
|
||||
property bool horizontal: true
|
||||
property real buttonSize: 50;
|
||||
property var buttons: []
|
||||
property var container: horizontal ? row : column
|
||||
|
||||
Settings {
|
||||
category: "toolbar/" + window.objectName
|
||||
property alias x: window.x
|
||||
property alias y: window.y
|
||||
}
|
||||
|
||||
Component {
|
||||
id: buttonComponent
|
||||
ToolbarButton {
|
||||
id: toolbarButton
|
||||
property var proxy: modelData;
|
||||
onClicked: proxy.clicked()
|
||||
Component.onCompleted: updateProperties()
|
||||
|
||||
onHorizontalChanged: {
|
||||
var newParent = horizontal ? row : column;
|
||||
for (var i in buttons) {
|
||||
var child = buttons[i];
|
||||
child.parent = newParent;
|
||||
if (horizontal) {
|
||||
child.y = 0
|
||||
} else {
|
||||
child.x = 0
|
||||
Connections {
|
||||
target: proxy;
|
||||
onPropertiesChanged: updateProperties();
|
||||
}
|
||||
|
||||
function updateProperties() {
|
||||
Object.keys(proxy.properties).forEach(function (key) {
|
||||
if (toolbarButton[key] !== proxy.properties[key]) {
|
||||
toolbarButton[key] = proxy.properties[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,97 +62,22 @@ Window {
|
|||
|
||||
Row {
|
||||
id: row
|
||||
visible: window.horizontal
|
||||
spacing: 6
|
||||
Repeater {
|
||||
model: buttonModel
|
||||
delegate: buttonComponent
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Column {
|
||||
id: column
|
||||
visible: !window.horizontal
|
||||
spacing: 6
|
||||
}
|
||||
|
||||
Component { id: toolbarButtonBuilder; ToolbarButton { } }
|
||||
}
|
||||
|
||||
|
||||
function findButtonIndex(name) {
|
||||
if (!name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (var i in buttons) {
|
||||
var child = buttons[i];
|
||||
if (child.objectName === name) {
|
||||
return i;
|
||||
Repeater {
|
||||
model: buttonModel
|
||||
delegate: buttonComponent
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,8 @@ StateImage {
|
|||
property string activeHoverIcon: button.activeIcon
|
||||
|
||||
property int sortOrder: 100
|
||||
property int stableSortOrder: 0
|
||||
property int stableOrder: 0
|
||||
property var uuid;
|
||||
|
||||
signal clicked()
|
||||
|
||||
|
|
|
@ -2259,6 +2259,10 @@ void Application::initializeUi() {
|
|||
qmlRegisterType<ResourceImageItem>("Hifi", 1, 0, "ResourceImageItem");
|
||||
qmlRegisterType<Preference>("Hifi", 1, 0, "Preference");
|
||||
|
||||
{
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
tabletScriptingInterface->getTablet(SYSTEM_TABLET);
|
||||
}
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->create();
|
||||
|
||||
|
|
|
@ -106,6 +106,9 @@ void OffscreenUi::create() {
|
|||
myContext->setContextProperty("offscreenFlags", offscreenFlags = new OffscreenFlags());
|
||||
myContext->setContextProperty("fileDialogHelper", new FileDialogHelper());
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
qRegisterMetaType<TabletProxy*>();
|
||||
qRegisterMetaType<TabletButtonProxy*>();
|
||||
myContext->setContextProperty("Tablets", tabletScriptingInterface.data());
|
||||
TabletProxy* tablet = tabletScriptingInterface->getTablet("com.highfidelity.interface.tablet.system");
|
||||
myContext->engine()->setObjectOwnership(tablet, QQmlEngine::CppOwnership);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,14 @@ const QString SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system";
|
|||
const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
|
||||
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",
|
||||
"/sounds/Button04.wav",
|
||||
|
@ -39,6 +47,51 @@ static Setting::Handle<QStringList> tabletSoundsButtonClick("TabletSounds", QStr
|
|||
"/sounds/Tab01.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() {
|
||||
qmlRegisterType<TabletScriptingInterface>("TabletScriptingInterface", 1, 0, "TabletEnums");
|
||||
}
|
||||
|
@ -232,15 +285,6 @@ TabletProxy::~TabletProxy() {
|
|||
disconnect(this, &TabletProxy::tabletShownChanged, this, &TabletProxy::onTabletShown);
|
||||
}
|
||||
|
||||
QVariant TabletProxy::getButtons() {
|
||||
Q_ASSERT(QThread::currentThread() == qApp->thread());
|
||||
QVariantList result;
|
||||
for (const auto& button : _tabletButtonProxies) {
|
||||
result.push_back(QVariant::fromValue(button.data()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void TabletProxy::setToolbarMode(bool toolbarMode) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "setToolbarMode", Q_ARG(bool, toolbarMode));
|
||||
|
@ -256,8 +300,6 @@ void TabletProxy::setToolbarMode(bool toolbarMode) {
|
|||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
|
||||
if (toolbarMode) {
|
||||
addButtonsToToolbar();
|
||||
|
||||
// create new desktop window
|
||||
auto tabletRootWindow = new TabletRootWindow();
|
||||
tabletRootWindow->initQml(QVariantMap());
|
||||
|
@ -272,11 +314,7 @@ void TabletProxy::setToolbarMode(bool toolbarMode) {
|
|||
// forward qml surface events to interface js
|
||||
connect(tabletRootWindow, &QmlWindowClass::fromQml, this, &TabletProxy::fromQml);
|
||||
} else {
|
||||
removeButtonsFromToolbar();
|
||||
|
||||
if (_currentPathLoaded == TABLET_HOME_SOURCE_URL) {
|
||||
// Tablet QML now pulls buttons from Tablet proxy
|
||||
} else {
|
||||
if (_currentPathLoaded != TABLET_HOME_SOURCE_URL) {
|
||||
loadHomeScreen(true);
|
||||
}
|
||||
//check if running scripts window opened and save it for reopen in Tablet
|
||||
|
@ -290,44 +328,8 @@ void TabletProxy::setToolbarMode(bool toolbarMode) {
|
|||
_desktopWindow = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void addButtonProxyToQmlTablet(QQuickItem* qmlTablet, TabletButtonProxy* buttonProxy) {
|
||||
Q_ASSERT(QThread::currentThread() == qApp->thread());
|
||||
if (buttonProxy == NULL){
|
||||
qCCritical(uiLogging) << __FUNCTION__ << "buttonProxy is NULL";
|
||||
return;
|
||||
}
|
||||
|
||||
QVariant resultVar;
|
||||
qCDebug(uiLogging) << "QQQ" << __FUNCTION__ << "adding button " << buttonProxy;
|
||||
bool hasResult = QMetaObject::invokeMethod(qmlTablet, "addButtonProxy", Qt::DirectConnection,
|
||||
Q_RETURN_ARG(QVariant, resultVar), Q_ARG(QVariant, buttonProxy->getProperties()));
|
||||
if (!hasResult) {
|
||||
qCWarning(uiLogging) << __FUNCTION__ << " 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));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static QString getUsername() {
|
||||
QString username = "Unknown user";
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
if (accountManager->isLoggedIn()) {
|
||||
return accountManager->getAccountInfo().getUsername();
|
||||
} else {
|
||||
return "Unknown user";
|
||||
}
|
||||
emit toolbarModeChanged();
|
||||
}
|
||||
|
||||
void TabletProxy::initialScreen(const QVariant& url) {
|
||||
|
@ -702,20 +704,7 @@ TabletButtonProxy* TabletProxy::addButton(const QVariant& properties) {
|
|||
return result;
|
||||
}
|
||||
|
||||
auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap()));
|
||||
_tabletButtonProxies.push_back(tabletButtonProxy);
|
||||
if (!_toolbarMode && _qmlTabletRoot) {
|
||||
// Tablet now pulls buttons from the tablet proxy
|
||||
// FIXME emit a signal so that the tablet can refresh buttons if they change
|
||||
} 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();
|
||||
return _buttons.addButton(properties);
|
||||
}
|
||||
|
||||
bool TabletProxy::onHomeScreen() {
|
||||
|
@ -734,35 +723,7 @@ void TabletProxy::removeButton(TabletButtonProxy* tabletButtonProxy) {
|
|||
return;
|
||||
}
|
||||
|
||||
auto tablet = getQmlTablet();
|
||||
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);
|
||||
}
|
||||
}
|
||||
_buttons.removeButton(tabletButtonProxy);
|
||||
}
|
||||
|
||||
void TabletProxy::emitScriptEvent(const QVariant& msg) {
|
||||
|
@ -801,27 +762,6 @@ void TabletProxy::desktopWindowClosed() {
|
|||
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 {
|
||||
if (!_qmlTabletRoot) {
|
||||
|
@ -891,25 +831,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() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVariantMap result;
|
||||
|
@ -926,20 +847,19 @@ void TabletButtonProxy::editProperties(const QVariantMap& properties) {
|
|||
return;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
QVariantMap::const_iterator iter = properties.constBegin();
|
||||
while (iter != properties.constEnd()) {
|
||||
const auto& key = iter.key();
|
||||
const auto& value = iter.value();
|
||||
if (!_properties.contains(key) || _properties[key] != value) {
|
||||
_properties[iter.key()] = iter.value();
|
||||
if (_qmlButton) {
|
||||
QMetaObject::invokeMethod(_qmlButton, "changeProperty", Qt::AutoConnection, Q_ARG(QVariant, QVariant(iter.key())), Q_ARG(QVariant, iter.value()));
|
||||
}
|
||||
_properties[key] = value;
|
||||
changed = true;
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (_toolbarButtonProxy) {
|
||||
QMetaObject::invokeMethod(_toolbarButtonProxy, "editProperties", Qt::AutoConnection, Q_ARG(QVariantMap, properties));
|
||||
if (changed) {
|
||||
emit propertiesChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,13 +12,16 @@
|
|||
#include <mutex>
|
||||
#include <atomic>
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QUuid>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtCore/QAbstractListModel>
|
||||
|
||||
#include <QtScript/QScriptValue>
|
||||
#include <QScriptEngine>
|
||||
#include <QScriptValueIterator>
|
||||
#include <QQuickItem>
|
||||
#include <QUuid>
|
||||
#include <QtScript/QScriptEngine>
|
||||
#include <QtScript/QScriptValueIterator>
|
||||
|
||||
#include <QtQuick/QQuickItem>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
@ -90,6 +93,31 @@ protected:
|
|||
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
|
||||
* @class TabletProxy
|
||||
* @property name {string} READ_ONLY: name of this tablet
|
||||
|
@ -99,9 +127,10 @@ protected:
|
|||
class TabletProxy : public QObject {
|
||||
Q_OBJECT
|
||||
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 tabletShown MEMBER _tabletShown NOTIFY tabletShownChanged)
|
||||
Q_PROPERTY(TabletButtonListModel* buttons READ getButtons CONSTANT)
|
||||
public:
|
||||
TabletProxy(QObject* parent, const QString& name);
|
||||
~TabletProxy();
|
||||
|
@ -196,8 +225,6 @@ public:
|
|||
|
||||
Q_INVOKABLE bool isPathLoaded(const QVariant& path);
|
||||
|
||||
Q_INVOKABLE QVariant getButtons();
|
||||
|
||||
QQuickItem* getTabletRoot() const { return _qmlTabletRoot; }
|
||||
|
||||
OffscreenQmlSurface* getTabletSurface();
|
||||
|
@ -206,6 +233,7 @@ public:
|
|||
|
||||
QQuickItem* getQmlMenu() const;
|
||||
|
||||
TabletButtonListModel* getButtons() { return &_buttons; }
|
||||
signals:
|
||||
/**jsdoc
|
||||
* Signaled when this tablet receives an event from the html/js embedded in the tablet
|
||||
|
@ -238,20 +266,20 @@ signals:
|
|||
*/
|
||||
void tabletShownChanged();
|
||||
|
||||
void toolbarModeChanged();
|
||||
|
||||
protected slots:
|
||||
void desktopWindowClosed();
|
||||
void emitWebEvent(const QVariant& msg);
|
||||
void onTabletShown();
|
||||
|
||||
protected:
|
||||
void loadHomeScreen(bool forceOntoHomeScreen);
|
||||
void addButtonsToToolbar();
|
||||
void removeButtonsFromToolbar();
|
||||
|
||||
bool _initialScreen { false };
|
||||
QVariant _initialPath { "" };
|
||||
QVariant _currentPathLoaded { "" };
|
||||
QString _name;
|
||||
std::vector<QSharedPointer<TabletButtonProxy>> _tabletButtonProxies;
|
||||
QQuickItem* _qmlTabletRoot { nullptr };
|
||||
OffscreenQmlSurface* _qmlOffscreenSurface { nullptr };
|
||||
QmlWindowClass* _desktopWindow { nullptr };
|
||||
|
@ -262,6 +290,8 @@ protected:
|
|||
State _state { State::Uninitialized };
|
||||
bool _landscape { false };
|
||||
bool _showRunningScripts { false };
|
||||
|
||||
TabletButtonListModel _buttons;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(TabletProxy*);
|
||||
|
@ -273,15 +303,11 @@ Q_DECLARE_METATYPE(TabletProxy*);
|
|||
class TabletButtonProxy : public QObject {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QUuid uuid READ getUuid)
|
||||
Q_PROPERTY(QVariantMap properties READ getProperties NOTIFY propertiesChanged)
|
||||
public:
|
||||
TabletButtonProxy(const QVariantMap& properties);
|
||||
~TabletButtonProxy();
|
||||
|
||||
|
||||
Q_INVOKABLE void setQmlButton(QQuickItem* qmlButton);
|
||||
|
||||
void setToolbarButtonProxy(QObject* toolbarButtonProxy);
|
||||
|
||||
QUuid getUuid() const { return _uuid; }
|
||||
|
||||
/**jsdoc
|
||||
|
@ -298,9 +324,6 @@ public:
|
|||
*/
|
||||
Q_INVOKABLE void editProperties(const QVariantMap& properties);
|
||||
|
||||
public slots:
|
||||
void clickedSlot() { emit clicked(); }
|
||||
|
||||
signals:
|
||||
/**jsdoc
|
||||
* Signaled when this button has been clicked on by the user.
|
||||
|
@ -308,12 +331,11 @@ signals:
|
|||
* @returns {Signal}
|
||||
*/
|
||||
void clicked();
|
||||
void propertiesChanged();
|
||||
|
||||
protected:
|
||||
QUuid _uuid;
|
||||
int _stableOrder;
|
||||
QQuickItem* _qmlButton { nullptr };
|
||||
QObject* _toolbarButtonProxy { nullptr };
|
||||
QVariantMap _properties;
|
||||
};
|
||||
|
||||
|
|
|
@ -128,6 +128,12 @@
|
|||
} else {
|
||||
ContextOverlay.isInMarketplaceInspectionMode = false;
|
||||
}
|
||||
|
||||
if (!onCommerceScreen) {
|
||||
tablet.sendToQml({
|
||||
method: 'inspectionCertificate_resetCert'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function openWallet() {
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
#include <PathUtils.h>
|
||||
|
||||
|
||||
QTEST_MAIN(PathUtilsTests)
|
||||
|
||||
void PathUtilsTests::testPathUtils() {
|
||||
|
|
Loading…
Reference in a new issue