From 0aaa07a2ded462426c26175db133072f03c87916 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 24 Aug 2015 22:55:40 -0700 Subject: [PATCH] Remove items from the QML version of the menu when they are removed from the main menu --- interface/resources/qml/VrMenu.qml | 22 ++++++ interface/src/Menu.cpp | 3 + libraries/ui/src/VrMenu.cpp | 115 +++++++++++------------------ libraries/ui/src/VrMenu.h | 2 - 4 files changed, 68 insertions(+), 74 deletions(-) diff --git a/interface/resources/qml/VrMenu.qml b/interface/resources/qml/VrMenu.qml index f0b7bf9fd3..ef7ae852d4 100644 --- a/interface/resources/qml/VrMenu.qml +++ b/interface/resources/qml/VrMenu.qml @@ -185,4 +185,26 @@ Hifi.VrMenu { } } } + + function addMenu(menu, newMenu) { + return menu.addMenu(newMenu); + } + + function addItem(menu, newMenuItem) { + return menu.addItem(newMenuItem); + } + + function insertItem(menu, beforeItem, newMenuItem) { + for (var i = 0; i < menu.items.length; ++i) { + console.log(menu.items[i]); + if (menu.items[i] === beforeItem) { + return menu.insertItem(i, newMenuItem); + } + } + return addItem(menu, newMenuItem); + } + + function removeItem(menu, menuItem) { + menu.removeItem(menuItem); + } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 1c2cdbaa26..9d47df1c73 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1046,6 +1046,9 @@ QAction* MenuWrapper::addAction(const QString& menuName, const QObject* receiver void MenuWrapper::removeAction(QAction* action) { _realMenu->removeAction(action); + VrMenu::executeOrQueue([=](VrMenu* vrMenu) { + vrMenu->removeAction(action); + }); } void MenuWrapper::insertAction(QAction* before, QAction* action) { diff --git a/libraries/ui/src/VrMenu.cpp b/libraries/ui/src/VrMenu.cpp index ce4aba83d3..1ede74fc86 100644 --- a/libraries/ui/src/VrMenu.cpp +++ b/libraries/ui/src/VrMenu.cpp @@ -83,46 +83,6 @@ VrMenu::VrMenu(QQuickItem* parent) : QQuickItem(parent) { this->setEnabled(false); } - -// QML helper functions -QObject* addMenu(QObject* parent, const QString& text) { - // FIXME add more checking here to ensure no name conflicts - QVariant returnedValue; - QMetaObject::invokeMethod(parent, "addMenu", Qt::DirectConnection, - Q_RETURN_ARG(QVariant, returnedValue), - Q_ARG(QVariant, text)); - QObject* result = returnedValue.value(); - if (result) { - result->setObjectName(text); - } - return result; -} - -class QQuickMenuItem; -QObject* addItem(QObject* parent, const QString& text) { - // FIXME add more checking here to ensure no name conflicts - QQuickMenuItem* returnedValue{ nullptr }; - bool invokeResult = - QMetaObject::invokeMethod(parent, "addItem", Qt::DirectConnection, Q_RETURN_ARG(QQuickMenuItem*, returnedValue), - Q_ARG(QString, text)); - -#ifndef QT_NO_DEBUG - Q_ASSERT(invokeResult); -#else - Q_UNUSED(invokeResult); -#endif - QObject* result = reinterpret_cast(returnedValue); - return result; -} - -const QObject* VrMenu::findMenuObject(const QString& menuOption) const { - if (menuOption.isEmpty()) { - return _rootMenu; - } - const QObject* result = _rootMenu->findChild(menuOption); - return result; -} - QObject* VrMenu::findMenuObject(const QString& menuOption) { if (menuOption.isEmpty()) { return _rootMenu; @@ -147,7 +107,16 @@ void VrMenu::addMenu(QMenu* menu) { } else { Q_ASSERT(false); } - QObject* result = ::addMenu(qmlParent, menu->title()); + QVariant returnedValue; + bool invokeResult = QMetaObject::invokeMethod(this, "addMenu", Qt::DirectConnection, + Q_RETURN_ARG(QVariant, returnedValue), + Q_ARG(QVariant, QVariant::fromValue(qmlParent)), + Q_ARG(QVariant, QVariant::fromValue(menu->title()))); + Q_ASSERT(invokeResult); + QObject* result = returnedValue.value(); + Q_ASSERT(result); + + // Bind the QML and Widget together new MenuUserData(menu, result); } @@ -175,9 +144,15 @@ void VrMenu::addAction(QMenu* menu, QAction* action) { Q_ASSERT(!MenuUserData::forObject(action)); Q_ASSERT(MenuUserData::forObject(menu)); MenuUserData* userData = MenuUserData::forObject(menu); - QObject* parent = findMenuObject(userData->uuid.toString()); - Q_ASSERT(parent); - QObject* result = ::addItem(parent, action->text()); + QObject* menuQml = findMenuObject(userData->uuid.toString()); + Q_ASSERT(menuQml); + QVariant returnedValue; + bool invokeResult = QMetaObject::invokeMethod(this, "addItem", Qt::DirectConnection, + Q_RETURN_ARG(QVariant, returnedValue), + Q_ARG(QVariant, QVariant::fromValue(menuQml)), + Q_ARG(QVariant, QVariant::fromValue(action->text()))); + Q_ASSERT(invokeResult); + QObject* result = returnedValue.value(); Q_ASSERT(result); // Bind the QML and Widget together bindActionToQmlAction(result, action); @@ -190,38 +165,34 @@ void VrMenu::insertAction(QAction* before, QAction* action) { Q_ASSERT(beforeUserData); beforeQml = findMenuObject(beforeUserData->uuid.toString()); } - QObject* menu = beforeQml->parent(); - int index{ -1 }; - QVariant itemsVar = menu->property("items"); - QList items = itemsVar.toList(); - // FIXME add more checking here to ensure no name conflicts - for (index = 0; index < items.length(); ++index) { - QObject* currentQmlItem = items.at(index).value(); - if (currentQmlItem == beforeQml) { - break; - } - } - - QObject* result{ nullptr }; - if (index < 0 || index >= items.length()) { - result = ::addItem(menu, action->text()); - } else { - QQuickMenuItem* returnedValue{ nullptr }; - bool invokeResult = - QMetaObject::invokeMethod(menu, "insertItem", Qt::DirectConnection, Q_RETURN_ARG(QQuickMenuItem*, returnedValue), - Q_ARG(int, index), Q_ARG(QString, action->text())); -#ifndef QT_NO_DEBUG - Q_ASSERT(invokeResult); -#else - Q_UNUSED(invokeResult); -#endif - result = reinterpret_cast(returnedValue); - } + QVariant returnedValue; + bool invokeResult = QMetaObject::invokeMethod(this, "insertItem", Qt::DirectConnection, + Q_RETURN_ARG(QVariant, returnedValue), + Q_ARG(QVariant, QVariant::fromValue(menu)), + Q_ARG(QVariant, QVariant::fromValue(beforeQml)), + Q_ARG(QVariant, QVariant::fromValue(action->text()))); + Q_ASSERT(invokeResult); + QObject* result = returnedValue.value(); Q_ASSERT(result); bindActionToQmlAction(result, action); } void VrMenu::removeAction(QAction* action) { - // FIXME implement + MenuUserData* userData = MenuUserData::forObject(action); + if (!userData) { + qWarning("Attempted to remove menu action with no found QML object"); + return; + } + QObject* item = findMenuObject(userData->uuid.toString()); + QObject* menu = item->parent(); + // Proxy QuickItem requests through the QML layer + bool invokeResult = QMetaObject::invokeMethod(this, "removeItem", Qt::DirectConnection, + Q_ARG(QVariant, QVariant::fromValue(menu)), + Q_ARG(QVariant, QVariant::fromValue(item))); +#ifndef QT_NO_DEBUG + Q_ASSERT(invokeResult); +#else + Q_UNUSED(invokeResult); +#endif } diff --git a/libraries/ui/src/VrMenu.h b/libraries/ui/src/VrMenu.h index 06a16588af..38e3b54739 100644 --- a/libraries/ui/src/VrMenu.h +++ b/libraries/ui/src/VrMenu.h @@ -38,9 +38,7 @@ public: protected: QObject* _rootMenu{ nullptr }; - QObject* findMenuObject(const QString& name); - const QObject* findMenuObject(const QString& name) const; static VrMenu* _instance; friend class MenuUserData;