1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #include "modelnodecontextmenu.h"
27 #include "modelnodecontextmenu_helper.h"
28 #include "designeractionmanager.h"
29 #include <qmldesignerplugin.h>
30 
31 #include <modelnode.h>
32 
33 #include <utils/algorithm.h>
34 
35 #include <QSet>
36 
37 namespace QmlDesigner {
38 
ModelNodeContextMenu(AbstractView * view)39 ModelNodeContextMenu::ModelNodeContextMenu(AbstractView *view) :
40     m_selectionContext(view)
41 {
42 }
43 
findMembers(QSet<ActionInterface * > actionInterface,const QByteArray & category)44 static QSet<ActionInterface* > findMembers(QSet<ActionInterface* > actionInterface,
45                                                           const QByteArray &category)
46 {
47     QSet<ActionInterface* > ret;
48 
49      foreach (ActionInterface* factory, actionInterface) {
50          if (factory->category() == category)
51              ret.insert(factory);
52      }
53      return ret;
54 }
55 
56 
populateMenu(QSet<ActionInterface * > & actionInterfaces,const QByteArray & category,QMenu * menu,const SelectionContext & selectionContext)57 void populateMenu(QSet<ActionInterface* > &actionInterfaces,
58                   const QByteArray &category,
59                   QMenu* menu,
60                   const SelectionContext &selectionContext)
61 {
62     QSet<ActionInterface* > matchingFactories = findMembers(actionInterfaces, category);
63 
64     actionInterfaces.subtract(matchingFactories);
65 
66     QList<ActionInterface* > matchingFactoriesList = Utils::toList(matchingFactories);
67     Utils::sort(matchingFactoriesList, [](ActionInterface *l, ActionInterface *r) {
68         return l->priority() > r->priority();
69     });
70 
71     foreach (ActionInterface* actionInterface, matchingFactoriesList) {
72         if (actionInterface->type() == ActionInterface::ContextMenu) {
73             actionInterface->currentContextChanged(selectionContext);
74             QMenu *newMenu = actionInterface->action()->menu();
75             if (newMenu && !newMenu->title().isEmpty())
76                 menu->addMenu(newMenu);
77 
78             //recurse
79 
80             populateMenu(actionInterfaces, actionInterface->menuId(), newMenu, selectionContext);
81         } else if (actionInterface->type() == ActionInterface::ContextMenuAction
82                    || actionInterface->type() == ActionInterface::Action
83                    || actionInterface->type() == ActionInterface::FormEditorAction) {
84            QAction* action = actionInterface->action();
85            actionInterface->currentContextChanged(selectionContext);
86            action->setIconVisibleInMenu(false);
87            menu->addAction(action);
88        }
89     }
90 }
91 
execute(const QPoint & position,bool selectionMenuBool)92 void ModelNodeContextMenu::execute(const QPoint &position, bool selectionMenuBool)
93 {
94     auto mainMenu = new QMenu();
95 
96     m_selectionContext.setShowSelectionTools(selectionMenuBool);
97     m_selectionContext.setScenePosition(m_scenePos);
98 
99     auto &manager = QmlDesignerPlugin::instance()->designerActionManager();
100 
101     manager.setupContext();
102 
103     QSet<ActionInterface* > factories = Utils::toSet(manager.designerActions());
104 
105      populateMenu(factories, QByteArray(), mainMenu, m_selectionContext);
106 
107      mainMenu->exec(position);
108      mainMenu->deleteLater();
109 }
110 
setScenePos(const QPoint & position)111 void ModelNodeContextMenu::setScenePos(const QPoint &position)
112 {
113     m_scenePos = position;
114 }
115 
showContextMenu(AbstractView * view,const QPoint & globalPosition,const QPoint & scenePosition,bool showSelection)116 void ModelNodeContextMenu::showContextMenu(AbstractView *view,
117                                            const QPoint &globalPosition,
118                                            const QPoint &scenePosition,
119                                            bool showSelection)
120 {
121     ModelNodeContextMenu contextMenu(view);
122     contextMenu.setScenePos(scenePosition);
123     contextMenu.execute(globalPosition, showSelection);
124 }
125 
126 } //QmlDesigner
127