VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser/UIChooserHandlerMouse.cpp

Last change on this file was 106061, checked in by vboxsync, 3 weeks ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.4 KB
Line 
1/* $Id: UIChooserHandlerMouse.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIChooserHandlerMouse class implementation.
4 */
5
6/*
7 * Copyright (C) 2012-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QGraphicsSceneMouseEvent>
30
31/* GUI incluedes: */
32#include "UIChooserHandlerMouse.h"
33#include "UIChooserModel.h"
34#include "UIChooserItemGroup.h"
35#include "UIChooserItemGlobal.h"
36#include "UIChooserItemMachine.h"
37
38
39UIChooserHandlerMouse::UIChooserHandlerMouse(UIChooserModel *pParent)
40 : QObject(pParent)
41 , m_pModel(pParent)
42{
43}
44
45bool UIChooserHandlerMouse::handle(QGraphicsSceneMouseEvent *pEvent, UIMouseEventType type) const
46{
47 /* Process passed event: */
48 switch (type)
49 {
50 case UIMouseEventType_Press: return handleMousePress(pEvent);
51 case UIMouseEventType_Release: return handleMouseRelease(pEvent);
52 case UIMouseEventType_DoubleClick: return handleMouseDoubleClick(pEvent);
53 }
54 /* Pass event if unknown: */
55 return false;
56}
57
58UIChooserModel* UIChooserHandlerMouse::model() const
59{
60 return m_pModel;
61}
62
63bool UIChooserHandlerMouse::handleMousePress(QGraphicsSceneMouseEvent *pEvent) const
64{
65 /* Get item under mouse cursor: */
66 QPointF scenePos = pEvent->scenePos();
67 if (QGraphicsItem *pItemUnderMouse = model()->itemAt(scenePos))
68 {
69 /* Which button it was? */
70 switch (pEvent->button())
71 {
72 /* Left one? */
73 case Qt::LeftButton:
74 {
75 /* Which item we just clicked? */
76 UIChooserItem *pClickedItem = 0;
77 /* Was that a group item? */
78 if (UIChooserItemGroup *pGroupItem = qgraphicsitem_cast<UIChooserItemGroup*>(pItemUnderMouse))
79 pClickedItem = pGroupItem;
80 /* Or a global one? */
81 else if (UIChooserItemGlobal *pGlobalItem = qgraphicsitem_cast<UIChooserItemGlobal*>(pItemUnderMouse))
82 {
83 const QPoint itemCursorPos = pGlobalItem->mapFromScene(scenePos).toPoint();
84 if ( pGlobalItem->isToolButtonArea(itemCursorPos)
85 && ( model()->firstSelectedItem() == pGlobalItem
86 || pGlobalItem->isHovered()))
87 {
88 model()->handleToolButtonClick(pGlobalItem);
89 if (model()->firstSelectedItem() != pGlobalItem)
90 pClickedItem = pGlobalItem;
91 }
92 else
93 if ( pGlobalItem->isPinButtonArea(itemCursorPos)
94 && ( model()->firstSelectedItem() == pGlobalItem
95 || pGlobalItem->isHovered()))
96 model()->handlePinButtonClick(pGlobalItem);
97 else
98 pClickedItem = pGlobalItem;
99 }
100 /* Or a machine one? */
101 else if (UIChooserItemMachine *pMachineItem = qgraphicsitem_cast<UIChooserItemMachine*>(pItemUnderMouse))
102 {
103 const QPoint itemCursorPos = pMachineItem->mapFromScene(scenePos).toPoint();
104 if ( pMachineItem->isToolButtonArea(itemCursorPos)
105 && ( model()->firstSelectedItem() == pMachineItem
106 || pMachineItem->isHovered()))
107 {
108 model()->handleToolButtonClick(pMachineItem);
109 if (model()->firstSelectedItem() != pMachineItem)
110 pClickedItem = pMachineItem;
111 }
112 else
113 pClickedItem = pMachineItem;
114 }
115 /* If we had clicked one of required item types: */
116 if (pClickedItem && !pClickedItem->isRoot())
117 {
118 /* Was 'shift' modifier pressed? */
119 if (pEvent->modifiers() == Qt::ShiftModifier)
120 {
121 /* Calculate positions: */
122 UIChooserItem *pFirstItem = model()->firstSelectedItem();
123 AssertPtrReturn(pFirstItem, false); // is failure possible?
124 const int iFirstPosition = model()->navigationItems().indexOf(pFirstItem);
125 const int iClickedPosition = model()->navigationItems().indexOf(pClickedItem);
126 /* Populate list of items from 'first' to 'clicked': */
127 QList<UIChooserItem*> items;
128 if (iFirstPosition <= iClickedPosition)
129 for (int i = iFirstPosition; i <= iClickedPosition; ++i)
130 items << model()->navigationItems().at(i);
131 else
132 for (int i = iFirstPosition; i >= iClickedPosition; --i)
133 items << model()->navigationItems().at(i);
134 /* Wipe out items of inconsistent types: */
135 QList<UIChooserItem*> filteredItems;
136 foreach (UIChooserItem *pIteratedItem, items)
137 {
138 /* So, the logic is to add intermediate item if
139 * - first and intermediate selected items are global or
140 * - first and intermediate selected items are NOT global. */
141 if ( ( pFirstItem->type() == UIChooserNodeType_Global
142 && pIteratedItem->type() == UIChooserNodeType_Global)
143 || ( pFirstItem->type() != UIChooserNodeType_Global
144 && pIteratedItem->type() != UIChooserNodeType_Global))
145 filteredItems << pIteratedItem;
146 }
147 /* Make that list selected: */
148 model()->setSelectedItems(filteredItems);
149 /* Make item closest to clicked the current one: */
150 if (!filteredItems.isEmpty())
151 model()->setCurrentItem(filteredItems.last());
152 }
153 /* Was 'control' modifier pressed? */
154 else if (pEvent->modifiers() == Qt::ControlModifier)
155 {
156 /* Invert selection state for clicked item: */
157 if (model()->selectedItems().contains(pClickedItem))
158 model()->removeFromSelectedItems(pClickedItem);
159 else
160 {
161 /* So, the logic is to add newly clicked item if
162 * - previously and newly selected items are global or
163 * - previously and newly selected items are NOT global. */
164 UIChooserItem *pFirstItem = model()->firstSelectedItem();
165 AssertPtrReturn(pFirstItem, false); // is failure possible?
166 if ( ( pFirstItem->type() == UIChooserNodeType_Global
167 && pClickedItem->type() == UIChooserNodeType_Global)
168 || ( pFirstItem->type() != UIChooserNodeType_Global
169 && pClickedItem->type() != UIChooserNodeType_Global))
170 model()->addToSelectedItems(pClickedItem);
171 }
172 /* Make clicked item current one: */
173 model()->setCurrentItem(pClickedItem);
174 }
175 /* Was no modifiers pressed? */
176 else if (pEvent->modifiers() == Qt::NoModifier)
177 {
178 /* Make clicked item the only selected one: */
179 model()->setSelectedItem(pClickedItem);
180 }
181 }
182 break;
183 }
184 /* Right one? */
185 case Qt::RightButton:
186 {
187 /* Which item we just clicked? */
188 UIChooserItem *pClickedItem = 0;
189 /* Was that a group item? */
190 if (UIChooserItemGroup *pGroupItem = qgraphicsitem_cast<UIChooserItemGroup*>(pItemUnderMouse))
191 pClickedItem = pGroupItem;
192 /* Or a global one? */
193 else if (UIChooserItemGlobal *pGlobalItem = qgraphicsitem_cast<UIChooserItemGlobal*>(pItemUnderMouse))
194 pClickedItem = pGlobalItem;
195 /* Or a machine one? */
196 else if (UIChooserItemMachine *pMachineItem = qgraphicsitem_cast<UIChooserItemMachine*>(pItemUnderMouse))
197 pClickedItem = pMachineItem;
198 /* If we had clicked one of required item types: */
199 if (pClickedItem && !pClickedItem->isRoot())
200 {
201 /* Select clicked item if not selected yet: */
202 if (!model()->selectedItems().contains(pClickedItem))
203 model()->setSelectedItem(pClickedItem);
204 }
205 break;
206 }
207 default:
208 break;
209 }
210 }
211 /* Pass all other events: */
212 return false;
213}
214
215bool UIChooserHandlerMouse::handleMouseRelease(QGraphicsSceneMouseEvent*) const
216{
217 /* Pass all events: */
218 return false;
219}
220
221bool UIChooserHandlerMouse::handleMouseDoubleClick(QGraphicsSceneMouseEvent *pEvent) const
222{
223 /* Get item under mouse cursor: */
224 QPointF scenePos = pEvent->scenePos();
225 if (QGraphicsItem *pItemUnderMouse = model()->itemAt(scenePos))
226 {
227 /* Which button it was? */
228 switch (pEvent->button())
229 {
230 /* Left one? */
231 case Qt::LeftButton:
232 {
233 /* Was that a group item? */
234 if (UIChooserItemGroup *pGroupItem = qgraphicsitem_cast<UIChooserItemGroup*>(pItemUnderMouse))
235 {
236 /* If it was not root: */
237 if (!pGroupItem->isRoot())
238 {
239 /* Toggle it: */
240 if (pGroupItem->isClosed())
241 pGroupItem->open();
242 else if (pGroupItem->isOpened())
243 pGroupItem->close();
244 }
245 /* Filter that event out: */
246 return true;
247 }
248 /* Or a machine one? */
249 else if (pItemUnderMouse->type() == UIChooserNodeType_Machine)
250 {
251 /* Start or show selected items: */
252 model()->startOrShowSelectedItems();
253 }
254 break;
255 }
256 default:
257 break;
258 }
259 }
260 /* Pass all other events: */
261 return false;
262}
263
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette