fd2bf8d241be4729f630f7fe8b0953dcf72142d8
[profile/ivi/qtdeclarative.git] / src / plugins / qmltooling / qmldbg_qtquick1 / liveselectiontool.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "liveselectiontool.h"
43 #include "livelayeritem.h"
44
45 #include "qdeclarativeviewinspector_p.h"
46
47 #include <QtWidgets/QApplication>
48 #include <QtGui/QWheelEvent>
49 #include <QtGui/QMouseEvent>
50 #include <QtGui/QClipboard>
51 #include <QtWidgets/QMenu>
52 #include <QtWidgets/QAction>
53 #include <QtWidgets/QGraphicsObject>
54
55 #include <QtQuick1/QDeclarativeItem>
56 #include <QtDeclarative/QDeclarativeEngine>
57
58 #include <QtCore/QDebug>
59
60 namespace QmlJSDebugger {
61 namespace QtQuick1 {
62
63 LiveSelectionTool::LiveSelectionTool(QDeclarativeViewInspector *editorView) :
64     AbstractLiveEditTool(editorView),
65     m_rubberbandSelectionMode(false),
66     m_rubberbandSelectionManipulator(
67         QDeclarativeViewInspectorPrivate::get(editorView)->manipulatorLayer, editorView),
68     m_singleSelectionManipulator(editorView),
69     m_selectionIndicator(editorView,
70         QDeclarativeViewInspectorPrivate::get(editorView)->manipulatorLayer),
71     //m_resizeIndicator(editorView->manipulatorLayer()),
72     m_selectOnlyContentItems(true)
73 {
74
75 }
76
77 LiveSelectionTool::~LiveSelectionTool()
78 {
79 }
80
81 void LiveSelectionTool::setRubberbandSelectionMode(bool value)
82 {
83     m_rubberbandSelectionMode = value;
84 }
85
86 LiveSingleSelectionManipulator::SelectionType LiveSelectionTool::getSelectionType(Qt::KeyboardModifiers
87                                                                           modifiers)
88 {
89    LiveSingleSelectionManipulator::SelectionType selectionType
90             = LiveSingleSelectionManipulator::ReplaceSelection;
91     if (modifiers.testFlag(Qt::ControlModifier)) {
92         selectionType = LiveSingleSelectionManipulator::RemoveFromSelection;
93     } else if (modifiers.testFlag(Qt::ShiftModifier)) {
94         selectionType = LiveSingleSelectionManipulator::AddToSelection;
95     }
96     return selectionType;
97 }
98
99 bool LiveSelectionTool::alreadySelected(const QList<QGraphicsItem*> &itemList) const
100 {
101     QDeclarativeViewInspectorPrivate *inspectorPrivate
102             = QDeclarativeViewInspectorPrivate::get(inspector());
103     const QList<QGraphicsItem*> selectedItems = inspectorPrivate->selectedItems();
104
105     if (selectedItems.isEmpty())
106         return false;
107
108     foreach (QGraphicsItem *item, itemList)
109         if (selectedItems.contains(item))
110             return true;
111
112     return false;
113 }
114
115 void LiveSelectionTool::mousePressEvent(QMouseEvent *event)
116 {
117     QDeclarativeViewInspectorPrivate *inspectorPrivate
118             = QDeclarativeViewInspectorPrivate::get(inspector());
119     QList<QGraphicsItem*> itemList = inspectorPrivate->selectableItems(event->pos());
120     LiveSingleSelectionManipulator::SelectionType selectionType = getSelectionType(event->modifiers());
121
122     if (event->buttons() & Qt::LeftButton) {
123         m_mousePressTimer.start();
124
125         if (m_rubberbandSelectionMode) {
126             m_rubberbandSelectionManipulator.begin(event->pos());
127         } else {
128             m_singleSelectionManipulator.begin(event->pos());
129             m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
130         }
131     } else if (event->buttons() & Qt::RightButton) {
132         createContextMenu(itemList, event->globalPos());
133     }
134 }
135
136 void LiveSelectionTool::createContextMenu(const QList<QGraphicsItem*> &itemList, QPoint globalPos)
137 {
138     QMenu contextMenu;
139     connect(&contextMenu, SIGNAL(hovered(QAction*)),
140             this, SLOT(contextMenuElementHovered(QAction*)));
141
142     m_contextMenuItemList = itemList;
143
144     contextMenu.addAction(tr("Items"));
145     contextMenu.addSeparator();
146     int shortcutKey = Qt::Key_1;
147     int i = 0;
148
149     foreach (QGraphicsItem * const item, itemList) {
150         QString itemTitle = titleForItem(item);
151         QAction *elementAction = contextMenu.addAction(itemTitle, this,
152                                                        SLOT(contextMenuElementSelected()));
153
154         if (inspector()->selectedItems().contains(item)) {
155             QFont boldFont = elementAction->font();
156             boldFont.setBold(true);
157             elementAction->setFont(boldFont);
158         }
159
160         elementAction->setData(i);
161
162         if (shortcutKey <= Qt::Key_9) {
163             elementAction->setShortcut(QKeySequence(shortcutKey));
164             shortcutKey++;
165         }
166
167         ++i;
168     }
169     // add root item separately
170     //    QString itemTitle = QString(tr("%1")).arg(titleForItem(view()->currentRootItem()));
171     //    contextMenu.addAction(itemTitle, this, SLOT(contextMenuElementSelected()));
172     //    m_contextMenuItemList.append(view()->currentRootItem());
173
174     contextMenu.exec(globalPos);
175     m_contextMenuItemList.clear();
176 }
177
178 void LiveSelectionTool::contextMenuElementSelected()
179 {
180     QAction *senderAction = static_cast<QAction*>(sender());
181     int itemListIndex = senderAction->data().toInt();
182     if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) {
183
184         QPointF updatePt(0, 0);
185         QGraphicsItem *item = m_contextMenuItemList.at(itemListIndex);
186         m_singleSelectionManipulator.begin(updatePt);
187         m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::InvertSelection,
188                                             QList<QGraphicsItem*>() << item,
189                                             false);
190         m_singleSelectionManipulator.end(updatePt);
191     }
192 }
193
194 void LiveSelectionTool::contextMenuElementHovered(QAction *action)
195 {
196     int itemListIndex = action->data().toInt();
197     if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) {
198         QGraphicsObject *item = m_contextMenuItemList.at(itemListIndex)->toGraphicsObject();
199         QDeclarativeViewInspectorPrivate::get(inspector())->highlight(item);
200     }
201 }
202
203 void LiveSelectionTool::mouseMoveEvent(QMouseEvent *event)
204 {
205     if (m_singleSelectionManipulator.isActive()) {
206         QPointF mouseMovementVector = m_singleSelectionManipulator.beginPoint() - event->pos();
207
208         if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance)
209                 && (m_mousePressTimer.elapsed() > Constants::DragStartTime))
210         {
211             m_singleSelectionManipulator.end(event->pos());
212             //view()->changeToMoveTool(m_singleSelectionManipulator.beginPoint());
213             return;
214         }
215     } else if (m_rubberbandSelectionManipulator.isActive()) {
216         QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos();
217
218         if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance)
219                 && (m_mousePressTimer.elapsed() > Constants::DragStartTime)) {
220             m_rubberbandSelectionManipulator.update(event->pos());
221
222             if (event->modifiers().testFlag(Qt::ControlModifier))
223                 m_rubberbandSelectionManipulator.select(
224                             LiveRubberBandSelectionManipulator::RemoveFromSelection);
225             else if (event->modifiers().testFlag(Qt::ShiftModifier))
226                 m_rubberbandSelectionManipulator.select(
227                             LiveRubberBandSelectionManipulator::AddToSelection);
228             else
229                 m_rubberbandSelectionManipulator.select(
230                             LiveRubberBandSelectionManipulator::ReplaceSelection);
231         }
232     }
233 }
234
235 void LiveSelectionTool::hoverMoveEvent(QMouseEvent * event)
236 {
237 // ### commented out until move tool is re-enabled
238 //    QList<QGraphicsItem*> itemList = view()->items(event->pos());
239 //    if (!itemList.isEmpty() && !m_rubberbandSelectionMode) {
240 //
241 //        foreach (QGraphicsItem *item, itemList) {
242 //            if (item->type() == Constants::ResizeHandleItemType) {
243 //                ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(item);
244 //                if (resizeHandle)
245 //                    view()->changeTool(Constants::ResizeToolMode);
246 //                return;
247 //            }
248 //        }
249 //        if (topSelectedItemIsMovable(itemList))
250 //            view()->changeTool(Constants::MoveToolMode);
251 //    }
252     QDeclarativeViewInspectorPrivate *inspectorPrivate
253             = QDeclarativeViewInspectorPrivate::get(inspector());
254
255     QList<QGraphicsItem*> selectableItemList = inspectorPrivate->selectableItems(event->pos());
256     if (!selectableItemList.isEmpty()) {
257         QGraphicsObject *item = selectableItemList.first()->toGraphicsObject();
258         if (item)
259             QDeclarativeViewInspectorPrivate::get(inspector())->highlight(item);
260
261         return;
262     }
263
264     QDeclarativeViewInspectorPrivate::get(inspector())->clearHighlight();
265 }
266
267 void LiveSelectionTool::mouseReleaseEvent(QMouseEvent *event)
268 {
269     if (m_singleSelectionManipulator.isActive()) {
270         m_singleSelectionManipulator.end(event->pos());
271     }
272     else if (m_rubberbandSelectionManipulator.isActive()) {
273
274         QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos();
275         if (mouseMovementVector.toPoint().manhattanLength() < Constants::DragStartDistance) {
276             m_singleSelectionManipulator.begin(event->pos());
277
278             if (event->modifiers().testFlag(Qt::ControlModifier))
279                 m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::RemoveFromSelection,
280                                                     m_selectOnlyContentItems);
281             else if (event->modifiers().testFlag(Qt::ShiftModifier))
282                 m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::AddToSelection,
283                                                     m_selectOnlyContentItems);
284             else
285                 m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::InvertSelection,
286                                                     m_selectOnlyContentItems);
287
288             m_singleSelectionManipulator.end(event->pos());
289         } else {
290             m_rubberbandSelectionManipulator.update(event->pos());
291
292             if (event->modifiers().testFlag(Qt::ControlModifier))
293                 m_rubberbandSelectionManipulator.select(
294                             LiveRubberBandSelectionManipulator::RemoveFromSelection);
295             else if (event->modifiers().testFlag(Qt::ShiftModifier))
296                 m_rubberbandSelectionManipulator.select(
297                             LiveRubberBandSelectionManipulator::AddToSelection);
298             else
299                 m_rubberbandSelectionManipulator.select(
300                             LiveRubberBandSelectionManipulator::ReplaceSelection);
301
302             m_rubberbandSelectionManipulator.end();
303         }
304     }
305 }
306
307 void LiveSelectionTool::keyPressEvent(QKeyEvent *event)
308 {
309     switch (event->key()) {
310     case Qt::Key_Left:
311     case Qt::Key_Right:
312     case Qt::Key_Up:
313     case Qt::Key_Down:
314         // disabled for now, cannot move stuff yet.
315         //view()->changeTool(Constants::MoveToolMode);
316         //view()->currentTool()->keyPressEvent(event);
317         break;
318     }
319 }
320
321 void LiveSelectionTool::wheelEvent(QWheelEvent *event)
322 {
323     if (event->orientation() == Qt::Horizontal || m_rubberbandSelectionMode)
324         return;
325
326     QDeclarativeViewInspectorPrivate *inspectorPrivate
327             = QDeclarativeViewInspectorPrivate::get(inspector());
328     QList<QGraphicsItem*> itemList = inspectorPrivate->selectableItems(event->pos());
329
330     if (itemList.isEmpty())
331         return;
332
333     int selectedIdx = 0;
334     if (!inspector()->selectedItems().isEmpty()) {
335         selectedIdx = itemList.indexOf(inspector()->selectedItems().first());
336         if (selectedIdx >= 0) {
337             if (event->delta() > 0) {
338                 selectedIdx++;
339                 if (selectedIdx == itemList.length())
340                     selectedIdx = 0;
341             } else if (event->delta() < 0) {
342                 selectedIdx--;
343                 if (selectedIdx == -1)
344                     selectedIdx = itemList.length() - 1;
345             }
346         } else {
347             selectedIdx = 0;
348         }
349     }
350
351     QPointF updatePt(0, 0);
352     m_singleSelectionManipulator.begin(updatePt);
353     m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::ReplaceSelection,
354                                         QList<QGraphicsItem*>() << itemList.at(selectedIdx),
355                                         false);
356     m_singleSelectionManipulator.end(updatePt);
357
358 }
359
360 void LiveSelectionTool::setSelectOnlyContentItems(bool selectOnlyContentItems)
361 {
362     m_selectOnlyContentItems = selectOnlyContentItems;
363 }
364
365 void LiveSelectionTool::clear()
366 {
367     view()->setCursor(Qt::ArrowCursor);
368     m_rubberbandSelectionManipulator.clear(),
369             m_singleSelectionManipulator.clear();
370     m_selectionIndicator.clear();
371     //m_resizeIndicator.clear();
372 }
373
374 void LiveSelectionTool::selectedItemsChanged(const QList<QGraphicsItem*> &itemList)
375 {
376     foreach (const QWeakPointer<QGraphicsObject> &obj, m_selectedItemList) {
377         if (!obj.isNull()) {
378             disconnect(obj.data(), SIGNAL(xChanged()), this, SLOT(repaintBoundingRects()));
379             disconnect(obj.data(), SIGNAL(yChanged()), this, SLOT(repaintBoundingRects()));
380             disconnect(obj.data(), SIGNAL(widthChanged()), this, SLOT(repaintBoundingRects()));
381             disconnect(obj.data(), SIGNAL(heightChanged()), this, SLOT(repaintBoundingRects()));
382             disconnect(obj.data(), SIGNAL(rotationChanged()), this, SLOT(repaintBoundingRects()));
383         }
384     }
385
386     QList<QGraphicsObject*> objects = toGraphicsObjectList(itemList);
387     m_selectedItemList.clear();
388
389     foreach (QGraphicsObject *obj, objects) {
390         m_selectedItemList.append(obj);
391         connect(obj, SIGNAL(xChanged()), this, SLOT(repaintBoundingRects()));
392         connect(obj, SIGNAL(yChanged()), this, SLOT(repaintBoundingRects()));
393         connect(obj, SIGNAL(widthChanged()), this, SLOT(repaintBoundingRects()));
394         connect(obj, SIGNAL(heightChanged()), this, SLOT(repaintBoundingRects()));
395         connect(obj, SIGNAL(rotationChanged()), this, SLOT(repaintBoundingRects()));
396     }
397
398     m_selectionIndicator.setItems(m_selectedItemList);
399     //m_resizeIndicator.setItems(toGraphicsObjectList(itemList));
400 }
401
402 void LiveSelectionTool::repaintBoundingRects()
403 {
404     m_selectionIndicator.setItems(m_selectedItemList);
405 }
406
407 void LiveSelectionTool::selectUnderPoint(QMouseEvent *event)
408 {
409     m_singleSelectionManipulator.begin(event->pos());
410
411     if (event->modifiers().testFlag(Qt::ControlModifier))
412         m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::RemoveFromSelection,
413                                             m_selectOnlyContentItems);
414     else if (event->modifiers().testFlag(Qt::ShiftModifier))
415         m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::AddToSelection,
416                                             m_selectOnlyContentItems);
417     else
418         m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::InvertSelection,
419                                             m_selectOnlyContentItems);
420
421     m_singleSelectionManipulator.end(event->pos());
422 }
423
424 } // namespace QtQuick1
425 } // namespace QmlJSDebugger