mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 02:14:26 +02:00
More cleanup & menu fixing
This commit is contained in:
parent
4ea5c11b73
commit
d2900200a1
22 changed files with 440 additions and 488 deletions
|
@ -16,8 +16,6 @@ Windows.Window {
|
|||
destroyOnCloseButton: false
|
||||
property alias source: webview.url
|
||||
|
||||
function raiseWindow() { Desktop.raise(root) }
|
||||
|
||||
Controls.WebView {
|
||||
id: webview
|
||||
url: "about:blank"
|
||||
|
|
|
@ -21,16 +21,10 @@ Windows.Window {
|
|||
destroyOnCloseButton: false
|
||||
property alias source: pageLoader.source
|
||||
|
||||
function raiseWindow() { Desktop.raise(root) }
|
||||
|
||||
Loader {
|
||||
id: pageLoader
|
||||
objectName: "Loader"
|
||||
focus: true
|
||||
property var dialog: root
|
||||
|
||||
Keys.onPressed: {
|
||||
console.log("QmlWindow pageLoader keypress")
|
||||
}
|
||||
}
|
||||
} // dialog
|
||||
|
|
|
@ -1,229 +0,0 @@
|
|||
import Hifi 1.0 as Hifi
|
||||
|
||||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.3
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
|
||||
import "controls"
|
||||
import "styles"
|
||||
|
||||
|
||||
Hifi.VrMenu {
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
objectName: "VrMenu"
|
||||
enabled: false
|
||||
opacity: 0.0
|
||||
z: 10000
|
||||
|
||||
property int animationDuration: 200
|
||||
property var models: []
|
||||
property var columns: []
|
||||
|
||||
onEnabledChanged: {
|
||||
if (enabled && columns.length == 0) {
|
||||
pushColumn(rootMenu.items);
|
||||
}
|
||||
opacity = enabled ? 1.0 : 0.0
|
||||
offscreenFlags.navigationFocused = enabled;
|
||||
}
|
||||
|
||||
// The actual animator
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: root.animationDuration
|
||||
easing.type: Easing.InOutBounce
|
||||
}
|
||||
}
|
||||
|
||||
onOpacityChanged: {
|
||||
visible = (opacity != 0.0);
|
||||
}
|
||||
|
||||
onVisibleChanged: {
|
||||
if (!visible) reset();
|
||||
}
|
||||
|
||||
property var menuBuilder: Component {
|
||||
VrMenuView {
|
||||
property int menuDepth: root.models.length - 1
|
||||
model: root.models[menuDepth]
|
||||
|
||||
function fit(position, size, maxposition) {
|
||||
var padding = 8;
|
||||
if (position < padding) {
|
||||
position = padding;
|
||||
} else if (position + size + padding > maxposition) {
|
||||
position = maxposition - (size + padding);
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (menuDepth === 0) {
|
||||
x = lastMousePosition.x - 20
|
||||
y = lastMousePosition.y - 20
|
||||
} else {
|
||||
var lastColumn = root.columns[menuDepth - 1]
|
||||
x = lastColumn.x + 64;
|
||||
y = lastMousePosition.y - height / 2;
|
||||
}
|
||||
x = fit(x, width, parent.width);
|
||||
y = fit(y, height, parent.height);
|
||||
}
|
||||
|
||||
onSelected: {
|
||||
root.selectItem(menuDepth, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function lastColumn() {
|
||||
return columns[root.columns.length - 1];
|
||||
}
|
||||
|
||||
function pushColumn(items) {
|
||||
models.push(itemsToModel(items))
|
||||
if (columns.length) {
|
||||
var oldColumn = lastColumn();
|
||||
//oldColumn.enabled = false
|
||||
}
|
||||
var newColumn = menuBuilder.createObject(root);
|
||||
columns.push(newColumn);
|
||||
forceActiveFocus();
|
||||
}
|
||||
|
||||
function popColumn() {
|
||||
if (columns.length > 0) {
|
||||
var curColumn = columns.pop();
|
||||
curColumn.visible = false;
|
||||
curColumn.destroy();
|
||||
models.pop();
|
||||
}
|
||||
|
||||
if (columns.length == 0) {
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
curColumn = lastColumn();
|
||||
curColumn.enabled = true;
|
||||
curColumn.opacity = 1.0;
|
||||
curColumn.forceActiveFocus();
|
||||
}
|
||||
|
||||
function itemsToModel(items) {
|
||||
var newListModel = Qt.createQmlObject('import QtQuick 2.2; ListModel {}', root);
|
||||
for (var i = 0; i < items.length; ++i) {
|
||||
var item = items[i];
|
||||
switch (item.type) {
|
||||
case 2:
|
||||
newListModel.append({"type":item.type, "name": item.title, "item": item})
|
||||
break;
|
||||
case 1:
|
||||
newListModel.append({"type":item.type, "name": item.text, "item": item})
|
||||
break;
|
||||
case 0:
|
||||
newListModel.append({"type":item.type, "name": "-----", "item": item})
|
||||
break;
|
||||
}
|
||||
}
|
||||
return newListModel;
|
||||
}
|
||||
|
||||
function selectItem(depth, source) {
|
||||
var popped = false;
|
||||
while (depth + 1 < columns.length) {
|
||||
popColumn()
|
||||
popped = true
|
||||
}
|
||||
|
||||
switch (source.type) {
|
||||
case 2:
|
||||
lastColumn().enabled = false
|
||||
pushColumn(source.items)
|
||||
break;
|
||||
case 1:
|
||||
if (!popped) source.trigger()
|
||||
enabled = false
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function reset() {
|
||||
while (columns.length > 0) {
|
||||
popColumn();
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
id: mouseArea
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onClicked: {
|
||||
if (mouse.button == Qt.RightButton) {
|
||||
root.popColumn();
|
||||
} else {
|
||||
root.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addMenu(menu, newMenu) {
|
||||
return menu.addMenu(newMenu);
|
||||
}
|
||||
|
||||
function addItem(menu, newMenuItem) {
|
||||
return menu.addItem(newMenuItem);
|
||||
}
|
||||
|
||||
function insertItem(menu, beforeItem, newMenuItem) {
|
||||
for (var i = 0; i < menu.items.length; ++i) {
|
||||
if (menu.items[i] === beforeItem) {
|
||||
return menu.insertItem(i, newMenuItem);
|
||||
}
|
||||
}
|
||||
return addItem(menu, newMenuItem);
|
||||
}
|
||||
|
||||
function removeItem(menu, menuItem) {
|
||||
menu.removeItem(menuItem);
|
||||
}
|
||||
|
||||
function previousItem() {
|
||||
if (columns.length) {
|
||||
lastColumn().incrementCurrentIndex()
|
||||
}
|
||||
}
|
||||
|
||||
function nextItem() {
|
||||
if (columns.length) {
|
||||
lastColumn().decrementCurrentIndex()
|
||||
}
|
||||
}
|
||||
|
||||
function selectCurrentItem() {
|
||||
if (columns.length) {
|
||||
var depth = columns.length - 1;
|
||||
var index = lastColumn().currentIndex;
|
||||
if (index >= 0) {
|
||||
var model = models[depth];
|
||||
var item = model.get(index).item;
|
||||
selectItem(depth, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onDownPressed: previousItem();
|
||||
Keys.onUpPressed: nextItem();
|
||||
Keys.onSpacePressed: selectCurrentItem();
|
||||
Keys.onReturnPressed: selectCurrentItem();
|
||||
Keys.onRightPressed: selectCurrentItem();
|
||||
Keys.onLeftPressed: popColumn();
|
||||
Keys.onEscapePressed: popColumn();
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.3
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
|
||||
import "styles"
|
||||
|
||||
ListView {
|
||||
id: root
|
||||
HifiConstants { id: hifi }
|
||||
width: 128
|
||||
height: count * 32
|
||||
onEnabledChanged: recalcSize();
|
||||
onVisibleChanged: recalcSize();
|
||||
onCountChanged: recalcSize();
|
||||
|
||||
signal selected(var item)
|
||||
|
||||
highlight: Rectangle {
|
||||
width: root.currentItem ? root.currentItem.width : 0
|
||||
height: root.currentItem ? root.currentItem.height : 0
|
||||
color: "lightsteelblue"; radius: 3
|
||||
}
|
||||
|
||||
delegate: VrMenuItem {
|
||||
text: name
|
||||
source: item
|
||||
onImplicitHeightChanged: root.recalcSize()
|
||||
onImplicitWidthChanged: root.recalcSize()
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: root.currentIndex = index
|
||||
onClicked: root.selected(item)
|
||||
}
|
||||
}
|
||||
|
||||
function recalcSize() {
|
||||
if (model.count !== count || !visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
var originalIndex = currentIndex;
|
||||
var maxWidth = width;
|
||||
var newHeight = 0;
|
||||
for (var i = 0; i < count; ++i) {
|
||||
currentIndex = i;
|
||||
if (!currentItem) {
|
||||
continue;
|
||||
}
|
||||
if (currentItem && currentItem.implicitWidth > maxWidth) {
|
||||
maxWidth = currentItem.implicitWidth
|
||||
}
|
||||
if (currentItem.visible) {
|
||||
newHeight += currentItem.implicitHeight
|
||||
}
|
||||
}
|
||||
if (maxWidth > width) {
|
||||
width = maxWidth;
|
||||
}
|
||||
if (newHeight > height) {
|
||||
height = newHeight
|
||||
}
|
||||
currentIndex = originalIndex;
|
||||
}
|
||||
|
||||
Border {
|
||||
id: border
|
||||
anchors.fill: parent
|
||||
anchors.margins: -8
|
||||
z: parent.z - 1
|
||||
border.color: hifi.colors.hifiBlue
|
||||
color: hifi.colors.window
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2,74 +2,34 @@ import QtQuick 2.5
|
|||
import QtQuick.Controls 1.4
|
||||
import QtQuick.Dialogs 1.2 as OriginalDialogs;
|
||||
|
||||
import "dialogs"
|
||||
import "../dialogs"
|
||||
import "../menus"
|
||||
|
||||
// This is our primary 'desktop' object to which all VR dialogs and
|
||||
// windows will be childed.
|
||||
FocusScope {
|
||||
id: desktop
|
||||
anchors.fill: parent;
|
||||
|
||||
// Debugging help for figuring out focus issues
|
||||
property var offscreenWindow;
|
||||
onOffscreenWindowChanged: offscreenWindow.activeFocusItemChanged.connect(onWindowFocusChanged);
|
||||
function onWindowFocusChanged() {
|
||||
console.log("Focus item is " + offscreenWindow.activeFocusItem);
|
||||
var focusedItem = offscreenWindow.activeFocusItem ;
|
||||
if (DebugQML && focusedItem) {
|
||||
var rect = desktop.mapToItem(desktop, focusedItem.x, focusedItem.y, focusedItem.width, focusedItem.height);
|
||||
focusDebugger.visible = true
|
||||
focusDebugger.x = rect.x;
|
||||
focusDebugger.y = rect.y;
|
||||
focusDebugger.width = rect.width
|
||||
focusDebugger.height = rect.height
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: focusDebugger;
|
||||
z: 9999; visible: false; color: "red"
|
||||
ColorAnimation on color { from: "#7fffff00"; to: "#7f0000ff"; duration: 1000; loops: 9999 }
|
||||
}
|
||||
objectName: "desktop"
|
||||
|
||||
// Allows QML/JS to find the desktop through the parent chain
|
||||
property bool desktopRoot: true
|
||||
|
||||
// The VR version of the primary menu
|
||||
property var rootMenu: Menu { objectName: "rootMenu" }
|
||||
|
||||
// The tool window, one instance
|
||||
property alias toolWindow: toolWindow
|
||||
ToolWindow { id: toolWindow }
|
||||
|
||||
// FIXME support always on top flags
|
||||
function raise(item) {
|
||||
d.raiseWindow(item);
|
||||
}
|
||||
|
||||
Component {
|
||||
id: messageDialogBuilder
|
||||
MessageDialog { }
|
||||
}
|
||||
|
||||
Component {
|
||||
id: nativeMessageDialogBuilder
|
||||
OriginalDialogs.MessageDialog { }
|
||||
}
|
||||
|
||||
function messageBox(properties) {
|
||||
// Debugging: native message dialog for comparison
|
||||
// nativeMessageDialogBuilder.createObject(desktop, properties);
|
||||
return messageDialogBuilder.createObject(desktop, properties);
|
||||
property var rootMenu: Menu {
|
||||
id: rootMenu; objectName: "rootMenu"
|
||||
Component.onCompleted: {
|
||||
console.log("ROOT_MENU " + rootMenu);
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property int zBasisNormal: 0
|
||||
readonly property int zBasisAlwaysOnTop: 4096
|
||||
readonly property int zBasisModal: 8192
|
||||
|
||||
readonly property var messageDialogBuilder: Component { MessageDialog { } }
|
||||
readonly property var nativeMessageDialogBuilder: Component { OriginalDialogs.MessageDialog { } }
|
||||
|
||||
function findChild(item, name) {
|
||||
for (var i = 0; i < item.children.length; ++i) {
|
||||
|
@ -203,6 +163,43 @@ FocusScope {
|
|||
}
|
||||
}
|
||||
|
||||
MenuMouseHandler { id: menuPopperUpper }
|
||||
|
||||
function raise(item) {
|
||||
d.raiseWindow(item);
|
||||
}
|
||||
|
||||
function messageBox(properties) {
|
||||
// Debugging: native message dialog for comparison
|
||||
// d.nativeMessageDialogBuilder.createObject(desktop, properties);
|
||||
return d.messageDialogBuilder.createObject(desktop, properties);
|
||||
}
|
||||
|
||||
function popupMenu(point) {
|
||||
menuPopperUpper.popup(desktop, rootMenu.items, point);
|
||||
}
|
||||
|
||||
function toggleMenu(point) {
|
||||
menuPopperUpper.toggle(desktop, rootMenu.items, point);
|
||||
}
|
||||
|
||||
Keys.onEscapePressed: {
|
||||
if (menuPopperUpper.closeLastMenu()) {
|
||||
event.accepted = true;
|
||||
return;
|
||||
}
|
||||
event.accepted = false;
|
||||
}
|
||||
|
||||
Keys.onLeftPressed: {
|
||||
if (menuPopperUpper.closeLastMenu()) {
|
||||
event.accepted = true;
|
||||
return;
|
||||
}
|
||||
event.accepted = false;
|
||||
}
|
||||
|
||||
|
||||
function unfocusWindows() {
|
||||
var windows = d.getTopLevelWindows();
|
||||
for (var i = 0; i < windows.length; ++i) {
|
||||
|
@ -210,6 +207,27 @@ FocusScope {
|
|||
}
|
||||
desktop.focus = true;
|
||||
}
|
||||
|
||||
// Debugging help for figuring out focus issues
|
||||
property var offscreenWindow;
|
||||
onOffscreenWindowChanged: offscreenWindow.activeFocusItemChanged.connect(onWindowFocusChanged);
|
||||
function onWindowFocusChanged() {
|
||||
console.log("Focus item is " + offscreenWindow.activeFocusItem);
|
||||
var focusedItem = offscreenWindow.activeFocusItem ;
|
||||
if (DebugQML && focusedItem) {
|
||||
var rect = desktop.mapToItem(null, focusedItem.x, focusedItem.y, focusedItem.width, focusedItem.height);
|
||||
focusDebugger.visible = true
|
||||
focusDebugger.x = rect.x;
|
||||
focusDebugger.y = rect.y;
|
||||
focusDebugger.width = rect.width
|
||||
focusDebugger.height = rect.height
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
id: focusDebugger;
|
||||
z: 9999; visible: false; color: "red"
|
||||
ColorAnimation on color { from: "#7fffff00"; to: "#7f0000ff"; duration: 1000; loops: 9999 }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -14,6 +14,7 @@ Window {
|
|||
resizable: true
|
||||
destroyOnInvisible: true
|
||||
x: 40; y: 40
|
||||
implicitWidth: 384; implicitHeight: 640
|
||||
|
||||
property var scripts: ScriptDiscoveryService;
|
||||
property var scriptsModel: scripts.scriptsModelFilter
|
||||
|
@ -77,7 +78,7 @@ Window {
|
|||
}
|
||||
|
||||
function loadFromFile() {
|
||||
var fileDialog = fileDialogBuilder.createObject(Desktop, { filterModel: fileFilters });
|
||||
var fileDialog = fileDialogBuilder.createObject(desktop, { filterModel: fileFilters });
|
||||
fileDialog.canceled.connect(function(){
|
||||
console.debug("Cancelled file open")
|
||||
})
|
||||
|
@ -90,7 +91,7 @@ Window {
|
|||
|
||||
Rectangle {
|
||||
color: "white"
|
||||
implicitWidth: 384; implicitHeight: 640
|
||||
anchors.fill: parent
|
||||
|
||||
Item {
|
||||
anchors { fill: parent; margins: 8 }
|
||||
|
|
15
interface/resources/qml/hifi/Desktop.qml
Normal file
15
interface/resources/qml/hifi/Desktop.qml
Normal file
|
@ -0,0 +1,15 @@
|
|||
import QtQuick 2.5
|
||||
|
||||
import "../desktop"
|
||||
import ".."
|
||||
|
||||
Desktop {
|
||||
id: desktop
|
||||
|
||||
// The tool window, one instance
|
||||
property alias toolWindow: toolWindow
|
||||
ToolWindow { id: toolWindow }
|
||||
}
|
||||
|
||||
|
||||
|
149
interface/resources/qml/menus/MenuMouseHandler.qml
Normal file
149
interface/resources/qml/menus/MenuMouseHandler.qml
Normal file
|
@ -0,0 +1,149 @@
|
|||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4
|
||||
|
||||
import "."
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property int zBasis: 8192 - 1024
|
||||
anchors.fill: parent
|
||||
|
||||
MouseArea {
|
||||
id: menuRoot;
|
||||
anchors.fill: parent
|
||||
enabled: d.topMenu !== null
|
||||
onClicked: {
|
||||
d.clearMenus();
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property var menuStack: []
|
||||
property var topMenu: null;
|
||||
property var modelMaker: Component { ListModel { } }
|
||||
property var menuViewMaker: Component {
|
||||
VrMenuView {
|
||||
id: subMenu
|
||||
onSelected: d.handleSelection(subMenu, currentItem, item)
|
||||
}
|
||||
}
|
||||
|
||||
function toModel(items) {
|
||||
var result = modelMaker.createObject(desktop);
|
||||
for (var i = 0; i < items.length; ++i) {
|
||||
var item = items[i];
|
||||
if (!item.visible) continue;
|
||||
switch (item.type) {
|
||||
case MenuItemType.Menu:
|
||||
result.append({"name": item.title, "item": item})
|
||||
break;
|
||||
case MenuItemType.Item:
|
||||
result.append({"name": item.text, "item": item})
|
||||
break;
|
||||
case MenuItemType.Separator:
|
||||
result.append({"name": "", "item": item})
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function popMenu() {
|
||||
if (menuStack.length) {
|
||||
menuStack.pop().destroy();
|
||||
}
|
||||
if (menuStack.length) {
|
||||
topMenu = menuStack[menuStack.length - 1];
|
||||
topMenu.focus = true;
|
||||
} else {
|
||||
topMenu = null;
|
||||
offscreenFlags.navigationFocused = false;
|
||||
menuRoot.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
function pushMenu(newMenu) {
|
||||
menuStack.push(newMenu);
|
||||
topMenu = newMenu;
|
||||
topMenu.focus = true;
|
||||
offscreenFlags.navigationFocused = true;
|
||||
}
|
||||
|
||||
function clearMenus() {
|
||||
while (menuStack.length) {
|
||||
popMenu()
|
||||
}
|
||||
}
|
||||
|
||||
function clampMenuPosition(menu) {
|
||||
var margins = 0;
|
||||
if (menu.x < margins) {
|
||||
menu.x = margins
|
||||
} else if ((menu.x + menu.width + margins) > root.width) {
|
||||
menu.x = root.width - (menu.width + margins);
|
||||
}
|
||||
|
||||
if (menu.y < 0) {
|
||||
menu.y = margins
|
||||
} else if ((menu.y + menu.height + margins) > root.height) {
|
||||
menu.y = root.height - (menu.height + margins);
|
||||
}
|
||||
}
|
||||
|
||||
function buildMenu(items, targetPosition) {
|
||||
var model = toModel(items);
|
||||
var newMenu = menuViewMaker.createObject(menuRoot, { model: model, z: topMenu ? topMenu.z + 1 : zBasis });
|
||||
if (targetPosition) {
|
||||
newMenu.x = targetPosition.x
|
||||
newMenu.y = targetPosition.y - newMenu.height / 3 * 1
|
||||
}
|
||||
clampMenuPosition(newMenu);
|
||||
pushMenu(newMenu);
|
||||
return newMenu;
|
||||
}
|
||||
|
||||
function handleSelection(parentMenu, selectedItem, item) {
|
||||
while (topMenu && topMenu !== parentMenu) {
|
||||
popMenu();
|
||||
}
|
||||
|
||||
switch (item.type) {
|
||||
case MenuItemType.Menu:
|
||||
var target = Qt.vector2d(topMenu.x, topMenu.y).plus(Qt.vector2d(selectedItem.x + 96, selectedItem.y));
|
||||
buildMenu(item.items, target).objectName = item.title;
|
||||
break;
|
||||
|
||||
case MenuItemType.Item:
|
||||
console.log("Triggering " + item.text)
|
||||
item.trigger();
|
||||
clearMenus();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function popup(parent, items, point) {
|
||||
d.clearMenus();
|
||||
menuRoot.enabled = true;
|
||||
d.buildMenu(items, point);
|
||||
}
|
||||
|
||||
function toggle(parent, items, point) {
|
||||
if (d.topMenu) {
|
||||
d.clearMenus();
|
||||
return;
|
||||
}
|
||||
popup(parent, items, point);
|
||||
}
|
||||
|
||||
function closeLastMenu() {
|
||||
if (d.menuStack.length) {
|
||||
d.popMenu();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +1,13 @@
|
|||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.3
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
import "controls"
|
||||
import "styles"
|
||||
|
||||
import "../controls"
|
||||
import "../styles"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
HifiConstants {
|
||||
id: hifi
|
||||
}
|
||||
|
||||
// The model object
|
||||
HifiConstants { id: hifi }
|
||||
property alias text: label.text
|
||||
property var source
|
||||
|
100
interface/resources/qml/menus/VrMenuView.qml
Normal file
100
interface/resources/qml/menus/VrMenuView.qml
Normal file
|
@ -0,0 +1,100 @@
|
|||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.3
|
||||
import QtQuick.Controls.Styles 1.3
|
||||
|
||||
import "../styles"
|
||||
|
||||
|
||||
FocusScope {
|
||||
id: root
|
||||
implicitHeight: border.height
|
||||
implicitWidth: border.width
|
||||
|
||||
property alias currentItem: listView.currentItem
|
||||
property alias model: listView.model
|
||||
signal selected(var item)
|
||||
|
||||
|
||||
Border {
|
||||
id: border
|
||||
anchors.fill: listView
|
||||
anchors.margins: -8
|
||||
border.color: hifi.colors.hifiBlue
|
||||
color: hifi.colors.window
|
||||
// color: "#7f7f7f7f"
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: listView
|
||||
x: 8; y: 8
|
||||
HifiConstants { id: hifi }
|
||||
width: 128
|
||||
height: count * 32
|
||||
onEnabledChanged: recalcSize();
|
||||
onVisibleChanged: recalcSize();
|
||||
onCountChanged: recalcSize();
|
||||
focus: true
|
||||
|
||||
highlight: Rectangle {
|
||||
width: listView.currentItem ? listView.currentItem.width : 0
|
||||
height: listView.currentItem ? listView.currentItem.height : 0
|
||||
color: "lightsteelblue"; radius: 3
|
||||
}
|
||||
|
||||
delegate: VrMenuItem {
|
||||
text: name
|
||||
source: item
|
||||
onImplicitHeightChanged: listView.recalcSize()
|
||||
onImplicitWidthChanged: listView.recalcSize()
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onEntered: listView.currentIndex = index
|
||||
onClicked: root.selected(item)
|
||||
}
|
||||
}
|
||||
|
||||
function recalcSize() {
|
||||
if (model.count !== count || !visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
var originalIndex = currentIndex;
|
||||
var maxWidth = width;
|
||||
var newHeight = 0;
|
||||
for (var i = 0; i < count; ++i) {
|
||||
currentIndex = i;
|
||||
if (!currentItem) {
|
||||
continue;
|
||||
}
|
||||
if (currentItem && currentItem.implicitWidth > maxWidth) {
|
||||
maxWidth = currentItem.implicitWidth
|
||||
}
|
||||
if (currentItem.visible) {
|
||||
newHeight += currentItem.implicitHeight
|
||||
}
|
||||
}
|
||||
if (maxWidth > width) {
|
||||
width = maxWidth;
|
||||
}
|
||||
if (newHeight > height) {
|
||||
height = newHeight
|
||||
}
|
||||
currentIndex = originalIndex;
|
||||
}
|
||||
|
||||
function previousItem() { currentIndex = (currentIndex + count - 1) % count; }
|
||||
function nextItem() { currentIndex = (currentIndex + count + 1) % count; }
|
||||
function selectCurrentItem() { if (currentIndex != -1) root.selected(currentItem.source); }
|
||||
|
||||
Keys.onUpPressed: previousItem();
|
||||
Keys.onDownPressed: nextItem();
|
||||
Keys.onSpacePressed: selectCurrentItem();
|
||||
Keys.onRightPressed: selectCurrentItem();
|
||||
Keys.onReturnPressed: selectCurrentItem();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ Fadable {
|
|||
|
||||
function raise() {
|
||||
if (visible && parent) {
|
||||
Desktop.raise(window)
|
||||
desktop.raise(window)
|
||||
if (!focus) {
|
||||
focus = true;
|
||||
}
|
||||
|
|
|
@ -793,7 +793,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
|
|||
} else if (action == controller::toInt(controller::Action::CYCLE_CAMERA)) {
|
||||
cycleCamera();
|
||||
} else if (action == controller::toInt(controller::Action::CONTEXT_MENU)) {
|
||||
VrMenu::toggle(); // show context menu even on non-stereo displays
|
||||
offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QCursor::pos()));
|
||||
} else if (action == controller::toInt(controller::Action::RETICLE_X)) {
|
||||
auto oldPos = QCursor::pos();
|
||||
auto newPos = oldPos;
|
||||
|
@ -1176,7 +1176,6 @@ void Application::initializeUi() {
|
|||
AddressBarDialog::registerType();
|
||||
ErrorDialog::registerType();
|
||||
LoginDialog::registerType();
|
||||
VrMenu::registerType();
|
||||
Tooltip::registerType();
|
||||
UpdateDialog::registerType();
|
||||
|
||||
|
@ -1186,7 +1185,7 @@ void Application::initializeUi() {
|
|||
offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
|
||||
// OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to
|
||||
// support the window management and scripting proxies for VR use
|
||||
offscreenUi->createDesktop();
|
||||
offscreenUi->createDesktop(QString("hifi/Desktop.qml"));
|
||||
|
||||
// FIXME either expose so that dialogs can set this themselves or
|
||||
// do better detection in the offscreen UI of what has focus
|
||||
|
@ -1244,8 +1243,6 @@ void Application::initializeUi() {
|
|||
rootContext->setContextProperty("Render", DependencyManager::get<RenderScriptingInterface>().data());
|
||||
|
||||
_glWidget->installEventFilter(offscreenUi.data());
|
||||
VrMenu::load();
|
||||
VrMenu::executeQueuedLambdas();
|
||||
offscreenUi->setMouseTranslator([=](const QPointF& pt) {
|
||||
QPointF result = pt;
|
||||
auto displayPlugin = getActiveDisplayPlugin();
|
||||
|
@ -2063,7 +2060,8 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
|
||||
void Application::keyReleaseEvent(QKeyEvent* event) {
|
||||
if (event->key() == Qt::Key_Alt && _altPressed && hasFocus()) {
|
||||
VrMenu::toggle(); // show context menu even on non-stereo displays
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->toggleMenu(_glWidget->mapFromGlobal(QCursor::pos()));
|
||||
}
|
||||
|
||||
_keysPressed.remove(event->key());
|
||||
|
|
|
@ -628,3 +628,30 @@ QQmlContext* OffscreenQmlSurface::getRootContext() {
|
|||
return _qmlEngine->rootContext();
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(std::function<void()>);
|
||||
static auto VoidLambdaType = qRegisterMetaType<std::function<void()>>();
|
||||
Q_DECLARE_METATYPE(std::function<QVariant()>);
|
||||
static auto VariantLambdaType = qRegisterMetaType<std::function<QVariant()>>();
|
||||
|
||||
|
||||
void OffscreenQmlSurface::executeOnUiThread(std::function<void()> function, bool blocking ) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "executeOnUiThread", blocking ? Qt::BlockingQueuedConnection : Qt::QueuedConnection,
|
||||
Q_ARG(std::function<void()>, function));
|
||||
return;
|
||||
}
|
||||
|
||||
function();
|
||||
}
|
||||
|
||||
QVariant OffscreenQmlSurface::returnFromUiThread(std::function<QVariant()> function) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVariant result;
|
||||
QMetaObject::invokeMethod(this, "returnFromUiThread", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(std::function<QVariant()>, function));
|
||||
return result;
|
||||
}
|
||||
|
||||
return function();
|
||||
}
|
||||
|
|
|
@ -45,6 +45,9 @@ public:
|
|||
return load(QUrl(qmlSourceFile), f);
|
||||
}
|
||||
|
||||
Q_INVOKABLE void executeOnUiThread(std::function<void()> function, bool blocking = false);
|
||||
Q_INVOKABLE QVariant returnFromUiThread(std::function<QVariant()> function);
|
||||
|
||||
void setMaxFps(uint8_t maxFps) { _maxFps = maxFps; }
|
||||
// Optional values for event handling
|
||||
void setProxyWindow(QWindow* window);
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include <AbstractUriHandler.h>
|
||||
#include <AccountManager.h>
|
||||
|
||||
#include "VrMenu.h"
|
||||
|
||||
// Needs to match the constants in resources/qml/Global.js
|
||||
class OffscreenFlags : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -192,7 +194,7 @@ QMessageBox::StandardButton OffscreenUi::messageBox(QMessageBox::Icon icon, cons
|
|||
map.insert("buttons", buttons.operator int());
|
||||
map.insert("defaultButton", defaultButton);
|
||||
QVariant result;
|
||||
bool invokeResult = QMetaObject::invokeMethod(getDesktop(), "messageBox",
|
||||
bool invokeResult = QMetaObject::invokeMethod(_desktop, "messageBox",
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(QVariant, QVariant::fromValue(map)));
|
||||
|
||||
|
@ -231,16 +233,22 @@ void OffscreenUi::setNavigationFocused(bool focused) {
|
|||
offscreenFlags->setNavigationFocused(focused);
|
||||
}
|
||||
|
||||
void OffscreenUi::createDesktop() {
|
||||
void OffscreenUi::createDesktop(const QUrl& url) {
|
||||
if (_desktop) {
|
||||
qDebug() << "Desktop already created";
|
||||
return;
|
||||
}
|
||||
getRootContext()->setContextProperty("DebugQML", QVariant(false));
|
||||
_desktop = dynamic_cast<QQuickItem*>(load("Root.qml"));
|
||||
_desktop = dynamic_cast<QQuickItem*>(load(url));
|
||||
Q_ASSERT(_desktop);
|
||||
getRootContext()->setContextProperty("Desktop", _desktop);
|
||||
getRootContext()->setContextProperty("desktop", _desktop);
|
||||
|
||||
// Enable focus debugging
|
||||
_desktop->setProperty("offscreenWindow", QVariant::fromValue(getWindow()));
|
||||
|
||||
_toolWindow = _desktop->findChild<QQuickItem*>("ToolWindow");
|
||||
|
||||
new VrMenu(this);
|
||||
}
|
||||
|
||||
QQuickItem* OffscreenUi::getDesktop() {
|
||||
|
@ -251,38 +259,15 @@ QQuickItem* OffscreenUi::getToolWindow() {
|
|||
return _toolWindow;
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(std::function<void()>);
|
||||
static auto VoidLambdaType = qRegisterMetaType<std::function<void()>>();
|
||||
Q_DECLARE_METATYPE(std::function<QVariant()>);
|
||||
static auto VariantLambdaType = qRegisterMetaType<std::function<QVariant()>>();
|
||||
|
||||
|
||||
void OffscreenUi::executeOnUiThread(std::function<void()> function) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "executeOnUiThread", Qt::QueuedConnection,
|
||||
Q_ARG(std::function<void()>, function));
|
||||
return;
|
||||
}
|
||||
|
||||
function();
|
||||
}
|
||||
|
||||
QVariant OffscreenUi::returnFromUiThread(std::function<QVariant()> function) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QVariant result;
|
||||
QMetaObject::invokeMethod(this, "returnFromUiThread", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(QVariant, result),
|
||||
Q_ARG(std::function<QVariant()>, function));
|
||||
return result;
|
||||
}
|
||||
|
||||
return function();
|
||||
}
|
||||
|
||||
void OffscreenUi::unfocusWindows() {
|
||||
bool invokeResult = QMetaObject::invokeMethod(_desktop, "unfocusWindows");
|
||||
Q_ASSERT(invokeResult);
|
||||
}
|
||||
|
||||
void OffscreenUi::toggleMenu(const QPoint& screenPosition) {
|
||||
auto virtualPos = mapToVirtualScreen(screenPosition, nullptr);
|
||||
QMetaObject::invokeMethod(_desktop, "toggleMenu", Q_ARG(QVariant, virtualPos));
|
||||
}
|
||||
|
||||
|
||||
#include "OffscreenUi.moc"
|
||||
|
|
|
@ -27,18 +27,18 @@ class OffscreenUi : public OffscreenQmlSurface, public Dependency {
|
|||
public:
|
||||
OffscreenUi();
|
||||
virtual void create(QOpenGLContext* context) override;
|
||||
void createDesktop();
|
||||
void createDesktop(const QUrl& url);
|
||||
void show(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
void toggle(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
bool shouldSwallowShortcut(QEvent* event);
|
||||
bool navigationFocused();
|
||||
void setNavigationFocused(bool focused);
|
||||
void unfocusWindows();
|
||||
void toggleMenu(const QPoint& screenCoordinates);
|
||||
|
||||
QQuickItem* getDesktop();
|
||||
QQuickItem* getToolWindow();
|
||||
|
||||
Q_INVOKABLE void executeOnUiThread(std::function<void()> function);
|
||||
Q_INVOKABLE QVariant returnFromUiThread(std::function<QVariant()> function);
|
||||
|
||||
/// Same design as QMessageBox::critical(), will block, returns result
|
||||
static QMessageBox::StandardButton critical(void* ignored, const QString& title, const QString& text,
|
||||
|
|
|
@ -345,7 +345,7 @@ void QmlWindowClass::hasClosed() {
|
|||
}
|
||||
|
||||
void QmlWindowClass::raise() {
|
||||
QMetaObject::invokeMethod(asQuickItem(), "raiseWindow", Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(asQuickItem(), "raise", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
#include "QmlWindowClass.moc"
|
||||
|
|
|
@ -36,7 +36,6 @@ public:
|
|||
|
||||
private:
|
||||
MenuUserData(const MenuUserData&);
|
||||
|
||||
void init(QObject* widgetObject, QObject* qmlObject) {
|
||||
widgetObject->setUserData(USER_DATA_ID, this);
|
||||
qmlObject->setUserData(USER_DATA_ID, this);
|
||||
|
@ -48,14 +47,6 @@ private:
|
|||
|
||||
const int MenuUserData::USER_DATA_ID = QObject::registerUserData();
|
||||
|
||||
HIFI_QML_DEF_LAMBDA(VrMenu, [&](QQmlContext* context, QObject* newItem) {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
QObject* rootMenu = offscreenUi->getRootItem()->findChild<QObject*>("rootMenu");
|
||||
Q_ASSERT(rootMenu);
|
||||
static_cast<VrMenu*>(newItem)->setRootMenu(rootMenu);
|
||||
context->setContextProperty("rootMenu", rootMenu);
|
||||
});
|
||||
|
||||
VrMenu* VrMenu::_instance{ nullptr };
|
||||
static QQueue<std::function<void(VrMenu*)>> queuedLambdas;
|
||||
|
||||
|
@ -70,19 +61,18 @@ void VrMenu::executeOrQueue(std::function<void(VrMenu*)> f) {
|
|||
}
|
||||
}
|
||||
|
||||
void VrMenu::executeQueuedLambdas() {
|
||||
Q_ASSERT(_instance);
|
||||
|
||||
VrMenu::VrMenu(QObject* parent) : QObject(parent) {
|
||||
_instance = this;
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
_rootMenu = offscreenUi->getRootItem()->findChild<QObject*>("rootMenu");
|
||||
offscreenUi->getRootContext()->setContextProperty("rootMenu", _rootMenu);
|
||||
foreach(std::function<void(VrMenu*)> f, queuedLambdas) {
|
||||
f(_instance);
|
||||
f(this);
|
||||
}
|
||||
queuedLambdas.clear();
|
||||
}
|
||||
|
||||
VrMenu::VrMenu(QQuickItem* parent) : QQuickItem(parent) {
|
||||
_instance = this;
|
||||
this->setEnabled(false);
|
||||
}
|
||||
|
||||
QObject* VrMenu::findMenuObject(const QString& menuOption) {
|
||||
if (menuOption.isEmpty()) {
|
||||
return _rootMenu;
|
||||
|
@ -91,10 +81,6 @@ QObject* VrMenu::findMenuObject(const QString& menuOption) {
|
|||
return result;
|
||||
}
|
||||
|
||||
void VrMenu::setRootMenu(QObject* rootMenu) {
|
||||
_rootMenu = rootMenu;
|
||||
}
|
||||
|
||||
void updateQmlItemFromAction(QObject* target, QAction* source) {
|
||||
target->setProperty("checkable", source->isCheckable());
|
||||
target->setProperty("enabled", source->isEnabled());
|
||||
|
@ -116,9 +102,8 @@ void VrMenu::addMenu(QMenu* menu) {
|
|||
Q_ASSERT(false);
|
||||
}
|
||||
QVariant returnedValue;
|
||||
bool invokeResult = QMetaObject::invokeMethod(this, "addMenu", Qt::DirectConnection,
|
||||
bool invokeResult = QMetaObject::invokeMethod(qmlParent, "addMenu", Qt::DirectConnection,
|
||||
Q_RETURN_ARG(QVariant, returnedValue),
|
||||
Q_ARG(QVariant, QVariant::fromValue(qmlParent)),
|
||||
Q_ARG(QVariant, QVariant::fromValue(menu->title())));
|
||||
Q_ASSERT(invokeResult);
|
||||
Q_UNUSED(invokeResult); // FIXME - apparently we haven't upgraded the Qt on our unix Jenkins environments to 5.5.x
|
||||
|
@ -147,21 +132,24 @@ void bindActionToQmlAction(QObject* qmlAction, QAction* action) {
|
|||
QObject::connect(qmlAction, SIGNAL(triggered()), action, SLOT(trigger()));
|
||||
}
|
||||
|
||||
class QQuickMenuItem;
|
||||
|
||||
void VrMenu::addAction(QMenu* menu, QAction* action) {
|
||||
Q_ASSERT(!MenuUserData::forObject(action));
|
||||
Q_ASSERT(MenuUserData::forObject(menu));
|
||||
MenuUserData* userData = MenuUserData::forObject(menu);
|
||||
QObject* menuQml = findMenuObject(userData->uuid.toString());
|
||||
Q_ASSERT(menuQml);
|
||||
QVariant returnedValue;
|
||||
QQuickMenuItem* returnedValue { nullptr };
|
||||
|
||||
bool invokeResult = QMetaObject::invokeMethod(this, "addItem", Qt::DirectConnection,
|
||||
Q_RETURN_ARG(QVariant, returnedValue),
|
||||
Q_ARG(QVariant, QVariant::fromValue(menuQml)),
|
||||
Q_ARG(QVariant, QVariant::fromValue(action->text())));
|
||||
qDebug() << menuQml;
|
||||
bool invokeResult = QMetaObject::invokeMethod(menuQml, "addItem", Qt::DirectConnection,
|
||||
Q_RETURN_ARG(QQuickMenuItem*, returnedValue),
|
||||
Q_ARG(QString, action->text()));
|
||||
|
||||
Q_ASSERT(invokeResult);
|
||||
Q_UNUSED(invokeResult); // FIXME - apparently we haven't upgraded the Qt on our unix Jenkins environments to 5.5.x
|
||||
QObject* result = returnedValue.value<QObject*>();
|
||||
QObject* result = reinterpret_cast<QObject*>(returnedValue); // returnedValue.value<QObject*>();
|
||||
Q_ASSERT(result);
|
||||
// Bind the QML and Widget together
|
||||
bindActionToQmlAction(result, action);
|
||||
|
@ -175,19 +163,19 @@ void VrMenu::insertAction(QAction* before, QAction* action) {
|
|||
beforeQml = findMenuObject(beforeUserData->uuid.toString());
|
||||
}
|
||||
QObject* menu = beforeQml->parent();
|
||||
QVariant returnedValue;
|
||||
bool invokeResult = QMetaObject::invokeMethod(this, "insertItem", Qt::DirectConnection,
|
||||
Q_RETURN_ARG(QVariant, returnedValue),
|
||||
Q_ARG(QVariant, QVariant::fromValue(menu)),
|
||||
Q_ARG(QVariant, QVariant::fromValue(beforeQml)),
|
||||
Q_ARG(QVariant, QVariant::fromValue(action->text())));
|
||||
QQuickMenuItem* returnedValue { nullptr };
|
||||
// FIXME this needs to find the index of the beforeQml item and call insertItem(int, object)
|
||||
bool invokeResult = QMetaObject::invokeMethod(menu, "addItem", Qt::DirectConnection,
|
||||
Q_RETURN_ARG(QQuickMenuItem*, returnedValue),
|
||||
Q_ARG(QString, action->text()));
|
||||
Q_ASSERT(invokeResult);
|
||||
Q_UNUSED(invokeResult); // FIXME - apparently we haven't upgraded the Qt on our unix Jenkins environments to 5.5.x
|
||||
QObject* result = returnedValue.value<QObject*>();
|
||||
QObject* result = reinterpret_cast<QObject*>(returnedValue); // returnedValue.value<QObject*>();
|
||||
Q_ASSERT(result);
|
||||
bindActionToQmlAction(result, action);
|
||||
}
|
||||
|
||||
class QQuickMenuBase;
|
||||
|
||||
void VrMenu::removeAction(QAction* action) {
|
||||
if (!action) {
|
||||
qWarning("Attempted to remove invalid menu action");
|
||||
|
@ -198,12 +186,12 @@ void VrMenu::removeAction(QAction* action) {
|
|||
qWarning("Attempted to remove menu action with no found QML object");
|
||||
return;
|
||||
}
|
||||
|
||||
QObject* item = findMenuObject(userData->uuid.toString());
|
||||
QObject* menu = item->parent();
|
||||
// Proxy QuickItem requests through the QML layer
|
||||
bool invokeResult = QMetaObject::invokeMethod(this, "removeItem", Qt::DirectConnection,
|
||||
Q_ARG(QVariant, QVariant::fromValue(menu)),
|
||||
Q_ARG(QVariant, QVariant::fromValue(item)));
|
||||
QQuickMenuBase* qmlItem = reinterpret_cast<QQuickMenuBase*>(item);
|
||||
bool invokeResult = QMetaObject::invokeMethod(menu, "removeItem", Qt::DirectConnection,
|
||||
Q_ARG(QQuickMenuBase*, qmlItem));
|
||||
Q_ASSERT(invokeResult);
|
||||
Q_UNUSED(invokeResult); // FIXME - apparently we haven't upgraded the Qt on our unix Jenkins environments to 5.5.x
|
||||
}
|
||||
|
|
|
@ -21,21 +21,16 @@
|
|||
#include "OffscreenUi.h"
|
||||
|
||||
// FIXME break up the rendering code (VrMenu) and the code for mirroring a Widget based menu in QML
|
||||
class VrMenu : public QQuickItem {
|
||||
class VrMenu : public QObject {
|
||||
Q_OBJECT
|
||||
HIFI_QML_DECL_LAMBDA
|
||||
|
||||
public:
|
||||
static void executeOrQueue(std::function<void(VrMenu*)> f);
|
||||
static void executeQueuedLambdas();
|
||||
VrMenu(QQuickItem* parent = nullptr);
|
||||
VrMenu(QObject* parent = nullptr);
|
||||
void addMenu(QMenu* menu);
|
||||
void addAction(QMenu* parent, QAction* action);
|
||||
void insertAction(QAction* before, QAction* action);
|
||||
void removeAction(QAction* action);
|
||||
|
||||
void setRootMenu(QObject* rootMenu);
|
||||
|
||||
protected:
|
||||
QObject* _rootMenu{ nullptr };
|
||||
QObject* findMenuObject(const QString& name);
|
||||
|
|
|
@ -6,6 +6,8 @@ import Qt.labs.settings 1.0
|
|||
import "../../../interface/resources/qml"
|
||||
import "../../../interface/resources/qml/windows"
|
||||
import "../../../interface/resources/qml/dialogs"
|
||||
import "../../../interface/resources/qml/hifi"
|
||||
import "../../../interface/resources/qml/hifi/dialogs"
|
||||
|
||||
ApplicationWindow {
|
||||
id: appWindow
|
||||
|
@ -36,7 +38,7 @@ ApplicationWindow {
|
|||
return newListModel;
|
||||
}
|
||||
|
||||
Root {
|
||||
Desktop {
|
||||
id: desktop
|
||||
anchors.fill: parent
|
||||
StubMenu { id: stubMenu }
|
||||
|
@ -70,28 +72,6 @@ ApplicationWindow {
|
|||
blue.enabled = !blue.enabled
|
||||
}
|
||||
}
|
||||
// Button {
|
||||
// text: "add web tab"
|
||||
// onClicked: {
|
||||
// testButtons.urls.push("http://slashdot.org?" + testButtons.count++);
|
||||
// testButtons.tabs.push(desktop.toolWindow.addWebTab({ title: "test", source: testButtons.urls[testButtons.urls.length - 1], width: 500, height: 720 }))
|
||||
// }
|
||||
// }
|
||||
// Button {
|
||||
// text: "toggle tab visible"
|
||||
// onClicked: {
|
||||
// var lastUrl = testButtons.urls[testButtons.urls.length - 1];
|
||||
// var tab = desktop.toolWindow.findTabForUrl(lastUrl);
|
||||
// desktop.toolWindow.showTabForUrl(lastUrl, !tab.enabled)
|
||||
// }
|
||||
// }
|
||||
// Button {
|
||||
// text: "Remove last tab"
|
||||
// onClicked: {
|
||||
// testButtons.tabs.pop();
|
||||
// desktop.toolWindow.removeTabForUrl(testButtons.urls.pop());
|
||||
// }
|
||||
// }
|
||||
Button {
|
||||
text: "Show Long Error"
|
||||
onClicked: {
|
||||
|
@ -152,6 +132,11 @@ ApplicationWindow {
|
|||
console.log(appWindow.activeFocusItem);
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "Preferences"
|
||||
property var preferencesComponent: Component { PreferencesDialog { } }
|
||||
onClicked: preferencesComponent.createObject(desktop);
|
||||
}
|
||||
}
|
||||
|
||||
Window {
|
||||
|
|
|
@ -80,5 +80,10 @@ DISTFILES += \
|
|||
../../interface/resources/qml/VrMenu.qml \
|
||||
../../interface/resources/qml/VrMenuItem.qml \
|
||||
../../interface/resources/qml/VrMenuView.qml \
|
||||
../../interface/resources/qml/WebEntity.qml
|
||||
../../interface/resources/qml/WebEntity.qml \
|
||||
../../interface/resources/qml/desktop/Desktop.qml \
|
||||
../../interface/resources/qml/hifi/Desktop.qml \
|
||||
../../interface/resources/qml/menus/MenuMouseHandler.qml \
|
||||
../../interface/resources/qml/menus/VrMenuItem.qml \
|
||||
../../interface/resources/qml/menus/VrMenuView.qml
|
||||
|
||||
|
|
Loading…
Reference in a new issue