dragtool.cpp 12.7 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
2
**
3
** Copyright (C) 2014 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
** 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.
23
**
hjk's avatar
hjk committed
24
25
** 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
31
32
33
34
35

#include "dragtool.h"

#include "formeditorscene.h"
#include "formeditorview.h"
#include <customdraganddrop.h>
#include <metainfo.h>
36
#include <rewritingexception.h>
37
38

#include <QGraphicsSceneMouseEvent>
hjk's avatar
hjk committed
39
#include <QDebug>
40
#include <QMimeData>
Thomas Hartmann's avatar
Thomas Hartmann committed
41
#include <QTimer>
42
43
44

namespace QmlDesigner {

Thomas Hartmann's avatar
Thomas Hartmann committed
45
46
47
48
49
50
51
52
namespace Internal {
void TimerHandler::clearMoveDelay()
{
    m_dragTool->clearMoveDelay();
}

}

53
54
55
DragTool::DragTool(FormEditorView *editorView)
    : AbstractFormEditorTool(editorView),
    m_moveManipulator(editorView->scene()->manipulatorLayerItem(), editorView),
Thomas Hartmann's avatar
Thomas Hartmann committed
56
57
    m_selectionIndicator(editorView->scene()->manipulatorLayerItem()),
    m_timerHandler(new Internal::TimerHandler(this)),
58
59
    m_blockMove(false),
    m_Aborted(false)
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
{
}


DragTool::~DragTool()
{

}

void DragTool::clear()
{
    m_moveManipulator.clear();
    m_selectionIndicator.clear();
    m_movingItem.clear();
}

void DragTool::mousePressEvent(const QList<QGraphicsItem*> &,
                                            QGraphicsSceneMouseEvent *)
{

}

void DragTool::mouseMoveEvent(const QList<QGraphicsItem*> &,
                                           QGraphicsSceneMouseEvent *)
{

}

void DragTool::hoverMoveEvent(const QList<QGraphicsItem*> &,
                        QGraphicsSceneMouseEvent * /*event*/)
{

}

94
void DragTool::keyPressEvent(QKeyEvent *event)
95
{
96
97
98
    if (event->key() == Qt::Key_Escape) {
        abort();
        event->accept();
99
        commitTransaction();
100
101
        view()->changeToSelectionTool();
    }
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
}

void DragTool::keyReleaseEvent(QKeyEvent *)
{

}


void DragTool::mouseReleaseEvent(const QList<QGraphicsItem*> &/*itemList*/,
                                 QGraphicsSceneMouseEvent *)
{

}

void DragTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> & /*itemList*/,
                                              QGraphicsSceneMouseEvent * /*event*/)
{

}

void DragTool::itemsAboutToRemoved(const QList<FormEditorItem*> & /* removedItemList */)
{

}

void DragTool::selectedItemsChanged(const QList<FormEditorItem*> &)
{

}



void DragTool::updateMoveManipulator()
{
    if (m_moveManipulator.isActive())
        return;
}

void DragTool::beginWithPoint(const QPointF &beginPoint)
{
    m_movingItem = scene()->itemForQmlItemNode(m_dragNode);

    m_moveManipulator.setItem(m_movingItem.data());
    m_moveManipulator.begin(beginPoint);
}

148
void DragTool::createQmlItemNode(const ItemLibraryEntry &itemLibraryEntry, QmlItemNode parentNode, QPointF scenePos)
149
150
151
152
153
154
{
    MetaInfo metaInfo = MetaInfo::global();

    FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode);
    QPointF pos = parentItem->mapFromScene(scenePos);

155
    m_dragNode = QmlItemNode::createQmlItemNode(view(), itemLibraryEntry, pos, parentNode);
156
157
158
159

    Q_ASSERT(m_dragNode.modelNode().isValid());

    QList<QmlItemNode> nodeList;
Orgad Shaneh's avatar
Orgad Shaneh committed
160
    nodeList.append(m_dragNode);
161
162
163
164
165
    m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList));
}

void DragTool::createQmlItemNodeFromImage(const QString &imageName, QmlItemNode parentNode, QPointF scenePos)
{
166
167
168
    if (!parentNode.isValid())
        return;

169
170
171
172
173
    MetaInfo metaInfo = MetaInfo::global();

    FormEditorItem *parentItem = scene()->itemForQmlItemNode(parentNode);
    QPointF pos = parentItem->mapFromScene(scenePos);

174
    m_dragNode = QmlItemNode::createQmlItemNodeFromImage(view(), imageName, pos, parentNode);
175
176
177
178
179
180

    QList<QmlItemNode> nodeList;
    nodeList.append(m_dragNode);
    m_selectionIndicator.setItems(scene()->itemsForQmlItemNodes(nodeList));
}

181
182
183
184
185
186
187
static inline bool isAncestorOf(FormEditorItem *formEditorItem, FormEditorItem *newParentItem)
{
    if (formEditorItem && newParentItem)
        return formEditorItem->isAncestorOf(newParentItem);
    return false;
}

188
189
190
191
192
FormEditorItem* DragTool::calculateContainer(const QPointF &point, FormEditorItem * currentItem)
{
    QList<QGraphicsItem *> list = scene()->items(point);
    foreach (QGraphicsItem *item, list) {
         FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item);
193
194
195
196
197
         if (formEditorItem
                 && formEditorItem != currentItem
                 && formEditorItem->isContainer()
                 && !formEditorItem->qmlItemNode().modelNode().metaInfo().isLayoutable()
                 && !isAncestorOf(currentItem, formEditorItem))
198
199
             return formEditorItem;
    }
200

201
    if (scene()->rootFormEditorItem())
202
        return scene()->rootFormEditorItem();
203
204
205
206
207
208
209
210
211
212
213
214
    return 0;
}

void DragTool::formEditorItemsChanged(const QList<FormEditorItem*> & itemList)
{
    if (m_movingItem && itemList.contains(m_movingItem.data())) {
        QList<FormEditorItem*> updateItemList;
        updateItemList.append(m_movingItem.data());
        m_selectionIndicator.updateItems(updateItemList);
    }
}

215
216
void DragTool::instancesCompleted(const QList<FormEditorItem*> &itemList)
{
217
218
219
    foreach (FormEditorItem* item, itemList)
        if (item->qmlItemNode() == m_dragNode)
            clearMoveDelay();
220
    QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::hide();
221
222
}

223
224
225
226
227
void DragTool::instancesParentChanged(const QList<FormEditorItem *> &itemList)
{
    m_moveManipulator.synchronizeInstanceParent(itemList);
}

228
229
230
void DragTool::instancePropertyChange(const QList<QPair<ModelNode, PropertyName> > & /*propertyList*/)
{
}
231

Thomas Hartmann's avatar
Thomas Hartmann committed
232
233
void DragTool::clearMoveDelay()
{
234
235
    if (!m_blockMove)
        return;
Thomas Hartmann's avatar
Thomas Hartmann committed
236
237
    m_blockMove = false;
    if  (m_dragNode.isValid())
238
        beginWithPoint(m_startPoint);
Thomas Hartmann's avatar
Thomas Hartmann committed
239
}
240

241
242
243
244
245
246
247
248
249
250
251
void DragTool::abort()
{
    if (m_Aborted)
        return;

    m_Aborted = true;

    if (m_dragNode.isValid())
        m_dragNode.destroy();

    QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::hide();
252
}
253

254
255
256
void DragTool::commitTransaction()
{
    try {
257
        m_rewriterTransaction.commit();
258
    } catch (RewritingException &e) {
259
        e.showException();
260
    }
261
262
}

263
264
265
266
267
void DragTool::dropEvent(QGraphicsSceneDragDropEvent * event)
{
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
       event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
        event->accept();
268
269
        end(generateUseSnapping(event->modifiers()));

270
271
        commitTransaction();

272
273
274
        if (m_dragNode.isValid()) {
            QList<QmlItemNode> nodeList;
            nodeList.append(m_dragNode);
275
            view()->setSelectedModelNodes(toModelNodeList(nodeList));
276
        }
277
278
279
280
281
        m_dragNode = ModelNode();
        view()->changeToSelectionTool();
    }
}

282
283
284
285
286
287
288
289
290
291
static ItemLibraryEntry itemLibraryEntryFromData(const QByteArray &data)
{
    QDataStream stream(data);

    ItemLibraryEntry itemLibraryEntry;
    stream >> itemLibraryEntry;

    return itemLibraryEntry;
}

292
293
294
295
void DragTool::dragEnterEvent(QGraphicsSceneDragDropEvent * event)
{
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
        event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
296
        QList<Import> importToBeAddedList;
297
        m_blockMove = false;
298
        if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
299
            view()->widgetInfo().widget->setFocus();
300
            m_Aborted = false;
301
302
303
            Q_ASSERT(!event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo").isEmpty());
        }

304
        if (!m_rewriterTransaction.isValid()) {
305
            view()->clearSelectedModelNodes();
306
            m_rewriterTransaction = view()->beginRewriterTransaction(QByteArrayLiteral("DragTool::dragEnterEvent"));
307
308
309
310
311
312
313
314
315
316
317
        }
    }
}

void DragTool::dragLeaveEvent(QGraphicsSceneDragDropEvent * event)
{
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
       event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
        event->accept();
        if (m_dragNode.isValid())
            m_dragNode.destroy();
318
319
320

        m_moveManipulator.end();
        clear();
321

322
        commitTransaction();
323

324
325
        QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::show();
        QList<QmlItemNode> nodeList;
326
        view()->setSelectedModelNodes(toModelNodeList(nodeList));
327
328
329
330
331
332
        view()->changeToSelectionTool();
    }
}

void DragTool::dragMoveEvent(QGraphicsSceneDragDropEvent * event)
{
Thomas Hartmann's avatar
Thomas Hartmann committed
333
334
    if (m_blockMove)
        return;
335
336
337
338
339

    if (m_Aborted) {
        event->ignore();
        return;
    }
340
341
    if (QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::isAnimated())
        return;
342
343
344
345
346
347
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
       event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
        event->accept();
        QPointF scenePos = event->scenePos();
        if  (m_dragNode.isValid()) {

348
            FormEditorItem *parentItem = calculateContainer(event->scenePos() + QPoint(2, 2));
349
            if (!parentItem) {      //if there is no parent any more - the use left the scene
350
                end();
351
                QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::show();
352
                m_dragNode.destroy(); //delete the node then
353
354
355
356
357
358
                return;
            }
            //move
            move(event->scenePos());
        } else {
            //create new node  if container
359
360
            if (m_dragNode.modelNode().isValid())
                return;
361

362
            FormEditorItem *parentItem = calculateContainer(scenePos);
363
364
            if (!parentItem)
                return;
Thomas Hartmann's avatar
Thomas Hartmann committed
365
            QmlItemNode parentNode;
366
367
368
369
370
            if (parentItem)
                parentNode = parentItem->qmlItemNode();

            if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
                Q_ASSERT(!event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo").isEmpty());
371
372
                ItemLibraryEntry itemLibraryEntry = itemLibraryEntryFromData(event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo"));
                createQmlItemNode(itemLibraryEntry, parentNode, event->scenePos());
373
374
            } else if (event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
                Q_ASSERT(!event->mimeData()->data("application/vnd.bauhaus.libraryresource").isEmpty());
375
                QString imageName = QString::fromUtf8((event->mimeData()->data("application/vnd.bauhaus.libraryresource")));
376
377
                createQmlItemNodeFromImage(imageName, parentNode, event->scenePos());
            } else Q_ASSERT(false);
Thomas Hartmann's avatar
Thomas Hartmann committed
378
            m_blockMove = true;
379
            m_startPoint = event->scenePos();
380
            QTimer::singleShot(10000, m_timerHandler.data(), SLOT(clearMoveDelay()));
381
382
        }
    }
383

384
385
386
387
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
    }
}

388
389
390
391
392
393
394
void  DragTool::end()
{
    m_moveManipulator.end();
    clear();
}

void DragTool::end(Snapper::Snapping useSnapping)
395
{
396
    m_moveManipulator.end(useSnapping);
397
398
399
400
401
402
403
404
405
    clear();
}

void  DragTool::move(QPointF scenePos)
{
    if (!m_movingItem)
        return;

    FormEditorItem *containerItem = calculateContainer(scenePos - QPoint(2, 2), m_movingItem.data());
406
    if (containerItem && m_movingItem->parentItem() &&
407
       containerItem != m_movingItem->parentItem()) {
408
409
410
411
412

        m_moveManipulator.reparentTo(containerItem);
    }

    //MoveManipulator::Snapping useSnapping = MoveManipulator::NoSnapping;
413
    Snapper::Snapping useSnapping = Snapper::UseSnapping;
414
415
416
   /* if (event->modifiers().testFlag(Qt::ControlModifier) != view()->isSnapButtonChecked())
        useSnapping = MoveManipulator::UseSnapping;*/

417
    m_moveManipulator.update(scenePos, useSnapping, MoveManipulator::UseBaseState);
418
419
420
421
}


}