dragtool.cpp 13.6 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
** 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>
41
#include <QMessageBox>
Thomas Hartmann's avatar
Thomas Hartmann committed
42
#include <QTimer>
43 44 45

namespace QmlDesigner {

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

}

54 55 56
DragTool::DragTool(FormEditorView *editorView)
    : AbstractFormEditorTool(editorView),
    m_moveManipulator(editorView->scene()->manipulatorLayerItem(), editorView),
Thomas Hartmann's avatar
Thomas Hartmann committed
57 58
    m_selectionIndicator(editorView->scene()->manipulatorLayerItem()),
    m_timerHandler(new Internal::TimerHandler(this)),
59 60
    m_blockMove(false),
    m_Aborted(false)
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 94
{
}


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*/)
{

}

95
void DragTool::keyPressEvent(QKeyEvent *event)
96
{
97 98 99 100 101
    if (event->key() == Qt::Key_Escape) {
        abort();
        event->accept();
        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 = view()->createQmlItemNode(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 174 175 176 177 178 179 180
    MetaInfo metaInfo = MetaInfo::global();

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

    m_dragNode = view()->createQmlItemNodeFromImage(imageName, pos, parentNode);

    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
         if (formEditorItem && formEditorItem != currentItem && formEditorItem->isContainer()
             && !isAncestorOf(currentItem, formEditorItem))
195 196
             return formEditorItem;
    }
197

198
    if (scene()->rootFormEditorItem())
199
        return scene()->rootFormEditorItem();
200 201 202
    return 0;
}

203 204 205 206 207 208 209 210 211
 QList<Import> DragTool::missingImportList(const ItemLibraryEntry &itemLibraryEntry)
{
    QList<Import> importToBeAddedList;

    if (!itemLibraryEntry.requiredImport().isEmpty()) {
        const QString newImportUrl = itemLibraryEntry.requiredImport();
        const QString newImportVersion = QString("%1.%2").arg(QString::number(itemLibraryEntry.majorVersion()), QString::number(itemLibraryEntry.minorVersion()));
        Import newImport = Import::createLibraryImport(newImportUrl, newImportVersion);

212
        if (itemLibraryEntry.majorVersion() == -1 && itemLibraryEntry.minorVersion() == -1)
213
            newImport = Import::createFileImport(newImportUrl, QString());
214
        else
215 216 217 218 219
            newImport = Import::createLibraryImport(newImportUrl, newImportVersion);
    }
    return importToBeAddedList;
}

220 221 222 223 224 225 226 227 228 229

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);
    }
}

230 231
void DragTool::instancesCompleted(const QList<FormEditorItem*> &itemList)
{
232 233 234
    foreach (FormEditorItem* item, itemList)
        if (item->qmlItemNode() == m_dragNode)
            clearMoveDelay();
235
    QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::hide();
236 237
}

238 239 240 241 242
void DragTool::instancesParentChanged(const QList<FormEditorItem *> &itemList)
{
    m_moveManipulator.synchronizeInstanceParent(itemList);
}

243 244 245
void DragTool::instancePropertyChange(const QList<QPair<ModelNode, PropertyName> > & /*propertyList*/)
{
}
246

Thomas Hartmann's avatar
Thomas Hartmann committed
247 248
void DragTool::clearMoveDelay()
{
249 250
    if (!m_blockMove)
        return;
Thomas Hartmann's avatar
Thomas Hartmann committed
251 252
    m_blockMove = false;
    if  (m_dragNode.isValid())
253
        beginWithPoint(m_startPoint);
Thomas Hartmann's avatar
Thomas Hartmann committed
254
}
255

256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
void DragTool::abort()
{
    if (m_Aborted)
        return;

    m_Aborted = true;

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

    QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::hide();

    if (m_rewriterTransaction.isValid())
        m_rewriterTransaction.commit();

}

273 274 275 276 277 278 279
void DragTool::dropEvent(QGraphicsSceneDragDropEvent * event)
{
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
       event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
        event->accept();
        end(event->scenePos());
        //Q_ASSERT(m_token.isValid());
280 281 282 283 284
        try {
            m_rewriterTransaction.commit();
        } catch (RewritingException &e) {
            QMessageBox::warning(0, "Error", e.description());
        }
285 286 287 288 289
        if (m_dragNode.isValid()) {
            QList<QmlItemNode> nodeList;
            nodeList.append(m_dragNode);
            view()->setSelectedQmlItemNodes(nodeList);
        }
290 291 292 293 294
        m_dragNode = ModelNode();
        view()->changeToSelectionTool();
    }
}

295 296 297 298 299 300 301 302 303 304
static ItemLibraryEntry itemLibraryEntryFromData(const QByteArray &data)
{
    QDataStream stream(data);

    ItemLibraryEntry itemLibraryEntry;
    stream >> itemLibraryEntry;

    return itemLibraryEntry;
}

305 306 307 308
void DragTool::dragEnterEvent(QGraphicsSceneDragDropEvent * event)
{
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo") ||
        event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
309
        QList<Import> importToBeAddedList;
310
        m_blockMove = false;
311
        if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
312
            view()->widgetInfo().widget->setFocus();
313
            m_Aborted = false;
314 315
            Q_ASSERT(!event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo").isEmpty());

316 317
            importToBeAddedList = missingImportList(
                        itemLibraryEntryFromData(event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo")));
318 319
        }

320 321
        view()->model()->changeImports(importToBeAddedList, QList<Import>());

322
        if (!m_rewriterTransaction.isValid()) {
323
            view()->clearSelectedModelNodes();
324 325 326 327 328 329 330 331 332 333 334 335 336
            m_rewriterTransaction = view()->beginRewriterTransaction();
        }
    }
}

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();
        end(event->scenePos());
337 338 339 340 341 342 343

        try {
            m_rewriterTransaction.commit();
        } catch (RewritingException &e) {
            QMessageBox::warning(0, "Error", e.description());
        }

344 345 346 347 348 349 350 351 352
        QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::show();
        QList<QmlItemNode> nodeList;
        view()->setSelectedQmlItemNodes(nodeList);
        view()->changeToSelectionTool();
    }
}

void DragTool::dragMoveEvent(QGraphicsSceneDragDropEvent * event)
{
Thomas Hartmann's avatar
Thomas Hartmann committed
353 354
    if (m_blockMove)
        return;
355 356 357 358 359

    if (m_Aborted) {
        event->ignore();
        return;
    }
360 361
    if (QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::isAnimated())
        return;
362 363 364 365 366 367
    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()) {

368
            FormEditorItem *parentItem = calculateContainer(event->scenePos() + QPoint(2, 2));
369 370 371
            if (!parentItem) {      //if there is no parent any more - the use left the scene
                end(event->scenePos());
                QmlDesignerItemLibraryDragAndDrop::CustomDragAndDrop::show();
372
                m_dragNode.destroy(); //delete the node then
373 374 375 376 377 378
                return;
            }
            //move
            move(event->scenePos());
        } else {
            //create new node  if container
379 380
            if (m_dragNode.modelNode().isValid())
                return;
381

382
            FormEditorItem *parentItem = calculateContainer(scenePos);
383 384
            if (!parentItem)
                return;
Thomas Hartmann's avatar
Thomas Hartmann committed
385
            QmlItemNode parentNode;
386 387 388 389 390
            if (parentItem)
                parentNode = parentItem->qmlItemNode();

            if (event->mimeData()->hasFormat("application/vnd.bauhaus.itemlibraryinfo")) {
                Q_ASSERT(!event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo").isEmpty());
391 392
                ItemLibraryEntry itemLibraryEntry = itemLibraryEntryFromData(event->mimeData()->data("application/vnd.bauhaus.itemlibraryinfo"));
                createQmlItemNode(itemLibraryEntry, parentNode, event->scenePos());
393 394
            } else if (event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
                Q_ASSERT(!event->mimeData()->data("application/vnd.bauhaus.libraryresource").isEmpty());
395
                QString imageName = QString::fromUtf8((event->mimeData()->data("application/vnd.bauhaus.libraryresource")));
396 397
                createQmlItemNodeFromImage(imageName, parentNode, event->scenePos());
            } else Q_ASSERT(false);
Thomas Hartmann's avatar
Thomas Hartmann committed
398
            m_blockMove = true;
399
            m_startPoint = event->scenePos();
400
            QTimer::singleShot(1000, m_timerHandler.data(), SLOT(clearMoveDelay()));
401 402
        }
    }
403

404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
    if (event->mimeData()->hasFormat("application/vnd.bauhaus.libraryresource")) {
    }
}

void  DragTool::end(QPointF scenePos)
{
    m_moveManipulator.end(scenePos);
    clear();
}

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

    FormEditorItem *containerItem = calculateContainer(scenePos - QPoint(2, 2), m_movingItem.data());
420
    if (containerItem && m_movingItem->parentItem() &&
421
       containerItem != m_movingItem->parentItem()) {
422 423 424 425 426 427 428 429 430

        m_moveManipulator.reparentTo(containerItem);
    }

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

431
    m_moveManipulator.update(scenePos, useSnapping, MoveManipulator::UseBaseState);
432 433 434 435
}


}