liveselectiontool.cpp 16.1 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
7
**
hjk's avatar
hjk committed
8 9 10 11 12 13 14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15 16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17 18 19 20 21 22 23 24 25
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26 27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
29

30
#include "liveselectiontool.h"
31
#include "livelayeritem.h"
32

33
#include "../qdeclarativeviewinspector_p.h"
34

35 36 37 38 39 40 41
#include <QApplication>
#include <QWheelEvent>
#include <QMouseEvent>
#include <QClipboard>
#include <QMenu>
#include <QAction>
#include <QGraphicsObject>
42

43 44
#include <QDeclarativeItem>
#include <QDeclarativeEngine>
45

46
#include <QDebug>
47

48
namespace QmlJSDebugger {
49

50
LiveSelectionTool::LiveSelectionTool(QDeclarativeViewInspector *editorView) :
51
    AbstractLiveEditTool(editorView),
52
    m_rubberbandSelectionMode(false),
Kai Koehne's avatar
Kai Koehne committed
53
    m_rubberbandSelectionManipulator(
54
        QDeclarativeViewInspectorPrivate::get(editorView)->manipulatorLayer, editorView),
55
    m_singleSelectionManipulator(editorView),
Kai Koehne's avatar
Kai Koehne committed
56
    m_selectionIndicator(editorView,
57
        QDeclarativeViewInspectorPrivate::get(editorView)->manipulatorLayer),
58 59 60 61 62 63
    //m_resizeIndicator(editorView->manipulatorLayer()),
    m_selectOnlyContentItems(true)
{

}

64
LiveSelectionTool::~LiveSelectionTool()
65 66 67
{
}

68
void LiveSelectionTool::setRubberbandSelectionMode(bool value)
69 70 71 72
{
    m_rubberbandSelectionMode = value;
}

73
LiveSingleSelectionManipulator::SelectionType LiveSelectionTool::getSelectionType(Qt::KeyboardModifiers
Kai Koehne's avatar
Kai Koehne committed
74
                                                                          modifiers)
75
{
76 77
   LiveSingleSelectionManipulator::SelectionType selectionType
            = LiveSingleSelectionManipulator::ReplaceSelection;
78
    if (modifiers.testFlag(Qt::ControlModifier)) {
79
        selectionType = LiveSingleSelectionManipulator::RemoveFromSelection;
80
    } else if (modifiers.testFlag(Qt::ShiftModifier)) {
81
        selectionType = LiveSingleSelectionManipulator::AddToSelection;
82 83 84 85
    }
    return selectionType;
}

86
bool LiveSelectionTool::alreadySelected(const QList<QGraphicsItem*> &itemList) const
87
{
88 89 90
    QDeclarativeViewInspectorPrivate *inspectorPrivate
            = QDeclarativeViewInspectorPrivate::get(inspector());
    const QList<QGraphicsItem*> selectedItems = inspectorPrivate->selectedItems();
91 92 93 94

    if (selectedItems.isEmpty())
        return false;

95 96
    foreach (QGraphicsItem *item, itemList)
        if (selectedItems.contains(item))
97 98 99 100 101
            return true;

    return false;
}

102
void LiveSelectionTool::mousePressEvent(QMouseEvent *event)
103
{
104 105 106
    QDeclarativeViewInspectorPrivate *inspectorPrivate
            = QDeclarativeViewInspectorPrivate::get(inspector());
    QList<QGraphicsItem*> itemList = inspectorPrivate->selectableItems(event->pos());
107
    LiveSingleSelectionManipulator::SelectionType selectionType = getSelectionType(event->modifiers());
108 109 110 111 112 113 114

    if (event->buttons() & Qt::LeftButton) {
        m_mousePressTimer.start();

        if (m_rubberbandSelectionMode) {
            m_rubberbandSelectionManipulator.begin(event->pos());
        } else {
115 116
            m_singleSelectionManipulator.begin(event->pos());
            m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems);
117 118 119 120 121 122
        }
    } else if (event->buttons() & Qt::RightButton) {
        createContextMenu(itemList, event->globalPos());
    }
}

123
void LiveSelectionTool::createContextMenu(QList<QGraphicsItem*> itemList, QPoint globalPos)
124 125
{
    QMenu contextMenu;
Kai Koehne's avatar
Kai Koehne committed
126 127
    connect(&contextMenu, SIGNAL(hovered(QAction*)),
            this, SLOT(contextMenuElementHovered(QAction*)));
128 129 130 131 132 133 134 135 136

    m_contextMenuItemList = itemList;

    contextMenu.addAction("Items");
    contextMenu.addSeparator();
    int shortcutKey = Qt::Key_1;
    bool addKeySequence = true;
    int i = 0;

137
    foreach (QGraphicsItem * const item, itemList) {
138
        QString itemTitle = titleForItem(item);
Kai Koehne's avatar
Kai Koehne committed
139 140
        QAction *elementAction = contextMenu.addAction(itemTitle, this,
                                                       SLOT(contextMenuElementSelected()));
141

142
        if (inspector()->selectedItems().contains(item)) {
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
            QFont boldFont = elementAction->font();
            boldFont.setBold(true);
            elementAction->setFont(boldFont);
        }

        elementAction->setData(i);
        if (addKeySequence)
            elementAction->setShortcut(QKeySequence(shortcutKey));

        shortcutKey++;
        if (shortcutKey > Qt::Key_9)
            addKeySequence = false;

        ++i;
    }
    // add root item separately
Kai Koehne's avatar
Kai Koehne committed
159 160 161
    //    QString itemTitle = QString(tr("%1")).arg(titleForItem(view()->currentRootItem()));
    //    contextMenu.addAction(itemTitle, this, SLOT(contextMenuElementSelected()));
    //    m_contextMenuItemList.append(view()->currentRootItem());
162 163 164 165 166

    contextMenu.exec(globalPos);
    m_contextMenuItemList.clear();
}

167
void LiveSelectionTool::contextMenuElementSelected()
168 169 170 171 172 173
{
    QAction *senderAction = static_cast<QAction*>(sender());
    int itemListIndex = senderAction->data().toInt();
    if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) {

        QPointF updatePt(0, 0);
174
        QGraphicsItem *item = m_contextMenuItemList.at(itemListIndex);
175
        m_singleSelectionManipulator.begin(updatePt);
176
        m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::InvertSelection,
177
                                            QList<QGraphicsItem*>() << item,
178 179 180 181 182
                                            false);
        m_singleSelectionManipulator.end(updatePt);
    }
}

183
void LiveSelectionTool::contextMenuElementHovered(QAction *action)
184 185 186
{
    int itemListIndex = action->data().toInt();
    if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) {
187
        QGraphicsObject *item = m_contextMenuItemList.at(itemListIndex)->toGraphicsObject();
188
        QDeclarativeViewInspectorPrivate::get(inspector())->highlight(item);
189 190 191
    }
}

192
void LiveSelectionTool::mouseMoveEvent(QMouseEvent *event)
193 194 195 196 197
{
    if (m_singleSelectionManipulator.isActive()) {
        QPointF mouseMovementVector = m_singleSelectionManipulator.beginPoint() - event->pos();

        if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance)
Kai Koehne's avatar
Kai Koehne committed
198
                && (m_mousePressTimer.elapsed() > Constants::DragStartTime))
199 200 201 202 203 204 205 206 207
        {
            m_singleSelectionManipulator.end(event->pos());
            //view()->changeToMoveTool(m_singleSelectionManipulator.beginPoint());
            return;
        }
    } else if (m_rubberbandSelectionManipulator.isActive()) {
        QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos();

        if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance)
Kai Koehne's avatar
Kai Koehne committed
208
                && (m_mousePressTimer.elapsed() > Constants::DragStartTime)) {
209 210 211
            m_rubberbandSelectionManipulator.update(event->pos());

            if (event->modifiers().testFlag(Qt::ControlModifier))
Kai Koehne's avatar
Kai Koehne committed
212
                m_rubberbandSelectionManipulator.select(
213
                            LiveRubberBandSelectionManipulator::RemoveFromSelection);
214
            else if (event->modifiers().testFlag(Qt::ShiftModifier))
Kai Koehne's avatar
Kai Koehne committed
215
                m_rubberbandSelectionManipulator.select(
216
                            LiveRubberBandSelectionManipulator::AddToSelection);
217
            else
Kai Koehne's avatar
Kai Koehne committed
218
                m_rubberbandSelectionManipulator.select(
219
                            LiveRubberBandSelectionManipulator::ReplaceSelection);
220 221 222 223
        }
    }
}

224
void LiveSelectionTool::hoverMoveEvent(QMouseEvent * event)
225
{
226 227 228 229
// ### commented out until move tool is re-enabled
//    QList<QGraphicsItem*> itemList = view()->items(event->pos());
//    if (!itemList.isEmpty() && !m_rubberbandSelectionMode) {
//
230
//        foreach (QGraphicsItem *item, itemList) {
231 232 233 234 235 236 237 238 239
//            if (item->type() == Constants::ResizeHandleItemType) {
//                ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(item);
//                if (resizeHandle)
//                    view()->changeTool(Constants::ResizeToolMode);
//                return;
//            }
//        }
//        if (topSelectedItemIsMovable(itemList))
//            view()->changeTool(Constants::MoveToolMode);
240
//    }
241 242
    QDeclarativeViewInspectorPrivate *inspectorPrivate
            = QDeclarativeViewInspectorPrivate::get(inspector());
Kai Koehne's avatar
Kai Koehne committed
243

244
    QList<QGraphicsItem*> selectableItemList = inspectorPrivate->selectableItems(event->pos());
245
    if (!selectableItemList.isEmpty()) {
246 247
        QGraphicsObject *item = selectableItemList.first()->toGraphicsObject();
        if (item)
248
            QDeclarativeViewInspectorPrivate::get(inspector())->highlight(item);
249

250
        return;
251
    }
252

253
    QDeclarativeViewInspectorPrivate::get(inspector())->clearHighlight();
254 255
}

256
void LiveSelectionTool::mouseReleaseEvent(QMouseEvent *event)
257 258 259
{
    if (m_singleSelectionManipulator.isActive()) {
        m_singleSelectionManipulator.end(event->pos());
260
    } else if (m_rubberbandSelectionManipulator.isActive()) {
261 262 263 264 265
        QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos();
        if (mouseMovementVector.toPoint().manhattanLength() < Constants::DragStartDistance) {
            m_singleSelectionManipulator.begin(event->pos());

            if (event->modifiers().testFlag(Qt::ControlModifier))
266
                m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::RemoveFromSelection,
Kai Koehne's avatar
Kai Koehne committed
267
                                                    m_selectOnlyContentItems);
268
            else if (event->modifiers().testFlag(Qt::ShiftModifier))
269
                m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::AddToSelection,
Kai Koehne's avatar
Kai Koehne committed
270
                                                    m_selectOnlyContentItems);
271
            else
272
                m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::InvertSelection,
Kai Koehne's avatar
Kai Koehne committed
273
                                                    m_selectOnlyContentItems);
274 275 276 277 278 279

            m_singleSelectionManipulator.end(event->pos());
        } else {
            m_rubberbandSelectionManipulator.update(event->pos());

            if (event->modifiers().testFlag(Qt::ControlModifier))
Kai Koehne's avatar
Kai Koehne committed
280
                m_rubberbandSelectionManipulator.select(
281
                            LiveRubberBandSelectionManipulator::RemoveFromSelection);
282
            else if (event->modifiers().testFlag(Qt::ShiftModifier))
Kai Koehne's avatar
Kai Koehne committed
283
                m_rubberbandSelectionManipulator.select(
284
                            LiveRubberBandSelectionManipulator::AddToSelection);
285
            else
Kai Koehne's avatar
Kai Koehne committed
286
                m_rubberbandSelectionManipulator.select(
287
                            LiveRubberBandSelectionManipulator::ReplaceSelection);
288 289 290 291 292 293

            m_rubberbandSelectionManipulator.end();
        }
    }
}

294
void LiveSelectionTool::mouseDoubleClickEvent(QMouseEvent * /*event*/)
295 296 297
{
}

298
void LiveSelectionTool::keyPressEvent(QKeyEvent *event)
299 300
{
    switch(event->key()) {
Kai Koehne's avatar
Kai Koehne committed
301 302 303 304 305 306 307 308
    case Qt::Key_Left:
    case Qt::Key_Right:
    case Qt::Key_Up:
    case Qt::Key_Down:
        // disabled for now, cannot move stuff yet.
        //view()->changeTool(Constants::MoveToolMode);
        //view()->currentTool()->keyPressEvent(event);
        break;
309 310 311
    }
}

312
void LiveSelectionTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
313 314 315 316
{

}

317
void LiveSelectionTool::wheelEvent(QWheelEvent *event)
318 319 320 321
{
    if (event->orientation() == Qt::Horizontal || m_rubberbandSelectionMode)
        return;

322 323 324
    QDeclarativeViewInspectorPrivate *inspectorPrivate
            = QDeclarativeViewInspectorPrivate::get(inspector());
    QList<QGraphicsItem*> itemList = inspectorPrivate->selectableItems(event->pos());
325

326 327 328
    if (itemList.isEmpty())
        return;

329
    int selectedIdx = 0;
330 331
    if (!inspector()->selectedItems().isEmpty()) {
        selectedIdx = itemList.indexOf(inspector()->selectedItems().first());
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
        if (selectedIdx >= 0) {
            if (event->delta() > 0) {
                selectedIdx++;
                if (selectedIdx == itemList.length())
                    selectedIdx = 0;
            } else if (event->delta() < 0) {
                selectedIdx--;
                if (selectedIdx == -1)
                    selectedIdx = itemList.length() - 1;
            }
        } else {
            selectedIdx = 0;
        }
    }

    QPointF updatePt(0, 0);
    m_singleSelectionManipulator.begin(updatePt);
349
    m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::ReplaceSelection,
350 351 352 353 354 355
                                        QList<QGraphicsItem*>() << itemList.at(selectedIdx),
                                        false);
    m_singleSelectionManipulator.end(updatePt);

}

356
void LiveSelectionTool::setSelectOnlyContentItems(bool selectOnlyContentItems)
357 358 359 360
{
    m_selectOnlyContentItems = selectOnlyContentItems;
}

361
void LiveSelectionTool::itemsAboutToRemoved(const QList<QGraphicsItem*> &/*itemList*/)
362 363 364
{
}

365
void LiveSelectionTool::clear()
366 367 368
{
    view()->setCursor(Qt::ArrowCursor);
    m_rubberbandSelectionManipulator.clear(),
Kai Koehne's avatar
Kai Koehne committed
369
            m_singleSelectionManipulator.clear();
370 371 372 373
    m_selectionIndicator.clear();
    //m_resizeIndicator.clear();
}

374
void LiveSelectionTool::selectedItemsChanged(const QList<QGraphicsItem*> &itemList)
375
{
Friedemann Kleint's avatar
Friedemann Kleint committed
376
    foreach (const QWeakPointer<QGraphicsObject> &obj, m_selectedItemList) {
377 378 379 380 381 382 383 384
        if (!obj.isNull()) {
            disconnect(obj.data(), SIGNAL(xChanged()), this, SLOT(repaintBoundingRects()));
            disconnect(obj.data(), SIGNAL(yChanged()), this, SLOT(repaintBoundingRects()));
            disconnect(obj.data(), SIGNAL(widthChanged()), this, SLOT(repaintBoundingRects()));
            disconnect(obj.data(), SIGNAL(heightChanged()), this, SLOT(repaintBoundingRects()));
            disconnect(obj.data(), SIGNAL(rotationChanged()), this, SLOT(repaintBoundingRects()));
        }
    }
385

386 387 388
    QList<QGraphicsObject*> objects = toGraphicsObjectList(itemList);
    m_selectedItemList.clear();

389
    foreach (QGraphicsObject *obj, objects) {
390 391 392 393 394 395 396 397 398
        m_selectedItemList.append(obj);
        connect(obj, SIGNAL(xChanged()), this, SLOT(repaintBoundingRects()));
        connect(obj, SIGNAL(yChanged()), this, SLOT(repaintBoundingRects()));
        connect(obj, SIGNAL(widthChanged()), this, SLOT(repaintBoundingRects()));
        connect(obj, SIGNAL(heightChanged()), this, SLOT(repaintBoundingRects()));
        connect(obj, SIGNAL(rotationChanged()), this, SLOT(repaintBoundingRects()));
    }

    m_selectionIndicator.setItems(m_selectedItemList);
399 400 401
    //m_resizeIndicator.setItems(toGraphicsObjectList(itemList));
}

402
void LiveSelectionTool::repaintBoundingRects()
403 404 405 406
{
    m_selectionIndicator.setItems(m_selectedItemList);
}

407
void LiveSelectionTool::selectUnderPoint(QMouseEvent *event)
408 409 410 411
{
    m_singleSelectionManipulator.begin(event->pos());

    if (event->modifiers().testFlag(Qt::ControlModifier))
412
        m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::RemoveFromSelection,
Kai Koehne's avatar
Kai Koehne committed
413
                                            m_selectOnlyContentItems);
414
    else if (event->modifiers().testFlag(Qt::ShiftModifier))
415
        m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::AddToSelection,
Kai Koehne's avatar
Kai Koehne committed
416
                                            m_selectOnlyContentItems);
417
    else
418
        m_singleSelectionManipulator.select(LiveSingleSelectionManipulator::InvertSelection,
Kai Koehne's avatar
Kai Koehne committed
419
                                            m_selectOnlyContentItems);
420 421 422 423

    m_singleSelectionManipulator.end(event->pos());
}

Kai Koehne's avatar
Kai Koehne committed
424
} // namespace QmlJSDebugger