mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 11:28:03 +02:00
Working on menus
This commit is contained in:
parent
bb1c73adc7
commit
f17387fab4
13 changed files with 749 additions and 924 deletions
|
@ -29,12 +29,12 @@ NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit
|
||||||
|
|
||||||
* [Download the online installer](http://qt-project.org/downloads)
|
* [Download the online installer](http://qt-project.org/downloads)
|
||||||
* When it asks you to select components, ONLY select the following:
|
* When it asks you to select components, ONLY select the following:
|
||||||
* Qt > Qt 5.3.2 > **msvc2013 32-bit OpenGL**
|
* Qt > Qt 5.4.1 > **msvc2013 32-bit OpenGL**
|
||||||
|
|
||||||
* [Download the offline installer](http://download.qt-project.org/official_releases/qt/5.3/5.3.2/qt-opensource-windows-x86-msvc2013_opengl-5.3.2.exe)
|
* [Download the offline installer](http://download.qt.io/official_releases/qt/5.4/5.4.1/qt-opensource-windows-x86-msvc2013_opengl-5.4.1.exe)
|
||||||
|
|
||||||
Once Qt is installed, you need to manually configure the following:
|
Once Qt is installed, you need to manually configure the following:
|
||||||
* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.3.2\msvc2013_opengl\lib\cmake` directory.
|
* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.4.1\msvc2013_opengl\lib\cmake` directory.
|
||||||
* You can set an environment variable from Control Panel > System > Advanced System Settings > Environment Variables > New
|
* You can set an environment variable from Control Panel > System > Advanced System Settings > Environment Variables > New
|
||||||
|
|
||||||
###External Libraries
|
###External Libraries
|
||||||
|
|
|
@ -6,35 +6,5 @@ import QtQuick 2.3
|
||||||
Root {
|
Root {
|
||||||
id: root
|
id: root
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Item {
|
|
||||||
Menu {
|
|
||||||
objectName: "rootMenu"
|
|
||||||
Menu {
|
|
||||||
title: "File"
|
|
||||||
MenuItem {
|
|
||||||
text: "Test"
|
|
||||||
checkable: true
|
|
||||||
}
|
|
||||||
MenuItem {
|
|
||||||
text: "Quit"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Menu {
|
|
||||||
title: "Edit"
|
|
||||||
MenuItem {
|
|
||||||
text: "Copy"
|
|
||||||
}
|
|
||||||
MenuItem {
|
|
||||||
text: "Cut"
|
|
||||||
}
|
|
||||||
MenuItem {
|
|
||||||
text: "Paste"
|
|
||||||
}
|
|
||||||
MenuItem {
|
|
||||||
text: "Undo"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,32 +3,7 @@ import QtQuick.Controls 1.3
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
Menu {
|
Menu {
|
||||||
id: rootMenuFooBar
|
id: root
|
||||||
objectName: "rootMenu"
|
objectName: "rootMenu"
|
||||||
Menu {
|
|
||||||
title: "File"
|
|
||||||
MenuItem {
|
|
||||||
text: "Test"
|
|
||||||
checkable: true
|
|
||||||
}
|
|
||||||
MenuItem {
|
|
||||||
text: "Quit"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Menu {
|
|
||||||
title: "Edit"
|
|
||||||
MenuItem {
|
|
||||||
text: "Copy"
|
|
||||||
}
|
|
||||||
MenuItem {
|
|
||||||
text: "Cut"
|
|
||||||
}
|
|
||||||
MenuItem {
|
|
||||||
text: "Paste"
|
|
||||||
}
|
|
||||||
MenuItem {
|
|
||||||
text: "Undo"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -786,6 +786,7 @@ void Application::initializeUi() {
|
||||||
offscreenUi->setProxyWindow(_window->windowHandle());
|
offscreenUi->setProxyWindow(_window->windowHandle());
|
||||||
offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
|
offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/"));
|
||||||
offscreenUi->load("Root.qml");
|
offscreenUi->load("Root.qml");
|
||||||
|
offscreenUi->load("RootMenu.qml");
|
||||||
offscreenUi->setMouseTranslator([this](const QPointF& p){
|
offscreenUi->setMouseTranslator([this](const QPointF& p){
|
||||||
if (OculusManager::isConnected()) {
|
if (OculusManager::isConnected()) {
|
||||||
glm::vec2 pos = _applicationOverlay.screenToOverlay(toGlm(p));
|
glm::vec2 pos = _applicationOverlay.screenToOverlay(toGlm(p));
|
||||||
|
@ -1079,9 +1080,11 @@ bool Application::eventFilter(QObject* object, QEvent* event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _altPressed;
|
static bool _altPressed;
|
||||||
|
static bool _ctrlPressed;
|
||||||
|
|
||||||
void Application::keyPressEvent(QKeyEvent* event) {
|
void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
_altPressed = event->key() == Qt::Key_Alt;
|
_altPressed = event->key() == Qt::Key_Alt;
|
||||||
|
_ctrlPressed = event->key() == Qt::Key_Control;
|
||||||
_keysPressed.insert(event->key());
|
_keysPressed.insert(event->key());
|
||||||
|
|
||||||
_controllerScriptingInterface.emitKeyPressEvent(event); // send events to any registered scripts
|
_controllerScriptingInterface.emitKeyPressEvent(event); // send events to any registered scripts
|
||||||
|
@ -1336,6 +1339,12 @@ void Application::keyReleaseEvent(QKeyEvent* event) {
|
||||||
if (event->key() == Qt::Key_Alt && _altPressed) {
|
if (event->key() == Qt::Key_Alt && _altPressed) {
|
||||||
Menu::toggle();
|
Menu::toggle();
|
||||||
}
|
}
|
||||||
|
if (event->key() == Qt::Key_Control && _ctrlPressed) {
|
||||||
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
auto rootMenu = offscreenUi->getRootItem()->findChild<QObject*>("rootMenu");
|
||||||
|
QMetaObject::invokeMethod(rootMenu, "popup");
|
||||||
|
}
|
||||||
|
_ctrlPressed = event->key() == Qt::Key_Control;
|
||||||
|
|
||||||
_keysPressed.remove(event->key());
|
_keysPressed.remove(event->key());
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -24,6 +24,7 @@
|
||||||
#include <OffscreenUi.h>
|
#include <OffscreenUi.h>
|
||||||
|
|
||||||
#include "DiscoverabilityManager.h"
|
#include "DiscoverabilityManager.h"
|
||||||
|
#include <HifiMenu.h>
|
||||||
|
|
||||||
class Settings;
|
class Settings;
|
||||||
|
|
||||||
|
@ -41,46 +42,58 @@ public:
|
||||||
void setToggleAction(std::function<void(bool)>);
|
void setToggleAction(std::function<void(bool)>);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Menu : public QQuickItem {
|
class Menu : public HifiMenu {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
HIFI_QML_DECL
|
|
||||||
public:
|
public:
|
||||||
Menu(QQuickItem * parent = 0);
|
Menu(QQuickItem * parent = 0);
|
||||||
static Menu* getInstance();
|
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 loadSettings();
|
||||||
void saveSettings();
|
void saveSettings();
|
||||||
HifiAction * getActionForOption(const QString& menuOption) {
|
HifiAction * getActionForOption(const QString& menuOption) {
|
||||||
return new HifiAction(menuOption);
|
return new HifiAction(menuOption);
|
||||||
}
|
}
|
||||||
// QMenu* addMenu(const QString& menuName);
|
// QMenu* addMenu(const QString& menuName);
|
||||||
void removeMenu(const QString& menuName);
|
//void removeMenu(const QString& menuName);
|
||||||
bool menuExists(const QString& menuName);
|
//bool menuExists(const QString& menuName);
|
||||||
void addSeparator(const QString& menuName, const QString& separatorName);
|
//void addSeparator(const QString& menuName, const QString& separatorName);
|
||||||
void removeSeparator(const QString& menuName, const QString& separatorName);
|
//void removeSeparator(const QString& menuName, const QString& separatorName);
|
||||||
void addMenuItem(const MenuItemProperties& properties);
|
//void addMenuItem(const MenuItemProperties& properties);
|
||||||
void removeMenuItem(const QString& menuitem);
|
//void removeMenuItem(const QString& menuitem);
|
||||||
bool menuItemExists(const QString& menuName, const QString& menuitem);
|
//bool menuItemExists(const QString& menuName, const QString& menuitem);
|
||||||
bool isOptionChecked(const QString& menuOption) const;
|
bool isOptionChecked(const QString& menuOption) const {
|
||||||
void setIsOptionChecked(const QString& menuOption, bool isChecked);
|
return HifiMenu::isChecked(menuOption);
|
||||||
void triggerOption(const QString& menuOption);
|
}
|
||||||
void setOptionText(const QString& menuOption, const QString & text);
|
void setIsOptionChecked(const QString& menuOption, bool isChecked) {
|
||||||
void setOptionTriggerAction(const QString& menuOption, std::function<void()> f);
|
HifiMenu::setChecked(menuOption, isChecked);
|
||||||
void setOptionToggleAction(const QString& menuOption, std::function<void(bool)> f);
|
}
|
||||||
void addMenuItem(const QString & parentMenu, const QString & menuOption, std::function<void()> f);
|
void triggerOption(const QString& menuOption) {
|
||||||
void addMenuItem(const QString & parentMenu, const QString & menuOption);
|
HifiMenu::triggerMenuItem(menuOption);
|
||||||
void addMenu(const QString & parentMenu, const QString & menuOption);
|
}
|
||||||
void enableMenuItem(const QString & menuOption, bool enabled = true);
|
void setOptionText(const QString& menuOption, const QString & text) {
|
||||||
|
HifiMenu::setText(menuOption, text);
|
||||||
|
}
|
||||||
|
void setOptionTriggerAction(const QString& menuOption, std::function<void()> f) {
|
||||||
|
HifiMenu::setTriggerAction(menuOption, f);
|
||||||
|
}
|
||||||
|
//void setOptionToggleAction(const QString& menuOption, std::function<void(bool)> f);
|
||||||
|
//void addMenuItem(const QString & parentMenu, const QString & menuOption, std::function<void()> f);
|
||||||
|
//void addMenuItem(const QString & parentMenu, const QString & menuOption);
|
||||||
|
//void addMenu(const QString & parentMenu, const QString & menuOption);
|
||||||
|
//void enableMenuItem(const QString & menuOption, bool enabled = true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Menu* _instance;
|
static Menu* _instance;
|
||||||
|
friend class HifiAction;
|
||||||
QHash<QString, std::function<void()>> _triggerActions;
|
|
||||||
QHash<QString, std::function<void(bool)>> _toggleActions;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace MenuOption {
|
namespace MenuOption {
|
||||||
|
|
221
libraries/ui/src/HifiMenu.cpp
Normal file
221
libraries/ui/src/HifiMenu.cpp
Normal file
|
@ -0,0 +1,221 @@
|
||||||
|
#include "HifiMenu.h"
|
||||||
|
#include <QtQml>
|
||||||
|
|
||||||
|
// FIXME can this be made a class member?
|
||||||
|
static const QString MENU_SUFFIX{ "__Menu" };
|
||||||
|
|
||||||
|
HIFI_QML_DEF_LAMBDA(HifiMenu, [=](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);
|
||||||
|
context->setContextProperty("rootMenu", rootMenu);
|
||||||
|
});
|
||||||
|
|
||||||
|
HifiMenu::HifiMenu(QQuickItem* parent) : QQuickItem(parent), _triggerMapper(this), _toggleMapper(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject* addMenu(QObject* parent, const QString & text) {
|
||||||
|
// FIXME add more checking here to ensure no name conflicts
|
||||||
|
QVariant returnedValue;
|
||||||
|
QMetaObject::invokeMethod(parent, "addMenu",
|
||||||
|
Q_RETURN_ARG(QVariant, returnedValue),
|
||||||
|
Q_ARG(QVariant, text));
|
||||||
|
QObject* result = returnedValue.value<QObject*>();
|
||||||
|
if (result) {
|
||||||
|
result->setObjectName(text + MENU_SUFFIX);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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",
|
||||||
|
Q_RETURN_ARG(QQuickMenuItem*, returnedValue),
|
||||||
|
Q_ARG(QString, text));
|
||||||
|
Q_ASSERT(invokeResult);
|
||||||
|
QObject* result = reinterpret_cast<QObject*>(returnedValue);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QObject* HifiMenu::findMenuObject(const QString & menuOption) const {
|
||||||
|
if (menuOption.isEmpty()) {
|
||||||
|
return _rootMenu;
|
||||||
|
}
|
||||||
|
const QObject* result = _rootMenu->findChild<QObject*>(menuOption + MENU_SUFFIX);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QObject* HifiMenu::findMenuObject(const QString & menuOption) {
|
||||||
|
if (menuOption.isEmpty()) {
|
||||||
|
return _rootMenu;
|
||||||
|
}
|
||||||
|
QObject* result = _rootMenu->findChild<QObject*>(menuOption + MENU_SUFFIX);
|
||||||
|
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) {
|
||||||
|
// FIXME 'add sep'
|
||||||
|
// addMenu(parentMenu, separatorName);
|
||||||
|
// setEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
void HifiMenu::removeSeparator(const QString& parentMenu, const QString& separatorName) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void HifiMenu::addMenuItem(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::addMenuItem(const QString & parentMenu, const QString & menuOption, std::function<void()> f) {
|
||||||
|
setTriggerAction(menuOption, f);
|
||||||
|
addMenuItem(parentMenu, menuOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HifiMenu::removeMenuItem(const QString& menuOption) {
|
||||||
|
removeMenu(menuOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HifiMenu::menuItemExists(const QString& menuName, const QString& menuitem) const {
|
||||||
|
return findMenuObject(menuName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HifiMenu::triggerMenuItem(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;
|
||||||
|
}
|
||||||
|
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::setText(const QString& menuOption, const QString & text) {
|
||||||
|
QObject* menuItem = findMenuObject(menuOption);
|
||||||
|
if (!menuItem) {
|
||||||
|
warn(menuOption);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
menuItem->setProperty("text", QVariant::fromValue(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HifiMenu::setRootMenu(QObject* rootMenu) {
|
||||||
|
_rootMenu = rootMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HifiMenu::enableMenuItem(const QString & menuOption, bool enabled) {
|
||||||
|
QObject* menuItem = findMenuObject(menuOption);
|
||||||
|
if (!menuItem) {
|
||||||
|
warn(menuOption);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
menuItem->setProperty("enabled", QVariant::fromValue(enabled));
|
||||||
|
}
|
||||||
|
|
||||||
|
void HifiMenu::addCheckableMenuItem(const QString& parentMenu, const QString& menuOption, bool checked) {
|
||||||
|
addMenuItem(parentMenu, menuOption);
|
||||||
|
setCheckable(menuOption);
|
||||||
|
if (checked) {
|
||||||
|
setChecked(menuOption, checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HifiMenu::addCheckableMenuItem(const QString& parentMenu, const QString& menuOption, bool checked, std::function<void(bool)> f) {
|
||||||
|
setToggleAction(menuOption, f);
|
||||||
|
addCheckableMenuItem(parentMenu, menuOption, checked);
|
||||||
|
}
|
72
libraries/ui/src/HifiMenu.h
Normal file
72
libraries/ui/src/HifiMenu.h
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
//
|
||||||
|
// MenuConstants.h
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2015/04/21
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#ifndef hifi_MenuContants_h
|
||||||
|
#define hifi_MenuConstants_h
|
||||||
|
|
||||||
|
#include <QQuickItem>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QList>
|
||||||
|
#include <QSignalMapper>
|
||||||
|
#include "OffscreenUi.h"
|
||||||
|
|
||||||
|
class HifiMenu : public QQuickItem {
|
||||||
|
Q_OBJECT
|
||||||
|
HIFI_QML_DECL_LAMBDA
|
||||||
|
|
||||||
|
public:
|
||||||
|
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 addMenuItem(const QString& parentMenu, const QString& menuOption);
|
||||||
|
void addCheckableMenuItem(const QString& parentMenu, const QString& menuOption, bool checked = false);
|
||||||
|
void addCheckableMenuItem(const QString& parentMenu, const QString& menuOption, bool checked, std::function<void(bool)> f);
|
||||||
|
void addMenuItem(const QString& parentMenu, const QString& menuOption, std::function<void()> f);
|
||||||
|
void removeMenuItem(const QString& menuitem);
|
||||||
|
bool menuItemExists(const QString& menuName, const QString& menuitem) const;
|
||||||
|
void triggerMenuItem(const QString& menuOption);
|
||||||
|
void enableMenuItem(const QString& menuOption, bool enabled = true);
|
||||||
|
bool isChecked(const QString& menuOption) const;
|
||||||
|
void setChecked(const QString& menuOption, bool isChecked = true);
|
||||||
|
void setCheckable(const QString& menuOption, bool checkable = true);
|
||||||
|
void setExclusiveGroup(const QString& menuOption, const QString & groupName);
|
||||||
|
void setText(const QString& menuOption, const QString& text);
|
||||||
|
|
||||||
|
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* findMenuObject(const QString& name);
|
||||||
|
const QObject* findMenuObject(const QString& name) const;
|
||||||
|
QObject* _rootMenu{ nullptr };
|
||||||
|
QSignalMapper _triggerMapper;
|
||||||
|
QSignalMapper _toggleMapper;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_MenuConstants_h
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
#include "MenuConstants.h"
|
|
||||||
#include <QtQml>
|
|
||||||
|
|
||||||
QML_DIALOG_DEF(HifiMenu)
|
|
||||||
|
|
||||||
static bool init = false;
|
|
||||||
|
|
||||||
HifiMenu::HifiMenu(QQuickItem * parent) : QQuickItem(parent) {
|
|
||||||
this->setEnabled(false);
|
|
||||||
qWarning() << "Setting up connection";
|
|
||||||
connect(this, &HifiMenu::enabledChanged, this, [=]() {
|
|
||||||
if (init) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
init = true;
|
|
||||||
foreach(QObject * action, findChildren<QObject*>(QRegularExpression(".*HifiAction"))) {
|
|
||||||
connect(action, SIGNAL(triggeredByName(QString)), this, SLOT(onTriggeredByName(QString)));
|
|
||||||
connect(action, SIGNAL(toggledByName(QString)), this, SLOT(onToggledByName(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 (triggerActions.count(name)) {
|
|
||||||
if (toggleActions.count(name)) {
|
|
||||||
QObject * action = findChild<QObject*>(name + "HifiAction");
|
|
||||||
bool checked = action->property("checked").toBool();
|
|
||||||
toggleActions[name](checked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<QString, std::function<void()>> HifiMenu::triggerActions;
|
|
||||||
QHash<QString, std::function<void(bool)>> HifiMenu::toggleActions;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
//
|
|
||||||
// MenuConstants.h
|
|
||||||
//
|
|
||||||
// Created by Bradley Austin Davis on 2015/04/21
|
|
||||||
// Copyright 2015 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef hifi_MenuContants_h
|
|
||||||
#define hifi_MenuConstants_h
|
|
||||||
|
|
||||||
#include <QQuickItem>
|
|
||||||
#include <QHash>
|
|
||||||
#include <QList>
|
|
||||||
#include "OffscreenQmlDialog.h"
|
|
||||||
|
|
||||||
class HifiMenu : public QQuickItem
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
QML_DIALOG_DECL
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
HifiMenu(QQuickItem * parent = nullptr);
|
|
||||||
static void setToggleAction(const QString & name, std::function<void(bool)> f);
|
|
||||||
static void setTriggerAction(const QString & name, std::function<void()> f);
|
|
||||||
private slots:
|
|
||||||
void onTriggeredByName(const QString & name);
|
|
||||||
void onToggledByName(const QString & name);
|
|
||||||
private:
|
|
||||||
static QHash<QString, std::function<void()>> triggerActions;
|
|
||||||
static QHash<QString, std::function<void(bool)>> toggleActions;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_MenuConstants_h
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
#include <QtQml>
|
#include <QtQml>
|
||||||
#include "MessageDialog.h"
|
#include "MessageDialog.h"
|
||||||
|
|
||||||
|
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(offscreenFocus)
|
||||||
|
Q_LOGGING_CATEGORY(offscreenFocus, "hifi.offscreen.focus")
|
||||||
|
|
||||||
// Time between receiving a request to render the offscreen UI actually triggering
|
// Time between receiving a request to render the offscreen UI actually triggering
|
||||||
// the render. Could possibly be increased depending on the framerate we expect to
|
// the render. Could possibly be increased depending on the framerate we expect to
|
||||||
// achieve.
|
// achieve.
|
||||||
|
@ -93,10 +97,10 @@ void OffscreenUi::create(QOpenGLContext* shareContext) {
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
connect(_quickWindow, &QQuickWindow::focusObjectChanged, [this]{
|
connect(_quickWindow, &QQuickWindow::focusObjectChanged, [this]{
|
||||||
qDebug() << "New focus item " << _quickWindow->focusObject();
|
qCDebug(offscreenFocus) << "New focus item " << _quickWindow->focusObject();
|
||||||
});
|
});
|
||||||
connect(_quickWindow, &QQuickWindow::activeFocusItemChanged, [this] {
|
connect(_quickWindow, &QQuickWindow::activeFocusItemChanged, [this] {
|
||||||
qDebug() << "New active focus item " << _quickWindow->activeFocusItem();
|
qCDebug(offscreenFocus) << "New active focus item " << _quickWindow->activeFocusItem();
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,17 @@ public: \
|
||||||
static void load(std::function<void(QQmlContext*, QQuickItem *)> f = [](QQmlContext*, QQuickItem*) {}); \
|
static void load(std::function<void(QQmlContext*, QQuickItem *)> f = [](QQmlContext*, QQuickItem*) {}); \
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
#define HIFI_QML_DECL_LAMBDA \
|
||||||
|
protected: \
|
||||||
|
static const QString NAME; \
|
||||||
|
static const QUrl QML; \
|
||||||
|
public: \
|
||||||
|
static void registerType(); \
|
||||||
|
static void show(); \
|
||||||
|
static void toggle(); \
|
||||||
|
static void load(); \
|
||||||
|
private:
|
||||||
|
|
||||||
#define HIFI_QML_DEF(x) \
|
#define HIFI_QML_DEF(x) \
|
||||||
const QUrl x::QML = QUrl(#x ".qml"); \
|
const QUrl x::QML = QUrl(#x ".qml"); \
|
||||||
const QString x::NAME = #x; \
|
const QString x::NAME = #x; \
|
||||||
|
@ -65,6 +76,25 @@ private:
|
||||||
offscreenUi->load(QML, f); \
|
offscreenUi->load(QML, f); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HIFI_QML_DEF_LAMBDA(x, f) \
|
||||||
|
const QUrl x::QML = QUrl(#x ".qml"); \
|
||||||
|
const QString x::NAME = #x; \
|
||||||
|
\
|
||||||
|
void x::registerType() { \
|
||||||
|
qmlRegisterType<x>("Hifi", 1, 0, NAME.toLocal8Bit().constData()); \
|
||||||
|
} \
|
||||||
|
void x::show() { \
|
||||||
|
auto offscreenUi = DependencyManager::get<OffscreenUi>(); \
|
||||||
|
offscreenUi->show(QML, NAME, f); \
|
||||||
|
} \
|
||||||
|
void x::toggle() { \
|
||||||
|
auto offscreenUi = DependencyManager::get<OffscreenUi>(); \
|
||||||
|
offscreenUi->toggle(QML, NAME, f); \
|
||||||
|
} \
|
||||||
|
void x::load() { \
|
||||||
|
auto offscreenUi = DependencyManager::get<OffscreenUi>(); \
|
||||||
|
offscreenUi->load(QML, f); \
|
||||||
|
}
|
||||||
|
|
||||||
class OffscreenUi : public OffscreenGlCanvas, public Dependency {
|
class OffscreenUi : public OffscreenGlCanvas, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
|
||||||
#include "MessageDialog.h"
|
#include "MessageDialog.h"
|
||||||
#include "MenuConstants.h"
|
#include "HifiMenu.h"
|
||||||
|
|
||||||
class RateCounter {
|
class RateCounter {
|
||||||
std::vector<float> times;
|
std::vector<float> times;
|
||||||
|
@ -181,11 +181,25 @@ public:
|
||||||
offscreenUi->setBaseUrl(QUrl::fromLocalFile(getQmlDir()));
|
offscreenUi->setBaseUrl(QUrl::fromLocalFile(getQmlDir()));
|
||||||
offscreenUi->load(QUrl("TestRoot.qml"));
|
offscreenUi->load(QUrl("TestRoot.qml"));
|
||||||
offscreenUi->load(QUrl("RootMenu.qml"));
|
offscreenUi->load(QUrl("RootMenu.qml"));
|
||||||
|
HifiMenu::load();
|
||||||
|
QObject* menuObject = offscreenUi->getRootItem()->findChild<QObject*>("HifiMenu");
|
||||||
|
HifiMenu* menu = offscreenUi->getRootItem()->findChild<HifiMenu*>();
|
||||||
|
menu->addMenu("", "File");
|
||||||
|
menu->addMenuItem("File", "Quit", []{
|
||||||
|
QApplication::quit();
|
||||||
|
});
|
||||||
|
menu->addCheckableMenuItem("File", "Toggle", false, [](bool toggled) {
|
||||||
|
qDebug() << "Toggle is " << toggled;
|
||||||
|
});
|
||||||
|
menu->addMenu("", "Edit");
|
||||||
|
menu->addMenuItem("Edit", "Undo");
|
||||||
|
menu->addMenuItem("Edit", "Redo");
|
||||||
|
menu->addMenuItem("Edit", "Copy");
|
||||||
|
menu->addMenuItem("Edit", "Cut");
|
||||||
|
menu->addMenuItem("Edit", "Paste");
|
||||||
|
menu->addMenu("", "Long Menu Name...");
|
||||||
#endif
|
#endif
|
||||||
installEventFilter(offscreenUi.data());
|
installEventFilter(offscreenUi.data());
|
||||||
//HifiMenu::setTriggerAction(MenuOption::Quit, [] {
|
|
||||||
// QApplication::quit();
|
|
||||||
//});
|
|
||||||
offscreenUi->resume();
|
offscreenUi->resume();
|
||||||
_timer.start();
|
_timer.start();
|
||||||
}
|
}
|
||||||
|
@ -233,30 +247,16 @@ protected:
|
||||||
resizeWindow(ev->size());
|
resizeWindow(ev->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static QObject * addMenu(QObject * parent, const QString & text) {
|
|
||||||
// FIXME add more checking here to ensure no name conflicts
|
|
||||||
QVariant returnedValue;
|
|
||||||
QMetaObject::invokeMethod(parent, "addMenu",
|
|
||||||
Q_RETURN_ARG(QVariant, returnedValue),
|
|
||||||
Q_ARG(QVariant, text));
|
|
||||||
QObject * result = returnedValue.value<QObject*>();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void keyPressEvent(QKeyEvent *event) {
|
void keyPressEvent(QKeyEvent *event) {
|
||||||
_altPressed = Qt::Key_Alt == event->key();
|
_altPressed = Qt::Key_Alt == event->key();
|
||||||
switch (event->key()) {
|
switch (event->key()) {
|
||||||
case Qt::Key_L:
|
case Qt::Key_L:
|
||||||
if (event->modifiers() & Qt::CTRL) {
|
if (event->modifiers() & Qt::CTRL) {
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
rootMenu = offscreenUi->getRootItem()->findChild<QObject*>("rootMenu");
|
HifiMenu * menu = offscreenUi->findChild<HifiMenu*>();
|
||||||
QObject * result = addMenu(rootMenu, "Test 3");
|
menu->addMenuItem("", "Test 3");
|
||||||
result->setParent(rootMenu);
|
menu->addMenuItem("File", "Test 3");
|
||||||
qDebug() << "Added " << result;
|
|
||||||
if (menuContext) {
|
|
||||||
menuContext->setContextProperty("rootMenu", rootMenu);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Qt::Key_K:
|
case Qt::Key_K:
|
||||||
|
@ -279,12 +279,7 @@ protected:
|
||||||
QQmlContext* menuContext{ nullptr };
|
QQmlContext* menuContext{ nullptr };
|
||||||
void keyReleaseEvent(QKeyEvent *event) {
|
void keyReleaseEvent(QKeyEvent *event) {
|
||||||
if (_altPressed && Qt::Key_Alt == event->key()) {
|
if (_altPressed && Qt::Key_Alt == event->key()) {
|
||||||
HifiMenu::toggle([=](QQmlContext* context, QObject* newItem) {
|
HifiMenu::toggle();
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
|
||||||
rootMenu = offscreenUi->getRootItem()->findChild<QObject*>("rootMenu");
|
|
||||||
menuContext = context;
|
|
||||||
menuContext->setContextProperty("rootMenu", rootMenu);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,13 +322,12 @@ void QTestWindow::renderQml() {
|
||||||
|
|
||||||
const char * LOG_FILTER_RULES = R"V0G0N(
|
const char * LOG_FILTER_RULES = R"V0G0N(
|
||||||
*.debug=false
|
*.debug=false
|
||||||
qt.quick.dialogs.registration=true
|
qt.quick.mouse.debug=false
|
||||||
qt.quick.mouse.debug = true
|
|
||||||
)V0G0N";
|
)V0G0N";
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app(argc, argv);
|
||||||
//QLoggingCategory::setFilterRules(LOG_FILTER_RULES);
|
// QLoggingCategory::setFilterRules(LOG_FILTER_RULES);
|
||||||
QTestWindow window;
|
QTestWindow window;
|
||||||
app.exec();
|
app.exec();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue