mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 06:19:02 +02:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
c54711614e
29 changed files with 433 additions and 292 deletions
|
@ -680,11 +680,11 @@ void AudioMixer::domainSettingsRequestComplete() {
|
||||||
void AudioMixer::broadcastMixes() {
|
void AudioMixer::broadcastMixes() {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
|
||||||
int nextFrame = 0;
|
int64_t nextFrame = 0;
|
||||||
QElapsedTimer timer;
|
QElapsedTimer timer;
|
||||||
timer.start();
|
timer.start();
|
||||||
|
|
||||||
int usecToSleep = AudioConstants::NETWORK_FRAME_USECS;
|
int64_t usecToSleep = AudioConstants::NETWORK_FRAME_USECS;
|
||||||
|
|
||||||
const int TRAILING_AVERAGE_FRAMES = 100;
|
const int TRAILING_AVERAGE_FRAMES = 100;
|
||||||
int framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES;
|
int framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES;
|
||||||
|
@ -826,12 +826,7 @@ void AudioMixer::broadcastMixes() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - timer.nsecsElapsed() / 1000; // ns to us
|
usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - (timer.nsecsElapsed() / 1000);
|
||||||
|
|
||||||
if (usecToSleep > int(USECS_PER_SECOND)) {
|
|
||||||
qDebug() << "DANGER: amount to sleep is" << usecToSleep;
|
|
||||||
qDebug() << "NextFrame is" << nextFrame << "and timer nsecs elapsed is" << timer.nsecsElapsed();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usecToSleep > 0) {
|
if (usecToSleep > 0) {
|
||||||
usleep(usecToSleep);
|
usleep(usecToSleep);
|
||||||
|
|
|
@ -1103,10 +1103,13 @@
|
||||||
<div class="input-area">B <input class="coord" type='number' id="property-zone-skybox-color-blue"></div>
|
<div class="input-area">B <input class="coord" type='number' id="property-zone-skybox-color-blue"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="zone-section skybox-section property">
|
<div class="zone-section skybox-section property">
|
||||||
<div class="label">Skybox URL</div>
|
<div class="label">Skybox URL</div>
|
||||||
<div class="value">
|
<div class="value">
|
||||||
<input type="text" id="property-zone-skybox-url" class="url">
|
<input type="text" id="property-zone-skybox-url" class="url">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="section-header web-section">
|
<div class="section-header web-section">
|
||||||
<label>Web</label>
|
<label>Web</label>
|
||||||
|
|
|
@ -91,8 +91,10 @@ FocusScope {
|
||||||
id: popup
|
id: popup
|
||||||
parent: desktop
|
parent: desktop
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
z: desktop.zLevels.menu
|
||||||
visible: false
|
visible: false
|
||||||
focus: true
|
focus: true
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: hideList();
|
onClicked: hideList();
|
||||||
|
@ -116,7 +118,7 @@ FocusScope {
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: listView
|
id: listView
|
||||||
height: textView.height * count
|
height: textField.height * count * 1.4
|
||||||
model: root.model
|
model: root.model
|
||||||
highlight: Rectangle{
|
highlight: Rectangle{
|
||||||
width: listView.currentItem ? listView.currentItem.width : 0
|
width: listView.currentItem ? listView.currentItem.width : 0
|
||||||
|
|
|
@ -252,11 +252,17 @@ FocusScope {
|
||||||
return messageDialogBuilder.createObject(desktop, properties);
|
return messageDialogBuilder.createObject(desktop, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
Component { id: queryDialogBuilder; QueryDialog { } }
|
Component { id: inputDialogBuilder; QueryDialog { } }
|
||||||
function queryBox(properties) {
|
function inputDialog(properties) {
|
||||||
return queryDialogBuilder.createObject(desktop, properties);
|
return inputDialogBuilder.createObject(desktop, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component { id: fileDialogBuilder; FileDialog { } }
|
||||||
|
function fileOpenDialog(properties) {
|
||||||
|
return fileDialogBuilder.createObject(desktop, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
MenuMouseHandler { id: menuPopperUpper }
|
MenuMouseHandler { id: menuPopperUpper }
|
||||||
function popupMenu(point) {
|
function popupMenu(point) {
|
||||||
menuPopperUpper.popup(desktop, rootMenu.items, point);
|
menuPopperUpper.popup(desktop, rootMenu.items, point);
|
||||||
|
|
|
@ -12,6 +12,27 @@ import "fileDialog"
|
||||||
//FIXME implement shortcuts for favorite location
|
//FIXME implement shortcuts for favorite location
|
||||||
ModalWindow {
|
ModalWindow {
|
||||||
id: root
|
id: root
|
||||||
|
resizable: true
|
||||||
|
width: 640
|
||||||
|
height: 480
|
||||||
|
|
||||||
|
Settings {
|
||||||
|
category: "FileDialog"
|
||||||
|
property alias width: root.width
|
||||||
|
property alias height: root.height
|
||||||
|
property alias x: root.x
|
||||||
|
property alias y: root.y
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Set from OffscreenUi::getOpenFile()
|
||||||
|
property alias caption: root.title;
|
||||||
|
// Set from OffscreenUi::getOpenFile()
|
||||||
|
property alias dir: model.folder;
|
||||||
|
// Set from OffscreenUi::getOpenFile()
|
||||||
|
property alias filter: selectionType.filtersString;
|
||||||
|
// Set from OffscreenUi::getOpenFile()
|
||||||
|
property int options; // <-- FIXME unused
|
||||||
|
|
||||||
property bool selectDirectory: false;
|
property bool selectDirectory: false;
|
||||||
property bool showHidden: false;
|
property bool showHidden: false;
|
||||||
|
@ -19,17 +40,11 @@ ModalWindow {
|
||||||
property bool multiSelect: false;
|
property bool multiSelect: false;
|
||||||
// FIXME implement
|
// FIXME implement
|
||||||
property bool saveDialog: false;
|
property bool saveDialog: false;
|
||||||
|
property var helper: fileDialogHelper
|
||||||
|
property alias model: fileTableView.model
|
||||||
|
|
||||||
signal selectedFile(var file);
|
signal selectedFile(var file);
|
||||||
signal canceled();
|
signal canceled();
|
||||||
resizable: true
|
|
||||||
width: 640
|
|
||||||
height: 480
|
|
||||||
|
|
||||||
property var helper: fileDialogHelper
|
|
||||||
property alias model: fileTableView.model
|
|
||||||
property alias filterModel: selectionType.model
|
|
||||||
property alias folder: model.folder
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -120,6 +135,7 @@ ModalWindow {
|
||||||
onDoubleClicked: navigateToRow(row);
|
onDoubleClicked: navigateToRow(row);
|
||||||
model: FolderListModel {
|
model: FolderListModel {
|
||||||
id: model
|
id: model
|
||||||
|
nameFilters: selectionType.currentFilter
|
||||||
showDirsFirst: true
|
showDirsFirst: true
|
||||||
showDotAndDotDot: false
|
showDotAndDotDot: false
|
||||||
showFiles: !root.selectDirectory
|
showFiles: !root.selectDirectory
|
||||||
|
@ -157,12 +173,10 @@ ModalWindow {
|
||||||
readOnly: true
|
readOnly: true
|
||||||
}
|
}
|
||||||
|
|
||||||
ComboBox {
|
FileTypeSelection {
|
||||||
id: selectionType
|
id: selectionType
|
||||||
anchors { bottom: buttonRow.top; bottomMargin: 8; right: parent.right; rightMargin: 8; left: buttonRow.left }
|
anchors { bottom: buttonRow.top; bottomMargin: 8; right: parent.right; rightMargin: 8; left: buttonRow.left }
|
||||||
visible: !selectDirectory
|
visible: !selectDirectory
|
||||||
model: ListModel { ListElement { text: "All Files (*.*)"; filter: "*.*" } }
|
|
||||||
// onCurrentIndexChanged: model.nameFilters = [ filterModel.get(currentIndex).filter ]
|
|
||||||
KeyNavigation.left: fileTableView
|
KeyNavigation.left: fileTableView
|
||||||
KeyNavigation.right: openButton
|
KeyNavigation.right: openButton
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import QtQuick.Dialogs 1.2 as OriginalDialogs
|
||||||
import "../controls"
|
import "../controls"
|
||||||
import "../styles"
|
import "../styles"
|
||||||
import "../windows"
|
import "../windows"
|
||||||
|
import "messageDialog"
|
||||||
|
|
||||||
// FIXME respect default button functionality
|
// FIXME respect default button functionality
|
||||||
ModalWindow {
|
ModalWindow {
|
||||||
|
@ -126,126 +127,23 @@ ModalWindow {
|
||||||
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
onHeightChanged: d.resize(); onWidthChanged: d.resize();
|
||||||
layoutDirection: Qt.RightToLeft
|
layoutDirection: Qt.RightToLeft
|
||||||
anchors { bottom: details.top; right: parent.right; margins: d.spacing * 2; bottomMargin: 0 }
|
anchors { bottom: details.top; right: parent.right; margins: d.spacing * 2; bottomMargin: 0 }
|
||||||
Button {
|
MessageDialogButton { dialog: root; text: qsTr("OK"); button: OriginalDialogs.StandardButton.Ok; }
|
||||||
id: okButton
|
MessageDialogButton { dialog: root; text: qsTr("Open"); button: OriginalDialogs.StandardButton.Open; }
|
||||||
text: qsTr("OK")
|
MessageDialogButton { dialog: root; text: qsTr("Save"); button: OriginalDialogs.StandardButton.Save; }
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.Ok
|
MessageDialogButton { dialog: root; text: qsTr("Save All"); button: OriginalDialogs.StandardButton.SaveAll; }
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.Ok)
|
MessageDialogButton { dialog: root; text: qsTr("Retry"); button: OriginalDialogs.StandardButton.Retry; }
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.Ok
|
MessageDialogButton { dialog: root; text: qsTr("Ignore"); button: OriginalDialogs.StandardButton.Ignore; }
|
||||||
|
MessageDialogButton { dialog: root; text: qsTr("Apply"); button: OriginalDialogs.StandardButton.Apply; }
|
||||||
}
|
MessageDialogButton { dialog: root; text: qsTr("Yes"); button: OriginalDialogs.StandardButton.Yes; }
|
||||||
Button {
|
MessageDialogButton { dialog: root; text: qsTr("Yes to All"); button: OriginalDialogs.StandardButton.YesToAll; }
|
||||||
id: openButton
|
MessageDialogButton { dialog: root; text: qsTr("No"); button: OriginalDialogs.StandardButton.No; }
|
||||||
text: qsTr("Open")
|
MessageDialogButton { dialog: root; text: qsTr("No to All"); button: OriginalDialogs.StandardButton.NoToAll; }
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.Open
|
MessageDialogButton { dialog: root; text: qsTr("Discard"); button: OriginalDialogs.StandardButton.Discard; }
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.Open)
|
MessageDialogButton { dialog: root; text: qsTr("Reset"); button: OriginalDialogs.StandardButton.Reset; }
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.Open
|
MessageDialogButton { dialog: root; text: qsTr("Restore Defaults"); button: OriginalDialogs.StandardButton.RestoreDefaults; }
|
||||||
}
|
MessageDialogButton { dialog: root; text: qsTr("Cancel"); button: OriginalDialogs.StandardButton.Cancel; }
|
||||||
Button {
|
MessageDialogButton { dialog: root; text: qsTr("Abort"); button: OriginalDialogs.StandardButton.Abort; }
|
||||||
id: saveButton
|
MessageDialogButton { dialog: root; text: qsTr("Close"); button: OriginalDialogs.StandardButton.Close; }
|
||||||
text: qsTr("Save")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.Save
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.Save)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.Save
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: saveAllButton
|
|
||||||
text: qsTr("Save All")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.SaveAll
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.SaveAll)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.SaveAll
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: retryButton
|
|
||||||
text: qsTr("Retry")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.Retry
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.Retry)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.Retry
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: ignoreButton
|
|
||||||
text: qsTr("Ignore")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.Ignore
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.Ignore)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.Ignore
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: applyButton
|
|
||||||
text: qsTr("Apply")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.Apply
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.Apply)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.Apply
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: yesButton
|
|
||||||
text: qsTr("Yes")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.Yes
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.Yes)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.Yes
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: yesAllButton
|
|
||||||
text: qsTr("Yes to All")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.YesToAll
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.YesToAll)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.YesToAll
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: noButton
|
|
||||||
text: qsTr("No")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.No
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.No)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.No
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: noAllButton
|
|
||||||
text: qsTr("No to All")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.NoToAll
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.NoToAll)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.NoToAll
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: discardButton
|
|
||||||
text: qsTr("Discard")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.Discard
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.Discard)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.Discard
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: resetButton
|
|
||||||
text: qsTr("Reset")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.Reset
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.Reset)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.Reset
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: restoreDefaultsButton
|
|
||||||
text: qsTr("Restore Defaults")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.RestoreDefaults
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.RestoreDefaults)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.RestoreDefaults
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: cancelButton
|
|
||||||
text: qsTr("Cancel")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.Cancel
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.Cancel)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.Cancel
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: abortButton
|
|
||||||
text: qsTr("Abort")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.Abort
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.Abort)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.Abort
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
id: closeButton
|
|
||||||
text: qsTr("Close")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.Close
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.Close)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.Close
|
|
||||||
}
|
|
||||||
Button {
|
Button {
|
||||||
id: moreButton
|
id: moreButton
|
||||||
text: qsTr("Show Details...")
|
text: qsTr("Show Details...")
|
||||||
|
@ -253,13 +151,7 @@ ModalWindow {
|
||||||
}
|
}
|
||||||
visible: detailedText && detailedText.length > 0
|
visible: detailedText && detailedText.length > 0
|
||||||
}
|
}
|
||||||
Button {
|
MessageDialogButton { dialog: root; text: qsTr("Help"); button: OriginalDialogs.StandardButton.Help; }
|
||||||
id: helpButton
|
|
||||||
text: qsTr("Help")
|
|
||||||
focus: root.defaultButton === OriginalDialogs.StandardButton.Help
|
|
||||||
onClicked: root.click(OriginalDialogs.StandardButton.Help)
|
|
||||||
visible: root.buttons & OriginalDialogs.StandardButton.Help
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
@ -328,7 +220,7 @@ ModalWindow {
|
||||||
case Qt.Key_Enter:
|
case Qt.Key_Enter:
|
||||||
case Qt.Key_Return:
|
case Qt.Key_Return:
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
root.click(OriginalDialogs.StandardButton.Ok)
|
root.click(root.defaultButton)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,17 @@ ModalWindow {
|
||||||
signal selected(var result);
|
signal selected(var result);
|
||||||
signal canceled();
|
signal canceled();
|
||||||
|
|
||||||
property alias result: textResult.text
|
property var items;
|
||||||
|
property alias label: mainTextContainer.text
|
||||||
|
property var result;
|
||||||
|
// FIXME not current honored
|
||||||
|
property var current;
|
||||||
|
|
||||||
|
// For text boxes
|
||||||
property alias placeholderText: textResult.placeholderText
|
property alias placeholderText: textResult.placeholderText
|
||||||
property alias text: mainTextContainer.text
|
|
||||||
|
// For combo boxes
|
||||||
|
property bool editable: true;
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
clip: true
|
clip: true
|
||||||
|
@ -55,10 +63,20 @@ ModalWindow {
|
||||||
anchors { top: mainTextContainer.bottom; bottom: buttons.top; left: parent.left; right: parent.right; margins: d.spacing }
|
anchors { top: mainTextContainer.bottom; bottom: buttons.top; left: parent.left; right: parent.right; margins: d.spacing }
|
||||||
// FIXME make a text field type that can be bound to a history for autocompletion
|
// FIXME make a text field type that can be bound to a history for autocompletion
|
||||||
TextField {
|
TextField {
|
||||||
focus: true
|
|
||||||
id: textResult
|
id: textResult
|
||||||
|
focus: items ? false : true
|
||||||
|
visible: items ? false : true
|
||||||
anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter }
|
anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VrControls.ComboBox {
|
||||||
|
id: comboBox
|
||||||
|
focus: items ? true : false
|
||||||
|
visible: items ? true : false
|
||||||
|
anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter }
|
||||||
|
model: items ? items : []
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Flow {
|
Flow {
|
||||||
|
@ -86,6 +104,7 @@ ModalWindow {
|
||||||
text: qsTr("OK")
|
text: qsTr("OK")
|
||||||
shortcut: Qt.Key_Return
|
shortcut: Qt.Key_Return
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
|
root.result = items ? comboBox.currentText : textResult.text
|
||||||
root.selected(root.result);
|
root.selected(root.result);
|
||||||
root.destroy();
|
root.destroy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,23 +72,6 @@ Window {
|
||||||
scripts.stopAllScripts();
|
scripts.stopAllScripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
Component {
|
|
||||||
id: fileDialogBuilder
|
|
||||||
FileDialog { }
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadFromFile() {
|
|
||||||
var fileDialog = fileDialogBuilder.createObject(desktop, { filterModel: fileFilters });
|
|
||||||
fileDialog.canceled.connect(function(){
|
|
||||||
console.debug("Cancelled file open")
|
|
||||||
})
|
|
||||||
|
|
||||||
fileDialog.selectedFile.connect(function(file){
|
|
||||||
console.debug("Selected " + file)
|
|
||||||
scripts.loadOneScript(file);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
color: "white"
|
color: "white"
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -123,26 +106,42 @@ Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
|
id: listView
|
||||||
clip: true
|
clip: true
|
||||||
anchors { fill: parent; margins: 0 }
|
anchors { fill: parent; margins: 0 }
|
||||||
|
|
||||||
model: runningScriptsModel
|
model: runningScriptsModel
|
||||||
|
|
||||||
delegate: Rectangle {
|
delegate: Rectangle {
|
||||||
|
id: rectangle
|
||||||
|
clip: true
|
||||||
radius: 3
|
radius: 3
|
||||||
anchors { left: parent.left; right: parent.right }
|
anchors { left: parent.left; right: parent.right }
|
||||||
|
|
||||||
height: scriptName.height + 12
|
height: scriptName.height + 12 + (ListView.isCurrentItem ? scriptName.height + 6 : 0)
|
||||||
color: index % 2 ? "#ddd" : "#eee"
|
color: ListView.isCurrentItem ? "#39f" :
|
||||||
|
index % 2 ? "#ddd" : "#eee"
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
anchors { left: parent.left; leftMargin: 4; verticalCenter: parent.verticalCenter }
|
|
||||||
id: scriptName
|
id: scriptName
|
||||||
|
anchors { left: parent.left; leftMargin: 4; top: parent.top; topMargin:6 }
|
||||||
text: name
|
text: name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: scriptUrl
|
||||||
|
anchors { left: scriptName.left; right: parent.right; rightMargin: 4; top: scriptName.bottom; topMargin: 6 }
|
||||||
|
text: url
|
||||||
|
elide: Text.ElideMiddle
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: listView.currentIndex = index
|
||||||
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: scriptName.verticalCenter
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 4
|
anchors.rightMargin: 4
|
||||||
spacing: 4
|
spacing: 4
|
||||||
|
@ -185,31 +184,38 @@ Window {
|
||||||
anchors.bottomMargin: 8
|
anchors.bottomMargin: 8
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
// For some reason trigginer an API that enters
|
|
||||||
// an internal event loop directly from the button clicked
|
|
||||||
// trigger below causes the appliction to behave oddly.
|
|
||||||
// Most likely because the button onClicked handling is never
|
|
||||||
// completed until the function returns.
|
|
||||||
// FIXME find a better way of handling the input dialogs that
|
|
||||||
// doesn't trigger this.
|
|
||||||
Timer {
|
|
||||||
id: asyncAction
|
|
||||||
interval: 50
|
|
||||||
repeat: false
|
|
||||||
running: false
|
|
||||||
onTriggered: ApplicationInterface.loadScriptURLDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
text: "from URL";
|
text: "from URL";
|
||||||
onClicked: {
|
onClicked: fromUrlTimer.running = true;
|
||||||
focus = false;
|
|
||||||
asyncAction.running = true;
|
// For some reason trigginer an API that enters
|
||||||
|
// an internal event loop directly from the button clicked
|
||||||
|
// trigger below causes the appliction to behave oddly.
|
||||||
|
// Most likely because the button onClicked handling is never
|
||||||
|
// completed until the function returns.
|
||||||
|
// FIXME find a better way of handling the input dialogs that
|
||||||
|
// doesn't trigger this.
|
||||||
|
Timer {
|
||||||
|
id: fromUrlTimer
|
||||||
|
interval: 5
|
||||||
|
repeat: false
|
||||||
|
running: false
|
||||||
|
onTriggered: ApplicationInterface.loadScriptURLDialog();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
text: "from Disk"
|
text: "from Disk"
|
||||||
onClicked: loadFromFile();
|
onClicked: fromDiskTimer.running = true;
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: fromDiskTimer
|
||||||
|
interval: 5
|
||||||
|
repeat: false
|
||||||
|
running: false
|
||||||
|
onTriggered: ApplicationInterface.loadDialog();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
import QtQuick 2.5
|
||||||
|
|
||||||
|
import "../../controls" as VrControls
|
||||||
|
|
||||||
|
VrControls.ComboBox {
|
||||||
|
id: root
|
||||||
|
property string filtersString: "All Files (*.*)";
|
||||||
|
property var currentFilter: [ "*.*" ];
|
||||||
|
|
||||||
|
// Per http://doc.qt.io/qt-5/qfiledialog.html#getOpenFileName the string can contain
|
||||||
|
// multiple filters separated by semicolons
|
||||||
|
// ex: "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
|
||||||
|
model: filtersString.split(';;');
|
||||||
|
|
||||||
|
enabled: model.length > 1
|
||||||
|
|
||||||
|
onCurrentTextChanged: {
|
||||||
|
var globRegex = /\((.*)\)$/
|
||||||
|
var globs = globRegex.exec(currentText);
|
||||||
|
if (!globs[1]) {
|
||||||
|
console.warn("Unable to parse filter " + currentText);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentFilter = globs[1].split(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
|
||||||
|
Button {
|
||||||
|
property var dialog;
|
||||||
|
property int button: StandardButton.NoButton;
|
||||||
|
|
||||||
|
focus: dialog.defaultButton === button
|
||||||
|
onClicked: dialog.click(button)
|
||||||
|
visible: dialog.buttons & button
|
||||||
|
}
|
|
@ -20,12 +20,8 @@ Frame {
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: controlsRow
|
id: controlsRow
|
||||||
anchors.right: parent.right
|
anchors { right: parent.right; top: parent.top; rightMargin: iconSize; topMargin: iconSize / 2; }
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.rightMargin: iconSize
|
|
||||||
anchors.topMargin: iconSize / 2
|
|
||||||
spacing: iconSize / 4
|
spacing: iconSize / 4
|
||||||
|
|
||||||
FontAwesome {
|
FontAwesome {
|
||||||
visible: false
|
visible: false
|
||||||
text: "\uf08d"
|
text: "\uf08d"
|
||||||
|
@ -54,6 +50,18 @@ Frame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: titleText
|
||||||
|
anchors { left: parent.left; leftMargin: iconSize; right: controlsRow.left; rightMargin: iconSize; top: parent.top; topMargin: iconSize / 2; }
|
||||||
|
text: window.title
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.bold: true
|
||||||
|
color: window.focus ? "white" : "gray"
|
||||||
|
style: Text.Outline;
|
||||||
|
styleColor: "black"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ Item {
|
||||||
id: debugZ
|
id: debugZ
|
||||||
visible: DebugQML
|
visible: DebugQML
|
||||||
text: window ? "Z: " + window.z : ""
|
text: window ? "Z: " + window.z : ""
|
||||||
y: -height
|
y: window.height + 4
|
||||||
}
|
}
|
||||||
|
|
||||||
function deltaSize(dx, dy) {
|
function deltaSize(dx, dy) {
|
||||||
|
|
|
@ -13,5 +13,16 @@ Frame {
|
||||||
color: "#7f7f7f7f";
|
color: "#7f7f7f7f";
|
||||||
radius: 3;
|
radius: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
y: -implicitHeight - iconSize / 2
|
||||||
|
text: window.title
|
||||||
|
elide: Text.ElideRight
|
||||||
|
font.bold: true
|
||||||
|
color: window.focus ? "white" : "gray"
|
||||||
|
style: Text.Outline;
|
||||||
|
styleColor: "black"
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -406,6 +406,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
||||||
_entityClipboard(new EntityTree()),
|
_entityClipboard(new EntityTree()),
|
||||||
_lastQueriedTime(usecTimestampNow()),
|
_lastQueriedTime(usecTimestampNow()),
|
||||||
_mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)),
|
_mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)),
|
||||||
|
_previousScriptLocation("LastScriptLocation", DESKTOP_LOCATION),
|
||||||
_fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES),
|
_fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES),
|
||||||
_scaleMirror(1.0f),
|
_scaleMirror(1.0f),
|
||||||
_rotateMirror(0.0f),
|
_rotateMirror(0.0f),
|
||||||
|
@ -4501,14 +4502,24 @@ void Application::domainSettingsReceived(const QJsonObject& domainSettingsObject
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::loadDialog() {
|
void Application::loadDialog() {
|
||||||
// To be migratd to QML
|
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||||
QString fileNameString = QFileDialog::getOpenFileName(
|
QString fileNameString = OffscreenUi::getOpenFileName(
|
||||||
_glWidget, tr("Open Script"), "", tr("JavaScript Files (*.js)"));
|
_glWidget, tr("Open Script"), getPreviousScriptLocation(), tr("JavaScript Files (*.js)"));
|
||||||
if (!fileNameString.isEmpty()) {
|
if (!fileNameString.isEmpty() && QFile(fileNameString).exists()) {
|
||||||
|
setPreviousScriptLocation(QFileInfo(fileNameString).absolutePath());
|
||||||
DependencyManager::get<ScriptEngines>()->loadScript(fileNameString, true, false, false, true); // Don't load from cache
|
DependencyManager::get<ScriptEngines>()->loadScript(fileNameString, true, false, false, true); // Don't load from cache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Application::getPreviousScriptLocation() {
|
||||||
|
QString result = _previousScriptLocation.get();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::setPreviousScriptLocation(const QString& location) {
|
||||||
|
_previousScriptLocation.set(location);
|
||||||
|
}
|
||||||
|
|
||||||
void Application::loadScriptURLDialog() {
|
void Application::loadScriptURLDialog() {
|
||||||
auto newScript = OffscreenUi::getText(nullptr, "Open and Run Script", "Script URL");
|
auto newScript = OffscreenUi::getText(nullptr, "Open and Run Script", "Script URL");
|
||||||
if (!newScript.isEmpty()) {
|
if (!newScript.isEmpty()) {
|
||||||
|
|
|
@ -103,6 +103,9 @@ public:
|
||||||
|
|
||||||
void postLambdaEvent(std::function<void()> f) override;
|
void postLambdaEvent(std::function<void()> f) override;
|
||||||
|
|
||||||
|
QString getPreviousScriptLocation();
|
||||||
|
void setPreviousScriptLocation(const QString& previousScriptLocation);
|
||||||
|
|
||||||
void initializeGL();
|
void initializeGL();
|
||||||
void initializeUi();
|
void initializeUi();
|
||||||
void paintGL();
|
void paintGL();
|
||||||
|
@ -431,6 +434,7 @@ private:
|
||||||
Camera _mirrorCamera; // Cammera for mirror view
|
Camera _mirrorCamera; // Cammera for mirror view
|
||||||
QRect _mirrorViewRect;
|
QRect _mirrorViewRect;
|
||||||
|
|
||||||
|
Setting::Handle<QString> _previousScriptLocation;
|
||||||
Setting::Handle<float> _fieldOfView;
|
Setting::Handle<float> _fieldOfView;
|
||||||
|
|
||||||
float _scaleMirror;
|
float _scaleMirror;
|
||||||
|
|
|
@ -20,12 +20,14 @@
|
||||||
|
|
||||||
#include <AddressManager.h>
|
#include <AddressManager.h>
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
|
#include <OffscreenUi.h>
|
||||||
|
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
|
|
||||||
#include "Bookmarks.h"
|
#include "Bookmarks.h"
|
||||||
|
#include <QtQuick/QQuickWindow>
|
||||||
|
|
||||||
Bookmarks::Bookmarks() {
|
Bookmarks::Bookmarks() {
|
||||||
_bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + BOOKMARKS_FILENAME;
|
_bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + BOOKMARKS_FILENAME;
|
||||||
|
@ -104,18 +106,13 @@ void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bookmarks::bookmarkLocation() {
|
void Bookmarks::bookmarkLocation() {
|
||||||
QInputDialog bookmarkLocationDialog(qApp->getWindow());
|
bool ok = false;
|
||||||
bookmarkLocationDialog.setWindowTitle("Bookmark Location");
|
auto bookmarkName = OffscreenUi::getText(nullptr, "Bookmark Location", "Name:", QLineEdit::Normal, QString(), &ok);
|
||||||
bookmarkLocationDialog.setLabelText("Name:");
|
if (!ok) {
|
||||||
bookmarkLocationDialog.setInputMode(QInputDialog::TextInput);
|
|
||||||
bookmarkLocationDialog.resize(400, 200);
|
|
||||||
|
|
||||||
if (bookmarkLocationDialog.exec() == QDialog::Rejected) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString bookmarkName = bookmarkLocationDialog.textValue().trimmed();
|
bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
|
||||||
bookmarkName = bookmarkName.replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
|
|
||||||
if (bookmarkName.length() == 0) {
|
if (bookmarkName.length() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -125,13 +122,14 @@ void Bookmarks::bookmarkLocation() {
|
||||||
|
|
||||||
Menu* menubar = Menu::getInstance();
|
Menu* menubar = Menu::getInstance();
|
||||||
if (contains(bookmarkName)) {
|
if (contains(bookmarkName)) {
|
||||||
QMessageBox duplicateBookmarkMessage;
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
duplicateBookmarkMessage.setIcon(QMessageBox::Warning);
|
auto duplicateBookmarkMessage = offscreenUi->createMessageBox(QMessageBox::Warning, "Duplicate Bookmark",
|
||||||
duplicateBookmarkMessage.setText("The bookmark name you entered already exists in your list.");
|
"The bookmark name you entered already exists in your list.",
|
||||||
duplicateBookmarkMessage.setInformativeText("Would you like to overwrite it?");
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||||
duplicateBookmarkMessage.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?");
|
||||||
duplicateBookmarkMessage.setDefaultButton(QMessageBox::Yes);
|
|
||||||
if (duplicateBookmarkMessage.exec() == QMessageBox::No) {
|
auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage);
|
||||||
|
if (result != QMessageBox::Yes) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
removeLocationFromMenu(menubar, bookmarkName);
|
removeLocationFromMenu(menubar, bookmarkName);
|
||||||
|
@ -157,19 +155,13 @@ void Bookmarks::deleteBookmark() {
|
||||||
bookmarkList.append(menuItems[i]->text());
|
bookmarkList.append(menuItems[i]->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
QInputDialog deleteBookmarkDialog(qApp->getWindow());
|
bool ok = false;
|
||||||
deleteBookmarkDialog.setWindowTitle("Delete Bookmark");
|
auto bookmarkName = OffscreenUi::getItem(nullptr, "Delete Bookmark", "Select the bookmark to delete", bookmarkList, 0, false, &ok);
|
||||||
deleteBookmarkDialog.setLabelText("Select the bookmark to delete");
|
if (!ok) {
|
||||||
deleteBookmarkDialog.resize(400, 400);
|
|
||||||
deleteBookmarkDialog.setOption(QInputDialog::UseListViewForComboBoxItems);
|
|
||||||
deleteBookmarkDialog.setComboBoxItems(bookmarkList);
|
|
||||||
deleteBookmarkDialog.setOkButtonText("Delete");
|
|
||||||
|
|
||||||
if (deleteBookmarkDialog.exec() == QDialog::Rejected) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString bookmarkName = deleteBookmarkDialog.textValue().trimmed();
|
bookmarkName = bookmarkName.trimmed();
|
||||||
if (bookmarkName.length() == 0) {
|
if (bookmarkName.length() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,10 +191,10 @@ bool ScriptEditorWidget::save() {
|
||||||
bool ScriptEditorWidget::saveAs() {
|
bool ScriptEditorWidget::saveAs() {
|
||||||
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||||
QString fileName = QFileDialog::getSaveFileName(this, tr("Save script"),
|
QString fileName = QFileDialog::getSaveFileName(this, tr("Save script"),
|
||||||
scriptEngines->getPreviousScriptLocation(),
|
qApp->getPreviousScriptLocation(),
|
||||||
tr("JavaScript Files (*.js)"));
|
tr("JavaScript Files (*.js)"));
|
||||||
if (!fileName.isEmpty()) {
|
if (!fileName.isEmpty()) {
|
||||||
scriptEngines->setPreviousScriptLocation(fileName);
|
qApp->setPreviousScriptLocation(fileName);
|
||||||
return saveFile(fileName);
|
return saveFile(fileName);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -87,12 +87,11 @@ void ScriptEditorWindow::loadScriptMenu(const QString& scriptName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptEditorWindow::loadScriptClicked() {
|
void ScriptEditorWindow::loadScriptClicked() {
|
||||||
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
|
||||||
QString scriptName = QFileDialog::getOpenFileName(this, tr("Interface"),
|
QString scriptName = QFileDialog::getOpenFileName(this, tr("Interface"),
|
||||||
scriptEngines->getPreviousScriptLocation(),
|
qApp->getPreviousScriptLocation(),
|
||||||
tr("JavaScript Files (*.js)"));
|
tr("JavaScript Files (*.js)"));
|
||||||
if (!scriptName.isEmpty()) {
|
if (!scriptName.isEmpty()) {
|
||||||
scriptEngines->setPreviousScriptLocation(scriptName);
|
qApp->setPreviousScriptLocation(scriptName);
|
||||||
addScriptEditorWidget("loading...")->loadFile(scriptName);
|
addScriptEditorWidget("loading...")->loadFile(scriptName);
|
||||||
updateButtons();
|
updateButtons();
|
||||||
}
|
}
|
||||||
|
@ -100,7 +99,7 @@ void ScriptEditorWindow::loadScriptClicked() {
|
||||||
|
|
||||||
void ScriptEditorWindow::loadMenuAboutToShow() {
|
void ScriptEditorWindow::loadMenuAboutToShow() {
|
||||||
_loadMenu->clear();
|
_loadMenu->clear();
|
||||||
QStringList runningScripts = DependencyManager::get<ScriptEngines>()->getRunningScripts();;
|
QStringList runningScripts = DependencyManager::get<ScriptEngines>()->getRunningScripts();
|
||||||
if (runningScripts.count() > 0) {
|
if (runningScripts.count() > 0) {
|
||||||
QSignalMapper* signalMapper = new QSignalMapper(this);
|
QSignalMapper* signalMapper = new QSignalMapper(this);
|
||||||
foreach (const QString& runningScript, runningScripts) {
|
foreach (const QString& runningScript, runningScripts) {
|
||||||
|
|
|
@ -102,6 +102,11 @@ void AudioInjector::restart() {
|
||||||
// reset the current send offset to zero
|
// reset the current send offset to zero
|
||||||
_currentSendOffset = 0;
|
_currentSendOffset = 0;
|
||||||
|
|
||||||
|
// reset state to start sending from beginning again
|
||||||
|
_nextFrame = 0;
|
||||||
|
_frameTimer->invalidate();
|
||||||
|
_hasSentFirstFrame = false;
|
||||||
|
|
||||||
// check our state to decide if we need extra handling for the restart request
|
// check our state to decide if we need extra handling for the restart request
|
||||||
if (_state == State::Finished) {
|
if (_state == State::Finished) {
|
||||||
// we finished playing, need to reset state so we can get going again
|
// we finished playing, need to reset state so we can get going again
|
||||||
|
@ -246,6 +251,11 @@ int64_t AudioInjector::injectNextFrame() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_frameTimer->isValid()) {
|
||||||
|
// in the case where we have been restarted, the frame timer will be invalid and we need to start it back over here
|
||||||
|
_frameTimer->restart();
|
||||||
|
}
|
||||||
|
|
||||||
int totalBytesLeftToCopy = (_options.stereo ? 2 : 1) * AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL;
|
int totalBytesLeftToCopy = (_options.stereo ? 2 : 1) * AudioConstants::NETWORK_FRAME_BYTES_PER_CHANNEL;
|
||||||
if (!_options.loop) {
|
if (!_options.loop) {
|
||||||
// If we aren't looping, let's make sure we don't read past the end
|
// If we aren't looping, let's make sure we don't read past the end
|
||||||
|
|
|
@ -79,6 +79,12 @@ void AudioInjectorManager::run() {
|
||||||
if (_injectors.size() > 0) {
|
if (_injectors.size() > 0) {
|
||||||
// loop through the injectors in the map and send whatever frames need to go out
|
// loop through the injectors in the map and send whatever frames need to go out
|
||||||
auto front = _injectors.top();
|
auto front = _injectors.top();
|
||||||
|
|
||||||
|
// create an InjectorQueue to hold injectors to be queued
|
||||||
|
// this allows us to call processEvents even if a single injector wants to be re-queued immediately
|
||||||
|
std::vector<TimeInjectorPointerPair> heldInjectors;
|
||||||
|
heldInjectors.reserve(_injectors.size());
|
||||||
|
|
||||||
while (_injectors.size() > 0 && front.first <= usecTimestampNow()) {
|
while (_injectors.size() > 0 && front.first <= usecTimestampNow()) {
|
||||||
// either way we're popping this injector off - get a copy first
|
// either way we're popping this injector off - get a copy first
|
||||||
auto injector = front.second;
|
auto injector = front.second;
|
||||||
|
@ -89,8 +95,8 @@ void AudioInjectorManager::run() {
|
||||||
auto nextCallDelta = injector->injectNextFrame();
|
auto nextCallDelta = injector->injectNextFrame();
|
||||||
|
|
||||||
if (nextCallDelta >= 0 && !injector->isFinished()) {
|
if (nextCallDelta >= 0 && !injector->isFinished()) {
|
||||||
// re-enqueue the injector with the correct timing
|
// enqueue the injector with the correct timing in our holding queue
|
||||||
_injectors.emplace(usecTimestampNow() + nextCallDelta, injector);
|
heldInjectors.emplace(heldInjectors.end(), usecTimestampNow() + nextCallDelta, injector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +107,12 @@ void AudioInjectorManager::run() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if there are injectors in the holding queue, push them to our persistent queue now
|
||||||
|
while (!heldInjectors.empty()) {
|
||||||
|
_injectors.push(heldInjectors.back());
|
||||||
|
heldInjectors.pop_back();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -490,6 +490,9 @@ void NodeList::processDomainServerList(QSharedPointer<ReceivedMessage> message)
|
||||||
// this is a packet from the domain server, reset the count of un-replied check-ins
|
// this is a packet from the domain server, reset the count of un-replied check-ins
|
||||||
_numNoReplyDomainCheckIns = 0;
|
_numNoReplyDomainCheckIns = 0;
|
||||||
|
|
||||||
|
// emit our signal so listeners know we just heard from the DS
|
||||||
|
emit receivedDomainServerList();
|
||||||
|
|
||||||
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::ReceiveDSList);
|
DependencyManager::get<NodeList>()->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::ReceiveDSList);
|
||||||
|
|
||||||
QDataStream packetStream(message->getMessage());
|
QDataStream packetStream(message->getMessage());
|
||||||
|
|
|
@ -87,6 +87,7 @@ public slots:
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void limitOfSilentDomainCheckInsReached();
|
void limitOfSilentDomainCheckInsReached();
|
||||||
|
void receivedDomainServerList();
|
||||||
private slots:
|
private slots:
|
||||||
void stopKeepalivePingTimer();
|
void stopKeepalivePingTimer();
|
||||||
void sendPendingDSPathQuery();
|
void sendPendingDSPathQuery();
|
||||||
|
|
|
@ -30,6 +30,10 @@ ThreadedAssignment::ThreadedAssignment(ReceivedMessage& message) :
|
||||||
|
|
||||||
connect(&_domainServerTimer, &QTimer::timeout, this, &ThreadedAssignment::checkInWithDomainServerOrExit);
|
connect(&_domainServerTimer, &QTimer::timeout, this, &ThreadedAssignment::checkInWithDomainServerOrExit);
|
||||||
_domainServerTimer.setInterval(DOMAIN_SERVER_CHECK_IN_MSECS);
|
_domainServerTimer.setInterval(DOMAIN_SERVER_CHECK_IN_MSECS);
|
||||||
|
|
||||||
|
// if the NL tells us we got a DS response, clear our member variable of queued check-ins
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
connect(nodeList.data(), &NodeList::receivedDomainServerList, this, &ThreadedAssignment::clearQueuedCheckIns);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadedAssignment::setFinished(bool isFinished) {
|
void ThreadedAssignment::setFinished(bool isFinished) {
|
||||||
|
@ -103,11 +107,18 @@ void ThreadedAssignment::sendStatsPacket() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadedAssignment::checkInWithDomainServerOrExit() {
|
void ThreadedAssignment::checkInWithDomainServerOrExit() {
|
||||||
if (DependencyManager::get<NodeList>()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
|
// verify that the number of queued check-ins is not >= our max
|
||||||
|
// the number of queued check-ins is cleared anytime we get a response from the domain-server
|
||||||
|
if (_numQueuedCheckIns >= MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
|
||||||
|
qDebug() << "At least" << MAX_SILENT_DOMAIN_SERVER_CHECK_INS << "have been queued without a response from domain-server"
|
||||||
|
<< "Stopping the current assignment";
|
||||||
setFinished(true);
|
setFinished(true);
|
||||||
} else {
|
} else {
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
QMetaObject::invokeMethod(nodeList.data(), "sendDomainServerCheckIn");
|
QMetaObject::invokeMethod(nodeList.data(), "sendDomainServerCheckIn");
|
||||||
|
|
||||||
|
// increase the number of queued check ins
|
||||||
|
_numQueuedCheckIns++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ public slots:
|
||||||
virtual void run() = 0;
|
virtual void run() = 0;
|
||||||
Q_INVOKABLE virtual void stop() { setFinished(true); }
|
Q_INVOKABLE virtual void stop() { setFinished(true); }
|
||||||
virtual void sendStatsPacket();
|
virtual void sendStatsPacket();
|
||||||
|
void clearQueuedCheckIns() { _numQueuedCheckIns = 0; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void finished();
|
void finished();
|
||||||
|
@ -42,6 +43,7 @@ protected:
|
||||||
bool _isFinished;
|
bool _isFinished;
|
||||||
QTimer _domainServerTimer;
|
QTimer _domainServerTimer;
|
||||||
QTimer _statsTimer;
|
QTimer _statsTimer;
|
||||||
|
int _numQueuedCheckIns { 0 };
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void domainSettingsRequestFailed();
|
void domainSettingsRequestFailed();
|
||||||
|
|
|
@ -34,8 +34,7 @@ ScriptsModel& getScriptsModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptEngines::ScriptEngines()
|
ScriptEngines::ScriptEngines()
|
||||||
: _scriptsLocationHandle("scriptsLocation", DESKTOP_LOCATION),
|
: _scriptsLocationHandle("scriptsLocation", DESKTOP_LOCATION)
|
||||||
_previousScriptLocation("LastScriptLocation", DESKTOP_LOCATION)
|
|
||||||
{
|
{
|
||||||
_scriptsModelFilter.setSourceModel(&_scriptsModel);
|
_scriptsModelFilter.setSourceModel(&_scriptsModel);
|
||||||
_scriptsModelFilter.sort(0, Qt::AscendingOrder);
|
_scriptsModelFilter.sort(0, Qt::AscendingOrder);
|
||||||
|
@ -445,14 +444,3 @@ void ScriptEngines::onScriptEngineError(const QString& scriptFilename) {
|
||||||
qCDebug(scriptengine) << "Application::loadScript(), script failed to load...";
|
qCDebug(scriptengine) << "Application::loadScript(), script failed to load...";
|
||||||
emit scriptLoadError(scriptFilename, "");
|
emit scriptLoadError(scriptFilename, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ScriptEngines::getPreviousScriptLocation() const {
|
|
||||||
return _previousScriptLocation.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScriptEngines::setPreviousScriptLocation(const QString& previousScriptLocation) {
|
|
||||||
if (_previousScriptLocation.get() != previousScriptLocation) {
|
|
||||||
_previousScriptLocation.set(previousScriptLocation);
|
|
||||||
emit previousScriptLocationChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -30,7 +30,6 @@ class ScriptEngines : public QObject, public Dependency {
|
||||||
|
|
||||||
Q_PROPERTY(ScriptsModel* scriptsModel READ scriptsModel CONSTANT)
|
Q_PROPERTY(ScriptsModel* scriptsModel READ scriptsModel CONSTANT)
|
||||||
Q_PROPERTY(ScriptsModelFilter* scriptsModelFilter READ scriptsModelFilter CONSTANT)
|
Q_PROPERTY(ScriptsModelFilter* scriptsModelFilter READ scriptsModelFilter CONSTANT)
|
||||||
Q_PROPERTY(QString previousScriptLocation READ getPreviousScriptLocation WRITE setPreviousScriptLocation NOTIFY previousScriptLocationChanged)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using ScriptInitializer = std::function<void(ScriptEngine*)>;
|
using ScriptInitializer = std::function<void(ScriptEngine*)>;
|
||||||
|
@ -48,9 +47,6 @@ public:
|
||||||
QStringList getRunningScripts();
|
QStringList getRunningScripts();
|
||||||
ScriptEngine* getScriptEngine(const QString& scriptHash);
|
ScriptEngine* getScriptEngine(const QString& scriptHash);
|
||||||
|
|
||||||
QString getPreviousScriptLocation() const;
|
|
||||||
void setPreviousScriptLocation(const QString& previousScriptLocation);
|
|
||||||
|
|
||||||
ScriptsModel* scriptsModel() { return &_scriptsModel; };
|
ScriptsModel* scriptsModel() { return &_scriptsModel; };
|
||||||
ScriptsModelFilter* scriptsModelFilter() { return &_scriptsModelFilter; };
|
ScriptsModelFilter* scriptsModelFilter() { return &_scriptsModelFilter; };
|
||||||
|
|
||||||
|
@ -73,7 +69,6 @@ signals:
|
||||||
void scriptCountChanged();
|
void scriptCountChanged();
|
||||||
void scriptsReloading();
|
void scriptsReloading();
|
||||||
void scriptLoadError(const QString& filename, const QString& error);
|
void scriptLoadError(const QString& filename, const QString& error);
|
||||||
void previousScriptLocationChanged();
|
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void onScriptFinished(const QString& fileNameString, ScriptEngine* engine);
|
void onScriptFinished(const QString& fileNameString, ScriptEngine* engine);
|
||||||
|
@ -97,7 +92,6 @@ protected:
|
||||||
std::atomic<bool> _stoppingAllScripts { false };
|
std::atomic<bool> _stoppingAllScripts { false };
|
||||||
std::list<ScriptInitializer> _scriptInitializers;
|
std::list<ScriptInitializer> _scriptInitializers;
|
||||||
mutable Setting::Handle<QString> _scriptsLocationHandle;
|
mutable Setting::Handle<QString> _scriptsLocationHandle;
|
||||||
mutable Setting::Handle<QString> _previousScriptLocation;
|
|
||||||
ScriptsModel _scriptsModel;
|
ScriptsModel _scriptsModel;
|
||||||
ScriptsModelFilter _scriptsModelFilter;
|
ScriptsModelFilter _scriptsModelFilter;
|
||||||
};
|
};
|
||||||
|
|
|
@ -199,19 +199,7 @@ private slots:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
QMessageBox::StandardButton OffscreenUi::messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
|
QQuickItem* OffscreenUi::createMessageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
|
||||||
if (QThread::currentThread() != thread()) {
|
|
||||||
QMessageBox::StandardButton result = QMessageBox::StandardButton::NoButton;
|
|
||||||
QMetaObject::invokeMethod(this, "messageBox", Qt::BlockingQueuedConnection,
|
|
||||||
Q_RETURN_ARG(QMessageBox::StandardButton, result),
|
|
||||||
Q_ARG(QMessageBox::Icon, icon),
|
|
||||||
Q_ARG(QString, title),
|
|
||||||
Q_ARG(QString, text),
|
|
||||||
Q_ARG(QMessageBox::StandardButtons, buttons),
|
|
||||||
Q_ARG(QMessageBox::StandardButton, defaultButton));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap map;
|
QVariantMap map;
|
||||||
map.insert("title", title);
|
map.insert("title", title);
|
||||||
map.insert("text", text);
|
map.insert("text", text);
|
||||||
|
@ -225,12 +213,34 @@ QMessageBox::StandardButton OffscreenUi::messageBox(QMessageBox::Icon icon, cons
|
||||||
|
|
||||||
if (!invokeResult) {
|
if (!invokeResult) {
|
||||||
qWarning() << "Failed to create message box";
|
qWarning() << "Failed to create message box";
|
||||||
return QMessageBox::StandardButton::NoButton;
|
return nullptr;
|
||||||
|
}
|
||||||
|
return qvariant_cast<QQuickItem*>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox::StandardButton OffscreenUi::waitForMessageBoxResult(QQuickItem* messageBox) {
|
||||||
|
if (!messageBox) {
|
||||||
|
return QMessageBox::NoButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMessageBox::StandardButton resultButton = MessageBoxListener(qvariant_cast<QQuickItem*>(result)).waitForButtonResult();
|
return MessageBoxListener(messageBox).waitForButtonResult();
|
||||||
qDebug() << "Message box got a result of " << resultButton;
|
}
|
||||||
return resultButton;
|
|
||||||
|
|
||||||
|
QMessageBox::StandardButton OffscreenUi::messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QMessageBox::StandardButton result = QMessageBox::StandardButton::NoButton;
|
||||||
|
QMetaObject::invokeMethod(this, "messageBox", Qt::BlockingQueuedConnection,
|
||||||
|
Q_RETURN_ARG(QMessageBox::StandardButton, result),
|
||||||
|
Q_ARG(QMessageBox::Icon, icon),
|
||||||
|
Q_ARG(QString, title),
|
||||||
|
Q_ARG(QString, text),
|
||||||
|
Q_ARG(QMessageBox::StandardButtons, buttons),
|
||||||
|
Q_ARG(QMessageBox::StandardButton, defaultButton));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return waitForMessageBoxResult(createMessageBox(icon, title, text, buttons, defaultButton));
|
||||||
}
|
}
|
||||||
|
|
||||||
QMessageBox::StandardButton OffscreenUi::critical(const QString& title, const QString& text,
|
QMessageBox::StandardButton OffscreenUi::critical(const QString& title, const QString& text,
|
||||||
|
@ -273,6 +283,7 @@ private slots:
|
||||||
|
|
||||||
// FIXME many input parameters currently ignored
|
// FIXME many input parameters currently ignored
|
||||||
QString OffscreenUi::getText(void* ignored, const QString & title, const QString & label, QLineEdit::EchoMode mode, const QString & text, bool * ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints) {
|
QString OffscreenUi::getText(void* ignored, const QString & title, const QString & label, QLineEdit::EchoMode mode, const QString & text, bool * ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints) {
|
||||||
|
if (ok) { *ok = false; }
|
||||||
QVariant result = DependencyManager::get<OffscreenUi>()->inputDialog(title, label, text).toString();
|
QVariant result = DependencyManager::get<OffscreenUi>()->inputDialog(title, label, text).toString();
|
||||||
if (ok && result.isValid()) {
|
if (ok && result.isValid()) {
|
||||||
*ok = true;
|
*ok = true;
|
||||||
|
@ -280,35 +291,70 @@ QString OffscreenUi::getText(void* ignored, const QString & title, const QString
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME many input parameters currently ignored
|
||||||
|
QString OffscreenUi::getItem(void *ignored, const QString & title, const QString & label, const QStringList & items, int current, bool editable, bool * ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints) {
|
||||||
|
if (ok) {
|
||||||
|
*ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
QVariant OffscreenUi::inputDialog(const QString& query, const QString& placeholderText, const QString& currentValue) {
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
auto inputDialog = offscreenUi->createInputDialog(title, label, current);
|
||||||
|
if (!inputDialog) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
inputDialog->setProperty("items", items);
|
||||||
|
inputDialog->setProperty("editable", editable);
|
||||||
|
|
||||||
|
QVariant result = offscreenUi->waitForInputDialogResult(inputDialog);
|
||||||
|
if (!result.isValid()) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
*ok = true;
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant OffscreenUi::inputDialog(const QString& title, const QString& label, const QVariant& current) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QVariant result;
|
QVariant result;
|
||||||
QMetaObject::invokeMethod(this, "queryBox", Qt::BlockingQueuedConnection,
|
QMetaObject::invokeMethod(this, "inputDialog", Qt::BlockingQueuedConnection,
|
||||||
Q_RETURN_ARG(QVariant, result),
|
Q_RETURN_ARG(QVariant, result),
|
||||||
Q_ARG(QString, query),
|
Q_ARG(QString, title),
|
||||||
Q_ARG(QString, placeholderText),
|
Q_ARG(QString, label),
|
||||||
Q_ARG(QString, currentValue));
|
Q_ARG(QVariant, current));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return waitForInputDialogResult(createInputDialog(title, label, current));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QQuickItem* OffscreenUi::createInputDialog(const QString& title, const QString& label, const QVariant& current) {
|
||||||
QVariantMap map;
|
QVariantMap map;
|
||||||
map.insert("text", query);
|
map.insert("title", title);
|
||||||
map.insert("placeholderText", placeholderText);
|
map.insert("label", label);
|
||||||
map.insert("result", currentValue);
|
map.insert("current", current);
|
||||||
QVariant result;
|
QVariant result;
|
||||||
bool invokeResult = QMetaObject::invokeMethod(_desktop, "queryBox",
|
bool invokeResult = QMetaObject::invokeMethod(_desktop, "inputDialog",
|
||||||
Q_RETURN_ARG(QVariant, result),
|
Q_RETURN_ARG(QVariant, result),
|
||||||
Q_ARG(QVariant, QVariant::fromValue(map)));
|
Q_ARG(QVariant, QVariant::fromValue(map)));
|
||||||
|
|
||||||
if (!invokeResult) {
|
if (!invokeResult) {
|
||||||
qWarning() << "Failed to create message box";
|
qWarning() << "Failed to create message box";
|
||||||
return QVariant();
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return InputDialogListener(qvariant_cast<QQuickItem*>(result)).waitForResult();
|
return qvariant_cast<QQuickItem*>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariant OffscreenUi::waitForInputDialogResult(QQuickItem* inputDialog) {
|
||||||
|
if (!inputDialog) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
return InputDialogListener(inputDialog).waitForResult();
|
||||||
|
}
|
||||||
|
|
||||||
bool OffscreenUi::navigationFocused() {
|
bool OffscreenUi::navigationFocused() {
|
||||||
return offscreenFlags->isNavigationFocused();
|
return offscreenFlags->isNavigationFocused();
|
||||||
|
@ -412,4 +458,66 @@ void OffscreenUi::toggleMenu(const QPoint& screenPosition) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FileDialogListener : public ModalDialogListener {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend class OffscreenUi;
|
||||||
|
FileDialogListener(QQuickItem* messageBox) : ModalDialogListener(messageBox) {
|
||||||
|
if (_finished) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
connect(_dialog, SIGNAL(selectedFile(QVariant)), this, SLOT(onSelectedFile(QVariant)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onSelectedFile(QVariant file) {
|
||||||
|
_result = file;
|
||||||
|
_finished = true;
|
||||||
|
disconnect(_dialog);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
QString OffscreenUi::fileOpenDialog(const QString& caption, const QString& dir, const QString& filter, QString* selectedFilter, QFileDialog::Options options) {
|
||||||
|
if (QThread::currentThread() != thread()) {
|
||||||
|
QString result;
|
||||||
|
QMetaObject::invokeMethod(this, "fileOpenDialog", Qt::BlockingQueuedConnection,
|
||||||
|
Q_RETURN_ARG(QString, result),
|
||||||
|
Q_ARG(QString, caption),
|
||||||
|
Q_ARG(QString, dir),
|
||||||
|
Q_ARG(QString, filter),
|
||||||
|
Q_ARG(QString*, selectedFilter),
|
||||||
|
Q_ARG(QFileDialog::Options, options));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME support returning the selected filter... somehow?
|
||||||
|
QVariantMap map;
|
||||||
|
map.insert("caption", caption);
|
||||||
|
map.insert("dir", QUrl::fromLocalFile(dir));
|
||||||
|
map.insert("filter", filter);
|
||||||
|
map.insert("options", static_cast<int>(options));
|
||||||
|
|
||||||
|
QVariant buildDialogResult;
|
||||||
|
bool invokeResult = QMetaObject::invokeMethod(_desktop, "fileOpenDialog",
|
||||||
|
Q_RETURN_ARG(QVariant, buildDialogResult),
|
||||||
|
Q_ARG(QVariant, QVariant::fromValue(map)));
|
||||||
|
|
||||||
|
if (!invokeResult) {
|
||||||
|
qWarning() << "Failed to create file open dialog";
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant result = FileDialogListener(qvariant_cast<QQuickItem*>(buildDialogResult)).waitForResult();
|
||||||
|
if (!result.isValid()) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
qDebug() << result.toString();
|
||||||
|
return result.toUrl().toLocalFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString OffscreenUi::getOpenFileName(void* ignored, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) {
|
||||||
|
return DependencyManager::get<OffscreenUi>()->fileOpenDialog(caption, dir, filter, selectedFilter, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#include "OffscreenUi.moc"
|
#include "OffscreenUi.moc"
|
||||||
|
|
|
@ -42,6 +42,13 @@ public:
|
||||||
QQuickItem* getToolWindow();
|
QQuickItem* getToolWindow();
|
||||||
|
|
||||||
|
|
||||||
|
// Message box compatibility
|
||||||
|
Q_INVOKABLE QMessageBox::StandardButton messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton);
|
||||||
|
// Must be called from the main thread
|
||||||
|
QQuickItem* createMessageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton);
|
||||||
|
// Must be called from the main thread
|
||||||
|
QMessageBox::StandardButton waitForMessageBoxResult(QQuickItem* messageBox);
|
||||||
|
|
||||||
/// Same design as QMessageBox::critical(), will block, returns result
|
/// Same design as QMessageBox::critical(), will block, returns result
|
||||||
static QMessageBox::StandardButton critical(void* ignored, const QString& title, const QString& text,
|
static QMessageBox::StandardButton critical(void* ignored, const QString& title, const QString& text,
|
||||||
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
||||||
|
@ -80,18 +87,21 @@ public:
|
||||||
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
|
||||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||||
|
|
||||||
Q_INVOKABLE QMessageBox::StandardButton messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton);
|
// file dialog compatibility
|
||||||
Q_INVOKABLE QVariant inputDialog(const QString& query, const QString& placeholderText = QString(), const QString& currentValue = QString());
|
Q_INVOKABLE QString fileOpenDialog(const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
|
||||||
|
|
||||||
// FIXME implement
|
|
||||||
static QVariant query(const QString& query, const QString& placeholderText = QString(), const QString& currentValue = QString());
|
|
||||||
|
|
||||||
// FIXME implement
|
|
||||||
// Compatibility with QFileDialog::getOpenFileName
|
// Compatibility with QFileDialog::getOpenFileName
|
||||||
static QString getOpenFileName(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
|
static QString getOpenFileName(void* ignored, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = 0, QFileDialog::Options options = 0);
|
||||||
|
|
||||||
|
|
||||||
|
// input dialog compatibility
|
||||||
|
Q_INVOKABLE QVariant inputDialog(const QString& title, const QString& label = QString(), const QVariant& current = QVariant());
|
||||||
|
QQuickItem* createInputDialog(const QString& title, const QString& label, const QVariant& current);
|
||||||
|
QVariant waitForInputDialogResult(QQuickItem* inputDialog);
|
||||||
|
|
||||||
// Compatibility with QInputDialog::getText
|
// Compatibility with QInputDialog::getText
|
||||||
static QString getText(void* ignored, const QString & title, const QString & label, QLineEdit::EchoMode mode = QLineEdit::Normal, const QString & text = QString(), bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
|
static QString getText(void* ignored, const QString & title, const QString & label, QLineEdit::EchoMode mode = QLineEdit::Normal, const QString & text = QString(), bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
|
||||||
|
// Compatibility with QInputDialog::getItem
|
||||||
|
static QString getItem(void *ignored, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QQuickItem* _desktop { nullptr };
|
QQuickItem* _desktop { nullptr };
|
||||||
|
|
|
@ -21,6 +21,7 @@ DISTFILES += \
|
||||||
../../interface/resources/qml/dialogs/*.qml \
|
../../interface/resources/qml/dialogs/*.qml \
|
||||||
../../interface/resources/qml/dialogs/fileDialog/*.qml \
|
../../interface/resources/qml/dialogs/fileDialog/*.qml \
|
||||||
../../interface/resources/qml/dialogs/preferences/*.qml \
|
../../interface/resources/qml/dialogs/preferences/*.qml \
|
||||||
|
../../interface/resources/qml/dialogs/messageDialog/*.qml \
|
||||||
../../interface/resources/qml/desktop/*.qml \
|
../../interface/resources/qml/desktop/*.qml \
|
||||||
../../interface/resources/qml/menus/*.qml \
|
../../interface/resources/qml/menus/*.qml \
|
||||||
../../interface/resources/qml/styles/*.qml \
|
../../interface/resources/qml/styles/*.qml \
|
||||||
|
|
Loading…
Reference in a new issue