mirror of
https://github.com/lubosz/overte.git
synced 2025-04-14 16:06:13 +02:00
Switching to a wrapper mechanism for VR menus
This commit is contained in:
parent
ee30588fd4
commit
a96f69a673
30 changed files with 1335 additions and 1045 deletions
|
@ -48,7 +48,7 @@ Dialog {
|
|||
helperText: "domain, location, @user, /x,y,z"
|
||||
anchors.margins: 8
|
||||
onAccepted: {
|
||||
event.accepted
|
||||
event.accepted
|
||||
addressBarDialog.loadAddress(addressLine.text)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import QtQuick 2.4
|
|||
import QtQuick.Controls 1.3
|
||||
import Hifi 1.0
|
||||
|
||||
// Currently for testing a pure QML replacement menu
|
||||
Item {
|
||||
Item {
|
||||
objectName: "AllActions"
|
||||
|
@ -10,7 +11,7 @@ Item {
|
|||
objectName: "HifiAction_" + MenuConstants.AboutApp
|
||||
text: qsTr("About Interface")
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// File Menu
|
||||
//
|
||||
|
@ -26,7 +27,7 @@ Item {
|
|||
//shortcut: StandardKey.Quit
|
||||
shortcut: "Ctrl+Q"
|
||||
}
|
||||
|
||||
|
||||
// Scripts
|
||||
Action {
|
||||
id: loadScript
|
||||
|
@ -58,7 +59,7 @@ Item {
|
|||
objectName: "HifiAction_" + MenuConstants.StopAllScripts
|
||||
text: qsTr("Stop All Scripts")
|
||||
}
|
||||
|
||||
|
||||
// Locations
|
||||
Action {
|
||||
id: bookmarkLocation
|
||||
|
@ -75,7 +76,7 @@ Item {
|
|||
objectName: "HifiAction_" + MenuConstants.AddressBar
|
||||
text: qsTr("Show Address Bar")
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Edit menu
|
||||
//
|
||||
|
@ -84,13 +85,13 @@ Item {
|
|||
text: "Undo"
|
||||
shortcut: StandardKey.Undo
|
||||
}
|
||||
|
||||
|
||||
Action {
|
||||
id: redo
|
||||
text: "Redo"
|
||||
shortcut: StandardKey.Redo
|
||||
}
|
||||
|
||||
|
||||
Action {
|
||||
id: animations
|
||||
objectName: "HifiAction_" + MenuConstants.Animations
|
||||
|
@ -157,7 +158,7 @@ Item {
|
|||
objectName: "HifiAction_" + MenuConstants.ResetSensors
|
||||
text: qsTr("Reset Sensors")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -853,7 +854,7 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
MenuBar {
|
||||
Menu {
|
||||
objectName: "rootMenu";
|
||||
Menu {
|
||||
title: "File"
|
|
@ -1,20 +0,0 @@
|
|||
import QtQuick 2.4
|
||||
import QtQuick.Controls 1.3
|
||||
|
||||
ApplicationWindow {
|
||||
id: root
|
||||
width: 800
|
||||
height: 600
|
||||
visible: true
|
||||
|
||||
menuBar: MenuBar {
|
||||
Menu {
|
||||
title: "File"
|
||||
MenuItem {
|
||||
text: "Quit"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ Dialog {
|
|||
property real spacing: 8
|
||||
property real outerSpacing: 16
|
||||
|
||||
|
||||
destroyOnCloseButton: true
|
||||
destroyOnInvisible: true
|
||||
implicitHeight: content.implicitHeight + outerSpacing * 2 + 48
|
||||
|
@ -35,7 +36,7 @@ Dialog {
|
|||
|
||||
onEnabledChanged: {
|
||||
if (enabled) {
|
||||
root.forceActiveFocus();
|
||||
root.forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,7 +335,7 @@ Dialog {
|
|||
case Qt.Key_Period:
|
||||
if (Qt.platform.os === "osx") {
|
||||
event.accepted = true
|
||||
content.reject()
|
||||
content.reject()
|
||||
}
|
||||
break
|
||||
} else switch (event.key) {
|
||||
|
@ -346,7 +347,7 @@ Dialog {
|
|||
|
||||
case Qt.Key_Enter:
|
||||
case Qt.Key_Return:
|
||||
console.log("Accepting");
|
||||
console.log("Accepting");
|
||||
event.accepted = true
|
||||
content.accept()
|
||||
break
|
||||
|
|
|
@ -8,7 +8,7 @@ Root {
|
|||
anchors.fill: parent
|
||||
|
||||
onParentChanged: {
|
||||
forceActiveFocus();
|
||||
forceActiveFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,12 +6,11 @@ import QtQuick.Controls 1.3
|
|||
import "controls"
|
||||
|
||||
Root {
|
||||
id: root
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
onParentChanged: {
|
||||
forceActiveFocus();
|
||||
forceActiveFocus();
|
||||
}
|
||||
|
||||
Button {
|
||||
id: messageBox
|
||||
anchors.right: createDialog.left
|
||||
|
@ -38,7 +37,7 @@ Root {
|
|||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
console.log(event.key);
|
||||
console.log("Key press root")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@ import QtQuick.Controls.Styles 1.3
|
|||
import "controls"
|
||||
import "styles"
|
||||
|
||||
Hifi.HifiMenu {
|
||||
Hifi.VrMenu {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
objectName: "HifiMenu"
|
||||
objectName: "VrMenu"
|
||||
enabled: false
|
||||
opacity: 0.0
|
||||
property int animationDuration: 200
|
||||
|
@ -17,7 +17,7 @@ Hifi.HifiMenu {
|
|||
|
||||
onEnabledChanged: {
|
||||
if (enabled && columns.length == 0) {
|
||||
pushColumn(rootMenu.menus);
|
||||
pushColumn(rootMenu.items);
|
||||
}
|
||||
opacity = enabled ? 1.0 : 0.0
|
||||
if (enabled) {
|
||||
|
@ -47,13 +47,21 @@ Hifi.HifiMenu {
|
|||
|
||||
property var menuBuilder: Component {
|
||||
Border {
|
||||
Component.onCompleted: {
|
||||
menuDepth = root.models.length - 1
|
||||
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;
|
||||
}
|
||||
}
|
||||
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
|
||||
property int menuDepth
|
||||
|
||||
ListView {
|
||||
spacing: 6
|
||||
|
@ -186,7 +194,25 @@ Hifi.HifiMenu {
|
|||
anchors.top: parent.top
|
||||
anchors.topMargin: 0
|
||||
width: listView.width
|
||||
hoverEnabled: true
|
||||
Timer {
|
||||
id: timer
|
||||
interval: 1000
|
||||
onTriggered: parent.select();
|
||||
}
|
||||
onEntered: {
|
||||
if (source.type == 2 && enabled) {
|
||||
timer.start()
|
||||
}
|
||||
}
|
||||
onExited: {
|
||||
timer.stop()
|
||||
}
|
||||
onClicked: {
|
||||
select();
|
||||
}
|
||||
function select() {
|
||||
timer.stop();
|
||||
listView.currentIndex = listViewIndex
|
||||
parent.root.selectItem(parent.source);
|
||||
}
|
|
@ -17,7 +17,7 @@ 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
|
||||
y: parent ? parent.height / 2 - height / 2 : 0
|
||||
|
||||
property int animationDuration: 400
|
||||
property bool destroyOnInvisible: false
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 253 B |
Binary file not shown.
Before Width: | Height: | Size: 254 B |
Binary file not shown.
Before Width: | Height: | Size: 257 B |
Binary file not shown.
Before Width: | Height: | Size: 224 B |
|
@ -52,8 +52,6 @@
|
|||
#include <QMimeData>
|
||||
#include <QMessageBox>
|
||||
#include <QJsonDocument>
|
||||
#include <QQmlNetworkAccessManagerFactory>
|
||||
#include <QThreadStorage>
|
||||
|
||||
#include <AddressManager.h>
|
||||
#include <AccountManager.h>
|
||||
|
@ -65,6 +63,7 @@
|
|||
#include <GlowEffect.h>
|
||||
#include <HFActionEvent.h>
|
||||
#include <HFBackEvent.h>
|
||||
#include <HifiMenu.h>
|
||||
#include <LogHandler.h>
|
||||
#include <MainWindow.h>
|
||||
#include <ModelEntityItem.h>
|
||||
|
@ -135,7 +134,6 @@
|
|||
#include "ui/DialogsManager.h"
|
||||
#include "ui/InfoView.h"
|
||||
#include "ui/LoginDialog.h"
|
||||
#include "ui/MarketplaceDialog.h"
|
||||
#include "ui/Snapshot.h"
|
||||
#include "ui/StandAloneJSConsole.h"
|
||||
#include "ui/Stats.h"
|
||||
|
@ -510,6 +508,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
// enable mouse tracking; otherwise, we only get drag events
|
||||
_glWidget->setMouseTracking(true);
|
||||
|
||||
_fullscreenMenuWidget->setParent(_glWidget);
|
||||
_menuBarHeight = Menu::getInstance()->height();
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) {
|
||||
setFullscreen(true); // Initialize menu bar show/hide
|
||||
}
|
||||
|
@ -730,6 +730,10 @@ void Application::initializeGL() {
|
|||
qCDebug(interfaceapp, "Initialized Offscreen UI.");
|
||||
_glWidget->makeCurrent();
|
||||
|
||||
// call Menu getInstance static method to set up the menu
|
||||
// Needs to happen AFTER the QML UI initialization
|
||||
_window->setMenuBar(Menu::getInstance());
|
||||
|
||||
init();
|
||||
qCDebug(interfaceapp, "init() complete.");
|
||||
|
||||
|
@ -764,9 +768,7 @@ void Application::initializeGL() {
|
|||
void Application::initializeUi() {
|
||||
AddressBarDialog::registerType();
|
||||
LoginDialog::registerType();
|
||||
MarketplaceDialog::registerType();
|
||||
MessageDialog::registerType();
|
||||
Menu::registerType();
|
||||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
offscreenUi->create(_glWidget->context()->contextHandle());
|
||||
|
@ -902,7 +904,9 @@ void Application::runTests() {
|
|||
}
|
||||
|
||||
void Application::audioMuteToggled() {
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::MuteAudio, DependencyManager::get<AudioClient>()->isMuted());
|
||||
QAction* muteAction = Menu::getInstance()->getActionForOption(MenuOption::MuteAudio);
|
||||
Q_CHECK_PTR(muteAction);
|
||||
muteAction->setChecked(DependencyManager::get<AudioClient>()->isMuted());
|
||||
}
|
||||
|
||||
void Application::aboutApp() {
|
||||
|
@ -1067,12 +1071,10 @@ bool Application::eventFilter(QObject* object, QEvent* event) {
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool altPressed;
|
||||
static bool ctrlPressed;
|
||||
static bool _altPressed{ false };
|
||||
|
||||
void Application::keyPressEvent(QKeyEvent* event) {
|
||||
altPressed = event->key() == Qt::Key_Alt;
|
||||
ctrlPressed = event->key() == Qt::Key_Control;
|
||||
_altPressed = event->key() == Qt::Key_Alt;
|
||||
_keysPressed.insert(event->key());
|
||||
|
||||
_controllerScriptingInterface.emitKeyPressEvent(event); // send events to any registered scripts
|
||||
|
@ -1162,9 +1164,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
break;
|
||||
|
||||
case Qt::Key_Backslash:
|
||||
MarketplaceDialog::show();
|
||||
|
||||
//Menu::getInstance()->triggerOption(MenuOption::Chat);
|
||||
Menu::getInstance()->triggerOption(MenuOption::Chat);
|
||||
break;
|
||||
|
||||
case Qt::Key_Up:
|
||||
|
@ -1329,13 +1329,15 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
}
|
||||
|
||||
void Application::keyReleaseEvent(QKeyEvent* event) {
|
||||
if (event->key() == Qt::Key_Alt && altPressed && _window->isActiveWindow()) {
|
||||
Menu::toggle();
|
||||
if (event->key() == Qt::Key_Alt && _altPressed && _window->isActiveWindow()) {
|
||||
#ifndef DEBUG
|
||||
if (OculusManager::isConnected()) {
|
||||
#endif
|
||||
VrMenu::toggle();
|
||||
#ifndef DEBUG
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (event->key() == Qt::Key_Control && ctrlPressed && _window->isActiveWindow()) {
|
||||
Menu::toggle();
|
||||
}
|
||||
ctrlPressed = altPressed = false;
|
||||
|
||||
_keysPressed.remove(event->key());
|
||||
|
||||
|
@ -1346,6 +1348,7 @@ void Application::keyReleaseEvent(QKeyEvent* event) {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
switch (event->key()) {
|
||||
case Qt::Key_E:
|
||||
case Qt::Key_PageUp:
|
||||
|
@ -1442,6 +1445,18 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)
|
||||
&& !Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) {
|
||||
// Show/hide menu bar in fullscreen
|
||||
if (event->globalY() > _menuBarHeight) {
|
||||
_fullscreenMenuWidget->setFixedHeight(0);
|
||||
Menu::getInstance()->setFixedHeight(0);
|
||||
} else {
|
||||
_fullscreenMenuWidget->setFixedHeight(_menuBarHeight);
|
||||
Menu::getInstance()->setFixedHeight(_menuBarHeight);
|
||||
}
|
||||
}
|
||||
|
||||
_entities.mouseMoveEvent(event, deviceID);
|
||||
|
||||
_controllerScriptingInterface.emitMouseMoveEvent(event, deviceID); // send events to any registered scripts
|
||||
|
@ -1449,6 +1464,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
|
|||
if (_controllerScriptingInterface.isMouseCaptured()) {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
|
||||
|
@ -1735,6 +1751,34 @@ void Application::setFullscreen(bool fullscreen) {
|
|||
Menu::getInstance()->getActionForOption(MenuOption::Fullscreen)->setChecked(fullscreen);
|
||||
}
|
||||
|
||||
// The following code block is useful on platforms that can have a visible
|
||||
// app menu in a fullscreen window. However the OSX mechanism hides the
|
||||
// application menu for fullscreen apps, so the check is not required.
|
||||
#ifndef Q_OS_MAC
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) {
|
||||
if (fullscreen) {
|
||||
// Menu hide() disables menu commands, and show() after hide() doesn't work with Rift VR display.
|
||||
// So set height instead.
|
||||
_window->menuBar()->setMaximumHeight(0);
|
||||
} else {
|
||||
_window->menuBar()->setMaximumHeight(QWIDGETSIZE_MAX);
|
||||
}
|
||||
} else {
|
||||
if (fullscreen) {
|
||||
// Move menu to a QWidget floating above _glWidget so that show/hide doesn't adjust viewport.
|
||||
_menuBarHeight = Menu::getInstance()->height();
|
||||
Menu::getInstance()->setParent(_fullscreenMenuWidget);
|
||||
Menu::getInstance()->setFixedWidth(_window->windowHandle()->screen()->size().width());
|
||||
_fullscreenMenuWidget->show();
|
||||
} else {
|
||||
// Restore menu to being part of MainWindow.
|
||||
_fullscreenMenuWidget->hide();
|
||||
_window->setMenuBar(Menu::getInstance());
|
||||
_window->menuBar()->setMaximumHeight(QWIDGETSIZE_MAX);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Work around Qt bug that prevents floating menus being shown when in fullscreen mode.
|
||||
// https://bugreports.qt.io/browse/QTBUG-41883
|
||||
// Known issue: Top-level menu items don't highlight when cursor hovers. This is probably a side-effect of the work-around.
|
||||
|
@ -1987,18 +2031,16 @@ void Application::init() {
|
|||
|
||||
OculusManager::connect();
|
||||
if (OculusManager::isConnected()) {
|
||||
// perform as a post-event so that the code is run after init is complete
|
||||
qApp->postLambdaEvent([] {
|
||||
Menu::getInstance()->triggerOption(MenuOption::Fullscreen);
|
||||
});
|
||||
QMetaObject::invokeMethod(Menu::getInstance()->getActionForOption(MenuOption::Fullscreen),
|
||||
"trigger",
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
TV3DManager::connect();
|
||||
if (TV3DManager::isConnected()) {
|
||||
// perform as a post-event so that the code is run after init is complete
|
||||
qApp->postLambdaEvent([] {
|
||||
Menu::getInstance()->triggerOption(MenuOption::Fullscreen);
|
||||
});
|
||||
QMetaObject::invokeMethod(Menu::getInstance()->getActionForOption(MenuOption::Fullscreen),
|
||||
"trigger",
|
||||
Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
_timerStart.start();
|
||||
|
|
|
@ -623,6 +623,9 @@ private:
|
|||
|
||||
void checkSkeleton();
|
||||
|
||||
QWidget* _fullscreenMenuWidget = new QWidget();
|
||||
int _menuBarHeight;
|
||||
|
||||
QHash<QString, AcceptURLMethod> _acceptedExtensions;
|
||||
|
||||
QList<QString> _domainConnectionRefusals;
|
||||
|
|
|
@ -84,16 +84,13 @@ void Bookmarks::persistToFile() {
|
|||
saveFile.write(data);
|
||||
}
|
||||
|
||||
void Bookmarks::setupMenus(const QString & parentMenu) {
|
||||
void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
|
||||
// Add menus/actions
|
||||
Menu * menu = Menu::getInstance();
|
||||
menu->addItem(parentMenu, MenuOption::BookmarkLocation, [this] {
|
||||
bookmarkLocation();
|
||||
});
|
||||
menu->addMenu(parentMenu, MenuOption::Bookmarks);
|
||||
menu->addItem(parentMenu, MenuOption::DeleteBookmark, [this] {
|
||||
deleteBookmark();
|
||||
});
|
||||
menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkLocation, 0,
|
||||
this, SLOT(bookmarkLocation()));
|
||||
_bookmarksMenu = menu->addMenu(MenuOption::Bookmarks);
|
||||
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark, 0,
|
||||
this, SLOT(deleteBookmark()));
|
||||
|
||||
// Enable/Disable menus as needed
|
||||
enableMenuItems(_bookmarks.count() > 0);
|
||||
|
@ -102,7 +99,7 @@ void Bookmarks::setupMenus(const QString & parentMenu) {
|
|||
for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it ) {
|
||||
QString bookmarkName = it.key();
|
||||
QString bookmarkAddress = it.value().toString();
|
||||
addLocationToMenu(bookmarkName, bookmarkAddress);
|
||||
addLocationToMenu(menubar, bookmarkName, bookmarkAddress);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,20 +134,29 @@ void Bookmarks::bookmarkLocation() {
|
|||
if (duplicateBookmarkMessage.exec() == QMessageBox::No) {
|
||||
return;
|
||||
}
|
||||
removeLocationFromMenu(bookmarkName);
|
||||
removeLocationFromMenu(menubar, bookmarkName);
|
||||
}
|
||||
|
||||
addLocationToMenu(bookmarkName, bookmarkAddress);
|
||||
addLocationToMenu(menubar, bookmarkName, bookmarkAddress);
|
||||
insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName.
|
||||
|
||||
enableMenuItems(true);
|
||||
}
|
||||
|
||||
void Bookmarks::teleportToBookmark() {
|
||||
QAction* action = qobject_cast<QAction*>(sender());
|
||||
QString address = action->data().toString();
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(address);
|
||||
}
|
||||
|
||||
void Bookmarks::deleteBookmark() {
|
||||
|
||||
QStringList bookmarkList;
|
||||
bookmarkList.append(_bookmarks.keys());
|
||||
|
||||
|
||||
QList<QAction*> menuItems = _bookmarksMenu->actions();
|
||||
for (int i = 0; i < menuItems.count(); i += 1) {
|
||||
bookmarkList.append(menuItems[i]->text());
|
||||
}
|
||||
|
||||
QInputDialog deleteBookmarkDialog(qApp->getWindow());
|
||||
deleteBookmarkDialog.setWindowTitle("Delete Bookmark");
|
||||
deleteBookmarkDialog.setLabelText("Select the bookmark to delete");
|
||||
|
@ -168,29 +174,34 @@ void Bookmarks::deleteBookmark() {
|
|||
return;
|
||||
}
|
||||
|
||||
removeLocationFromMenu(bookmarkName);
|
||||
removeLocationFromMenu(Menu::getInstance(), bookmarkName);
|
||||
remove(bookmarkName);
|
||||
|
||||
if (_bookmarks.keys().isEmpty()) {
|
||||
|
||||
if (_bookmarksMenu->actions().count() == 0) {
|
||||
enableMenuItems(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Bookmarks::enableMenuItems(bool enabled) {
|
||||
Menu* menu = Menu::getInstance();
|
||||
menu->enableItem(MenuOption::Bookmarks, enabled);
|
||||
menu->enableItem(MenuOption::DeleteBookmark, enabled);
|
||||
if (_bookmarksMenu) {
|
||||
_bookmarksMenu->setEnabled(enabled);
|
||||
}
|
||||
if (_deleteBookmarksAction) {
|
||||
_deleteBookmarksAction->setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void Bookmarks::addLocationToMenu(QString& name, QString& address) {
|
||||
|
||||
Menu::getInstance()->addItem(MenuOption::Bookmarks, name, [=] {
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(address);
|
||||
});
|
||||
void Bookmarks::addLocationToMenu(Menu* menubar, QString& name, QString& address) {
|
||||
QAction* teleportAction = _bookmarksMenu->newAction();
|
||||
teleportAction->setData(address);
|
||||
connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark()));
|
||||
|
||||
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction,
|
||||
name, 0, QAction::NoRole);
|
||||
}
|
||||
|
||||
void Bookmarks::removeLocationFromMenu(QString& name) {
|
||||
Menu::getInstance()->removeItem(name);
|
||||
void Bookmarks::removeLocationFromMenu(Menu* menubar, QString& name) {
|
||||
menubar->removeAction(_bookmarksMenu, name);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
class QAction;
|
||||
class QMenu;
|
||||
class Menu;
|
||||
class MenuWrapper;
|
||||
|
||||
class Bookmarks: public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -26,16 +27,19 @@ class Bookmarks: public QObject {
|
|||
public:
|
||||
Bookmarks();
|
||||
|
||||
void setupMenus(const QString & menu);
|
||||
void setupMenus(Menu* menubar, MenuWrapper* menu);
|
||||
|
||||
private slots:
|
||||
void bookmarkLocation();
|
||||
void teleportToBookmark();
|
||||
void deleteBookmark();
|
||||
|
||||
private:
|
||||
// FIXME bookmarks should be more categorizable
|
||||
// Can we leverage a system browser favorites API?
|
||||
QVariantMap _bookmarks; // { name: address, ... }
|
||||
|
||||
QPointer<MenuWrapper> _bookmarksMenu;
|
||||
QPointer<QAction> _deleteBookmarksAction;
|
||||
|
||||
const QString BOOKMARKS_FILENAME = "bookmarks.json";
|
||||
QString _bookmarksFilename;
|
||||
|
||||
|
@ -47,8 +51,8 @@ private:
|
|||
void persistToFile();
|
||||
|
||||
void enableMenuItems(bool enabled);
|
||||
void addLocationToMenu(QString& name, QString& address);
|
||||
void removeLocationFromMenu(QString& name);
|
||||
void addLocationToMenu(Menu* menubar, QString& name, QString& address);
|
||||
void removeLocationFromMenu(Menu* menubar, QString& name);
|
||||
};
|
||||
|
||||
#endif // hifi_Bookmarks_h
|
|
@ -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);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,77 +18,114 @@
|
|||
#include <QKeySequence>
|
||||
#include <QPointer>
|
||||
#include <QStandardPaths>
|
||||
#include <QQuickItem>
|
||||
|
||||
#include <MenuItemProperties.h>
|
||||
|
||||
#include <OffscreenUi.h>
|
||||
|
||||
#include "DiscoverabilityManager.h"
|
||||
#include <HifiMenu.h>
|
||||
|
||||
class Settings;
|
||||
|
||||
// Proxy object to simplify porting over
|
||||
class HifiAction {
|
||||
const QString _menuOption;
|
||||
class MenuWrapper : public QObject {
|
||||
public:
|
||||
HifiAction(const QString & menuOption);
|
||||
void setCheckable(bool);
|
||||
void setChecked(bool);
|
||||
void setVisible(bool);
|
||||
QString shortcut() const;
|
||||
void setText(const QString &);
|
||||
void setTriggerAction(std::function<void()>);
|
||||
void setToggleAction(std::function<void(bool)>);
|
||||
QList<QAction*> actions();
|
||||
MenuWrapper* addMenu(const QString& menuName);
|
||||
void setEnabled(bool enabled = true);
|
||||
void addSeparator();
|
||||
void addAction(QAction* action);
|
||||
|
||||
QAction* addAction(const QString& menuName);
|
||||
void insertAction(QAction* before, QAction* menuName);
|
||||
|
||||
QAction* addAction(const QString& menuName, const QObject* receiver, const char* member, const QKeySequence& shortcut = 0);
|
||||
void removeAction(QAction* action);
|
||||
|
||||
QAction* newAction() {
|
||||
return new QAction(_realMenu);
|
||||
}
|
||||
private:
|
||||
MenuWrapper(QMenu* menu);
|
||||
|
||||
static MenuWrapper* fromMenu(QMenu* menu) {
|
||||
return _backMap[menu];
|
||||
}
|
||||
|
||||
QMenu* const _realMenu;
|
||||
static QHash<QMenu*, MenuWrapper*> _backMap;
|
||||
friend class Menu;
|
||||
};
|
||||
|
||||
class Menu : public HifiMenu {
|
||||
class Menu : public QMenuBar {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Menu(QQuickItem * parent = 0);
|
||||
static Menu* getInstance();
|
||||
|
||||
// Override the base type HifiMenu with this class instead
|
||||
static void registerType() {
|
||||
qmlRegisterType<Menu>("Hifi", 1, 0, NAME.toLocal8Bit().constData());
|
||||
}
|
||||
|
||||
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
|
||||
MenuWrapper* getMenu(const QString& menuName);
|
||||
|
||||
HifiAction * getActionForOption(const QString& menuOption) {
|
||||
return new HifiAction(menuOption);
|
||||
}
|
||||
|
||||
void triggerOption(const QString& menuOption);
|
||||
QAction* getActionForOption(const QString& menuOption);
|
||||
|
||||
QAction* addActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
|
||||
const QString& actionName,
|
||||
const QKeySequence& shortcut = 0,
|
||||
const QObject* receiver = NULL,
|
||||
const char* member = NULL,
|
||||
QAction::MenuRole role = QAction::NoRole,
|
||||
int menuItemLocation = UNSPECIFIED_POSITION);
|
||||
QAction* addActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
|
||||
QAction* action,
|
||||
const QString& actionName = QString(),
|
||||
const QKeySequence& shortcut = 0,
|
||||
QAction::MenuRole role = QAction::NoRole,
|
||||
int menuItemLocation = UNSPECIFIED_POSITION);
|
||||
|
||||
void removeAction(MenuWrapper* menu, const QString& actionName);
|
||||
|
||||
public slots:
|
||||
MenuWrapper* addMenu(const QString& menuName);
|
||||
void removeMenu(const QString& menuName);
|
||||
bool menuExists(const QString& menuName);
|
||||
void addSeparator(const QString& menuName, const QString& separatorName);
|
||||
void removeSeparator(const QString& menuName, const QString& separatorName);
|
||||
void addMenuItem(const MenuItemProperties& properties);
|
||||
|
||||
bool isOptionChecked(const QString& menuOption) const {
|
||||
return HifiMenu::isChecked(menuOption);
|
||||
}
|
||||
|
||||
void setIsOptionChecked(const QString& menuOption, bool isChecked) {
|
||||
HifiMenu::setChecked(menuOption, isChecked);
|
||||
}
|
||||
|
||||
void triggerOption(const QString& menuOption) {
|
||||
HifiMenu::triggerItem(menuOption);
|
||||
}
|
||||
|
||||
void setOptionText(const QString& menuOption, const QString & text) {
|
||||
HifiMenu::setItemText(menuOption, text);
|
||||
}
|
||||
|
||||
void setOptionTriggerAction(const QString& menuOption, std::function<void()> f) {
|
||||
HifiMenu::setTriggerAction(menuOption, f);
|
||||
}
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
void removeMenuItem(const QString& menuName, const QString& menuitem);
|
||||
bool menuItemExists(const QString& menuName, const QString& menuitem);
|
||||
bool isOptionChecked(const QString& menuOption) const;
|
||||
void setIsOptionChecked(const QString& menuOption, bool isChecked);
|
||||
|
||||
private:
|
||||
static Menu* _instance;
|
||||
friend class HifiAction;
|
||||
Menu();
|
||||
|
||||
typedef void(*settingsAction)(Settings&, QAction&);
|
||||
static void loadAction(Settings& settings, QAction& action);
|
||||
static void saveAction(Settings& settings, QAction& action);
|
||||
void scanMenuBar(settingsAction modifySetting);
|
||||
void scanMenu(QMenu& menu, settingsAction modifySetting, Settings& settings);
|
||||
|
||||
/// helper method to have separators with labels that are also compatible with OS X
|
||||
void addDisabledActionAndSeparator(MenuWrapper* destinationMenu, const QString& actionName,
|
||||
int menuItemLocation = UNSPECIFIED_POSITION);
|
||||
|
||||
QAction* addCheckableActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
|
||||
const QString& actionName,
|
||||
const QKeySequence& shortcut = 0,
|
||||
const bool checked = false,
|
||||
const QObject* receiver = NULL,
|
||||
const char* member = NULL,
|
||||
int menuItemLocation = UNSPECIFIED_POSITION);
|
||||
|
||||
QAction* getActionFromName(const QString& menuName, MenuWrapper* menu);
|
||||
MenuWrapper* getSubMenuFromName(const QString& menuName, MenuWrapper* menu);
|
||||
MenuWrapper* getMenuParent(const QString& menuName, QString& finalMenuPart);
|
||||
|
||||
QAction* getMenuAction(const QString& menuName);
|
||||
int findPositionOfMenuItem(MenuWrapper* menu, const QString& searchMenuItem);
|
||||
int positionBeforeSeparatorIfNeeded(MenuWrapper* menu, int requestedPosition);
|
||||
|
||||
QHash<QString, QAction*> _actionHash;
|
||||
};
|
||||
|
||||
namespace MenuOption {
|
||||
|
@ -243,4 +280,5 @@ namespace MenuOption {
|
|||
const QString VisibleToNoOne = "No one";
|
||||
const QString Wireframe = "Wireframe";
|
||||
}
|
||||
|
||||
#endif // hifi_Menu_h
|
||||
|
|
|
@ -216,7 +216,7 @@ void OculusManager::connect() {
|
|||
_isConnected = false;
|
||||
|
||||
// we're definitely not in "VR mode" so tell the menu that
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::EnableVRMode, false);
|
||||
Menu::getInstance()->getActionForOption(MenuOption::EnableVRMode)->setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,50 +28,72 @@ void MenuScriptingInterface::menuItemTriggered() {
|
|||
}
|
||||
|
||||
void MenuScriptingInterface::addMenu(const QString& menu) {
|
||||
Menu::getInstance()->addMenu("", menu);
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "addMenu", Q_ARG(const QString&, menu));
|
||||
}
|
||||
|
||||
void MenuScriptingInterface::removeMenu(const QString& menu) {
|
||||
Menu::getInstance()->removeMenu(menu);
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "removeMenu", Q_ARG(const QString&, menu));
|
||||
}
|
||||
|
||||
bool MenuScriptingInterface::menuExists(const QString& menu) {
|
||||
return Menu::getInstance()->menuExists(menu);
|
||||
bool result;
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "menuExists", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, result),
|
||||
Q_ARG(const QString&, menu));
|
||||
return result;
|
||||
}
|
||||
|
||||
void MenuScriptingInterface::addSeparator(const QString& menuName, const QString& separatorName) {
|
||||
Menu::getInstance()->addSeparator(menuName, separatorName);
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "addSeparator",
|
||||
Q_ARG(const QString&, menuName),
|
||||
Q_ARG(const QString&, separatorName));
|
||||
}
|
||||
|
||||
void MenuScriptingInterface::removeSeparator(const QString& menuName, const QString& separatorName) {
|
||||
Menu::getInstance()->removeSeparator(menuName, separatorName);
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "removeSeparator",
|
||||
Q_ARG(const QString&, menuName),
|
||||
Q_ARG(const QString&, separatorName));
|
||||
}
|
||||
|
||||
void MenuScriptingInterface::addMenuItem(const MenuItemProperties& properties) {
|
||||
Menu::getInstance()->addMenuItem(properties);
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "addMenuItem", Q_ARG(const MenuItemProperties&, properties));
|
||||
}
|
||||
|
||||
void MenuScriptingInterface::addMenuItem(const QString& menu, const QString& menuitem, const QString& shortcutKey) {
|
||||
Menu::getInstance()->addItem(menu, menuitem);
|
||||
Menu::getInstance()->setItemShortcut(menuitem, shortcutKey);
|
||||
MenuItemProperties properties(menu, menuitem, shortcutKey);
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "addMenuItem", Q_ARG(const MenuItemProperties&, properties));
|
||||
}
|
||||
|
||||
void MenuScriptingInterface::addMenuItem(const QString& menu, const QString& menuitem) {
|
||||
Menu::getInstance()->addItem(menu, menuitem);
|
||||
MenuItemProperties properties(menu, menuitem);
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "addMenuItem", Q_ARG(const MenuItemProperties&, properties));
|
||||
}
|
||||
|
||||
void MenuScriptingInterface::removeMenuItem(const QString& menu, const QString& menuitem) {
|
||||
Menu::getInstance()->removeItem(menuitem);
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "removeMenuItem",
|
||||
Q_ARG(const QString&, menu),
|
||||
Q_ARG(const QString&, menuitem));
|
||||
};
|
||||
|
||||
bool MenuScriptingInterface::menuItemExists(const QString& menu, const QString& menuitem) {
|
||||
return Menu::getInstance()->itemExists(menu, 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;
|
||||
}
|
||||
|
||||
bool MenuScriptingInterface::isOptionChecked(const QString& menuOption) {
|
||||
return Menu::getInstance()->isChecked(menuOption);
|
||||
bool result;
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "isOptionChecked", Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, result),
|
||||
Q_ARG(const QString&, menuOption));
|
||||
return result;
|
||||
}
|
||||
|
||||
void MenuScriptingInterface::setIsOptionChecked(const QString& menuOption, bool isChecked) {
|
||||
Menu::getInstance()->setChecked(menuOption, isChecked);
|
||||
QMetaObject::invokeMethod(Menu::getInstance(), "setIsOptionChecked", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(const QString&, menuOption),
|
||||
Q_ARG(bool, isChecked));
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ QScriptValue WindowScriptingInterface::hasFocus() {
|
|||
}
|
||||
|
||||
void WindowScriptingInterface::setFocus() {
|
||||
// It's forbidden to call focus() from another thread.
|
||||
Application::getInstance()->postLambdaEvent([] {
|
||||
auto window = Application::getInstance()->getWindow();
|
||||
window->activateWindow();
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include <gpu/GPUConfig.h>
|
||||
|
||||
#include <QFormLayout>
|
||||
#include <QGuiApplication>
|
||||
|
|
|
@ -25,18 +25,19 @@ LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent), _root
|
|||
}
|
||||
|
||||
void LoginDialog::toggleAction() {
|
||||
AccountManager & accountManager = AccountManager::getInstance();
|
||||
Menu* menu = Menu::getInstance();
|
||||
AccountManager& accountManager = AccountManager::getInstance();
|
||||
QAction* loginAction = Menu::getInstance()->getActionForOption(MenuOption::Login);
|
||||
Q_CHECK_PTR(loginAction);
|
||||
disconnect(loginAction, 0, 0, 0);
|
||||
|
||||
if (accountManager.isLoggedIn()) {
|
||||
// change the menu item to logout
|
||||
menu->setOptionText(MenuOption::Login, "Logout " + accountManager.getAccountInfo().getUsername());
|
||||
menu->setOptionTriggerAction(MenuOption::Login, [] {
|
||||
AccountManager::getInstance().logout();
|
||||
});
|
||||
loginAction->setText("Logout " + accountManager.getAccountInfo().getUsername());
|
||||
connect(loginAction, &QAction::triggered, &accountManager, &AccountManager::logout);
|
||||
} else {
|
||||
// change the menu item to login
|
||||
menu->setOptionText(MenuOption::Login, "Login");
|
||||
menu->setOptionTriggerAction(MenuOption::Login, [] {
|
||||
loginAction->setText("Login");
|
||||
connect(loginAction, &QAction::triggered, [] {
|
||||
LoginDialog::show();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -44,9 +44,9 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
|
|||
connect(&_scriptsModelFilter, &QSortFilterProxyModel::modelReset,
|
||||
this, &RunningScriptsWidget::selectFirstInList);
|
||||
|
||||
// FIXME
|
||||
// QString shortcutText = Menu::getInstance()->getActionForOption(MenuOption::ReloadAllScripts)->shortcut().toString(QKeySequence::NativeText);
|
||||
// ui->tipLabel->setText("Tip: Use " + shortcutText + " to reload all scripts.");
|
||||
// FIXME: menu isn't prepared at this point.
|
||||
//QString shortcutText = Menu::getInstance()->getActionForOption(MenuOption::ReloadAllScripts)->shortcut().toString(QKeySequence::NativeText);
|
||||
//ui->tipLabel->setText("Tip: Use " + shortcutText + " to reload all scripts.");
|
||||
|
||||
_scriptsModelFilter.setSourceModel(&_scriptsModel);
|
||||
_scriptsModelFilter.sort(0, Qt::AscendingOrder);
|
||||
|
@ -162,7 +162,8 @@ void RunningScriptsWidget::showEvent(QShowEvent* event) {
|
|||
|
||||
QRect parentGeometry = Application::getInstance()->getDesirableApplicationGeometry();
|
||||
int titleBarHeight = UIUtil::getWindowTitleBarHeight(this);
|
||||
int topMargin = titleBarHeight;
|
||||
int menuBarHeight = Menu::getInstance()->geometry().height();
|
||||
int topMargin = titleBarHeight + menuBarHeight;
|
||||
|
||||
setGeometry(parentGeometry.topLeft().x(), parentGeometry.topLeft().y() + topMargin,
|
||||
size().width(), parentWidget()->height() - topMargin);
|
||||
|
|
|
@ -38,7 +38,8 @@ bool ToolWindow::event(QEvent* event) {
|
|||
QRect mainGeometry = mainWindow->geometry();
|
||||
|
||||
int titleBarHeight = UIUtil::getWindowTitleBarHeight(this);
|
||||
int topMargin = titleBarHeight;
|
||||
int menuBarHeight = Menu::getInstance()->geometry().height();
|
||||
int topMargin = titleBarHeight + menuBarHeight;
|
||||
|
||||
_lastGeometry = QRect(mainGeometry.topLeft().x(), mainGeometry.topLeft().y() + topMargin,
|
||||
DEFAULT_WIDTH, mainGeometry.height() - topMargin);
|
||||
|
|
|
@ -1,47 +1,64 @@
|
|||
#include "HifiMenu.h"
|
||||
#include <QtQml>
|
||||
#include <QMenuBar>
|
||||
|
||||
// FIXME can this be made a class member?
|
||||
static const QString MENU_SUFFIX{ "__Menu" };
|
||||
// Binds together a Qt Action or Menu with the QML Menu or MenuItem
|
||||
class MenuUserData : public QObjectUserData {
|
||||
static const int USER_DATA_ID;
|
||||
|
||||
HIFI_QML_DEF_LAMBDA(HifiMenu, [=](QQmlContext* context, QObject* newItem) {
|
||||
public:
|
||||
MenuUserData(QAction* action, QObject* qmlObject) {
|
||||
init(action, qmlObject);
|
||||
}
|
||||
MenuUserData(QMenu* menu, QObject* qmlObject) {
|
||||
init(menu, qmlObject);
|
||||
}
|
||||
|
||||
const QUuid uuid{ QUuid::createUuid() };
|
||||
|
||||
static MenuUserData* forObject(QObject* object) {
|
||||
return static_cast<MenuUserData*>(object->userData(USER_DATA_ID));
|
||||
}
|
||||
|
||||
private:
|
||||
MenuUserData(const MenuUserData&);
|
||||
|
||||
void init(QObject* widgetObject, QObject* qmlObject) {
|
||||
widgetObject->setUserData(USER_DATA_ID, this);
|
||||
qmlObject->setUserData(USER_DATA_ID, this);
|
||||
qmlObject->setObjectName(uuid.toString());
|
||||
// Make sure we can find it again in the future
|
||||
Q_ASSERT(VrMenu::instance()->findMenuObject(uuid.toString()));
|
||||
}
|
||||
};
|
||||
|
||||
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<HifiMenu*>(newItem)->setRootMenu(rootMenu);
|
||||
static_cast<VrMenu*>(newItem)->setRootMenu(rootMenu);
|
||||
context->setContextProperty("rootMenu", rootMenu);
|
||||
});
|
||||
|
||||
HifiMenu::HifiMenu(QQuickItem* parent) : QQuickItem(parent), _triggerMapper(this), _toggleMapper(this) {
|
||||
VrMenu* VrMenu::_instance{ nullptr };
|
||||
|
||||
VrMenu* VrMenu::instance() {
|
||||
if (!_instance) {
|
||||
VrMenu::registerType();
|
||||
VrMenu::load();
|
||||
Q_ASSERT(_instance);
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
VrMenu::VrMenu(QQuickItem* parent) : QQuickItem(parent) {
|
||||
_instance = this;
|
||||
this->setEnabled(false);
|
||||
connect(&_triggerMapper, SIGNAL(mapped(QString)), this, SLOT(onTriggeredByName(const QString &)));
|
||||
connect(&_toggleMapper, SIGNAL(mapped(QString)), this, SLOT(onToggledByName(const QString &)));
|
||||
}
|
||||
|
||||
void HifiMenu::onTriggeredByName(const QString & name) {
|
||||
qDebug() << name << " triggered";
|
||||
if (_triggerActions.count(name)) {
|
||||
_triggerActions[name]();
|
||||
}
|
||||
}
|
||||
|
||||
void HifiMenu::onToggledByName(const QString & name) {
|
||||
qDebug() << name << " toggled";
|
||||
if (_toggleActions.count(name)) {
|
||||
QObject* menu = findMenuObject(name);
|
||||
bool checked = menu->property("checked").toBool();
|
||||
_toggleActions[name](checked);
|
||||
}
|
||||
}
|
||||
|
||||
void HifiMenu::setToggleAction(const QString & name, std::function<void(bool)> f) {
|
||||
_toggleActions[name] = f;
|
||||
}
|
||||
|
||||
void HifiMenu::setTriggerAction(const QString & name, std::function<void()> f) {
|
||||
_triggerActions[name] = f;
|
||||
}
|
||||
|
||||
// QML helper functions
|
||||
QObject* addMenu(QObject* parent, const QString & text) {
|
||||
// FIXME add more checking here to ensure no name conflicts
|
||||
QVariant returnedValue;
|
||||
|
@ -50,7 +67,7 @@ QObject* addMenu(QObject* parent, const QString & text) {
|
|||
Q_ARG(QVariant, text));
|
||||
QObject* result = returnedValue.value<QObject*>();
|
||||
if (result) {
|
||||
result->setObjectName(text + MENU_SUFFIX);
|
||||
result->setObjectName(text);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -67,236 +84,109 @@ QObject* addItem(QObject* parent, const QString& text) {
|
|||
return result;
|
||||
}
|
||||
|
||||
const QObject* HifiMenu::findMenuObject(const QString & menuOption) const {
|
||||
const QObject* VrMenu::findMenuObject(const QString & menuOption) const {
|
||||
if (menuOption.isEmpty()) {
|
||||
return _rootMenu;
|
||||
}
|
||||
const QObject* result = _rootMenu->findChild<QObject*>(menuOption + MENU_SUFFIX);
|
||||
const QObject* result = _rootMenu->findChild<QObject*>(menuOption);
|
||||
return result;
|
||||
}
|
||||
|
||||
QObject* HifiMenu::findMenuObject(const QString & menuOption) {
|
||||
QObject* VrMenu::findMenuObject(const QString & menuOption) {
|
||||
if (menuOption.isEmpty()) {
|
||||
return _rootMenu;
|
||||
}
|
||||
QObject* result = _rootMenu->findChild<QObject*>(menuOption + MENU_SUFFIX);
|
||||
QObject* result = _rootMenu->findChild<QObject*>(menuOption);
|
||||
return result;
|
||||
}
|
||||
|
||||
void HifiMenu::addMenu(const QString & parentMenu, const QString & menuOption) {
|
||||
QObject* parent = findMenuObject(parentMenu);
|
||||
QObject* result = ::addMenu(parent, menuOption);
|
||||
Q_ASSERT(result);
|
||||
result->setObjectName(menuOption + MENU_SUFFIX);
|
||||
Q_ASSERT(findMenuObject(menuOption));
|
||||
}
|
||||
|
||||
void HifiMenu::removeMenu(const QString& menuName) {
|
||||
QObject* menu = findMenuObject(menuName);
|
||||
Q_ASSERT(menu);
|
||||
Q_ASSERT(menu != _rootMenu);
|
||||
QMetaObject::invokeMethod(menu->parent(), "removeItem",
|
||||
Q_ARG(QVariant, QVariant::fromValue(menu)));
|
||||
}
|
||||
|
||||
bool HifiMenu::menuExists(const QString& menuName) const {
|
||||
return findMenuObject(menuName);
|
||||
}
|
||||
|
||||
void HifiMenu::addSeparator(const QString& parentMenu, const QString& separatorName) {
|
||||
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) {
|
||||
}
|
||||
|
||||
void HifiMenu::addItem(const QString & parentMenu, const QString & menuOption) {
|
||||
QObject* parent = findMenuObject(parentMenu);
|
||||
Q_ASSERT(parent);
|
||||
QObject* result = ::addItem(parent, menuOption);
|
||||
Q_ASSERT(result);
|
||||
result->setObjectName(menuOption + MENU_SUFFIX);
|
||||
Q_ASSERT(findMenuObject(menuOption));
|
||||
|
||||
_triggerMapper.setMapping(result, menuOption);
|
||||
connect(result, SIGNAL(triggered()), &_triggerMapper, SLOT(map()));
|
||||
|
||||
_toggleMapper.setMapping(result, menuOption);
|
||||
connect(result, SIGNAL(toggled(bool)), &_toggleMapper, SLOT(map()));
|
||||
}
|
||||
|
||||
void HifiMenu::addItem(const QString & parentMenu, const QString & menuOption, std::function<void()> f) {
|
||||
setTriggerAction(menuOption, f);
|
||||
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);
|
||||
}
|
||||
|
||||
bool HifiMenu::itemExists(const QString& menuName, const QString& menuitem) const {
|
||||
return findMenuObject(menuName);
|
||||
}
|
||||
|
||||
void HifiMenu::triggerItem(const QString& menuOption) {
|
||||
QObject* menuItem = findMenuObject(menuOption);
|
||||
Q_ASSERT(menuItem);
|
||||
Q_ASSERT(menuItem != _rootMenu);
|
||||
QMetaObject::invokeMethod(menuItem, "trigger");
|
||||
}
|
||||
|
||||
QHash<QString, QString> warned;
|
||||
void warn(const QString & menuOption) {
|
||||
if (!warned.contains(menuOption)) {
|
||||
warned[menuOption] = menuOption;
|
||||
qWarning() << "No menu item: " << menuOption;
|
||||
}
|
||||
}
|
||||
|
||||
bool HifiMenu::isChecked(const QString& menuOption) const {
|
||||
const QObject* menuItem = findMenuObject(menuOption);
|
||||
if (!menuItem) {
|
||||
warn(menuOption);
|
||||
return false;
|
||||
}
|
||||
return menuItem->property("checked").toBool();
|
||||
}
|
||||
|
||||
void HifiMenu::setChecked(const QString& menuOption, bool isChecked) {
|
||||
QObject* menuItem = findMenuObject(menuOption);
|
||||
if (!menuItem) {
|
||||
warn(menuOption);
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
QObject* menuItem = findMenuObject(menuOption);
|
||||
if (!menuItem) {
|
||||
warn(menuOption);
|
||||
return;
|
||||
}
|
||||
|
||||
menuItem->setProperty("checkable", QVariant::fromValue(checkable));
|
||||
Q_ASSERT(menuItem->property("checkable").toBool() == checkable);
|
||||
}
|
||||
|
||||
void HifiMenu::setItemText(const QString& menuOption, const QString& text) {
|
||||
QObject* menuItem = findMenuObject(menuOption);
|
||||
if (!menuItem) {
|
||||
warn(menuOption);
|
||||
return;
|
||||
}
|
||||
if (menuItem->property("type").toInt() == 2) {
|
||||
menuItem->setProperty("title", QVariant::fromValue(text));
|
||||
} else {
|
||||
menuItem->setProperty("text", QVariant::fromValue(text));
|
||||
}
|
||||
}
|
||||
|
||||
void HifiMenu::setRootMenu(QObject* rootMenu) {
|
||||
void VrMenu::setRootMenu(QObject* rootMenu) {
|
||||
_rootMenu = rootMenu;
|
||||
}
|
||||
|
||||
void HifiMenu::enableItem(const QString & menuOption, bool enabled) {
|
||||
QObject* menuItem = findMenuObject(menuOption);
|
||||
if (!menuItem) {
|
||||
warn(menuOption);
|
||||
return;
|
||||
void VrMenu::addMenu(QMenu* menu) {
|
||||
Q_ASSERT(!MenuUserData::forObject(menu));
|
||||
QObject * parent = menu->parent();
|
||||
QObject * qmlParent;
|
||||
if (dynamic_cast<QMenu*>(parent)) {
|
||||
MenuUserData* userData = MenuUserData::forObject(parent);
|
||||
qmlParent = findMenuObject(userData->uuid.toString());
|
||||
} else if (dynamic_cast<QMenuBar*>(parent)) {
|
||||
qmlParent = _rootMenu;
|
||||
} else {
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
menuItem->setProperty("enabled", QVariant::fromValue(enabled));
|
||||
QObject* result = ::addMenu(qmlParent, menu->title());
|
||||
new MenuUserData(menu, result);
|
||||
}
|
||||
|
||||
void HifiMenu::addCheckableItem(const QString& parentMenu, const QString& menuOption, bool checked) {
|
||||
addItem(parentMenu, menuOption);
|
||||
setCheckable(menuOption);
|
||||
if (checked) {
|
||||
setChecked(menuOption, checked);
|
||||
}
|
||||
void updateQmlItemFromAction(QObject* target, QAction* source) {
|
||||
target->setProperty("checkable", source->isCheckable());
|
||||
target->setProperty("enabled", source->isEnabled());
|
||||
target->setProperty("visible", source->isVisible());
|
||||
target->setProperty("text", source->text());
|
||||
target->setProperty("checked", source->isChecked());
|
||||
}
|
||||
|
||||
void HifiMenu::addCheckableItem(const QString& parentMenu, const QString& menuOption, bool checked, std::function<void(bool)> f) {
|
||||
setToggleAction(menuOption, f);
|
||||
addCheckableItem(parentMenu, menuOption, checked);
|
||||
void bindActionToQmlAction(QObject* qmlAction, QAction* action) {
|
||||
new MenuUserData(action, qmlAction);
|
||||
updateQmlItemFromAction(qmlAction, action);
|
||||
QObject::connect(action, &QAction::changed, [=] {
|
||||
updateQmlItemFromAction(qmlAction, action);
|
||||
});
|
||||
QObject::connect(action, &QAction::toggled, [=](bool checked) {
|
||||
qmlAction->setProperty("checked", checked);
|
||||
});
|
||||
QObject::connect(qmlAction, SIGNAL(triggered()), action, SLOT(trigger()));
|
||||
}
|
||||
|
||||
void HifiMenu::setItemVisible(const QString& menuOption, bool visible) {
|
||||
QObject* result = findMenuObject(menuOption);
|
||||
if (result) {
|
||||
result->setProperty("visible", visible);
|
||||
}
|
||||
}
|
||||
|
||||
bool HifiMenu::isItemVisible(const QString& menuOption) {
|
||||
QObject* result = findMenuObject(menuOption);
|
||||
if (result) {
|
||||
return result->property("visible").toBool();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void HifiMenu::setItemShortcut(const QString& menuOption, const QString& shortcut) {
|
||||
QObject* result = findMenuObject(menuOption);
|
||||
if (result) {
|
||||
result->setProperty("shortcut", shortcut);
|
||||
}
|
||||
}
|
||||
|
||||
QString HifiMenu::getItemShortcut(const QString& menuOption) {
|
||||
QObject* result = findMenuObject(menuOption);
|
||||
if (result) {
|
||||
return result->property("shortcut").toString();
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
void HifiMenu::setExclusiveGroup(const QString& menuOption, const QString& groupName) {
|
||||
static const QString GROUP_SUFFIX{ "__Group" };
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
QObject* group = offscreenUi->getRootItem()->findChild<QObject*>(groupName + GROUP_SUFFIX);
|
||||
if (!group) {
|
||||
group = offscreenUi->load("ExclusiveGroup.qml");
|
||||
Q_ASSERT(group);
|
||||
}
|
||||
QObject* menuItem = findMenuObject(menuOption);
|
||||
bool result = menuItem->setProperty("text", QVariant::fromValue(group));
|
||||
void VrMenu::addAction(QMenu* menu, QAction* action) {
|
||||
Q_ASSERT(!MenuUserData::forObject(action));
|
||||
Q_ASSERT(MenuUserData::forObject(menu));
|
||||
MenuUserData* userData = MenuUserData::forObject(menu);
|
||||
QObject* parent = findMenuObject(userData->uuid.toString());
|
||||
Q_ASSERT(parent);
|
||||
QObject* result = ::addItem(parent, action->text());
|
||||
Q_ASSERT(result);
|
||||
// Bind the QML and Widget together
|
||||
bindActionToQmlAction(result, action);
|
||||
}
|
||||
|
||||
bool HifiMenu::connectAction(int action, QObject * receiver, const char * slot) {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
QObject* rootMenu = offscreenUi->getRootItem()->findChild<QObject*>("AllActions");
|
||||
QString name = "HifiAction_" + QVariant(action).toString();
|
||||
QObject* quitAction = rootMenu->findChild<QObject*>(name);
|
||||
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
|
||||
return true;
|
||||
void VrMenu::insertAction(QAction* before, QAction* action) {
|
||||
QObject* beforeQml{ nullptr };
|
||||
{
|
||||
MenuUserData* beforeUserData = MenuUserData::forObject(before);
|
||||
Q_ASSERT(beforeUserData);
|
||||
beforeQml = findMenuObject(beforeUserData->uuid.toString());
|
||||
}
|
||||
|
||||
QObject* menu = beforeQml->parent();
|
||||
int index{ -1 };
|
||||
QVariant itemsVar = menu->property("items");
|
||||
QList<QVariant> items = itemsVar.toList();
|
||||
// FIXME add more checking here to ensure no name conflicts
|
||||
for (index = 0; index < items.length(); ++index) {
|
||||
QObject* currentQmlItem = items.at(index).value<QObject*>();
|
||||
if (currentQmlItem == beforeQml) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QObject* result{ nullptr };
|
||||
if (index < 0 || index >= items.length()) {
|
||||
result = ::addItem(menu, action->text());
|
||||
} else {
|
||||
QQuickMenuItem* returnedValue{ nullptr };
|
||||
bool invokeResult = QMetaObject::invokeMethod(menu, "insertItem", Qt::DirectConnection,
|
||||
Q_RETURN_ARG(QQuickMenuItem*, returnedValue),
|
||||
Q_ARG(int, index), Q_ARG(QString, action->text()));
|
||||
Q_ASSERT(invokeResult);
|
||||
result = reinterpret_cast<QObject*>(returnedValue);
|
||||
}
|
||||
Q_ASSERT(result);
|
||||
bindActionToQmlAction(result, action);
|
||||
}
|
||||
|
||||
void VrMenu::removeAction(QAction* action) {
|
||||
// FIXME implement
|
||||
}
|
||||
|
|
|
@ -16,67 +16,32 @@
|
|||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QSignalMapper>
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include "OffscreenUi.h"
|
||||
|
||||
class HifiMenu : public QQuickItem {
|
||||
class VrMenu : public QQuickItem {
|
||||
Q_OBJECT
|
||||
HIFI_QML_DECL_LAMBDA
|
||||
|
||||
public:
|
||||
|
||||
static bool connectAction(int action, QObject * receiver, const char * slot);
|
||||
|
||||
HifiMenu(QQuickItem* parent = nullptr);
|
||||
|
||||
void setToggleAction(const QString& name, std::function<void(bool)> f);
|
||||
void setTriggerAction(const QString& name, std::function<void()> f);
|
||||
|
||||
void addMenu(const QString& parentMenu, const QString& menuOption);
|
||||
void removeMenu(const QString& menuName);
|
||||
bool menuExists(const QString& menuName) const;
|
||||
|
||||
void addSeparator(const QString& menuName, const QString& separatorName);
|
||||
void removeSeparator(const QString& menuName, const QString& separatorName);
|
||||
|
||||
void addItem(const QString& parentMenu, const QString& menuOption);
|
||||
void addItem(const QString& parentMenu, const QString& menuOption, std::function<void()> 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<void(bool)> 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;
|
||||
void triggerItem(const QString& menuOption);
|
||||
void enableItem(const QString& menuOption, bool enabled = true);
|
||||
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 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);
|
||||
QString getItemShortcut(const QString& menuOption);
|
||||
static VrMenu* instance();
|
||||
VrMenu(QQuickItem* 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);
|
||||
|
||||
private slots:
|
||||
void onTriggeredByName(const QString& name);
|
||||
void onToggledByName(const QString& name);
|
||||
|
||||
protected:
|
||||
QHash<QString, std::function<void()>> _triggerActions;
|
||||
QHash<QString, std::function<void(bool)>> _toggleActions;
|
||||
QObject* _rootMenu{ nullptr };
|
||||
|
||||
QObject* findMenuObject(const QString& name);
|
||||
const QObject* findMenuObject(const QString& name) const;
|
||||
QObject* _rootMenu{ nullptr };
|
||||
QSignalMapper _triggerMapper;
|
||||
QSignalMapper _toggleMapper;
|
||||
|
||||
static VrMenu* _instance;
|
||||
friend class MenuUserData;
|
||||
};
|
||||
|
||||
#endif // hifi_MenuConstants_h
|
||||
|
|
|
@ -366,10 +366,14 @@ bool OffscreenUi::eventFilter(QObject* originalDestination, QEvent* event) {
|
|||
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
QPointF originalPos = mouseEvent->localPos();
|
||||
QPointF transformedPos = _mouseTranslator(originalPos);
|
||||
transformedPos = mapWindowToUi(transformedPos, originalDestination);
|
||||
QMouseEvent mappedEvent(mouseEvent->type(),
|
||||
mapWindowToUi(transformedPos, originalDestination),
|
||||
transformedPos,
|
||||
mouseEvent->screenPos(), mouseEvent->button(),
|
||||
mouseEvent->buttons(), mouseEvent->modifiers());
|
||||
if (event->type() == QEvent::MouseMove) {
|
||||
_qmlEngine->rootContext()->setContextProperty("lastMousePosition", transformedPos);
|
||||
}
|
||||
mappedEvent.ignore();
|
||||
if (QCoreApplication::sendEvent(_quickWindow, &mappedEvent)) {
|
||||
return mappedEvent.isAccepted();
|
||||
|
@ -429,6 +433,7 @@ void OffscreenUi::toggle(const QUrl& url, const QString& name, std::function<voi
|
|||
item = _rootItem->findChild<QQuickItem*>(name);
|
||||
}
|
||||
if (item) {
|
||||
qDebug() << "Turning item " << !item->isEnabled();
|
||||
item->setEnabled(!item->isEnabled());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -320,7 +320,7 @@ public:
|
|||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
MessageDialog::registerType();
|
||||
HifiMenu::registerType();
|
||||
VrMenu::registerType();
|
||||
qmlRegisterType<MenuConstants>("Hifi", 1, 0, "MenuConstants");
|
||||
|
||||
|
||||
|
@ -348,10 +348,9 @@ public:
|
|||
#else
|
||||
offscreenUi->setBaseUrl(QUrl::fromLocalFile(getQmlDir()));
|
||||
offscreenUi->load(QUrl("TestRoot.qml"));
|
||||
offscreenUi->load(QUrl("Menu.qml"));
|
||||
offscreenUi->load(QUrl("InterfaceMenu.qml"));
|
||||
// Requires a root menu to have been loaded before it can load
|
||||
HifiMenu::load();
|
||||
HifiMenu::connectAction(MenuConstants::Quit, qApp, SLOT(quit()));
|
||||
VrMenu::load();
|
||||
#endif
|
||||
installEventFilter(offscreenUi.data());
|
||||
offscreenUi->resume();
|
||||
|
@ -407,10 +406,6 @@ protected:
|
|||
switch (event->key()) {
|
||||
case Qt::Key_L:
|
||||
if (event->modifiers() & Qt::CTRL) {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
HifiMenu * menu = offscreenUi->findChild<HifiMenu*>();
|
||||
menu->addItem("", "Test 3");
|
||||
menu->addItem("File", "Test 3");
|
||||
}
|
||||
break;
|
||||
case Qt::Key_K:
|
||||
|
@ -433,7 +428,7 @@ protected:
|
|||
QQmlContext* menuContext{ nullptr };
|
||||
void keyReleaseEvent(QKeyEvent *event) {
|
||||
if (_altPressed && Qt::Key_Alt == event->key()) {
|
||||
HifiMenu::toggle();
|
||||
VrMenu::toggle();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue