Working on menus

This commit is contained in:
Brad Davis 2015-04-22 18:11:42 -07:00
parent d2ff89aaec
commit 8cb298a55b
36 changed files with 1717 additions and 389 deletions

View file

@ -128,7 +128,7 @@ target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES})
# link required hifi libraries # link required hifi libraries
link_hifi_libraries(shared octree environment gpu model fbx networking entities avatars link_hifi_libraries(shared octree environment gpu model fbx networking entities avatars
audio audio-client animation script-engine physics audio audio-client animation script-engine physics
render-utils entities-renderer) render-utils entities-renderer ui)
add_dependency_external_projects(sdl2) add_dependency_external_projects(sdl2)

Binary file not shown.

View file

@ -1,6 +1,7 @@
import Hifi 1.0 import Hifi 1.0
import QtQuick 2.3 import QtQuick 2.3
import "controls" import "controls"
import "styles"
Dialog { Dialog {
title: "Go to..." title: "Go to..."

View file

@ -0,0 +1,20 @@
import QtQuick 2.4
import QtQuick.Controls 1.3
Action {
property string name
objectName: name + "HifiAction"
text: qsTr(name)
signal triggeredByName(string name);
signal toggledByName(string name);
onTriggered: {
triggeredByName(name);
}
onToggled: {
toggledByName(name, checked);
}
}

View file

@ -2,6 +2,7 @@ import Hifi 1.0
import QtQuick 2.3 import QtQuick 2.3
import QtQuick.Controls.Styles 1.3 import QtQuick.Controls.Styles 1.3
import "controls" import "controls"
import "styles"
Dialog { Dialog {
title: "Login" title: "Login"

View file

@ -0,0 +1,375 @@
import Hifi 1.0 as Hifi
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
import "controls"
import "styles"
Hifi.Menu {
id: root
anchors.fill: parent
objectName: "Menu"
enabled: false
opacity: 0.0
property int animationDuration: 200
HifiPalette { id: hifiPalette }
onEnabledChanged: {
if (enabled && columns.length == 0) {
pushColumn(menu.items);
}
opacity = enabled ? 1.0 : 0.0
if (enabled) {
forceActiveFocus()
}
}
// The actual animator
Behavior on opacity {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.InOutBounce
}
}
onOpacityChanged: {
visible = (opacity != 0.0);
}
onVisibleChanged: {
if (!visible) reset();
}
property var menu: Menu {}
property var models: []
property var columns: []
property var itemBuilder: Component {
Text {
SystemPalette { id: sp; colorGroup: SystemPalette.Active }
id: thisText
property var source
property var root
property var listViewIndex
property var listView
text: typedText()
height: implicitHeight
width: implicitWidth
color: source.enabled ? "black" : "gray"
onImplicitWidthChanged: {
width = implicitWidth
if (listView) {
listView.minWidth = Math.max(listView.minWidth, implicitWidth);
listView.recalculateSize();
}
}
onImplicitHeightChanged: {
height = implicitHeight
}
function typedText() {
switch(source.type) {
case 2:
return source.title;
case 1:
return source.text;
case 0:
return "-----"
}
}
MouseArea {
id: mouseArea
acceptedButtons: Qt.LeftButton
anchors.fill: parent
onClicked: {
listView.currentIndex = listViewIndex
parent.root.selectItem(parent.source);
}
}
}
}
property var menuBuilder: Component {
Border {
SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active }
x: root.models.length * 60;
anchors.verticalCenter: parent.verticalCenter
border.color: hifiPalette.hifiBlue
color: sysPalette.window
ListView {
spacing: 6
property int outerMargin: 8
property real minWidth: 0
anchors.fill: parent
anchors.margins: outerMargin
id: listView
height: root.height
currentIndex: -1
onCountChanged: {
recalculateSize()
}
function recalculateSize() {
var newHeight = 0
var newWidth = minWidth;
for (var i = 0; i < children.length; ++i) {
var item = children[i];
newHeight += item.height
}
parent.height = newHeight + outerMargin * 2;
parent.width = newWidth + outerMargin * 2
}
highlight: Rectangle {
width: 0; height: 32
color: sysPalette.highlight
y: (listView.currentItem) ? listView.currentItem.y : 0;
Behavior on y {
NumberAnimation {
duration: 100
easing.type: Easing.InOutQuint
}
}
}
Keys.onPressed: {
switch (event.key) {
case Qt.Key_Escape:
console.log("Backing out")
root.popColumn()
event.accepted = true;
}
}
property int columnIndex: root.models.length - 1
model: root.models[columnIndex]
delegate: Loader {
id: loader
sourceComponent: root.itemBuilder
Binding {
target: loader.item
property: "root"
value: root
when: loader.status == Loader.Ready
}
Binding {
target: loader.item
property: "source"
value: modelData
when: loader.status == Loader.Ready
}
Binding {
target: loader.item
property: "listViewIndex"
value: index
when: loader.status == Loader.Ready
}
Binding {
target: loader.item
property: "listView"
value: listView
when: loader.status == Loader.Ready
}
}
}
}
}
function lastColumn() {
return columns[root.columns.length - 1];
}
function pushColumn(items) {
models.push(items)
if (columns.length) {
var oldColumn = lastColumn();
oldColumn.enabled = false;
oldColumn.opacity = 0.5;
}
var newColumn = menuBuilder.createObject(root);
columns.push(newColumn);
newColumn.forceActiveFocus();
}
function popColumn() {
if (columns.length > 1) {
var curColumn = columns.pop();
console.log(curColumn);
curColumn.visible = false;
curColumn.destroy();
models.pop();
curColumn = lastColumn();
curColumn.enabled = true;
curColumn.opacity = 1.0;
curColumn.forceActiveFocus();
} else {
enabled = false;
}
}
function selectItem(source) {
switch (source.type) {
case 2:
pushColumn(source.items)
break;
case 1:
console.log("Triggering " + source.text);
source.trigger()
enabled = false
break;
case 0:
break;
}
}
function reset() {
console.log("Resettting")
while (columns.length > 1) {
popColumn();
}
lastColumn().children[0].currentIndex = -1
console.log(lastColumn().children[0])
}
/*
HifiMenu {
id: rootMenu
Menu {
id: menu
Menu {
title: "File"
MenuItem {
action: HifiAction {
name: rootMenu.login
}
}
MenuItem {
action: HifiAction {
name: "Test"
checkable: true
}
}
MenuItem {
action: HifiAction {
name: rootMenu.quit
}
}
}
Menu {
title: "Edit"
MenuItem {
action: HifiAction {
text: "Copy"
shortcut: StandardKey.Copy
}
}
MenuItem {
action: HifiAction {
text: "Cut"
shortcut: StandardKey.Cut
}
}
MenuItem {
action: HifiAction {
text: "Paste"
shortcut: StandardKey.Paste
}
}
MenuItem {
action: HifiAction {
text: "Undo"
shortcut: StandardKey.Undo
}
}
MenuItem {
action: HifiAction {
text: "Redo"
shortcut: StandardKey.Redo
}
}
MenuItem {
action: HifiAction {
name: rootMenu.attachments
}
}
MenuItem {
action: HifiAction {
name: rootMenu.animations
}
}
}
Menu {
title: "Scripts"
MenuItem {
action: HifiAction {
name: rootMenu.scriptEditor
}
}
MenuItem {
action: HifiAction {
name: rootMenu.loadScript
}
}
MenuItem {
action: HifiAction {
name: rootMenu.loadScriptURL
}
}
MenuItem {
action: HifiAction {
name: rootMenu.stopAllScripts
}
}
MenuItem {
action: HifiAction {
name: rootMenu.reloadAllScripts
}
}
MenuItem {
action: HifiAction {
name: rootMenu.runningScripts
}
}
}
Menu {
title: "Location"
MenuItem {
action: HifiAction {
name: rootMenu.addressBar
}
}
MenuItem {
action: HifiAction {
name: rootMenu.copyAddress
}
}
MenuItem {
action: HifiAction {
name: rootMenu.copyPath
}
}
}
}
}
*/
MouseArea {
anchors.fill: parent
id: mouseArea
acceptedButtons: Qt.RightButton
onClicked: {
root.popColumn();
}
}
}

View file

@ -1,12 +0,0 @@
import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Controls.Styles 1.3
Item {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "red"
}
}

View file

@ -41,7 +41,6 @@
import Hifi 1.0 as Hifi import Hifi 1.0 as Hifi
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Controls 1.2 import QtQuick.Controls 1.2
import QtQuick.Window 2.1
import QtQuick.Dialogs 1.2 import QtQuick.Dialogs 1.2
import "controls" import "controls"

View file

@ -30,14 +30,13 @@ Item {
property string frameColor: hifiPalette.hifiBlue property string frameColor: hifiPalette.hifiBlue
property string backgroundColor: sysPalette.window property string backgroundColor: sysPalette.window
property string headerBackgroundColor: sysPalette.dark property string headerBackgroundColor: sysPalette.dark
clip: true clip: true
enabled: false
scale: 0.0
/* /*
* Support for animating the dialog in and out. * Support for animating the dialog in and out.
*/ */
enabled: false
scale: 0.0
// The offscreen UI will enable an object, rather than manipulating it's // The offscreen UI will enable an object, rather than manipulating it's
// visibility, so that we can do animations in both directions. Because // visibility, so that we can do animations in both directions. Because

View file

@ -1,9 +1,5 @@
import QtQuick 2.3 import QtQuick 2.3
import QtQuick.Controls 1.3 as Original import QtQuick.Controls 1.3 as Original
import QtQuick.Controls.Styles 1.3
import "../styles" import "../styles"
import "../controls"
Original.Button {
style: MenuButtonStyle {
}
}

View file

@ -1,24 +1,22 @@
import QtQuick 2.4
import QtQuick.Controls.Styles 1.3
import "../controls" import "../controls"
import "." import "."
ButtonStyle { ButtonStyle {
SystemPalette { id: myPalette; colorGroup: SystemPalette.Active } HifiPalette { id: hifiPalette }
padding { padding {
top: 8 top: 2
left: 12 left: 4
right: 12 right: 4
bottom: 8 bottom: 2
} }
background: Border { background: Item {}
anchors.fill: parent
color: "#00000000"
borderColor: "red"
}
label: Text { label: Text {
renderType: Text.NativeRendering renderType: Text.NativeRendering
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
text: control.text text: control.text
color: control.enabled ? myPalette.text : myPalette.dark color: control.enabled ? "yellow" : "brown"
} }
} }

View file

@ -149,6 +149,23 @@ extern "C" {
} }
#endif #endif
enum CustomEventTypes {
Lambda = QEvent::User + 1
};
class LambdaEvent : public QEvent {
std::function<void()> _fun;
public:
LambdaEvent(const std::function<void()> & fun) :
QEvent(static_cast<QEvent::Type>(Lambda)), _fun(fun) {
}
LambdaEvent(std::function<void()> && fun) :
QEvent(static_cast<QEvent::Type>(Lambda)), _fun(fun) {
}
void call() { _fun(); }
};
using namespace std; using namespace std;
// Starfield information // Starfield information
@ -345,9 +362,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
_bookmarks = new Bookmarks(); // Before setting up the menu _bookmarks = new Bookmarks(); // Before setting up the menu
// call Menu getInstance static method to set up the menu
_window->setMenuBar(Menu::getInstance());
_runningScriptsWidget = new RunningScriptsWidget(_window); _runningScriptsWidget = new RunningScriptsWidget(_window);
// start the nodeThread so its event loop is running // start the nodeThread so its event loop is running
@ -497,8 +511,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
// enable mouse tracking; otherwise, we only get drag events // enable mouse tracking; otherwise, we only get drag events
_glWidget->setMouseTracking(true); _glWidget->setMouseTracking(true);
_fullscreenMenuWidget->setParent(_glWidget);
_menuBarHeight = Menu::getInstance()->height();
if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) { if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) {
setFullscreen(true); // Initialize menu bar show/hide setFullscreen(true); // Initialize menu bar show/hide
} }
@ -712,6 +724,13 @@ void Application::initializeGL() {
initDisplay(); initDisplay();
qCDebug(interfaceapp, "Initialized Display."); qCDebug(interfaceapp, "Initialized Display.");
// The UI can't be created until the primary OpenGL
// context is created, because it needs to share
// texture resources
initializeUi();
qCDebug(interfaceapp, "Initialized Offscreen UI.");
_glWidget->makeCurrent();
init(); init();
qCDebug(interfaceapp, "init() complete."); qCDebug(interfaceapp, "init() complete.");
@ -740,11 +759,6 @@ void Application::initializeGL() {
// update before the first render // update before the first render
update(1.0f / _fps); update(1.0f / _fps);
// The UI can't be created until the primary OpenGL
// context is created, because it needs to share
// texture resources
initializeUi();
InfoView::showFirstTime(INFO_HELP_PATH); InfoView::showFirstTime(INFO_HELP_PATH);
} }
@ -764,6 +778,7 @@ void Application::initializeUi() {
LoginDialog::registerType(); LoginDialog::registerType();
MarketplaceDialog::registerType(); MarketplaceDialog::registerType();
MessageDialog::registerType(); MessageDialog::registerType();
Menu::registerType();
auto offscreenUi = DependencyManager::get<OffscreenUi>(); auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->create(_glWidget->context()->contextHandle()); offscreenUi->create(_glWidget->context()->contextHandle());
@ -898,9 +913,7 @@ void Application::runTests() {
} }
void Application::audioMuteToggled() { void Application::audioMuteToggled() {
QAction* muteAction = Menu::getInstance()->getActionForOption(MenuOption::MuteAudio); Menu::getInstance()->setIsOptionChecked(MenuOption::MuteAudio, DependencyManager::get<AudioClient>()->isMuted());
Q_CHECK_PTR(muteAction);
muteAction->setChecked(DependencyManager::get<AudioClient>()->isMuted());
} }
void Application::aboutApp() { void Application::aboutApp() {
@ -982,6 +995,10 @@ bool Application::importSVOFromURL(const QString& urlString) {
bool Application::event(QEvent* event) { bool Application::event(QEvent* event) {
switch (event->type()) { switch (event->type()) {
case Lambda:
((LambdaEvent*)event)->call();
return true;
case QEvent::MouseMove: case QEvent::MouseMove:
mouseMoveEvent((QMouseEvent*)event); mouseMoveEvent((QMouseEvent*)event);
return true; return true;
@ -1061,8 +1078,10 @@ bool Application::eventFilter(QObject* object, QEvent* event) {
return false; return false;
} }
void Application::keyPressEvent(QKeyEvent* event) { static bool _altPressed;
void Application::keyPressEvent(QKeyEvent* event) {
_altPressed = event->key() == Qt::Key_Alt;
_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
@ -1314,6 +1333,9 @@ void Application::keyPressEvent(QKeyEvent* event) {
} }
void Application::keyReleaseEvent(QKeyEvent* event) { void Application::keyReleaseEvent(QKeyEvent* event) {
if (event->key() == Qt::Key_Alt && _altPressed) {
Menu::toggle();
}
_keysPressed.remove(event->key()); _keysPressed.remove(event->key());
@ -1420,18 +1442,6 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
return; 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); _entities.mouseMoveEvent(event, deviceID);
_controllerScriptingInterface.emitMouseMoveEvent(event, deviceID); // send events to any registered scripts _controllerScriptingInterface.emitMouseMoveEvent(event, deviceID); // send events to any registered scripts
@ -1439,7 +1449,6 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
if (_controllerScriptingInterface.isMouseCaptured()) { if (_controllerScriptingInterface.isMouseCaptured()) {
return; return;
} }
} }
void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) {
@ -1724,34 +1733,6 @@ void Application::setFullscreen(bool fullscreen) {
Menu::getInstance()->getActionForOption(MenuOption::Fullscreen)->setChecked(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. // Work around Qt bug that prevents floating menus being shown when in fullscreen mode.
// https://bugreports.qt.io/browse/QTBUG-41883 // 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. // Known issue: Top-level menu items don't highlight when cursor hovers. This is probably a side-effect of the work-around.
@ -2004,16 +1985,18 @@ void Application::init() {
OculusManager::connect(); OculusManager::connect();
if (OculusManager::isConnected()) { if (OculusManager::isConnected()) {
QMetaObject::invokeMethod(Menu::getInstance()->getActionForOption(MenuOption::Fullscreen), // perform as a post-event so that the code is run after init is complete
"trigger", qApp->postLambdaEvent([] {
Qt::QueuedConnection); Menu::getInstance()->triggerOption(MenuOption::Fullscreen);
});
} }
TV3DManager::connect(); TV3DManager::connect();
if (TV3DManager::isConnected()) { if (TV3DManager::isConnected()) {
QMetaObject::invokeMethod(Menu::getInstance()->getActionForOption(MenuOption::Fullscreen), // perform as a post-event so that the code is run after init is complete
"trigger", qApp->postLambdaEvent([] {
Qt::QueuedConnection); Menu::getInstance()->triggerOption(MenuOption::Fullscreen);
});
} }
_timerStart.start(); _timerStart.start();
@ -4434,3 +4417,7 @@ void Application::friendsWindowClosed() {
delete _friendsWindow; delete _friendsWindow;
_friendsWindow = NULL; _friendsWindow = NULL;
} }
void Application::postLambdaEvent(std::function<void()> f) {
QCoreApplication::postEvent(this, new LambdaEvent(f));
}

View file

@ -21,6 +21,7 @@
#include <QSet> #include <QSet>
#include <QStringList> #include <QStringList>
#include <QUndoStack> #include <QUndoStack>
#include <functional>
#include <AbstractScriptingServicesInterface.h> #include <AbstractScriptingServicesInterface.h>
#include <AbstractViewStateInterface.h> #include <AbstractViewStateInterface.h>
@ -147,6 +148,8 @@ public:
Application(int& argc, char** argv, QElapsedTimer &startup_time); Application(int& argc, char** argv, QElapsedTimer &startup_time);
~Application(); ~Application();
void postLambdaEvent(std::function<void()> f);
void loadScripts(); void loadScripts();
QString getPreviousScriptLocation(); QString getPreviousScriptLocation();
void setPreviousScriptLocation(const QString& previousScriptLocation); void setPreviousScriptLocation(const QString& previousScriptLocation);
@ -620,9 +623,6 @@ private:
void checkSkeleton(); void checkSkeleton();
QWidget* _fullscreenMenuWidget = new QWidget();
int _menuBarHeight;
QHash<QString, AcceptURLMethod> _acceptedExtensions; QHash<QString, AcceptURLMethod> _acceptedExtensions;
QList<QString> _domainConnectionRefusals; QList<QString> _domainConnectionRefusals;

View file

@ -84,13 +84,16 @@ void Bookmarks::persistToFile() {
saveFile.write(data); saveFile.write(data);
} }
void Bookmarks::setupMenus(Menu* menubar, QMenu* menu) { void Bookmarks::setupMenus(const QString & parentMenu) {
// Add menus/actions // Add menus/actions
menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkLocation, 0, Menu * menu = Menu::getInstance();
this, SLOT(bookmarkLocation())); menu->addMenuItem(parentMenu, MenuOption::BookmarkLocation, [this] {
_bookmarksMenu = menu->addMenu(MenuOption::Bookmarks); bookmarkLocation();
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark, 0, });
this, SLOT(deleteBookmark())); menu->addMenu(parentMenu, MenuOption::Bookmarks);
menu->addMenuItem(parentMenu, MenuOption::DeleteBookmark, [this] {
deleteBookmark();
});
// Enable/Disable menus as needed // Enable/Disable menus as needed
enableMenuItems(_bookmarks.count() > 0); enableMenuItems(_bookmarks.count() > 0);
@ -99,7 +102,7 @@ void Bookmarks::setupMenus(Menu* menubar, QMenu* menu) {
for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it ) { for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it ) {
QString bookmarkName = it.key(); QString bookmarkName = it.key();
QString bookmarkAddress = it.value().toString(); QString bookmarkAddress = it.value().toString();
addLocationToMenu(menubar, bookmarkName, bookmarkAddress); addLocationToMenu(bookmarkName, bookmarkAddress);
} }
} }
@ -134,29 +137,20 @@ void Bookmarks::bookmarkLocation() {
if (duplicateBookmarkMessage.exec() == QMessageBox::No) { if (duplicateBookmarkMessage.exec() == QMessageBox::No) {
return; return;
} }
removeLocationFromMenu(menubar, bookmarkName); removeLocationFromMenu(bookmarkName);
} }
addLocationToMenu(menubar, bookmarkName, bookmarkAddress); addLocationToMenu(bookmarkName, bookmarkAddress);
insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName. insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName.
enableMenuItems(true); enableMenuItems(true);
} }
void Bookmarks::teleportToBookmark() {
QAction* action = qobject_cast<QAction*>(sender());
QString address = action->data().toString();
DependencyManager::get<AddressManager>()->handleLookupString(address);
}
void Bookmarks::deleteBookmark() { void Bookmarks::deleteBookmark() {
QStringList bookmarkList; QStringList bookmarkList;
QList<QAction*> menuItems = _bookmarksMenu->actions(); bookmarkList.append(_bookmarks.keys());
for (int i = 0; i < menuItems.count(); i += 1) {
bookmarkList.append(menuItems[i]->text());
}
QInputDialog deleteBookmarkDialog(qApp->getWindow()); QInputDialog deleteBookmarkDialog(qApp->getWindow());
deleteBookmarkDialog.setWindowTitle("Delete Bookmark"); deleteBookmarkDialog.setWindowTitle("Delete Bookmark");
deleteBookmarkDialog.setLabelText("Select the bookmark to delete"); deleteBookmarkDialog.setLabelText("Select the bookmark to delete");
@ -174,34 +168,29 @@ void Bookmarks::deleteBookmark() {
return; return;
} }
removeLocationFromMenu(Menu::getInstance(), bookmarkName); removeLocationFromMenu(bookmarkName);
remove(bookmarkName); remove(bookmarkName);
if (_bookmarksMenu->actions().count() == 0) { if (_bookmarks.keys().isEmpty()) {
enableMenuItems(false); enableMenuItems(false);
} }
} }
void Bookmarks::enableMenuItems(bool enabled) { void Bookmarks::enableMenuItems(bool enabled) {
if (_bookmarksMenu) { Menu* menu = Menu::getInstance();
_bookmarksMenu->setEnabled(enabled); menu->enableMenuItem(MenuOption::Bookmarks, enabled);
} menu->enableMenuItem(MenuOption::DeleteBookmark, enabled);
if (_deleteBookmarksAction) {
_deleteBookmarksAction->setEnabled(enabled);
}
} }
void Bookmarks::addLocationToMenu(Menu* menubar, QString& name, QString& address) { void Bookmarks::addLocationToMenu(QString& name, QString& address) {
QAction* teleportAction = new QAction(_bookmarksMenu);
teleportAction->setData(address); Menu::getInstance()->addMenuItem(MenuOption::Bookmarks, name, [=] {
connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark())); DependencyManager::get<AddressManager>()->handleLookupString(address);
});
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction,
name, 0, QAction::NoRole);
} }
void Bookmarks::removeLocationFromMenu(Menu* menubar, QString& name) { void Bookmarks::removeLocationFromMenu(QString& name) {
menubar->removeAction(_bookmarksMenu, name); Menu::getInstance()->removeMenuItem(name);
} }

View file

@ -26,19 +26,16 @@ class Bookmarks: public QObject {
public: public:
Bookmarks(); Bookmarks();
void setupMenus(Menu* menubar, QMenu* menu); void setupMenus(const QString & menu);
private slots: private slots:
void bookmarkLocation(); void bookmarkLocation();
void teleportToBookmark();
void deleteBookmark(); void deleteBookmark();
private: private:
// FIXME bookmarks should be more categorizable
// Can we leverage a system browser favorites API?
QVariantMap _bookmarks; // { name: address, ... } QVariantMap _bookmarks; // { name: address, ... }
QPointer<QMenu> _bookmarksMenu;
QPointer<QAction> _deleteBookmarksAction;
const QString BOOKMARKS_FILENAME = "bookmarks.json"; const QString BOOKMARKS_FILENAME = "bookmarks.json";
QString _bookmarksFilename; QString _bookmarksFilename;
@ -50,8 +47,8 @@ private:
void persistToFile(); void persistToFile();
void enableMenuItems(bool enabled); void enableMenuItems(bool enabled);
void addLocationToMenu(Menu* menubar, QString& name, QString& address); void addLocationToMenu(QString& name, QString& address);
void removeLocationFromMenu(Menu* menubar, QString& name); void removeLocationFromMenu(QString& name);
}; };
#endif // hifi_Bookmarks_h #endif // hifi_Bookmarks_h

View file

@ -12,6 +12,7 @@
#include <QFileDialog> #include <QFileDialog>
#include <QMenuBar> #include <QMenuBar>
#include <QShortcut> #include <QShortcut>
#include <QmlContext>
#include <AddressManager.h> #include <AddressManager.h>
#include <AudioClient.h> #include <AudioClient.h>
@ -20,7 +21,7 @@
#include <PathUtils.h> #include <PathUtils.h>
#include <SettingHandle.h> #include <SettingHandle.h>
#include <UserActivityLogger.h> #include <UserActivityLogger.h>
#include <OffscreenUi.h>
#include "Application.h" #include "Application.h"
#include "AccountManager.h" #include "AccountManager.h"
#include "audio/AudioIOStatsRenderer.h" #include "audio/AudioIOStatsRenderer.h"
@ -42,64 +43,176 @@
#include "Menu.h" #include "Menu.h"
Menu* Menu::_instance = NULL; // Proxy object to simplify porting over
HifiAction::HifiAction(const QString & menuOption) : _menuOption(menuOption) {
}
//void HifiAction::setCheckable(bool) {
// Menu::getInstance()->set
// qFatal("Not implemented");
//}
void HifiAction::setChecked(bool) {
qFatal("Not implemented");
}
void HifiAction::setVisible(bool) {
qFatal("Not implemented");
}
const QString & HifiAction::shortcut() const {
qFatal("Not implemented");
return "";
}
void HifiAction::setText(const QString &) {
qFatal("Not implemented");
}
void HifiAction::setTriggerAction(std::function<void()> f) {
qFatal("Not implemented");
}
void HifiAction::setToggleAction(std::function<void(bool)> f) {
qFatal("Not implemented");
}
HIFI_QML_DEF(Menu)
Menu* Menu::_instance = nullptr;
Menu* Menu::getInstance() { Menu* Menu::getInstance() {
static QMutex menuInstanceMutex; // Optimistic check for menu existence
// lock the menu instance mutex to make sure we don't race and create two menus and crash
menuInstanceMutex.lock();
if (!_instance) { if (!_instance) {
qCDebug(interfaceapp, "First call to Menu::getInstance() - initing menu."); static QMutex menuInstanceMutex;
withLock(menuInstanceMutex, [] {
if (!_instance) {
OffscreenUi * offscreenUi = DependencyManager::get<OffscreenUi>().data();
QQmlContext * qmlContext = offscreenUi->qmlContext();
qmlContext->setContextProperty("foo", QVariant::fromValue(foo));
// qmlContext->setContextProperty("presetsModel", QVariant::fromValue(dataList));
_instance = new Menu(); qCDebug(interfaceapp, "First call to Menu::getInstance() - initing menu.");
load([&](QQmlContext *, QQuickItem* item) {
_instance = dynamic_cast<Menu*>(item);
});
if (!_instance) {
qFatal("Could not load menu QML");
} else {
_instance->init();
}
}
});
} }
menuInstanceMutex.unlock();
return _instance; return _instance;
} }
Menu::Menu() { Menu::Menu(QQuickItem * parent) : QQuickItem(parent) {
QMenu* fileMenu = addMenu("File"); }
QObject * _rootMenu;
static const QString FILE_MENU{ "File" };
static const QString EDIT_MENU{ "Edit" };
static const QString TOOLS_MENU{ "Tools" };
static const QString AVATAR_MENU{ "Avatar" };
static const QString MENU_SUFFIX{ "__Menu" };
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;
QMetaObject::invokeMethod(parent, "addItem",
Q_RETURN_ARG(QQuickMenuItem*, returnedValue),
Q_ARG(QString, text));
QObject* result = reinterpret_cast<QObject*>(returnedValue);
if (result) {
result->setObjectName(text + MENU_SUFFIX);
}
return result;
}
void Menu::init() {
_rootMenu = property("menu").value<QObject*>();
QObject * fileMenu = ::addMenu(_rootMenu, FILE_MENU);
#ifdef Q_OS_MAC
addActionToQMenuAndActionHash(fileMenu, MenuOption::AboutApp, 0, qApp, SLOT(aboutApp()), QAction::AboutRole);
#endif
auto dialogsManager = DependencyManager::get<DialogsManager>(); auto dialogsManager = DependencyManager::get<DialogsManager>();
AccountManager& accountManager = AccountManager::getInstance(); AccountManager& accountManager = AccountManager::getInstance();
{ {
addActionToQMenuAndActionHash(fileMenu, MenuOption::Login); ::addItem(fileMenu, MenuOption::Login);
// connect to the appropriate signal of the AccountManager so that we can change the Login/Logout menu item // connect to the appropriate signal of the AccountManager so that we can change the Login/Logout menu item
connect(&accountManager, &AccountManager::profileChanged, connect(&accountManager, &AccountManager::profileChanged,
dialogsManager.data(), &DialogsManager::toggleLoginDialog); dialogsManager.data(), &DialogsManager::toggleLoginDialog);
connect(&accountManager, &AccountManager::logoutComplete, connect(&accountManager, &AccountManager::logoutComplete,
dialogsManager.data(), &DialogsManager::toggleLoginDialog); dialogsManager.data(), &DialogsManager::toggleLoginDialog);
} }
addDisabledActionAndSeparator(fileMenu, "Scripts");
addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O,
qApp, SLOT(loadDialog()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScriptURL,
Qt::CTRL | Qt::SHIFT | Qt::Key_O, qApp, SLOT(loadScriptURLDialog()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::StopAllScripts, 0, qApp, SLOT(stopAllScripts()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::ReloadAllScripts, Qt::CTRL | Qt::Key_R,
qApp, SLOT(reloadAllScripts()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J,
qApp, SLOT(toggleRunningScriptsWidget()));
addDisabledActionAndSeparator(fileMenu, "Location");
qApp->getBookmarks()->setupMenus(this, fileMenu); #ifdef Q_OS_MAC
addActionToQMenuAndActionHash(fileMenu, MenuOption::AboutApp, 0, qApp, SLOT(aboutApp()), QAction::AboutRole);
#endif
{
static const QString SCRIPTS_MENU{ "Scripts" };
addMenu(FILE_MENU, SCRIPTS_MENU);
//Qt::CTRL | Qt::Key_O
addMenuItem(SCRIPTS_MENU, MenuOption::LoadScript, [=] {
qApp->loadDialog();
});
//Qt::CTRL | Qt::SHIFT | Qt::Key_O
addMenuItem(SCRIPTS_MENU, MenuOption::LoadScriptURL, [=] {
qApp->loadScriptURLDialog();
});
addMenuItem(SCRIPTS_MENU, MenuOption::StopAllScripts, [=] {
qApp->stopAllScripts();
});
//Qt::CTRL | Qt::Key_R,
addMenuItem(SCRIPTS_MENU, MenuOption::ReloadAllScripts, [=] {
qApp->reloadAllScripts();
});
// Qt::CTRL | Qt::Key_J,
addMenuItem(SCRIPTS_MENU, MenuOption::RunningScripts, [=] {
qApp->toggleRunningScriptsWidget();
});
}
{
static const QString LOCATION_MENU{ "Location" };
addMenu(FILE_MENU, LOCATION_MENU);
qApp->getBookmarks()->setupMenus(LOCATION_MENU);
//Qt::CTRL | Qt::Key_L
addMenuItem(LOCATION_MENU, MenuOption::AddressBar, [=] {
auto dialogsManager = DependencyManager::get<DialogsManager>();
dialogsManager->toggleAddressBar();
});
addMenuItem(LOCATION_MENU, MenuOption::CopyAddress, [=] {
auto addressManager = DependencyManager::get<AddressManager>();
addressManager->copyAddress();
});
addMenuItem(LOCATION_MENU, MenuOption::CopyAddress, [=] {
auto addressManager = DependencyManager::get<AddressManager>();
addressManager->copyPath();
});
}
#if 0
addActionToQMenuAndActionHash(fileMenu,
MenuOption::AddressBar,
Qt::CTRL | Qt::Key_L,
dialogsManager.data(),
SLOT(toggleAddressBar()));
auto addressManager = DependencyManager::get<AddressManager>();
addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyAddress, 0, addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyAddress, 0,
addressManager.data(), SLOT(copyAddress())); addressManager.data(), SLOT(copyAddress()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyPath, 0, addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyPath, 0,
@ -556,15 +669,17 @@ Menu::Menu() {
QAction* aboutAction = helpMenu->addAction(MenuOption::AboutApp); QAction* aboutAction = helpMenu->addAction(MenuOption::AboutApp);
connect(aboutAction, SIGNAL(triggered()), qApp, SLOT(aboutApp())); connect(aboutAction, SIGNAL(triggered()), qApp, SLOT(aboutApp()));
#endif #endif
#endif
} }
void Menu::loadSettings() { void Menu::loadSettings() {
scanMenuBar(&Menu::loadAction); // scanMenuBar(&Menu::loadAction);
} }
void Menu::saveSettings() { void Menu::saveSettings() {
scanMenuBar(&Menu::saveAction); // scanMenuBar(&Menu::saveAction);
} }
#if 0
void Menu::loadAction(Settings& settings, QAction& action) { void Menu::loadAction(Settings& settings, QAction& action) {
if (action.isChecked() != settings.value(action.text(), action.isChecked()).toBool()) { if (action.isChecked() != settings.value(action.text(), action.isChecked()).toBool()) {
@ -708,36 +823,20 @@ void Menu::removeAction(QMenu* menu, const QString& actionName) {
_actionHash.remove(actionName); _actionHash.remove(actionName);
} }
#endif
void Menu::setIsOptionChecked(const QString& menuOption, bool isChecked) { void Menu::setIsOptionChecked(const QString& menuOption, bool isChecked) {
if (thread() != QThread::currentThread()) {
QMetaObject::invokeMethod(Menu::getInstance(), "setIsOptionChecked", Qt::BlockingQueuedConnection,
Q_ARG(const QString&, menuOption),
Q_ARG(bool, isChecked));
return;
}
QAction* menu = _actionHash.value(menuOption);
if (menu) {
menu->setChecked(isChecked);
}
} }
bool Menu::isOptionChecked(const QString& menuOption) const { bool Menu::isOptionChecked(const QString& menuOption) const {
const QAction* menu = _actionHash.value(menuOption);
if (menu) {
return menu->isChecked();
}
return false; return false;
} }
void Menu::triggerOption(const QString& menuOption) { void Menu::triggerOption(const QString& menuOption) {
QAction* action = _actionHash.value(menuOption);
if (action) {
action->trigger();
} else {
qCDebug(interfaceapp) << "NULL Action for menuOption '" << menuOption << "'";
}
} }
#if 0
QAction* Menu::getActionForOption(const QString& menuOption) { QAction* Menu::getActionForOption(const QString& menuOption) {
return _actionHash.value(menuOption); return _actionHash.value(menuOption);
} }
@ -951,15 +1050,12 @@ void Menu::addMenuItem(const MenuItemProperties& properties) {
QMenuBar::repaint(); QMenuBar::repaint();
} }
} }
#endif
void Menu::removeMenuItem(const QString& menu, const QString& menuitem) { void Menu::removeMenuItem(const QString& menuitem) {
QMenu* menuObj = getMenu(menu);
if (menuObj) {
removeAction(menuObj, menuitem);
QMenuBar::repaint();
}
}; };
#if 0
bool Menu::menuItemExists(const QString& menu, const QString& menuitem) { bool Menu::menuItemExists(const QString& menu, const QString& menuitem) {
QAction* menuItemAction = _actionHash.value(menuitem); QAction* menuItemAction = _actionHash.value(menuitem);
if (menuItemAction) { if (menuItemAction) {
@ -967,3 +1063,29 @@ bool Menu::menuItemExists(const QString& menu, const QString& menuitem) {
} }
return false; return false;
}; };
#endif
void Menu::setOptionText(const QString& menuitem, const QString& text) {
}
void Menu::addMenu(const QString& parentMenu, const QString& text) {
}
void Menu::addMenuItem(const QString& parentMenu, const QString& menuItem) {
}
void Menu::addMenuItem(const QString& parentMenu, const QString& menuItem, std::function<void()> f) {
addMenuItem(parentMenu, menuItem);
setOptionTriggerAction(parentMenu, f);
}
void Menu::enableMenuItem(const QString& menuItem, bool enable) {
}
void Menu::setOptionTriggerAction(const QString& menuOption, std::function<void()> f) {
_triggerActions[menuOption] = f;
}
void Menu::setOptionToggleAction(const QString& menuOption, std::function<void(bool)> f) {
_toggleActions[menuOption] = f;
}

View file

@ -18,85 +18,69 @@
#include <QKeySequence> #include <QKeySequence>
#include <QPointer> #include <QPointer>
#include <QStandardPaths> #include <QStandardPaths>
#include <QQuickItem>
#include <MenuItemProperties.h> #include <MenuItemProperties.h>
#include <OffscreenUi.h>
#include "DiscoverabilityManager.h" #include "DiscoverabilityManager.h"
class Settings; class Settings;
class Menu : public QMenuBar { // Proxy object to simplify porting over
Q_OBJECT class HifiAction {
const QString _menuOption;
public: public:
HifiAction(const QString & menuOption);
void setCheckable(bool);
void setChecked(bool);
void setVisible(bool);
const QString & shortcut() const;
void setText(const QString &);
void setTriggerAction(std::function<void()>);
void setToggleAction(std::function<void(bool)>);
};
class Menu : public QQuickItem {
Q_OBJECT
HIFI_QML_DECL
public:
Menu(QQuickItem * parent = 0);
static Menu* getInstance(); static Menu* getInstance();
void loadSettings(); void loadSettings();
void saveSettings(); void saveSettings();
HifiAction * getActionForOption(const QString& menuOption) {
QMenu* getMenu(const QString& menuName); return new HifiAction(menuOption);
}
void triggerOption(const QString& menuOption); // QMenu* addMenu(const QString& menuName);
QAction* getActionForOption(const QString& menuOption);
QAction* addActionToQMenuAndActionHash(QMenu* 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(QMenu* destinationMenu,
QAction* action,
const QString& actionName = QString(),
const QKeySequence& shortcut = 0,
QAction::MenuRole role = QAction::NoRole,
int menuItemLocation = UNSPECIFIED_POSITION);
void removeAction(QMenu* menu, const QString& actionName);
public slots:
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& menuName, 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); void setIsOptionChecked(const QString& menuOption, bool isChecked);
void triggerOption(const QString& menuOption);
void setOptionText(const QString& menuOption, const QString & text);
void setOptionTriggerAction(const QString& menuOption, std::function<void()> 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:
void init();
private: private:
static Menu* _instance; static Menu* _instance;
Menu();
typedef void(*settingsAction)(Settings&, QAction&); QHash<QString, std::function<void()>> _triggerActions;
static void loadAction(Settings& settings, QAction& action); QHash<QString, std::function<void(bool)>> _toggleActions;
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(QMenu* destinationMenu, const QString& actionName,
int menuItemLocation = UNSPECIFIED_POSITION);
QAction* addCheckableActionToQMenuAndActionHash(QMenu* 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, QMenu* menu);
QMenu* getSubMenuFromName(const QString& menuName, QMenu* menu);
QMenu* getMenuParent(const QString& menuName, QString& finalMenuPart);
QAction* getMenuAction(const QString& menuName);
int findPositionOfMenuItem(QMenu* menu, const QString& searchMenuItem);
int positionBeforeSeparatorIfNeeded(QMenu* menu, int requestedPosition);
QHash<QString, QAction*> _actionHash;
}; };
namespace MenuOption { namespace MenuOption {
@ -251,5 +235,4 @@ namespace MenuOption {
const QString VisibleToNoOne = "No one"; const QString VisibleToNoOne = "No one";
const QString Wireframe = "Wireframe"; const QString Wireframe = "Wireframe";
} }
#endif // hifi_Menu_h #endif // hifi_Menu_h

View file

@ -216,7 +216,7 @@ void OculusManager::connect() {
_isConnected = false; _isConnected = false;
// we're definitely not in "VR mode" so tell the menu that // we're definitely not in "VR mode" so tell the menu that
Menu::getInstance()->getActionForOption(MenuOption::EnableVRMode)->setChecked(false); Menu::getInstance()->setIsOptionChecked(MenuOption::EnableVRMode, false);
} }
} }

View file

@ -8,6 +8,7 @@
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include <gpu/GPUConfig.h>
#include <QFormLayout> #include <QFormLayout>
#include <QGuiApplication> #include <QGuiApplication>

View file

@ -25,19 +25,18 @@ LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent), _root
} }
void LoginDialog::toggleAction() { void LoginDialog::toggleAction() {
AccountManager& accountManager = AccountManager::getInstance(); AccountManager & accountManager = AccountManager::getInstance();
QAction* loginAction = Menu::getInstance()->getActionForOption(MenuOption::Login); Menu* menu = Menu::getInstance();
Q_CHECK_PTR(loginAction);
disconnect(loginAction, 0, 0, 0);
if (accountManager.isLoggedIn()) { if (accountManager.isLoggedIn()) {
// change the menu item to logout // change the menu item to logout
loginAction->setText("Logout " + accountManager.getAccountInfo().getUsername()); menu->setOptionText(MenuOption::Login, "Logout " + accountManager.getAccountInfo().getUsername());
connect(loginAction, &QAction::triggered, &accountManager, &AccountManager::logout); menu->setOptionTriggerAction(MenuOption::Login, [] {
AccountManager::getInstance().logout();
});
} else { } else {
// change the menu item to login // change the menu item to login
loginAction->setText("Login"); menu->setOptionText(MenuOption::Login, "Login");
connect(loginAction, &QAction::triggered, [] { menu->setOptionTriggerAction(MenuOption::Login, [] {
LoginDialog::show(); LoginDialog::show();
}); });
} }

View file

@ -0,0 +1,19 @@
//
// MenuQml.cpp
//
// Created by Bradley Austin Davis on 2015/04/14
// 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
//
#include "Application.h"
#include "MenuQml.h"
QML_DIALOG_DEF(MenuQml)
MenuQml::MenuQml(QQuickItem *parent) : QQuickItem(parent) {
auto menu = Menu::getInstance();
}

View file

@ -0,0 +1,26 @@
//
// MenuQml.h
//
// Created by Bradley Austin Davis on 2015/04/14
// 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_MenuQml_h
#define hifi_MenuQml_h
#include <OffscreenQmlDialog.h>
class MenuQml : public QQuickItem
{
Q_OBJECT
QML_DIALOG_DECL
public:
MenuQml(QQuickItem *parent = 0);
};
#endif

View file

@ -44,8 +44,9 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
connect(&_scriptsModelFilter, &QSortFilterProxyModel::modelReset, connect(&_scriptsModelFilter, &QSortFilterProxyModel::modelReset,
this, &RunningScriptsWidget::selectFirstInList); this, &RunningScriptsWidget::selectFirstInList);
QString shortcutText = Menu::getInstance()->getActionForOption(MenuOption::ReloadAllScripts)->shortcut().toString(QKeySequence::NativeText); // FIXME
ui->tipLabel->setText("Tip: Use " + shortcutText + " to reload all scripts."); // 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.setSourceModel(&_scriptsModel);
_scriptsModelFilter.sort(0, Qt::AscendingOrder); _scriptsModelFilter.sort(0, Qt::AscendingOrder);
@ -161,8 +162,7 @@ void RunningScriptsWidget::showEvent(QShowEvent* event) {
QRect parentGeometry = Application::getInstance()->getDesirableApplicationGeometry(); QRect parentGeometry = Application::getInstance()->getDesirableApplicationGeometry();
int titleBarHeight = UIUtil::getWindowTitleBarHeight(this); int titleBarHeight = UIUtil::getWindowTitleBarHeight(this);
int menuBarHeight = Menu::getInstance()->geometry().height(); int topMargin = titleBarHeight;
int topMargin = titleBarHeight + menuBarHeight;
setGeometry(parentGeometry.topLeft().x(), parentGeometry.topLeft().y() + topMargin, setGeometry(parentGeometry.topLeft().x(), parentGeometry.topLeft().y() + topMargin,
size().width(), parentWidget()->height() - topMargin); size().width(), parentWidget()->height() - topMargin);

View file

@ -38,8 +38,7 @@ bool ToolWindow::event(QEvent* event) {
QRect mainGeometry = mainWindow->geometry(); QRect mainGeometry = mainWindow->geometry();
int titleBarHeight = UIUtil::getWindowTitleBarHeight(this); int titleBarHeight = UIUtil::getWindowTitleBarHeight(this);
int menuBarHeight = Menu::getInstance()->geometry().height(); int topMargin = titleBarHeight;
int topMargin = titleBarHeight + menuBarHeight;
_lastGeometry = QRect(mainGeometry.topLeft().x(), mainGeometry.topLeft().y() + topMargin, _lastGeometry = QRect(mainGeometry.topLeft().x(), mainGeometry.topLeft().y() + topMargin,
DEFAULT_WIDTH, mainGeometry.height() - topMargin); DEFAULT_WIDTH, mainGeometry.height() - topMargin);

View file

@ -0,0 +1,12 @@
set(TARGET_NAME ui)
# use setup_hifi_library macro to setup our project and link appropriate Qt modules
setup_hifi_library(OpenGL Network Qml Quick Script)
link_hifi_libraries(render-utils shared)
add_dependency_external_projects(glm)
find_package(GLM REQUIRED)
target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS})

View file

@ -0,0 +1,50 @@
#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;
}

View file

@ -0,0 +1,503 @@
//
// 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"
namespace MenuOption {
const QString AboutApp = "About Interface";
const QString AddRemoveFriends = "Add/Remove Friends...";
const QString AddressBar = "Show Address Bar";
const QString AlignForearmsWithWrists = "Align Forearms with Wrists";
const QString AlternateIK = "Alternate IK";
const QString AmbientOcclusion = "Ambient Occlusion";
const QString Animations = "Animations...";
const QString Atmosphere = "Atmosphere";
const QString Attachments = "Attachments...";
const QString AudioNoiseReduction = "Audio Noise Reduction";
const QString AudioScope = "Show Scope";
const QString AudioScopeFiftyFrames = "Fifty";
const QString AudioScopeFiveFrames = "Five";
const QString AudioScopeFrames = "Display Frames";
const QString AudioScopePause = "Pause Scope";
const QString AudioScopeTwentyFrames = "Twenty";
const QString AudioStats = "Audio Stats";
const QString AudioStatsShowInjectedStreams = "Audio Stats Show Injected Streams";
const QString BandwidthDetails = "Bandwidth Details";
const QString BlueSpeechSphere = "Blue Sphere While Speaking";
const QString BookmarkLocation = "Bookmark Location";
const QString Bookmarks = "Bookmarks";
const QString CascadedShadows = "Cascaded";
const QString CachesSize = "RAM Caches Size";
const QString Chat = "Chat...";
const QString Collisions = "Collisions";
const QString Console = "Console...";
const QString ControlWithSpeech = "Control With Speech";
const QString CopyAddress = "Copy Address to Clipboard";
const QString CopyPath = "Copy Path to Clipboard";
const QString DDEFaceRegression = "DDE Face Regression";
const QString DDEFiltering = "DDE Filtering";
const QString DecreaseAvatarSize = "Decrease Avatar Size";
const QString DeleteBookmark = "Delete Bookmark...";
const QString DisableActivityLogger = "Disable Activity Logger";
const QString DisableLightEntities = "Disable Light Entities";
const QString DisableNackPackets = "Disable NACK Packets";
const QString DiskCacheEditor = "Disk Cache Editor";
const QString DisplayHands = "Show Hand Info";
const QString DisplayHandTargets = "Show Hand Targets";
const QString DisplayModelBounds = "Display Model Bounds";
const QString DisplayModelTriangles = "Display Model Triangles";
const QString DisplayModelElementChildProxies = "Display Model Element Children";
const QString DisplayModelElementProxy = "Display Model Element Bounds";
const QString DisplayDebugTimingDetails = "Display Timing Details";
const QString DontDoPrecisionPicking = "Don't Do Precision Picking";
const QString DontFadeOnOctreeServerChanges = "Don't Fade In/Out on Octree Server Changes";
const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene";
const QString EchoLocalAudio = "Echo Local Audio";
const QString EchoServerAudio = "Echo Server Audio";
const QString EditEntitiesHelp = "Edit Entities Help...";
const QString Enable3DTVMode = "Enable 3DTV Mode";
const QString EnableCharacterController = "Enable avatar collisions";
const QString EnableGlowEffect = "Enable Glow Effect (Warning: Poor Oculus Performance)";
const QString EnableVRMode = "Enable VR Mode";
const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation";
const QString ExpandMyAvatarTiming = "Expand /myAvatar";
const QString ExpandOtherAvatarTiming = "Expand /otherAvatar";
const QString ExpandPaintGLTiming = "Expand /paintGL";
const QString ExpandUpdateTiming = "Expand /update";
const QString Faceshift = "Faceshift";
const QString FilterSixense = "Smooth Sixense Movement";
const QString FirstPerson = "First Person";
const QString FrameTimer = "Show Timer";
const QString Fullscreen = "Fullscreen";
const QString FullscreenMirror = "Fullscreen Mirror";
const QString GlowWhenSpeaking = "Glow When Speaking";
const QString NamesAboveHeads = "Names Above Heads";
const QString GoToUser = "Go To User";
const QString HMDTools = "HMD Tools";
const QString IncreaseAvatarSize = "Increase Avatar Size";
const QString KeyboardMotorControl = "Enable Keyboard Motor Control";
const QString LeapMotionOnHMD = "Leap Motion on HMD";
const QString LoadScript = "Open and Run Script File...";
const QString LoadScriptURL = "Open and Run Script from URL...";
const QString LoadRSSDKFile = "Load .rssdk file";
const QString LodTools = "LOD Tools";
const QString Login = "Login";
const QString Log = "Log";
const QString LowVelocityFilter = "Low Velocity Filter";
const QString Mirror = "Mirror";
const QString MuteAudio = "Mute Microphone";
const QString MuteEnvironment = "Mute Environment";
const QString NoFaceTracking = "None";
const QString OctreeStats = "Entity Statistics";
const QString OffAxisProjection = "Off-Axis Projection";
const QString OnlyDisplayTopTen = "Only Display Top Ten";
const QString PackageModel = "Package Model...";
const QString Pair = "Pair";
const QString PipelineWarnings = "Log Render Pipeline Warnings";
const QString Preferences = "Preferences...";
const QString Quit = "Quit";
const QString ReloadAllScripts = "Reload All Scripts";
const QString RenderBoundingCollisionShapes = "Show Bounding Collision Shapes";
const QString RenderFocusIndicator = "Show Eye Focus";
const QString RenderHeadCollisionShapes = "Show Head Collision Shapes";
const QString RenderLookAtVectors = "Show Look-at Vectors";
const QString RenderSkeletonCollisionShapes = "Show Skeleton Collision Shapes";
const QString RenderTargetFramerate = "Framerate";
const QString RenderTargetFramerateUnlimited = "Unlimited";
const QString RenderTargetFramerate60 = "60";
const QString RenderTargetFramerate50 = "50";
const QString RenderTargetFramerate40 = "40";
const QString RenderTargetFramerate30 = "30";
const QString RenderTargetFramerateVSyncOn = "V-Sync On";
const QString RenderResolution = "Scale Resolution";
const QString RenderResolutionOne = "1";
const QString RenderResolutionTwoThird = "2/3";
const QString RenderResolutionHalf = "1/2";
const QString RenderResolutionThird = "1/3";
const QString RenderResolutionQuarter = "1/4";
const QString RenderAmbientLight = "Ambient Light";
const QString RenderAmbientLightGlobal = "Global";
const QString RenderAmbientLight0 = "OLD_TOWN_SQUARE";
const QString RenderAmbientLight1 = "GRACE_CATHEDRAL";
const QString RenderAmbientLight2 = "EUCALYPTUS_GROVE";
const QString RenderAmbientLight3 = "ST_PETERS_BASILICA";
const QString RenderAmbientLight4 = "UFFIZI_GALLERY";
const QString RenderAmbientLight5 = "GALILEOS_TOMB";
const QString RenderAmbientLight6 = "VINE_STREET_KITCHEN";
const QString RenderAmbientLight7 = "BREEZEWAY";
const QString RenderAmbientLight8 = "CAMPUS_SUNSET";
const QString RenderAmbientLight9 = "FUNSTON_BEACH_SUNSET";
const QString ResetAvatarSize = "Reset Avatar Size";
const QString ResetDDETracking = "Reset DDE Tracking";
const QString ResetSensors = "Reset Sensors";
const QString RunningScripts = "Running Scripts";
const QString RunTimingTests = "Run Timing Tests";
const QString ScriptEditor = "Script Editor...";
const QString ScriptedMotorControl = "Enable Scripted Motor Control";
const QString ShowBordersEntityNodes = "Show Entity Nodes";
const QString ShowIKConstraints = "Show IK Constraints";
const QString SimpleShadows = "Simple";
const QString SixenseEnabled = "Enable Hydra Support";
const QString SixenseMouseInput = "Enable Sixense Mouse Input";
const QString SixenseLasers = "Enable Sixense UI Lasers";
const QString ShiftHipsForIdleAnimations = "Shift hips for idle animations";
const QString Stars = "Stars";
const QString Stats = "Stats";
const QString StereoAudio = "Stereo Audio (disables spatial sound)";
const QString StopAllScripts = "Stop All Scripts";
const QString SuppressShortTimings = "Suppress Timings Less than 10ms";
const QString TestPing = "Test Ping";
const QString ToolWindow = "Tool Window";
const QString TransmitterDrive = "Transmitter Drive";
const QString TurnWithHead = "Turn using Head";
const QString UseAudioForMouth = "Use Audio for Mouth";
const QString VisibleToEveryone = "Everyone";
const QString VisibleToFriends = "Friends";
const QString VisibleToNoOne = "No one";
const QString Wireframe = "Wireframe";
}
class HifiMenu : public QQuickItem
{
Q_OBJECT
QML_DIALOG_DECL
Q_PROPERTY(QString aboutApp READ aboutApp CONSTANT)
Q_PROPERTY(QString addRemoveFriends READ addRemoveFriends CONSTANT)
Q_PROPERTY(QString addressBar READ addressBar CONSTANT)
Q_PROPERTY(QString alignForearmsWithWrists READ alignForearmsWithWrists CONSTANT)
Q_PROPERTY(QString alternateIK READ alternateIK CONSTANT)
Q_PROPERTY(QString ambientOcclusion READ ambientOcclusion CONSTANT)
Q_PROPERTY(QString animations READ animations CONSTANT)
Q_PROPERTY(QString atmosphere READ atmosphere CONSTANT)
Q_PROPERTY(QString attachments READ attachments CONSTANT)
Q_PROPERTY(QString audioNoiseReduction READ audioNoiseReduction CONSTANT)
Q_PROPERTY(QString audioScope READ audioScope CONSTANT)
Q_PROPERTY(QString audioScopeFiftyFrames READ audioScopeFiftyFrames CONSTANT)
Q_PROPERTY(QString audioScopeFiveFrames READ audioScopeFiveFrames CONSTANT)
Q_PROPERTY(QString audioScopeFrames READ audioScopeFrames CONSTANT)
Q_PROPERTY(QString audioScopePause READ audioScopePause CONSTANT)
Q_PROPERTY(QString audioScopeTwentyFrames READ audioScopeTwentyFrames CONSTANT)
Q_PROPERTY(QString audioStats READ audioStats CONSTANT)
Q_PROPERTY(QString audioStatsShowInjectedStreams READ audioStatsShowInjectedStreams CONSTANT)
Q_PROPERTY(QString bandwidthDetails READ bandwidthDetails CONSTANT)
Q_PROPERTY(QString blueSpeechSphere READ blueSpeechSphere CONSTANT)
Q_PROPERTY(QString bookmarkLocation READ bookmarkLocation CONSTANT)
Q_PROPERTY(QString bookmarks READ bookmarks CONSTANT)
Q_PROPERTY(QString cascadedShadows READ cascadedShadows CONSTANT)
Q_PROPERTY(QString cachesSize READ cachesSize CONSTANT)
Q_PROPERTY(QString chat READ chat CONSTANT)
Q_PROPERTY(QString collisions READ collisions CONSTANT)
Q_PROPERTY(QString console READ console CONSTANT)
Q_PROPERTY(QString controlWithSpeech READ controlWithSpeech CONSTANT)
Q_PROPERTY(QString copyAddress READ copyAddress CONSTANT)
Q_PROPERTY(QString copyPath READ copyPath CONSTANT)
Q_PROPERTY(QString ddeFaceRegression READ ddeFaceRegression CONSTANT)
Q_PROPERTY(QString ddeFiltering READ ddeFiltering CONSTANT)
Q_PROPERTY(QString decreaseAvatarSize READ decreaseAvatarSize CONSTANT)
Q_PROPERTY(QString deleteBookmark READ deleteBookmark CONSTANT)
Q_PROPERTY(QString disableActivityLogger READ disableActivityLogger CONSTANT)
Q_PROPERTY(QString disableLightEntities READ disableLightEntities CONSTANT)
Q_PROPERTY(QString disableNackPackets READ disableNackPackets CONSTANT)
Q_PROPERTY(QString diskCacheEditor READ diskCacheEditor CONSTANT)
Q_PROPERTY(QString displayHands READ displayHands CONSTANT)
Q_PROPERTY(QString displayHandTargets READ displayHandTargets CONSTANT)
Q_PROPERTY(QString displayModelBounds READ displayModelBounds CONSTANT)
Q_PROPERTY(QString displayModelTriangles READ displayModelTriangles CONSTANT)
Q_PROPERTY(QString displayModelElementChildProxies READ displayModelElementChildProxies CONSTANT)
Q_PROPERTY(QString displayModelElementProxy READ displayModelElementProxy CONSTANT)
Q_PROPERTY(QString displayDebugTimingDetails READ displayDebugTimingDetails CONSTANT)
Q_PROPERTY(QString dontDoPrecisionPicking READ dontDoPrecisionPicking CONSTANT)
Q_PROPERTY(QString dontFadeOnOctreeServerChanges READ dontFadeOnOctreeServerChanges CONSTANT)
Q_PROPERTY(QString dontRenderEntitiesAsScene READ dontRenderEntitiesAsScene CONSTANT)
Q_PROPERTY(QString echoLocalAudio READ echoLocalAudio CONSTANT)
Q_PROPERTY(QString echoServerAudio READ echoServerAudio CONSTANT)
Q_PROPERTY(QString editEntitiesHelp READ editEntitiesHelp CONSTANT)
Q_PROPERTY(QString enable3DTVMode READ enable3DTVMode CONSTANT)
Q_PROPERTY(QString enableCharacterController READ enableCharacterController CONSTANT)
Q_PROPERTY(QString enableGlowEffect READ enableGlowEffect CONSTANT)
Q_PROPERTY(QString enableVRMode READ enableVRMode CONSTANT)
Q_PROPERTY(QString expandMyAvatarSimulateTiming READ expandMyAvatarSimulateTiming CONSTANT)
Q_PROPERTY(QString expandMyAvatarTiming READ expandMyAvatarTiming CONSTANT)
Q_PROPERTY(QString expandOtherAvatarTiming READ expandOtherAvatarTiming CONSTANT)
Q_PROPERTY(QString expandPaintGLTiming READ expandPaintGLTiming CONSTANT)
Q_PROPERTY(QString expandUpdateTiming READ expandUpdateTiming CONSTANT)
Q_PROPERTY(QString faceshift READ faceshift CONSTANT)
Q_PROPERTY(QString filterSixense READ filterSixense CONSTANT)
Q_PROPERTY(QString firstPerson READ firstPerson CONSTANT)
Q_PROPERTY(QString frameTimer READ frameTimer CONSTANT)
Q_PROPERTY(QString fullscreen READ fullscreen CONSTANT)
Q_PROPERTY(QString fullscreenMirror READ fullscreenMirror CONSTANT)
Q_PROPERTY(QString glowWhenSpeaking READ glowWhenSpeaking CONSTANT)
Q_PROPERTY(QString namesAboveHeads READ namesAboveHeads CONSTANT)
Q_PROPERTY(QString goToUser READ goToUser CONSTANT)
Q_PROPERTY(QString hmdTools READ hmdTools CONSTANT)
Q_PROPERTY(QString increaseAvatarSize READ increaseAvatarSize CONSTANT)
Q_PROPERTY(QString keyboardMotorControl READ keyboardMotorControl CONSTANT)
Q_PROPERTY(QString leapMotionOnHMD READ leapMotionOnHMD CONSTANT)
Q_PROPERTY(QString loadScript READ loadScript CONSTANT)
Q_PROPERTY(QString loadScriptURL READ loadScriptURL CONSTANT)
Q_PROPERTY(QString loadRSSDKFile READ loadRSSDKFile CONSTANT)
Q_PROPERTY(QString lodTools READ lodTools CONSTANT)
Q_PROPERTY(QString login READ login CONSTANT)
Q_PROPERTY(QString log READ log CONSTANT)
Q_PROPERTY(QString lowVelocityFilter READ lowVelocityFilter CONSTANT)
Q_PROPERTY(QString mirror READ mirror CONSTANT)
Q_PROPERTY(QString muteAudio READ muteAudio CONSTANT)
Q_PROPERTY(QString muteEnvironment READ muteEnvironment CONSTANT)
Q_PROPERTY(QString noFaceTracking READ noFaceTracking CONSTANT)
Q_PROPERTY(QString octreeStats READ octreeStats CONSTANT)
Q_PROPERTY(QString offAxisProjection READ offAxisProjection CONSTANT)
Q_PROPERTY(QString onlyDisplayTopTen READ onlyDisplayTopTen CONSTANT)
Q_PROPERTY(QString packageModel READ packageModel CONSTANT)
Q_PROPERTY(QString pair READ pair CONSTANT)
Q_PROPERTY(QString pipelineWarnings READ pipelineWarnings CONSTANT)
Q_PROPERTY(QString preferences READ preferences CONSTANT)
Q_PROPERTY(QString quit READ quit CONSTANT)
Q_PROPERTY(QString reloadAllScripts READ reloadAllScripts CONSTANT)
Q_PROPERTY(QString renderBoundingCollisionShapes READ renderBoundingCollisionShapes CONSTANT)
Q_PROPERTY(QString renderFocusIndicator READ renderFocusIndicator CONSTANT)
Q_PROPERTY(QString renderHeadCollisionShapes READ renderHeadCollisionShapes CONSTANT)
Q_PROPERTY(QString renderLookAtVectors READ renderLookAtVectors CONSTANT)
Q_PROPERTY(QString renderSkeletonCollisionShapes READ renderSkeletonCollisionShapes CONSTANT)
Q_PROPERTY(QString renderTargetFramerate READ renderTargetFramerate CONSTANT)
Q_PROPERTY(QString renderTargetFramerateUnlimited READ renderTargetFramerateUnlimited CONSTANT)
Q_PROPERTY(QString renderTargetFramerate60 READ renderTargetFramerate60 CONSTANT)
Q_PROPERTY(QString renderTargetFramerate50 READ renderTargetFramerate50 CONSTANT)
Q_PROPERTY(QString renderTargetFramerate40 READ renderTargetFramerate40 CONSTANT)
Q_PROPERTY(QString renderTargetFramerate30 READ renderTargetFramerate30 CONSTANT)
Q_PROPERTY(QString renderTargetFramerateVSyncOn READ renderTargetFramerateVSyncOn CONSTANT)
Q_PROPERTY(QString renderResolution READ renderResolution CONSTANT)
Q_PROPERTY(QString renderResolutionOne READ renderResolutionOne CONSTANT)
Q_PROPERTY(QString renderResolutionTwoThird READ renderResolutionTwoThird CONSTANT)
Q_PROPERTY(QString renderResolutionHalf READ renderResolutionHalf CONSTANT)
Q_PROPERTY(QString renderResolutionThird READ renderResolutionThird CONSTANT)
Q_PROPERTY(QString renderResolutionQuarter READ renderResolutionQuarter CONSTANT)
Q_PROPERTY(QString renderAmbientLight READ renderAmbientLight CONSTANT)
Q_PROPERTY(QString renderAmbientLightGlobal READ renderAmbientLightGlobal CONSTANT)
Q_PROPERTY(QString renderAmbientLight0 READ renderAmbientLight0 CONSTANT)
Q_PROPERTY(QString renderAmbientLight1 READ renderAmbientLight1 CONSTANT)
Q_PROPERTY(QString renderAmbientLight2 READ renderAmbientLight2 CONSTANT)
Q_PROPERTY(QString renderAmbientLight3 READ renderAmbientLight3 CONSTANT)
Q_PROPERTY(QString renderAmbientLight4 READ renderAmbientLight4 CONSTANT)
Q_PROPERTY(QString renderAmbientLight5 READ renderAmbientLight5 CONSTANT)
Q_PROPERTY(QString renderAmbientLight6 READ renderAmbientLight6 CONSTANT)
Q_PROPERTY(QString renderAmbientLight7 READ renderAmbientLight7 CONSTANT)
Q_PROPERTY(QString renderAmbientLight8 READ renderAmbientLight8 CONSTANT)
Q_PROPERTY(QString renderAmbientLight9 READ renderAmbientLight9 CONSTANT)
Q_PROPERTY(QString resetAvatarSize READ resetAvatarSize CONSTANT)
Q_PROPERTY(QString resetDDETracking READ resetDDETracking CONSTANT)
Q_PROPERTY(QString resetSensors READ resetSensors CONSTANT)
Q_PROPERTY(QString runningScripts READ runningScripts CONSTANT)
Q_PROPERTY(QString runTimingTests READ runTimingTests CONSTANT)
Q_PROPERTY(QString scriptEditor READ scriptEditor CONSTANT)
Q_PROPERTY(QString scriptedMotorControl READ scriptedMotorControl CONSTANT)
Q_PROPERTY(QString showBordersEntityNodes READ showBordersEntityNodes CONSTANT)
Q_PROPERTY(QString showIKConstraints READ showIKConstraints CONSTANT)
Q_PROPERTY(QString simpleShadows READ simpleShadows CONSTANT)
Q_PROPERTY(QString sixenseEnabled READ sixenseEnabled CONSTANT)
Q_PROPERTY(QString sixenseMouseInput READ sixenseMouseInput CONSTANT)
Q_PROPERTY(QString sixenseLasers READ sixenseLasers CONSTANT)
Q_PROPERTY(QString shiftHipsForIdleAnimations READ shiftHipsForIdleAnimations CONSTANT)
Q_PROPERTY(QString stars READ stars CONSTANT)
Q_PROPERTY(QString stats READ stats CONSTANT)
Q_PROPERTY(QString stereoAudio READ stereoAudio CONSTANT)
Q_PROPERTY(QString stopAllScripts READ stopAllScripts CONSTANT)
Q_PROPERTY(QString suppressShortTimings READ suppressShortTimings CONSTANT)
Q_PROPERTY(QString testPing READ testPing CONSTANT)
Q_PROPERTY(QString toolWindow READ toolWindow CONSTANT)
Q_PROPERTY(QString transmitterDrive READ transmitterDrive CONSTANT)
Q_PROPERTY(QString turnWithHead READ turnWithHead CONSTANT)
Q_PROPERTY(QString useAudioForMouth READ useAudioForMouth CONSTANT)
Q_PROPERTY(QString visibleToEveryone READ visibleToEveryone CONSTANT)
Q_PROPERTY(QString visibleToFriends READ visibleToFriends CONSTANT)
Q_PROPERTY(QString visibleToNoOne READ visibleToNoOne CONSTANT)
Q_PROPERTY(QString wireframe READ wireframe CONSTANT)
public:
const QString & aboutApp() { return MenuOption::AboutApp; }
const QString & addRemoveFriends() { return MenuOption::AddRemoveFriends; }
const QString & addressBar() { return MenuOption::AddressBar; }
const QString & alignForearmsWithWrists() { return MenuOption::AlignForearmsWithWrists; }
const QString & alternateIK() { return MenuOption::AlternateIK; }
const QString & ambientOcclusion() { return MenuOption::AmbientOcclusion; }
const QString & animations() { return MenuOption::Animations; }
const QString & atmosphere() { return MenuOption::Atmosphere; }
const QString & attachments() { return MenuOption::Attachments; }
const QString & audioNoiseReduction() { return MenuOption::AudioNoiseReduction; }
const QString & audioScope() { return MenuOption::AudioScope; }
const QString & audioScopeFiftyFrames() { return MenuOption::AudioScopeFiftyFrames; }
const QString & audioScopeFiveFrames() { return MenuOption::AudioScopeFiveFrames; }
const QString & audioScopeFrames() { return MenuOption::AudioScopeFrames; }
const QString & audioScopePause() { return MenuOption::AudioScopePause; }
const QString & audioScopeTwentyFrames() { return MenuOption::AudioScopeTwentyFrames; }
const QString & audioStats() { return MenuOption::AudioStats; }
const QString & audioStatsShowInjectedStreams() { return MenuOption::AudioStatsShowInjectedStreams; }
const QString & bandwidthDetails() { return MenuOption::BandwidthDetails; }
const QString & blueSpeechSphere() { return MenuOption::BlueSpeechSphere; }
const QString & bookmarkLocation() { return MenuOption::BookmarkLocation; }
const QString & bookmarks() { return MenuOption::Bookmarks; }
const QString & cascadedShadows() { return MenuOption::CascadedShadows; }
const QString & cachesSize() { return MenuOption::CachesSize; }
const QString & chat() { return MenuOption::Chat; }
const QString & collisions() { return MenuOption::Collisions; }
const QString & console() { return MenuOption::Console; }
const QString & controlWithSpeech() { return MenuOption::ControlWithSpeech; }
const QString & copyAddress() { return MenuOption::CopyAddress; }
const QString & copyPath() { return MenuOption::CopyPath; }
const QString & ddeFaceRegression() { return MenuOption::DDEFaceRegression; }
const QString & ddeFiltering() { return MenuOption::DDEFiltering; }
const QString & decreaseAvatarSize() { return MenuOption::DecreaseAvatarSize; }
const QString & deleteBookmark() { return MenuOption::DeleteBookmark; }
const QString & disableActivityLogger() { return MenuOption::DisableActivityLogger; }
const QString & disableLightEntities() { return MenuOption::DisableLightEntities; }
const QString & disableNackPackets() { return MenuOption::DisableNackPackets; }
const QString & diskCacheEditor() { return MenuOption::DiskCacheEditor; }
const QString & displayHands() { return MenuOption::DisplayHands; }
const QString & displayHandTargets() { return MenuOption::DisplayHandTargets; }
const QString & displayModelBounds() { return MenuOption::DisplayModelBounds; }
const QString & displayModelTriangles() { return MenuOption::DisplayModelTriangles; }
const QString & displayModelElementChildProxies() { return MenuOption::DisplayModelElementChildProxies; }
const QString & displayModelElementProxy() { return MenuOption::DisplayModelElementProxy; }
const QString & displayDebugTimingDetails() { return MenuOption::DisplayDebugTimingDetails; }
const QString & dontDoPrecisionPicking() { return MenuOption::DontDoPrecisionPicking; }
const QString & dontFadeOnOctreeServerChanges() { return MenuOption::DontFadeOnOctreeServerChanges; }
const QString & dontRenderEntitiesAsScene() { return MenuOption::DontRenderEntitiesAsScene; }
const QString & echoLocalAudio() { return MenuOption::EchoLocalAudio; }
const QString & echoServerAudio() { return MenuOption::EchoServerAudio; }
const QString & editEntitiesHelp() { return MenuOption::EditEntitiesHelp; }
const QString & enable3DTVMode() { return MenuOption::Enable3DTVMode; }
const QString & enableCharacterController() { return MenuOption::EnableCharacterController; }
const QString & enableGlowEffect() { return MenuOption::EnableGlowEffect; }
const QString & enableVRMode() { return MenuOption::EnableVRMode; }
const QString & expandMyAvatarSimulateTiming() { return MenuOption::ExpandMyAvatarSimulateTiming; }
const QString & expandMyAvatarTiming() { return MenuOption::ExpandMyAvatarTiming; }
const QString & expandOtherAvatarTiming() { return MenuOption::ExpandOtherAvatarTiming; }
const QString & expandPaintGLTiming() { return MenuOption::ExpandPaintGLTiming; }
const QString & expandUpdateTiming() { return MenuOption::ExpandUpdateTiming; }
const QString & faceshift() { return MenuOption::Faceshift; }
const QString & filterSixense() { return MenuOption::FilterSixense; }
const QString & firstPerson() { return MenuOption::FirstPerson; }
const QString & frameTimer() { return MenuOption::FrameTimer; }
const QString & fullscreen() { return MenuOption::Fullscreen; }
const QString & fullscreenMirror() { return MenuOption::FullscreenMirror; }
const QString & glowWhenSpeaking() { return MenuOption::GlowWhenSpeaking; }
const QString & namesAboveHeads() { return MenuOption::NamesAboveHeads; }
const QString & goToUser() { return MenuOption::GoToUser; }
const QString & hmdTools() { return MenuOption::HMDTools; }
const QString & increaseAvatarSize() { return MenuOption::IncreaseAvatarSize; }
const QString & keyboardMotorControl() { return MenuOption::KeyboardMotorControl; }
const QString & leapMotionOnHMD() { return MenuOption::LeapMotionOnHMD; }
const QString & loadScript() { return MenuOption::LoadScript; }
const QString & loadScriptURL() { return MenuOption::LoadScriptURL; }
const QString & loadRSSDKFile() { return MenuOption::LoadRSSDKFile; }
const QString & lodTools() { return MenuOption::LodTools; }
const QString & login() { return MenuOption::Login; }
const QString & log() { return MenuOption::Log; }
const QString & lowVelocityFilter() { return MenuOption::LowVelocityFilter; }
const QString & mirror() { return MenuOption::Mirror; }
const QString & muteAudio() { return MenuOption::MuteAudio; }
const QString & muteEnvironment() { return MenuOption::MuteEnvironment; }
const QString & noFaceTracking() { return MenuOption::NoFaceTracking; }
const QString & octreeStats() { return MenuOption::OctreeStats; }
const QString & offAxisProjection() { return MenuOption::OffAxisProjection; }
const QString & onlyDisplayTopTen() { return MenuOption::OnlyDisplayTopTen; }
const QString & packageModel() { return MenuOption::PackageModel; }
const QString & pair() { return MenuOption::Pair; }
const QString & pipelineWarnings() { return MenuOption::PipelineWarnings; }
const QString & preferences() { return MenuOption::Preferences; }
const QString & quit() { return MenuOption::Quit; }
const QString & reloadAllScripts() { return MenuOption::ReloadAllScripts; }
const QString & renderBoundingCollisionShapes() { return MenuOption::RenderBoundingCollisionShapes; }
const QString & renderFocusIndicator() { return MenuOption::RenderFocusIndicator; }
const QString & renderHeadCollisionShapes() { return MenuOption::RenderHeadCollisionShapes; }
const QString & renderLookAtVectors() { return MenuOption::RenderLookAtVectors; }
const QString & renderSkeletonCollisionShapes() { return MenuOption::RenderSkeletonCollisionShapes; }
const QString & renderTargetFramerate() { return MenuOption::RenderTargetFramerate; }
const QString & renderTargetFramerateUnlimited() { return MenuOption::RenderTargetFramerateUnlimited; }
const QString & renderTargetFramerate60() { return MenuOption::RenderTargetFramerate60; }
const QString & renderTargetFramerate50() { return MenuOption::RenderTargetFramerate50; }
const QString & renderTargetFramerate40() { return MenuOption::RenderTargetFramerate40; }
const QString & renderTargetFramerate30() { return MenuOption::RenderTargetFramerate30; }
const QString & renderTargetFramerateVSyncOn() { return MenuOption::RenderTargetFramerateVSyncOn; }
const QString & renderResolution() { return MenuOption::RenderResolution; }
const QString & renderResolutionOne() { return MenuOption::RenderResolutionOne; }
const QString & renderResolutionTwoThird() { return MenuOption::RenderResolutionTwoThird; }
const QString & renderResolutionHalf() { return MenuOption::RenderResolutionHalf; }
const QString & renderResolutionThird() { return MenuOption::RenderResolutionThird; }
const QString & renderResolutionQuarter() { return MenuOption::RenderResolutionQuarter; }
const QString & renderAmbientLight() { return MenuOption::RenderAmbientLight; }
const QString & renderAmbientLightGlobal() { return MenuOption::RenderAmbientLightGlobal; }
const QString & renderAmbientLight0() { return MenuOption::RenderAmbientLight0; }
const QString & renderAmbientLight1() { return MenuOption::RenderAmbientLight1; }
const QString & renderAmbientLight2() { return MenuOption::RenderAmbientLight2; }
const QString & renderAmbientLight3() { return MenuOption::RenderAmbientLight3; }
const QString & renderAmbientLight4() { return MenuOption::RenderAmbientLight4; }
const QString & renderAmbientLight5() { return MenuOption::RenderAmbientLight5; }
const QString & renderAmbientLight6() { return MenuOption::RenderAmbientLight6; }
const QString & renderAmbientLight7() { return MenuOption::RenderAmbientLight7; }
const QString & renderAmbientLight8() { return MenuOption::RenderAmbientLight8; }
const QString & renderAmbientLight9() { return MenuOption::RenderAmbientLight9; }
const QString & resetAvatarSize() { return MenuOption::ResetAvatarSize; }
const QString & resetDDETracking() { return MenuOption::ResetDDETracking; }
const QString & resetSensors() { return MenuOption::ResetSensors; }
const QString & runningScripts() { return MenuOption::RunningScripts; }
const QString & runTimingTests() { return MenuOption::RunTimingTests; }
const QString & scriptEditor() { return MenuOption::ScriptEditor; }
const QString & scriptedMotorControl() { return MenuOption::ScriptedMotorControl; }
const QString & showBordersEntityNodes() { return MenuOption::ShowBordersEntityNodes; }
const QString & showIKConstraints() { return MenuOption::ShowIKConstraints; }
const QString & simpleShadows() { return MenuOption::SimpleShadows; }
const QString & sixenseEnabled() { return MenuOption::SixenseEnabled; }
const QString & sixenseMouseInput() { return MenuOption::SixenseMouseInput; }
const QString & sixenseLasers() { return MenuOption::SixenseLasers; }
const QString & shiftHipsForIdleAnimations() { return MenuOption::ShiftHipsForIdleAnimations; }
const QString & stars() { return MenuOption::Stars; }
const QString & stats() { return MenuOption::Stats; }
const QString & stereoAudio() { return MenuOption::StereoAudio; }
const QString & stopAllScripts() { return MenuOption::StopAllScripts; }
const QString & suppressShortTimings() { return MenuOption::SuppressShortTimings; }
const QString & testPing() { return MenuOption::TestPing; }
const QString & toolWindow() { return MenuOption::ToolWindow; }
const QString & transmitterDrive() { return MenuOption::TransmitterDrive; }
const QString & turnWithHead() { return MenuOption::TurnWithHead; }
const QString & useAudioForMouth() { return MenuOption::UseAudioForMouth; }
const QString & visibleToEveryone() { return MenuOption::VisibleToEveryone; }
const QString & visibleToFriends() { return MenuOption::VisibleToFriends; }
const QString & visibleToNoOne() { return MenuOption::VisibleToNoOne; }
const QString & wireframe() { return MenuOption::Wireframe; }
public slots:
void onTriggeredByName(const QString & name);
void onToggledByName(const QString & name);
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:
static QHash<QString, std::function<void()>> triggerActions;
static QHash<QString, std::function<void(bool)>> toggleActions;
};
#endif // hifi_MenuConstants_h

View file

@ -118,15 +118,17 @@ void OffscreenUi::resize(const QSize& newSize) {
qDebug() << "Offscreen UI resizing to " << newSize.width() << "x" << newSize.height() << " with pixel ratio " << pixelRatio; qDebug() << "Offscreen UI resizing to " << newSize.width() << "x" << newSize.height() << " with pixel ratio " << pixelRatio;
_fboCache.setSize(newSize * pixelRatio); _fboCache.setSize(newSize * pixelRatio);
if (_quickWindow) {
_quickWindow->setGeometry(QRect(QPoint(), newSize));
}
_quickWindow->contentItem()->setSize(newSize);
// Update our members // Update our members
if (_rootItem) { if (_rootItem) {
_rootItem->setSize(newSize); _rootItem->setSize(newSize);
} }
if (_quickWindow) {
_quickWindow->setGeometry(QRect(QPoint(), newSize));
}
doneCurrent(); doneCurrent();
} }
@ -190,6 +192,7 @@ void OffscreenUi::finishQmlLoad(std::function<void(QQmlContext*, QQuickItem*)> f
QQuickItem* newItem = qobject_cast<QQuickItem*>(newObject); QQuickItem* newItem = qobject_cast<QQuickItem*>(newObject);
if (!newItem) { if (!newItem) {
qWarning("run: Not a QQuickItem"); qWarning("run: Not a QQuickItem");
return;
delete newObject; delete newObject;
if (!_rootItem) { if (!_rootItem) {
qFatal("Unable to find root QQuickItem"); qFatal("Unable to find root QQuickItem");
@ -206,6 +209,7 @@ void OffscreenUi::finishQmlLoad(std::function<void(QQmlContext*, QQuickItem*)> f
_rootItem = newItem; _rootItem = newItem;
_rootItem->setParentItem(_quickWindow->contentItem()); _rootItem->setParentItem(_quickWindow->contentItem());
_rootItem->setSize(_quickWindow->renderTargetSize()); _rootItem->setSize(_quickWindow->renderTargetSize());
_rootItem->forceActiveFocus();
} else { } else {
// Allow child windows to be destroyed from JS // Allow child windows to be destroyed from JS
QQmlEngine::setObjectOwnership(newItem, QQmlEngine::JavaScriptOwnership); QQmlEngine::setObjectOwnership(newItem, QQmlEngine::JavaScriptOwnership);

View file

@ -32,6 +32,39 @@
#include "FboCache.h" #include "FboCache.h"
#include <QQuickItem> #include <QQuickItem>
#define HIFI_QML_DECL \
private: \
static const QString NAME; \
static const QUrl QML; \
public: \
static void registerType(); \
static void show(std::function<void(QQmlContext*, QQuickItem *)> f = [](QQmlContext*, QQuickItem*) {}); \
static void toggle(std::function<void(QQmlContext*, QQuickItem *)> f = [](QQmlContext*, QQuickItem*) {}); \
static void load(std::function<void(QQmlContext*, QQuickItem *)> f = [](QQmlContext*, QQuickItem*) {}); \
private:
#define HIFI_QML_DEF(x) \
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(std::function<void(QQmlContext*, QQuickItem *)> f) { \
auto offscreenUi = DependencyManager::get<OffscreenUi>(); \
offscreenUi->show(QML, NAME, f); \
} \
\
void x::toggle(std::function<void(QQmlContext*, QQuickItem *)> f) { \
auto offscreenUi = DependencyManager::get<OffscreenUi>(); \
offscreenUi->toggle(QML, NAME, f); \
} \
void x::load(std::function<void(QQmlContext*, QQuickItem *)> f) { \
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

View file

@ -10,7 +10,6 @@
#include "TextRenderer.h" #include "TextRenderer.h"
#include "MatrixStack.h" #include "MatrixStack.h"
#include "OffscreenUi.h"
#include <QWindow> #include <QWindow>
#include <QFile> #include <QFile>
@ -27,7 +26,6 @@
#include <QOpenGLVertexArrayObject> #include <QOpenGLVertexArrayObject>
#include <QApplication> #include <QApplication>
#include <QOpenGLDebugLogger> #include <QOpenGLDebugLogger>
#include <QWebEnginePage>
#include <unordered_map> #include <unordered_map>
#include <memory> #include <memory>
@ -82,6 +80,7 @@ const QString& getQmlDir() {
} }
return dir; return dir;
} }
// Create a simple OpenGL window that renders text in various ways // Create a simple OpenGL window that renders text in various ways
class QTestWindow : public QWindow { class QTestWindow : public QWindow {
Q_OBJECT Q_OBJECT
@ -90,24 +89,17 @@ class QTestWindow : public QWindow {
QSize _size; QSize _size;
TextRenderer* _textRenderer[4]; TextRenderer* _textRenderer[4];
RateCounter fps; RateCounter fps;
int testQmlTexture{ 0 };
//ProgramPtr _planeProgam;
//ShapeWrapperPtr _planeShape;
protected: protected:
void renderText(); void renderText();
void renderQml();
private: private:
void resizeWindow(const QSize& size) { void resizeWindow(const QSize& size) {
_size = size; _size = size;
DependencyManager::get<OffscreenUi>()->resize(_size);
} }
public: public:
QTestWindow() { QTestWindow() {
DependencyManager::set<OffscreenUi>();
setSurfaceType(QSurface::OpenGLSurface); setSurfaceType(QSurface::OpenGLSurface);
QSurfaceFormat format; QSurfaceFormat format;
@ -167,32 +159,10 @@ public:
glClearColor(0.2f, 0.2f, 0.2f, 1); glClearColor(0.2f, 0.2f, 0.2f, 1);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
auto offscreenUi = DependencyManager::get<OffscreenUi>(); makeCurrent();
offscreenUi->create(_context);
// FIXME, need to switch to a QWindow for mouse and keyboard input to work
offscreenUi->setProxyWindow(this);
// "#0e7077"
setFramePosition(QPoint(-1000, 0)); setFramePosition(QPoint(-1000, 0));
resize(QSize(800, 600)); resize(QSize(800, 600));
offscreenUi->setBaseUrl(QUrl::fromLocalFile(getQmlDir()));
offscreenUi->load(QUrl("TestRoot.qml"));
offscreenUi->addImportPath(getQmlDir());
offscreenUi->addImportPath(".");
connect(offscreenUi.data(), &OffscreenUi::textureUpdated, this, [this, offscreenUi](int textureId) {
offscreenUi->lockTexture(textureId);
assert(!glGetError());
GLuint oldTexture = testQmlTexture;
testQmlTexture = textureId;
if (oldTexture) {
offscreenUi->releaseTexture(oldTexture);
}
});
installEventFilter(offscreenUi.data());
offscreenUi->resume();
QWebEnginePage *page = new QWebEnginePage;
page->runJavaScript("'Java''' 'Script'", [](const QVariant &result) { qDebug() << result; });
} }
virtual ~QTestWindow() { virtual ~QTestWindow() {
@ -208,41 +178,6 @@ protected:
void resizeEvent(QResizeEvent* ev) override { void resizeEvent(QResizeEvent* ev) override {
resizeWindow(ev->size()); resizeWindow(ev->size());
} }
void keyPressEvent(QKeyEvent* event) {
switch (event->key()) {
case Qt::Key_L:
if (event->modifiers() & Qt::CTRL) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->qmlEngine()->clearComponentCache();
DependencyManager::get<OffscreenUi>()->toggle(QString("TestDialog.qml"), "TestDialog");
}
break;
case Qt::Key_K:
if (event->modifiers() & Qt::CTRL) {
DependencyManager::get<OffscreenUi>()->toggle(QString("Browser.qml"), "Browser");
}
break;
case Qt::Key_J:
if (event->modifiers() & Qt::CTRL) {
QObject * obj = DependencyManager::get<OffscreenUi>()->findObject("WebView");
qDebug() << obj;
}
break;
}
QWindow::keyPressEvent(event);
}
void moveEvent(QMoveEvent* event) {
static qreal oldPixelRatio = 0.0;
if (devicePixelRatio() != oldPixelRatio) {
oldPixelRatio = devicePixelRatio();
resizeWindow(size());
}
QWindow::moveEvent(event);
}
}; };
#ifndef SERIF_FONT_FAMILY #ifndef SERIF_FONT_FAMILY
@ -299,39 +234,16 @@ void QTestWindow::renderText() {
} }
} }
void QTestWindow::renderQml() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if (testQmlTexture > 0) {
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, testQmlTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
glBegin(GL_QUADS);
{
glTexCoord2f(0, 0);
glVertex2f(-1, -1);
glTexCoord2f(0, 1);
glVertex2f(-1, 1);
glTexCoord2f(1, 1);
glVertex2f(1, 1);
glTexCoord2f(1, 0);
glVertex2f(1, -1);
}
glEnd();
}
void QTestWindow::draw() { void QTestWindow::draw() {
if (!isVisible()) {
return;
}
makeCurrent(); makeCurrent();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, _size.width() * devicePixelRatio(), _size.height() * devicePixelRatio()); glViewport(0, 0, _size.width() * devicePixelRatio(), _size.height() * devicePixelRatio());
//renderText(); renderText();
renderQml();
_context->swapBuffers(this); _context->swapBuffers(this);
glFinish(); glFinish();
@ -344,10 +256,8 @@ void QTestWindow::draw() {
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
QApplication app(argc, argv); QGuiApplication app(argc, argv);
//QLoggingCategory::setFilterRules("qt.quick.mouse.debug = true");
QTestWindow window; QTestWindow window;
QTimer timer; QTimer timer;
timer.setInterval(1); timer.setInterval(1);
app.connect(&timer, &QTimer::timeout, &app, [&] { app.connect(&timer, &QTimer::timeout, &app, [&] {

15
tests/ui/CMakeLists.txt Normal file
View file

@ -0,0 +1,15 @@
set(TARGET_NAME ui-tests)
setup_hifi_project(Widgets OpenGL Network Qml Quick Script)
if (WIN32)
add_dependency_external_projects(glew)
find_package(GLEW REQUIRED)
target_include_directories(${TARGET_NAME} PRIVATE ${GLEW_INCLUDE_DIRS})
target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} wsock32.lib opengl32.lib Winmm.lib)
endif()
# link in the shared libraries
link_hifi_libraries(ui render-utils gpu shared)
copy_dlls_beside_windows_executable()

302
tests/ui/src/main.cpp Normal file
View file

@ -0,0 +1,302 @@
//
// main.cpp
// tests/render-utils/src
//
// Copyright 2014 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
//
#include "OffscreenUi.h"
#include <QWindow>
#include <QFile>
#include <QTime>
#include <QImage>
#include <QTimer>
#include <QElapsedTimer>
#include <QOpenGLContext>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QResizeEvent>
#include <QLoggingCategory>
#include <QOpenGLTexture>
#include <QOpenGLVertexArrayObject>
#include <QApplication>
#include <QOpenGLDebugLogger>
#include <QOpenGLFunctions>
#include <unordered_map>
#include <memory>
#include <glm/glm.hpp>
#include <PathUtils.h>
#include <QDir>
#include "MessageDialog.h"
#include "MenuConstants.h"
class RateCounter {
std::vector<float> times;
QElapsedTimer timer;
public:
RateCounter() {
timer.start();
}
void reset() {
times.clear();
}
unsigned int count() const {
return times.size() - 1;
}
float elapsed() const {
if (times.size() < 1) {
return 0.0f;
}
float elapsed = *times.rbegin() - *times.begin();
return elapsed;
}
void increment() {
times.push_back(timer.elapsed() / 1000.0f);
}
float rate() const {
if (elapsed() == 0.0f) {
return NAN;
}
return (float) count() / elapsed();
}
};
const QString & getQmlDir() {
static QString dir;
if (dir.isEmpty()) {
QDir path(__FILE__);
path.cdUp();
dir = path.cleanPath(path.absoluteFilePath("../../../interface/resources/qml/")) + "/";
qDebug() << "Qml Path: " << dir;
}
return dir;
}
// Create a simple OpenGL window that renders text in various ways
class QTestWindow : public QWindow, private QOpenGLFunctions {
Q_OBJECT
QOpenGLContext * _context{ nullptr };
QSize _size;
bool _altPressed{ false };
RateCounter fps;
QTimer _timer;
int testQmlTexture{ 0 };
public:
QTestWindow() {
_timer.setInterval(1);
connect(&_timer, &QTimer::timeout, [=] {
draw();
});
DependencyManager::set<OffscreenUi>();
setSurfaceType(QSurface::OpenGLSurface);
QSurfaceFormat format;
format.setDepthBufferSize(16);
format.setStencilBufferSize(8);
format.setVersion(4, 1);
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile);
format.setOption(QSurfaceFormat::DebugContext);
setFormat(format);
_context = new QOpenGLContext;
_context->setFormat(format);
if (!_context->create()) {
qFatal("Could not create OpenGL context");
}
show();
makeCurrent();
initializeOpenGLFunctions();
{
QOpenGLDebugLogger *logger = new QOpenGLDebugLogger(this);
logger->initialize(); // initializes in the current context, i.e. ctx
logger->enableMessages();
connect(logger, &QOpenGLDebugLogger::messageLogged, this, [&](const QOpenGLDebugMessage & debugMessage) {
qDebug() << debugMessage;
});
// logger->startLogging(QOpenGLDebugLogger::SynchronousLogging);
}
qDebug() << (const char*)this->glGetString(GL_VERSION);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.2f, 0.2f, 0.2f, 1);
glDisable(GL_DEPTH_TEST);
MessageDialog::registerType();
HifiMenu::registerType();
auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->create(_context);
makeCurrent();
offscreenUi->setProxyWindow(this);
setFramePosition(QPoint(-1000, 0));
resize(QSize(800, 600));
offscreenUi->setBaseUrl(QUrl::fromLocalFile(getQmlDir()));
offscreenUi->load(QUrl("TestRoot.qml"));
offscreenUi->addImportPath(getQmlDir());
offscreenUi->addImportPath(".");
connect(offscreenUi.data(), &OffscreenUi::textureUpdated, this, [this, offscreenUi](int textureId) {
offscreenUi->lockTexture(textureId);
assert(!glGetError());
GLuint oldTexture = testQmlTexture;
testQmlTexture = textureId;
if (oldTexture) {
offscreenUi->releaseTexture(oldTexture);
}
});
installEventFilter(offscreenUi.data());
HifiMenu::setTriggerAction(MenuOption::Quit, [] {
QApplication::quit();
});
offscreenUi->resume();
_timer.start();
}
virtual ~QTestWindow() {
DependencyManager::destroy<OffscreenUi>();
}
private:
void draw() {
if (!isVisible()) {
return;
}
makeCurrent();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, _size.width() * devicePixelRatio(), _size.height() * devicePixelRatio());
renderQml();
_context->swapBuffers(this);
glFinish();
fps.increment();
if (fps.elapsed() >= 2.0f) {
qDebug() << "FPS: " << fps.rate();
fps.reset();
}
}
void makeCurrent() {
_context->makeCurrent(this);
}
void renderQml();
void resizeWindow(const QSize & size) {
_size = size;
DependencyManager::get<OffscreenUi>()->resize(_size);
}
protected:
void resizeEvent(QResizeEvent * ev) override {
resizeWindow(ev->size());
}
void keyPressEvent(QKeyEvent *event) {
_altPressed = Qt::Key_Alt == event->key();
switch (event->key()) {
case Qt::Key_L:
if (event->modifiers() & Qt::CTRL) {
//auto offscreenUi = DependencyManager::get<OffscreenUi>();
//DependencyManager::get<OffscreenUi>()->toggle(QString("TestDialog.qml"), "TestDialog");
//DependencyManager::get<OffscreenUi>()->toggle(QString("MenuTest.qml"), "MenuTest");
//HifiMenu::toggle();
}
break;
case Qt::Key_K:
if (event->modifiers() & Qt::CTRL) {
OffscreenUi::question("Message title", "Message contents", [](QMessageBox::Button b){
qDebug() << b;
});
}
break;
case Qt::Key_J:
if (event->modifiers() & Qt::CTRL) {
}
break;
}
QWindow::keyPressEvent(event);
}
void keyReleaseEvent(QKeyEvent *event) {
if (_altPressed && Qt::Key_Alt == event->key()) {
HifiMenu::toggle();
}
}
void moveEvent(QMoveEvent *event) {
static qreal oldPixelRatio = 0.0;
if (devicePixelRatio() != oldPixelRatio) {
oldPixelRatio = devicePixelRatio();
resizeWindow(size());
}
QWindow::moveEvent(event);
}
};
void QTestWindow::renderQml() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if (testQmlTexture > 0) {
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, testQmlTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
glBegin(GL_QUADS);
{
glTexCoord2f(0, 0);
glVertex2f(-1, -1);
glTexCoord2f(0, 1);
glVertex2f(-1, 1);
glTexCoord2f(1, 1);
glVertex2f(1, 1);
glTexCoord2f(1, 0);
glVertex2f(1, -1);
}
glEnd();
}
const char * LOG_FILTER_RULES = R"V0G0N(
*.debug=false
qt.quick.dialogs.registration=true
qt.quick.mouse.debug = true
)V0G0N";
int main(int argc, char** argv) {
QGuiApplication app(argc, argv);
//QLoggingCategory::setFilterRules(LOG_FILTER_RULES);
QTestWindow window;
app.exec();
return 0;
}
#include "main.moc"