diff --git a/interface/resources/qml/HifiAction.qml b/interface/resources/qml/HifiAction.qml index 8e6e7d59b4..0cecff91d7 100644 --- a/interface/resources/qml/HifiAction.qml +++ b/interface/resources/qml/HifiAction.qml @@ -2,19 +2,19 @@ import QtQuick 2.4 import QtQuick.Controls 1.3 Action { - property string name - objectName: name + "HifiAction" - text: qsTr(name) - - signal triggeredByName(string name); - signal toggledByName(string name); - - onTriggered: { - triggeredByName(name); - } - - onToggled: { - toggledByName(name, checked); - } + property string name + objectName: name + "HifiAction" + text: qsTr(name) + + signal triggeredByName(string name); + signal toggledByName(string name); + + onTriggered: { + triggeredByName(name); + } + + onToggled: { + toggledByName(name, checked); + } } diff --git a/interface/resources/qml/HifiMenu.qml b/interface/resources/qml/HifiMenu.qml index 254ae32520..d86821601a 100644 --- a/interface/resources/qml/HifiMenu.qml +++ b/interface/resources/qml/HifiMenu.qml @@ -6,19 +6,20 @@ import "controls" import "styles" Hifi.HifiMenu { - id: root - anchors.fill: parent - objectName: "HifiMenu" + id: root + anchors.fill: parent + objectName: "HifiMenu" enabled: false opacity: 0.0 property int animationDuration: 200 HifiPalette { id: hifiPalette } + z: 10000 onEnabledChanged: { - if (enabled && columns.length == 0) { - pushColumn(rootMenu.items); - } - opacity = enabled ? 1.0 : 0.0 + if (enabled && columns.length == 0) { + pushColumn(rootMenu.items); + } + opacity = enabled ? 1.0 : 0.0 if (enabled) { forceActiveFocus() } @@ -37,355 +38,235 @@ Hifi.HifiMenu { } onVisibleChanged: { - if (!visible) reset(); + if (!visible) reset(); } property var menu: Menu {} property var models: [] - property var columns: [] + property var columns: [] property var itemBuilder: Component { - Text { - SystemPalette { id: sp; colorGroup: SystemPalette.Active } - id: thisText - x: 32 - property var source - property var root - property var listViewIndex - property var listView - text: typedText() - height: implicitHeight - width: implicitWidth - color: source.enabled ? "black" : "gray" - - onImplicitWidthChanged: { - if (listView) { - listView.minWidth = Math.max(listView.minWidth, implicitWidth + 64); - listView.recalculateSize(); - } - } + Text { + SystemPalette { id: sp; colorGroup: SystemPalette.Active } + id: thisText + x: 32 + property var source + property var root + property var listViewIndex + property var listView + text: typedText() + height: implicitHeight + width: implicitWidth + color: source.enabled ? "black" : "gray" + + onImplicitWidthChanged: { + if (listView) { + listView.minWidth = Math.max(listView.minWidth, implicitWidth + 64); + listView.recalculateSize(); + } + } - FontAwesome { - visible: source.type == 1 && source.checkable - x: -32 - text: (source.type == 1 && source.checked) ? "\uF05D" : "\uF10C" - } - - FontAwesome { - visible: source.type == 2 - x: listView.width - 64 - text: "\uF0DA" - } - + FontAwesome { + visible: source.type == 1 && source.checkable + x: -32 + text: (source.type == 1 && source.checked) ? "\uF05D" : "\uF10C" + } + + FontAwesome { + visible: source.type == 2 + x: listView.width - 64 + text: "\uF0DA" + } + - function typedText() { - switch(source.type) { - case 2: - return source.title; - case 1: - return source.text; - case 0: - return "-----" - } - } - - MouseArea { - id: mouseArea - acceptedButtons: Qt.LeftButton + function typedText() { + switch(source.type) { + case 2: + return source.title; + case 1: + return source.text; + case 0: + return "-----" + } + } + + MouseArea { + id: mouseArea + acceptedButtons: Qt.LeftButton anchors.bottom: parent.bottom anchors.bottomMargin: 0 anchors.top: parent.top anchors.topMargin: 0 width: listView.width - onClicked: { - listView.currentIndex = listViewIndex - parent.root.selectItem(parent.source); - } - } - } + onClicked: { + listView.currentIndex = listViewIndex + parent.root.selectItem(parent.source); + } + } + } } - + property var menuBuilder: Component { - Border { - SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active } - x: root.models.length * 60; + Border { + SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active } + x: root.models.length == 1 ? + (root.width / 2 - width / 2) : + root.columns[root.models.length - 2].x + 60; anchors.verticalCenter: parent.verticalCenter - border.color: hifiPalette.hifiBlue - color: sysPalette.window + border.color: hifiPalette.hifiBlue + color: sysPalette.window - ListView { - spacing: 6 - property int outerMargin: 8 - property real minWidth: 0 - anchors.fill: parent - anchors.margins: outerMargin - id: listView - height: root.height - currentIndex: -1 + ListView { + spacing: 6 + property int outerMargin: 8 + property real minWidth: 0 + anchors.fill: parent + anchors.margins: outerMargin + id: listView + height: root.height + currentIndex: -1 - onCountChanged: { - recalculateSize() - } - - function recalculateSize() { - var newHeight = 0 - var newWidth = minWidth; - for (var i = 0; i < children.length; ++i) { - var item = children[i]; - newHeight += item.height - } - parent.height = newHeight + outerMargin * 2; - parent.width = newWidth + outerMargin * 2 - } - - highlight: Rectangle { - width: listView.minWidth; height: 32 - color: sysPalette.highlight - y: (listView.currentItem) ? listView.currentItem.y : 0; - Behavior on y { - NumberAnimation { - duration: 100 - easing.type: Easing.InOutQuint - } - } - } - + onCountChanged: { + recalculateSize() + } + + function recalculateSize() { + var newHeight = 0 + var newWidth = minWidth; + for (var i = 0; i < children.length; ++i) { + var item = children[i]; + newHeight += item.height + } + parent.height = newHeight + outerMargin * 2; + parent.width = newWidth + outerMargin * 2 + } + + highlight: Rectangle { + width: listView.minWidth; height: 32 + color: sysPalette.highlight + y: (listView.currentItem) ? listView.currentItem.y : 0; + x: 32 + Behavior on y { + NumberAnimation { + duration: 100 + easing.type: Easing.InOutQuint + } + } + } + - property int columnIndex: root.models.length - 1 - model: root.models[columnIndex] - delegate: Loader { - id: loader - sourceComponent: root.itemBuilder - Binding { - target: loader.item - property: "root" - value: root - when: loader.status == Loader.Ready - } - Binding { - target: loader.item - property: "source" - value: modelData - when: loader.status == Loader.Ready - } - Binding { - target: loader.item - property: "listViewIndex" - value: index - when: loader.status == Loader.Ready - } - Binding { - target: loader.item - property: "listView" - value: listView - when: loader.status == Loader.Ready - } - } + property int columnIndex: root.models.length - 1 + model: root.models[columnIndex] + delegate: Loader { + id: loader + sourceComponent: root.itemBuilder + Binding { + target: loader.item + property: "root" + value: root + when: loader.status == Loader.Ready + } + Binding { + target: loader.item + property: "source" + value: modelData + when: loader.status == Loader.Ready + } + Binding { + target: loader.item + property: "listViewIndex" + value: index + when: loader.status == Loader.Ready + } + Binding { + target: loader.item + property: "listView" + value: listView + when: loader.status == Loader.Ready + } + } - } - - } + } + + } } function lastColumn() { - return columns[root.columns.length - 1]; + return columns[root.columns.length - 1]; } - function pushColumn(items) { - models.push(items) - if (columns.length) { - var oldColumn = lastColumn(); - oldColumn.enabled = false; - oldColumn.opacity = 0.5; - } - var newColumn = menuBuilder.createObject(root); - columns.push(newColumn); - newColumn.forceActiveFocus(); - } + function pushColumn(items) { + models.push(items) + if (columns.length) { + var oldColumn = lastColumn(); + oldColumn.enabled = false; + oldColumn.opacity = 0.5; + } + var newColumn = menuBuilder.createObject(root); + columns.push(newColumn); + newColumn.forceActiveFocus(); + } - function popColumn() { - if (columns.length > 0) { - var curColumn = columns.pop(); - console.log(curColumn); - curColumn.visible = false; - curColumn.destroy(); - models.pop(); - } - - if (columns.length == 0) { - enabled = false; - return; - } + function popColumn() { + if (columns.length > 0) { + var curColumn = columns.pop(); + console.log(curColumn); + 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(); + curColumn = lastColumn(); + curColumn.enabled = true; + curColumn.opacity = 1.0; + curColumn.forceActiveFocus(); } - function selectItem(source) { - switch (source.type) { - case 2: - pushColumn(source.items) - break; - case 1: - source.trigger() - enabled = false - break; - case 0: - break; - } - } - - function reset() { - while (columns.length > 0) { - popColumn(); - } - } + function selectItem(source) { + switch (source.type) { + case 2: + pushColumn(source.items) + break; + case 1: + source.trigger() + enabled = false + break; + case 0: + break; + } + } + + function reset() { + while (columns.length > 0) { + popColumn(); + } + } - /* - HifiMenu { - id: rootMenu - Menu { - id: menu - Menu { - title: "File" - MenuItem { - action: HifiAction { - name: rootMenu.login - } - } - MenuItem { - action: HifiAction { - name: "Test" - checkable: true - } - } - MenuItem { - action: HifiAction { - name: rootMenu.quit - } - } - } - Menu { - title: "Edit" - MenuItem { - action: HifiAction { - text: "Copy" - shortcut: StandardKey.Copy - } - } - MenuItem { - action: HifiAction { - text: "Cut" - shortcut: StandardKey.Cut - } - } - MenuItem { - action: HifiAction { - text: "Paste" - shortcut: StandardKey.Paste - } - } - MenuItem { - action: HifiAction { - text: "Undo" - shortcut: StandardKey.Undo - } - } - MenuItem { - action: HifiAction { - text: "Redo" - shortcut: StandardKey.Redo - } - } - MenuItem { - action: HifiAction { - name: rootMenu.attachments - } - } - MenuItem { - action: HifiAction { - name: rootMenu.animations - } - } - } - - Menu { - title: "Scripts" - MenuItem { - action: HifiAction { - name: rootMenu.scriptEditor - } - } - MenuItem { - action: HifiAction { - name: rootMenu.loadScript - } - } - MenuItem { - action: HifiAction { - name: rootMenu.loadScriptURL - } - } - MenuItem { - action: HifiAction { - name: rootMenu.stopAllScripts - } - } - MenuItem { - action: HifiAction { - name: rootMenu.reloadAllScripts - } - } - MenuItem { - action: HifiAction { - name: rootMenu.runningScripts - } - } - } - Menu { - title: "Location" - MenuItem { - action: HifiAction { - name: rootMenu.addressBar - } - } - MenuItem { - action: HifiAction { - name: rootMenu.copyAddress - } - } - MenuItem { - action: HifiAction { - name: rootMenu.copyPath - } - } - } - } - } - */ - Keys.onPressed: { - switch (event.key) { - case Qt.Key_Escape: - root.popColumn() + switch (event.key) { + case Qt.Key_Escape: + root.popColumn() event.accepted = true; - } + } } - MouseArea { - anchors.fill: parent - id: mouseArea - acceptedButtons: Qt.LeftButton | Qt.RightButton - onClicked: { + MouseArea { + anchors.fill: parent + id: mouseArea + acceptedButtons: Qt.LeftButton | Qt.RightButton + onClicked: { if (mouse.button == Qt.RightButton) { - root.popColumn(); + root.popColumn(); } else { - root.enabled = false; - } - } - } + root.enabled = false; + } + } + } } diff --git a/interface/resources/qml/MarketplaceDialog.qml b/interface/resources/qml/MarketplaceDialog.qml index fe192179eb..58bb3e6183 100644 --- a/interface/resources/qml/MarketplaceDialog.qml +++ b/interface/resources/qml/MarketplaceDialog.qml @@ -14,7 +14,7 @@ Dialog { resizable: true MarketplaceDialog { - id: marketplaceDialog + id: marketplaceDialog } Item { @@ -33,13 +33,13 @@ Dialog { url: "https://metaverse.highfidelity.com/marketplace" anchors.fill: parent onNavigationRequested: { - console.log(request.url) + console.log(request.url) if (!marketplaceDialog.navigationRequested(request.url)) { - console.log("Application absorbed the request") + console.log("Application absorbed the request") request.action = WebView.IgnoreRequest; - return; + return; } - console.log("Application passed on the request") + console.log("Application passed on the request") request.action = WebView.AcceptRequest; return; } diff --git a/interface/resources/qml/MessageDialog.qml b/interface/resources/qml/MessageDialog.qml index eaf304b16a..26fd30db27 100644 --- a/interface/resources/qml/MessageDialog.qml +++ b/interface/resources/qml/MessageDialog.qml @@ -71,13 +71,13 @@ Dialog { onEnabledChanged: { if (enabled) { - content.forceActiveFocus(); + content.forceActiveFocus(); } } Hifi.MessageDialog { - id: content - clip: true + id: content + clip: true anchors.fill: parent anchors.topMargin: parent.topMargin + root.outerSpacing anchors.leftMargin: parent.margins + root.outerSpacing @@ -88,16 +88,16 @@ Dialog { property real buttonsRowImplicitWidth: Screen.pixelDensity * 50 Keys.onPressed: { - console.log("Key press at content") + console.log("Key press at content") event.accepted = true if (event.modifiers === Qt.ControlModifier) switch (event.key) { case Qt.Key_A: - console.log("Select All") + console.log("Select All") detailedText.selectAll() break case Qt.Key_C: - console.log("Copy") + console.log("Copy") detailedText.copy() break case Qt.Key_Period: @@ -107,12 +107,12 @@ Dialog { } else switch (event.key) { case Qt.Key_Escape: case Qt.Key_Back: - console.log("Rejecting") + console.log("Rejecting") reject() break case Qt.Key_Enter: case Qt.Key_Return: - console.log("Accepting") + console.log("Accepting") accept() break } @@ -123,18 +123,18 @@ Dialog { Component.onCompleted: { root.title = title } - + onTitleChanged: { - root.title = title + root.title = title } - + Column { id: contentColumn spacing: root.outerSpacing anchors { - top: parent.top - left: parent.left - right: parent.right + top: parent.top + left: parent.left + right: parent.right } Item { diff --git a/interface/resources/qml/RootMenu.qml b/interface/resources/qml/RootMenu.qml index dc2e36f89a..b8c81a6589 100644 --- a/interface/resources/qml/RootMenu.qml +++ b/interface/resources/qml/RootMenu.qml @@ -2,8 +2,8 @@ import QtQuick 2.4 import QtQuick.Controls 1.3 Item { - Menu { - id: root - objectName: "rootMenu" - } + Menu { + id: root + objectName: "rootMenu" + } } diff --git a/interface/resources/qml/TestRoot.qml b/interface/resources/qml/TestRoot.qml index 0b0f890361..80f8c900e3 100644 --- a/interface/resources/qml/TestRoot.qml +++ b/interface/resources/qml/TestRoot.qml @@ -10,17 +10,17 @@ Root { anchors.fill: parent onWidthChanged: { - console.log("Root width: " + width) - } - onHeightChanged: { - console.log("Root height: " + height) - } + console.log("Root width: " + width) + } + onHeightChanged: { + console.log("Root height: " + height) + } Component.onCompleted: { - console.log("Completed root") - root.forceActiveFocus() + console.log("Completed root") + root.forceActiveFocus() } - + Button { id: messageBox anchors.right: createDialog.left @@ -48,7 +48,7 @@ Root { } Keys.onPressed: { - console.log(event.key); + console.log(event.key); } } diff --git a/interface/resources/qml/controls/Dialog.qml b/interface/resources/qml/controls/Dialog.qml index 109889f738..07162ad1d8 100644 --- a/interface/resources/qml/controls/Dialog.qml +++ b/interface/resources/qml/controls/Dialog.qml @@ -16,6 +16,8 @@ Item { HifiPalette { id: hifiPalette } SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active } + x: parent ? parent.width / 2 - width / 2 : 0 + y: parent ? parent.height / 2 - height / 2 : 0 property int animationDuration: 400 property bool destroyOnInvisible: false diff --git a/interface/resources/qml/controls/FontAwesome.qml b/interface/resources/qml/controls/FontAwesome.qml index 16fd4a6ecc..e975c0342b 100644 --- a/interface/resources/qml/controls/FontAwesome.qml +++ b/interface/resources/qml/controls/FontAwesome.qml @@ -7,7 +7,7 @@ Text { FontLoader { id: iconFont; source: "../../fonts/fontawesome-webfont.ttf"; } property int size: 32 width: size - height: size + height: size verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter font.family: iconFont.name diff --git a/interface/resources/qml/styles/ButtonStyle.qml b/interface/resources/qml/styles/ButtonStyle.qml index caf366364a..8d866390a0 100644 --- a/interface/resources/qml/styles/ButtonStyle.qml +++ b/interface/resources/qml/styles/ButtonStyle.qml @@ -2,15 +2,15 @@ import QtQuick 2.4 as Original import QtQuick.Controls.Styles 1.3 as OriginalStyles import "." import "../controls" - + OriginalStyles.ButtonStyle { - Original.SystemPalette { id: myPalette; colorGroup: Original.SystemPalette.Active } - padding { + Original.SystemPalette { id: myPalette; colorGroup: Original.SystemPalette.Active } + padding { top: 8 left: 12 right: 12 bottom: 8 - } + } background: Border { anchors.fill: parent } diff --git a/interface/resources/qml/styles/HifiPalette.qml b/interface/resources/qml/styles/HifiPalette.qml index 641d533e3d..46ef0ef14e 100644 --- a/interface/resources/qml/styles/HifiPalette.qml +++ b/interface/resources/qml/styles/HifiPalette.qml @@ -1,5 +1,5 @@ import QtQuick 2.4 QtObject { - property string hifiBlue: "#0e7077" + property string hifiBlue: "#0e7077" } \ No newline at end of file diff --git a/interface/resources/qml/styles/MenuButtonStyle.qml b/interface/resources/qml/styles/MenuButtonStyle.qml index f30ade3d33..fd21e88d86 100644 --- a/interface/resources/qml/styles/MenuButtonStyle.qml +++ b/interface/resources/qml/styles/MenuButtonStyle.qml @@ -2,15 +2,15 @@ import QtQuick 2.4 import QtQuick.Controls.Styles 1.3 import "../controls" import "." - + ButtonStyle { - HifiPalette { id: hifiPalette } - padding { + HifiPalette { id: hifiPalette } + padding { top: 2 left: 4 right: 4 bottom: 2 - } + } background: Item {} label: Text { renderType: Text.NativeRendering diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d281282fc8..8df8009b95 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1079,12 +1079,12 @@ bool Application::eventFilter(QObject* object, QEvent* event) { return false; } -static bool _altPressed; -static bool _ctrlPressed; +static bool altPressed; +static bool ctrlPressed; void Application::keyPressEvent(QKeyEvent* event) { - _altPressed = event->key() == Qt::Key_Alt; - _ctrlPressed = event->key() == Qt::Key_Control; + altPressed = event->key() == Qt::Key_Alt; + ctrlPressed = event->key() == Qt::Key_Control; _keysPressed.insert(event->key()); _controllerScriptingInterface.emitKeyPressEvent(event); // send events to any registered scripts @@ -1336,15 +1336,13 @@ void Application::keyPressEvent(QKeyEvent* event) { } void Application::keyReleaseEvent(QKeyEvent* event) { - if (event->key() == Qt::Key_Alt && _altPressed) { + if (event->key() == Qt::Key_Alt && altPressed && _window->isActiveWindow()) { Menu::toggle(); } - if (event->key() == Qt::Key_Control && _ctrlPressed) { - auto offscreenUi = DependencyManager::get(); - auto rootMenu = offscreenUi->getRootItem()->findChild("rootMenu"); - QMetaObject::invokeMethod(rootMenu, "popup"); + if (event->key() == Qt::Key_Control && ctrlPressed && _window->isActiveWindow()) { + Menu::toggle(); } - _ctrlPressed = event->key() == Qt::Key_Control; + ctrlPressed = altPressed = false; _keysPressed.remove(event->key()); diff --git a/interface/src/MainWindow.cpp b/interface/src/MainWindow.cpp index f60716dc48..7e8d46f5ee 100644 --- a/interface/src/MainWindow.cpp +++ b/interface/src/MainWindow.cpp @@ -94,9 +94,9 @@ void MainWindow::changeEvent(QEvent* event) { emit windowShown(true); } - if (isFullScreen() != Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) { - Menu::getInstance()->setIsOptionChecked(MenuOption::Fullscreen, isFullScreen()); - } + //if (isFullScreen() != Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) { + // Menu::getInstance()->setIsOptionChecked(MenuOption::Fullscreen, isFullScreen()); + //} } else if (event->type() == QEvent::ActivationChange) { if (isActiveWindow()) { emit windowShown(true); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 029c150884..8c45f583f1 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -45,13 +45,12 @@ #include "Util.h" // Proxy object to simplify porting over -HifiAction::HifiAction(const QString & menuOption) : _menuOption(menuOption) { +HifiAction::HifiAction(const QString& menuOption) : _menuOption(menuOption) { } -//void HifiAction::setCheckable(bool) { -// Menu::getInstance()->set -// qFatal("Not implemented"); -//} +void HifiAction::setCheckable(bool checkable) { + Menu::getInstance()->setCheckable(_menuOption, checkable); +} void HifiAction::setChecked(bool checked) { Menu::getInstance()->setChecked(_menuOption, checked); @@ -65,7 +64,7 @@ QString HifiAction::shortcut() const { return Menu::getInstance()->getItemShortcut(_menuOption); } -void HifiAction::setText(const QString & text) { +void HifiAction::setText(const QString& text) { Menu::getInstance()->setItemText(_menuOption, text); } @@ -101,7 +100,7 @@ Menu* Menu::getInstance() { return _instance; } -Menu::Menu(QQuickItem * parent) : HifiMenu(parent) { +Menu::Menu(QQuickItem* parent) : HifiMenu(parent) { } void Menu::init() { @@ -125,12 +124,15 @@ void Menu::init() { #endif { +#if 0 static const QString SCRIPTS_MENU{ "Scripts" }; - addMenu(FILE_MENU, SCRIPTS_MENU); + addMenu(FILE_MENU, LOCATION_MENU); +#else + static const QString SCRIPTS_MENU{ FILE_MENU }; + addSeparator(FILE_MENU, "Scripts"); +#endif //Qt::CTRL | Qt::Key_O - addItem(SCRIPTS_MENU, MenuOption::LoadScript, [=] { - qApp->loadDialog(); - }); + addItem(SCRIPTS_MENU, MenuOption::LoadScript, qApp, SLOT(loadDialog())); //Qt::CTRL | Qt::SHIFT | Qt::Key_O addItem(SCRIPTS_MENU, MenuOption::LoadScriptURL, [=] { qApp->loadScriptURLDialog(); @@ -149,9 +151,15 @@ void Menu::init() { } { +#if 0 static const QString LOCATION_MENU{ "Location" }; addMenu(FILE_MENU, LOCATION_MENU); +#else + addSeparator(FILE_MENU, "Location"); + static const QString LOCATION_MENU{ FILE_MENU }; +#endif qApp->getBookmarks()->setupMenus(LOCATION_MENU); + //Qt::CTRL | Qt::Key_L addItem(LOCATION_MENU, MenuOption::AddressBar, [=] { auto dialogsManager = DependencyManager::get(); @@ -178,16 +186,15 @@ void Menu::init() { { static const QString EDIT_MENU{ "Edit" }; addMenu(ROOT_MENU, EDIT_MENU); -#if 0 - QUndoStack* undoStack = qApp->getUndoStack(); - QAction* undoAction = undoStack->createUndoAction(editMenu); - undoAction->setShortcut(Qt::CTRL | Qt::Key_Z); - addActionToQMenuAndActionHash(editMenu, undoAction); - QAction* redoAction = undoStack->createRedoAction(editMenu); - redoAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_Z); - addActionToQMenuAndActionHash(editMenu, redoAction); -#endif + QUndoStack* undoStack = qApp->getUndoStack(); + QAction* undoAction = undoStack->createUndoAction(this); + //undoAction->setShortcut(Qt::CTRL | Qt::Key_Z); + addItem(EDIT_MENU, undoAction->text(), undoAction, SLOT(trigger())); + + QAction* redoAction = undoStack->createRedoAction(this); + //redoAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_Z); + addItem(EDIT_MENU, redoAction->text(), redoAction, SLOT(trigger())); // Qt::CTRL | Qt::Key_Comma // QAction::PreferencesRole @@ -231,23 +238,20 @@ void Menu::init() { // FIXME group addCheckableItem(VIZ_MENU, MenuOption::VisibleToEveryone, discoverabilityManager->getDiscoverabilityMode() == Discoverability::All, - [=](bool) { discoverabilityManager->setVisibility(); }); + discoverabilityManager.data(), SLOT(setVisibility())); addCheckableItem(VIZ_MENU, MenuOption::VisibleToFriends, discoverabilityManager->getDiscoverabilityMode() == Discoverability::Friends, - [=](bool) { discoverabilityManager->setVisibility(); }); - addCheckableItem(VIZ_MENU, MenuOption::VisibleToNoOne, + discoverabilityManager.data(), SLOT(setVisibility())); + addCheckableItem(VIZ_MENU, MenuOption::VisibleToNoOne, discoverabilityManager->getDiscoverabilityMode() == Discoverability::None, - [=](bool) { discoverabilityManager->setVisibility(); }); - + discoverabilityManager.data(), SLOT(setVisibility())); connect(discoverabilityManager.data(), &DiscoverabilityManager::discoverabilityModeChanged, discoverabilityManager.data(), &DiscoverabilityManager::visibilityChanged); - } //Qt::CTRL | Qt::ALT | Qt::Key_T, - addItem(TOOLS_MENU, MenuOption::ToolWindow, [=] { -// dialogsManager->toggleToolWindow(); - }); + addItem(TOOLS_MENU, MenuOption::ToolWindow, + dialogsManager.data(), SLOT(toggleToolWindow())); //Qt::CTRL | Qt::ALT | Qt::Key_J, addItem(TOOLS_MENU, MenuOption::Console, [=] { @@ -297,12 +301,10 @@ void Menu::init() { addCheckableItem(AVATAR_MENU, MenuOption::NamesAboveHeads, true); addCheckableItem(AVATAR_MENU, MenuOption::GlowWhenSpeaking, true); addCheckableItem(AVATAR_MENU, MenuOption::BlueSpeechSphere, true); - addCheckableItem(AVATAR_MENU, MenuOption::EnableCharacterController, true, [=](bool) { - avatar->updateMotionBehavior(); - }); - addCheckableItem(AVATAR_MENU, MenuOption::ShiftHipsForIdleAnimations, false, [=](bool) { - avatar->updateMotionBehavior(); - }); + addCheckableItem(AVATAR_MENU, MenuOption::EnableCharacterController, true, + avatar, SLOT(updateMotionBehavior())); + addCheckableItem(AVATAR_MENU, MenuOption::ShiftHipsForIdleAnimations, false, + avatar, SLOT(updateMotionBehavior())); } { @@ -311,32 +313,28 @@ void Menu::init() { // Mac Qt::CTRL | Qt::META | Qt::Key_F, // Win32/Linux Qt::CTRL | Qt::Key_F, - addCheckableItem(VIEW_MENU, MenuOption::Fullscreen, false, [=](bool checked) { -// qApp->setFullscreen(checked); - }); + addCheckableItem(VIEW_MENU, MenuOption::Fullscreen, false); + connectCheckable(MenuOption::Fullscreen, qApp, SLOT(setFullscreen(bool))); // QML Qt::Key_P, - addCheckableItem(VIEW_MENU, MenuOption::FirstPerson, true, [=](bool checked) { -// qApp->cameraMenuChanged(); - }); + addCheckableItem(VIEW_MENU, MenuOption::FirstPerson, true, + qApp, SLOT(cameraMenuChanged())); //QML Qt::SHIFT | Qt::Key_H, - addCheckableItem(VIEW_MENU, MenuOption::Mirror, true); - + addCheckableItem(VIEW_MENU, MenuOption::Mirror, true, + qApp, SLOT(cameraMenuChanged())); // QML Qt::Key_H, - addCheckableItem(VIEW_MENU, MenuOption::FullscreenMirror, true, [=](bool checked) { -// qApp->cameraMenuChanged(); - }); + addCheckableItem(VIEW_MENU, MenuOption::FullscreenMirror, false, + qApp, SLOT(cameraMenuChanged())); + // Mac Qt::META | Qt::Key_H, // Win32/Linux Qt::CTRL | Qt::Key_H, addCheckableItem(VIEW_MENU, MenuOption::HMDTools, false, [=](bool checked) { dialogsManager->hmdTools(checked); }); - addCheckableItem(VIEW_MENU, MenuOption::EnableVRMode, false, [=](bool checked) { -// qApp->setEnableVRMode(checked); - }); - addCheckableItem(VIEW_MENU, MenuOption::Enable3DTVMode, false, [=](bool checked) { -// qApp->setEnable3DTVMode(checked); - }); + addCheckableItem(VIEW_MENU, MenuOption::EnableVRMode, false); + connectCheckable(MenuOption::EnableVRMode, qApp, SLOT(setEnableVRMode(bool))); + addCheckableItem(VIEW_MENU, MenuOption::Enable3DTVMode, false); + connectCheckable(MenuOption::Enable3DTVMode, qApp, SLOT(setEnable3DTVMode(bool))); { static const QString BORDER_MENU{ "Server Borders" }; @@ -362,7 +360,6 @@ void Menu::init() { dialogsManager->octreeStatsDetails(); }); } - { static const QString DEV_MENU{ "Developer" }; @@ -561,25 +558,19 @@ void Menu::init() { static const QString AUDIO_MENU{ "Audio" }; addMenu(DEV_MENU, AUDIO_MENU); auto audioIO = DependencyManager::get(); - addCheckableItem(AUDIO_MENU, MenuOption::AudioNoiseReduction, true, [=](bool checked) { - audioIO->toggleAudioNoiseReduction(); - }); - addCheckableItem(AUDIO_MENU, MenuOption::EchoServerAudio, false, [=](bool checked) { - audioIO->toggleServerEcho(); - }); - addCheckableItem(AUDIO_MENU, MenuOption::EchoLocalAudio, false, [=](bool checked) { - audioIO->toggleLocalEcho(); - }); - addCheckableItem(AUDIO_MENU, MenuOption::StereoAudio, false, [=](bool checked) { - audioIO->toggleStereoInput(); - }); + addCheckableItem(AUDIO_MENU, MenuOption::AudioNoiseReduction, true, + audioIO.data(), SLOT(toggleAudioNoiseReduction())); + addCheckableItem(AUDIO_MENU, MenuOption::EchoServerAudio, false, + audioIO.data(), SLOT(toggleServerEcho())); + addCheckableItem(AUDIO_MENU, MenuOption::EchoLocalAudio, false, + audioIO.data(), SLOT(toggleLocalEcho())); + addCheckableItem(AUDIO_MENU, MenuOption::StereoAudio, false, + audioIO.data(), SLOT(toggleStereoInput())); // Qt::CTRL | Qt::Key_M, - addCheckableItem(AUDIO_MENU, MenuOption::MuteAudio, false, [=](bool checked) { - audioIO->toggleMute(); - }); - addCheckableItem(AUDIO_MENU, MenuOption::MuteEnvironment, false, [=](bool checked) { - audioIO->sendMuteEnvironmentPacket(); - }); + addCheckableItem(AUDIO_MENU, MenuOption::MuteAudio, false, + audioIO.data(), SLOT(toggleMute())); + addCheckableItem(AUDIO_MENU, MenuOption::MuteEnvironment, false, + audioIO.data(), SLOT(sendMuteEnvironmentPacket())); { static const QString SCOPE_MENU{ "Audio Scope" }; addMenu(AUDIO_MENU, SCOPE_MENU); @@ -637,6 +628,37 @@ void Menu::loadSettings() { void Menu::saveSettings() { // scanMenuBar(&Menu::saveAction); } + +void Menu::addMenuItem(const MenuItemProperties& properties) { + if (QThread::currentThread() != Application::getInstance()->getMainThread()) { + Application::getInstance()->postLambdaEvent([=]{ + addMenuItem(properties); + }); + return; + } + // Shortcut key items: in order of priority + //QString shortcutKey; + //KeyEvent shortcutKeyEvent; + //QKeySequence shortcutKeySequence; // this is what we actually use, it's set from one of the above + + //// location related items: in order of priority + //int position; + //QString beforeItem; + //QString afterItem; + + if (properties.isSeparator) { + addSeparator(properties.menuName, properties.menuItemName); + return; + } + addItem(properties.menuName, properties.menuItemName); + if (properties.isCheckable) { + setCheckable(properties.menuItemName); + if (properties.isChecked) { + setChecked(properties.menuItemName); + } + } + } + #if 0 void Menu::loadAction(Settings& settings, QAction& action) { @@ -688,4 +710,5 @@ void Menu::addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& } } + #endif diff --git a/interface/src/scripting/MenuScriptingInterface.cpp b/interface/src/scripting/MenuScriptingInterface.cpp index 277c611f04..823bb9f8d0 100644 --- a/interface/src/scripting/MenuScriptingInterface.cpp +++ b/interface/src/scripting/MenuScriptingInterface.cpp @@ -28,72 +28,50 @@ void MenuScriptingInterface::menuItemTriggered() { } void MenuScriptingInterface::addMenu(const QString& menu) { - QMetaObject::invokeMethod(Menu::getInstance(), "addMenu", Q_ARG(const QString&, menu)); + Menu::getInstance()->addMenu("", menu); } void MenuScriptingInterface::removeMenu(const QString& menu) { - QMetaObject::invokeMethod(Menu::getInstance(), "removeMenu", Q_ARG(const QString&, menu)); + Menu::getInstance()->removeMenu(menu); } bool MenuScriptingInterface::menuExists(const QString& menu) { - bool result; - QMetaObject::invokeMethod(Menu::getInstance(), "menuExists", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(bool, result), - Q_ARG(const QString&, menu)); - return result; + return Menu::getInstance()->menuExists(menu); } void MenuScriptingInterface::addSeparator(const QString& menuName, const QString& separatorName) { - QMetaObject::invokeMethod(Menu::getInstance(), "addSeparator", - Q_ARG(const QString&, menuName), - Q_ARG(const QString&, separatorName)); + Menu::getInstance()->addSeparator(menuName, separatorName); } void MenuScriptingInterface::removeSeparator(const QString& menuName, const QString& separatorName) { - QMetaObject::invokeMethod(Menu::getInstance(), "removeSeparator", - Q_ARG(const QString&, menuName), - Q_ARG(const QString&, separatorName)); + Menu::getInstance()->removeSeparator(menuName, separatorName); } void MenuScriptingInterface::addMenuItem(const MenuItemProperties& properties) { - QMetaObject::invokeMethod(Menu::getInstance(), "addMenuItem", Q_ARG(const MenuItemProperties&, properties)); + Menu::getInstance()->addMenuItem(properties); } void MenuScriptingInterface::addMenuItem(const QString& menu, const QString& menuitem, const QString& shortcutKey) { - MenuItemProperties properties(menu, menuitem, shortcutKey); - QMetaObject::invokeMethod(Menu::getInstance(), "addMenuItem", Q_ARG(const MenuItemProperties&, properties)); + Menu::getInstance()->addItem(menu, menuitem); + Menu::getInstance()->setItemShortcut(menuitem, shortcutKey); } void MenuScriptingInterface::addMenuItem(const QString& menu, const QString& menuitem) { - MenuItemProperties properties(menu, menuitem); - QMetaObject::invokeMethod(Menu::getInstance(), "addMenuItem", Q_ARG(const MenuItemProperties&, properties)); + Menu::getInstance()->addItem(menu, menuitem); } void MenuScriptingInterface::removeMenuItem(const QString& menu, const QString& menuitem) { - QMetaObject::invokeMethod(Menu::getInstance(), "removeMenuItem", - Q_ARG(const QString&, menu), - Q_ARG(const QString&, menuitem)); + Menu::getInstance()->removeItem(menuitem); }; bool MenuScriptingInterface::menuItemExists(const QString& menu, const QString& menuitem) { - bool result; - QMetaObject::invokeMethod(Menu::getInstance(), "menuItemExists", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(bool, result), - Q_ARG(const QString&, menu), - Q_ARG(const QString&, menuitem)); - return result; + return Menu::getInstance()->itemExists(menu, menuitem); } bool MenuScriptingInterface::isOptionChecked(const QString& menuOption) { - bool result; - QMetaObject::invokeMethod(Menu::getInstance(), "isOptionChecked", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(bool, result), - Q_ARG(const QString&, menuOption)); - return result; + return Menu::getInstance()->isChecked(menuOption); } void MenuScriptingInterface::setIsOptionChecked(const QString& menuOption, bool isChecked) { - QMetaObject::invokeMethod(Menu::getInstance(), "setIsOptionChecked", Qt::BlockingQueuedConnection, - Q_ARG(const QString&, menuOption), - Q_ARG(bool, isChecked)); + Menu::getInstance()->setChecked(menuOption, isChecked); } diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 46ca0c160f..5e747f216d 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -45,13 +45,18 @@ QScriptValue WindowScriptingInterface::hasFocus() { } void WindowScriptingInterface::setFocus() { - auto window = Application::getInstance()->getWindow(); - window->activateWindow(); - window->setFocus(); + Application::getInstance()->postLambdaEvent([] { + auto window = Application::getInstance()->getWindow(); + window->activateWindow(); + window->setFocus(); + }); } void WindowScriptingInterface::raiseMainWindow() { -// Application::getInstance()->getWindow()->raise(); + // It's forbidden to call raise() from another thread. + Application::getInstance()->postLambdaEvent([] { + Application::getInstance()->getWindow()->raise(); + }); } void WindowScriptingInterface::setCursorVisible(bool visible) { diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 2a8f01aafc..7940a06993 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -323,7 +323,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { //Render magnifier, but dont show border for mouse magnifier glm::vec2 projection = screenToOverlay(glm::vec2(_reticlePosition[MOUSE].x(), _reticlePosition[MOUSE].y())); - with_each_texture(_overlays.getTexture(), _newUiTexture, [&] { + with_each_texture(_overlays.getTexture(), 0, [&] { renderMagnifier(projection, _magSizeMult[i], i != MOUSE); }); } diff --git a/libraries/shared/src/PathUtils.cpp b/libraries/shared/src/PathUtils.cpp index bf846c0bf2..47e5659c60 100644 --- a/libraries/shared/src/PathUtils.cpp +++ b/libraries/shared/src/PathUtils.cpp @@ -14,16 +14,26 @@ #include #include #include - +#include #include "PathUtils.h" QString& PathUtils::resourcesPath() { +#ifdef DEBUG + static QString staticResourcePath; + if (staticResourcePath.isEmpty()) { + QDir path(__FILE__); + path.cdUp(); + staticResourcePath = path.cleanPath(path.absoluteFilePath("../../../interface/resources/")) + "/"; + } +#else #ifdef Q_OS_MAC static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/../Resources/"; #else static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/resources/"; #endif +#endif + return staticResourcePath; } diff --git a/libraries/ui/src/HifiMenu.cpp b/libraries/ui/src/HifiMenu.cpp index 0c488e05a3..27517f99d7 100644 --- a/libraries/ui/src/HifiMenu.cpp +++ b/libraries/ui/src/HifiMenu.cpp @@ -45,7 +45,7 @@ void HifiMenu::setTriggerAction(const QString & name, std::function f) { QObject* addMenu(QObject* parent, const QString & text) { // FIXME add more checking here to ensure no name conflicts QVariant returnedValue; - QMetaObject::invokeMethod(parent, "addMenu", + QMetaObject::invokeMethod(parent, "addMenu", Qt::DirectConnection, Q_RETURN_ARG(QVariant, returnedValue), Q_ARG(QVariant, text)); QObject* result = returnedValue.value(); @@ -59,7 +59,7 @@ class QQuickMenuItem; QObject* addItem(QObject* parent, const QString& text) { // FIXME add more checking here to ensure no name conflicts QQuickMenuItem* returnedValue{ nullptr }; - bool invokeResult = QMetaObject::invokeMethod(parent, "addItem", + bool invokeResult = QMetaObject::invokeMethod(parent, "addItem", Qt::DirectConnection, Q_RETURN_ARG(QQuickMenuItem*, returnedValue), Q_ARG(QString, text)); Q_ASSERT(invokeResult); @@ -104,9 +104,11 @@ bool HifiMenu::menuExists(const QString& menuName) const { } void HifiMenu::addSeparator(const QString& parentMenu, const QString& separatorName) { - // FIXME 'add sep' -// addMenu(parentMenu, separatorName); -// setEnabled() + QObject * parent = findMenuObject(parentMenu); + bool invokeResult = QMetaObject::invokeMethod(parent, "addSeparator", Qt::DirectConnection); + Q_ASSERT(invokeResult); + addItem(parentMenu, separatorName); + enableItem(separatorName, false); } void HifiMenu::removeSeparator(const QString& parentMenu, const QString& separatorName) { @@ -132,6 +134,11 @@ void HifiMenu::addItem(const QString & parentMenu, const QString & menuOption, s addItem(parentMenu, menuOption); } +void HifiMenu::addItem(const QString & parentMenu, const QString & menuOption, QObject* receiver, const char* slot) { + addItem(parentMenu, menuOption); + connectItem(menuOption, receiver, slot); +} + void HifiMenu::removeItem(const QString& menuOption) { removeMenu(menuOption); } @@ -170,8 +177,10 @@ void HifiMenu::setChecked(const QString& menuOption, bool isChecked) { warn(menuOption); return; } - menuItem->setProperty("checked", QVariant::fromValue(isChecked)); - Q_ASSERT(menuItem->property("checked").toBool() == isChecked); + if (menuItem->property("checked").toBool() != isChecked) { + menuItem->setProperty("checked", QVariant::fromValue(isChecked)); + Q_ASSERT(menuItem->property("checked").toBool() == isChecked); + } } void HifiMenu::setCheckable(const QString& menuOption, bool checkable) { @@ -185,7 +194,7 @@ void HifiMenu::setCheckable(const QString& menuOption, bool checkable) { Q_ASSERT(menuItem->property("checkable").toBool() == checkable); } -void HifiMenu::setItemText(const QString& menuOption, const QString & text) { +void HifiMenu::setItemText(const QString& menuOption, const QString& text) { QObject* menuItem = findMenuObject(menuOption); if (!menuItem) { warn(menuOption); @@ -253,3 +262,18 @@ QString HifiMenu::getItemShortcut(const QString& menuOption) { } return QString(); } + +void HifiMenu::addCheckableItem(const QString& parentMenu, const QString& menuOption, bool checked, QObject* receiver, const char* slot) { + addCheckableItem(parentMenu, menuOption, checked); + connectItem(menuOption, receiver, slot); +} + +void HifiMenu::connectCheckable(const QString& menuOption, QObject* receiver, const char* slot) { + QObject* result = findMenuObject(menuOption); + connect(result, SIGNAL(toggled(bool)), receiver, slot); +} + +void HifiMenu::connectItem(const QString& menuOption, QObject* receiver, const char* slot) { + QObject* result = findMenuObject(menuOption); + connect(result, SIGNAL(triggered()), receiver, slot); +} diff --git a/libraries/ui/src/HifiMenu.h b/libraries/ui/src/HifiMenu.h index 299a927bc9..c89c91b028 100644 --- a/libraries/ui/src/HifiMenu.h +++ b/libraries/ui/src/HifiMenu.h @@ -37,9 +37,13 @@ public: void addItem(const QString& parentMenu, const QString& menuOption); void addItem(const QString& parentMenu, const QString& menuOption, std::function f); + void addItem(const QString& parentMenu, const QString& menuOption, QObject* receiver, const char* slot); void addCheckableItem(const QString& parentMenu, const QString& menuOption, bool checked = false); void addCheckableItem(const QString& parentMenu, const QString& menuOption, bool checked, std::function f); + void addCheckableItem(const QString& parentMenu, const QString& menuOption, bool checked, QObject* receiver, const char* slot); + void connectCheckable(const QString& menuOption, QObject* receiver, const char* slot); + void connectItem(const QString& menuOption, QObject* receiver, const char* slot); void removeItem(const QString& menuitem); bool itemExists(const QString& menuName, const QString& menuitem) const; @@ -48,15 +52,15 @@ public: bool isChecked(const QString& menuOption) const; void setChecked(const QString& menuOption, bool checked = true); void setCheckable(const QString& menuOption, bool checkable = true); - void setExclusiveGroup(const QString& menuOption, const QString & groupName); + void setExclusiveGroup(const QString& menuOption, const QString& groupName); void setItemText(const QString& menuOption, const QString& text); void setItemVisible(const QString& menuOption, bool visible = true); bool isItemVisible(const QString& menuOption); - void setItemShortcut(const QString& menuOption, const QString & shortcut); + void setItemShortcut(const QString& menuOption, const QString& shortcut); QString getItemShortcut(const QString& menuOption); - void setRootMenu(QObject * rootMenu); + void setRootMenu(QObject* rootMenu); private slots: void onTriggeredByName(const QString& name); diff --git a/tests/ui/main.qml b/tests/ui/main.qml index 89dac3d1af..168b9fb291 100644 --- a/tests/ui/main.qml +++ b/tests/ui/main.qml @@ -47,7 +47,7 @@ import "qml" //import "/Users/bdavis/Git/hifi/interface/resources/qml" Item { - anchors.fill: parent + anchors.fill: parent visible: true //title: "Qt Quick Controls Gallery"