diagramcontroller.cpp 30.5 KB
Newer Older
Jochen Becher's avatar
Jochen Becher committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
/***************************************************************************
**
** Copyright (C) 2015 Jochen Becher
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** 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 The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "diagramcontroller.h"

#include "dselection.h"
#include "dcontainer.h"
#include "dreferences.h"
#include "dflatassignmentvisitor.h"
#include "dclonevisitor.h"
#include "dupdatevisitor.h"

#include "qmt/model_controller/modelcontroller.h"
#include "qmt/model_controller/mchildrenvisitor.h"

#include "qmt/controller/undocontroller.h"
#include "qmt/controller/undocommand.h"

#include "qmt/diagram/dobject.h"
#include "qmt/diagram/drelation.h"

#include "qmt/model/mobject.h"
#include "qmt/model/mpackage.h"
#include "qmt/model/mdiagram.h"
#include "qmt/model/mrelation.h"

namespace qmt {

56 57 58
class DiagramController::Clone
{
public:
Jochen Becher's avatar
Jochen Becher committed
59
    Clone();
60 61 62
    Uid m_elementKey;
    int m_indexOfElement;
    DElement *m_clonedElement;
Jochen Becher's avatar
Jochen Becher committed
63 64 65
};

DiagramController::Clone::Clone()
66 67
    : m_indexOfElement(-1),
      m_clonedElement(0)
Jochen Becher's avatar
Jochen Becher committed
68 69 70
{
}

71
class DiagramController::DiagramUndoCommand : public UndoCommand
Jochen Becher's avatar
Jochen Becher committed
72 73
{
public:
74
    DiagramUndoCommand(DiagramController *diagramController, const Uid &diagramKey, const QString &text)
Jochen Becher's avatar
Jochen Becher committed
75
        : UndoCommand(text),
76 77
          m_diagramController(diagramController),
          m_diagramKey(diagramKey)
Jochen Becher's avatar
Jochen Becher committed
78 79 80 81
    {
    }

protected:
82
    DiagramController *diagramController() const
Jochen Becher's avatar
Jochen Becher committed
83
    {
84
        return m_diagramController;
Jochen Becher's avatar
Jochen Becher committed
85 86
    }

87
    Uid diagramKey() const { return m_diagramKey; }
Jochen Becher's avatar
Jochen Becher committed
88

89
    MDiagram *diagram() const
Jochen Becher's avatar
Jochen Becher committed
90
    {
91
        MDiagram *diagram = m_diagramController->findDiagram(m_diagramKey);
Jochen Becher's avatar
Jochen Becher committed
92 93 94 95 96
        QMT_CHECK(diagram);
        return diagram;
    }

private:
97 98
    DiagramController *m_diagramController;
    Uid m_diagramKey;
Jochen Becher's avatar
Jochen Becher committed
99 100
};

101
class DiagramController::UpdateElementCommand : public DiagramUndoCommand
Jochen Becher's avatar
Jochen Becher committed
102 103
{
public:
104 105 106 107
    UpdateElementCommand(DiagramController *diagramController, const Uid &diagramKey, DElement *element,
                         DiagramController::UpdateAction updateAction)
        : DiagramUndoCommand(diagramController, diagramKey, tr("Change")),
          m_updateAction(updateAction)
Jochen Becher's avatar
Jochen Becher committed
108 109 110
    {
        DCloneVisitor visitor;
        element->accept(&visitor);
111
        m_clonedElements.insert(visitor.cloned()->uid(), visitor.cloned());
Jochen Becher's avatar
Jochen Becher committed
112 113 114 115
    }

    ~UpdateElementCommand()
    {
116
        qDeleteAll(m_clonedElements);
Jochen Becher's avatar
Jochen Becher committed
117 118 119 120
    }

    bool mergeWith(const UndoCommand *other)
    {
121
        const UpdateElementCommand *otherUpdateCommand = dynamic_cast<const UpdateElementCommand *>(other);
122
        if (!otherUpdateCommand)
Jochen Becher's avatar
Jochen Becher committed
123
            return false;
124
        if (diagramKey() != otherUpdateCommand->diagramKey())
Jochen Becher's avatar
Jochen Becher committed
125
            return false;
126 127
        if (m_updateAction == DiagramController::UpdateMajor
                || otherUpdateCommand->m_updateAction == DiagramController::UpdateMajor
128
                || m_updateAction != otherUpdateCommand->m_updateAction) {
Jochen Becher's avatar
Jochen Becher committed
129 130 131
            return false;
        }
        // join other elements into this command
132
        foreach (const DElement *otherElement, otherUpdateCommand->m_clonedElements.values()) {
133
            if (!m_clonedElements.contains(otherElement->uid())) {
Jochen Becher's avatar
Jochen Becher committed
134
                DCloneVisitor visitor;
135
                otherElement->accept(&visitor);
136
                m_clonedElements.insert(visitor.cloned()->uid(), visitor.cloned());
Jochen Becher's avatar
Jochen Becher committed
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
            }
        }
        // the last update is a complete update of all changes...
        return true;
    }

    void redo()
    {
        if (canRedo()) {
            swap();
            UndoCommand::redo();
        }
    }

    void undo()
    {
        swap();
        UndoCommand::undo();
    }

private:
    void swap()
    {
160 161
        DiagramController *diagramController = this->diagramController();
        MDiagram *diagram = this->diagram();
162
        foreach (DElement *clonedElement, m_clonedElements) {
163
            DElement *activeElement = diagramController->findElement(clonedElement->uid(), diagram);
164
            QMT_CHECK(activeElement);
165
            int row = diagram->diagramElements().indexOf(activeElement);
166
            emit diagramController->beginUpdateElement(row, diagram);
Jochen Becher's avatar
Jochen Becher committed
167
            // clone active element
168 169
            DCloneVisitor cloneVisitor;
            activeElement->accept(&cloneVisitor);
170
            DElement *newElement = cloneVisitor.cloned();
Jochen Becher's avatar
Jochen Becher committed
171
            // reset active element to cloned element
172 173
            DFlatAssignmentVisitor visitor(activeElement);
            clonedElement->accept(&visitor);
Jochen Becher's avatar
Jochen Becher committed
174
            // replace stored element with new cloned active element
175 176
            QMT_CHECK(clonedElement->uid() == newElement->uid());
            m_clonedElements.insert(newElement->uid(), newElement);
177 178
            delete clonedElement;
            emit diagramController->endUpdateElement(row, diagram);
Jochen Becher's avatar
Jochen Becher committed
179
        }
180
        diagramController->diagramModified(diagram);
Jochen Becher's avatar
Jochen Becher committed
181 182
    }

183 184
    DiagramController::UpdateAction m_updateAction;
    QHash<Uid, DElement *> m_clonedElements;
Jochen Becher's avatar
Jochen Becher committed
185 186
};

187
class DiagramController::AbstractAddRemCommand : public DiagramUndoCommand
Jochen Becher's avatar
Jochen Becher committed
188 189
{
protected:
190 191
    AbstractAddRemCommand(DiagramController *diagramController, const Uid &diagramKey, const QString &commandLabel)
        : DiagramUndoCommand(diagramController, diagramKey, commandLabel)
Jochen Becher's avatar
Jochen Becher committed
192 193 194 195 196
    {
    }

    ~AbstractAddRemCommand()
    {
197
        foreach (const Clone &clone, m_clonedElements)
198
            delete clone.m_clonedElement;
Jochen Becher's avatar
Jochen Becher committed
199 200 201 202
    }

    void remove()
    {
203 204
        DiagramController *diagramController = this->diagramController();
        MDiagram *diagram = this->diagram();
Jochen Becher's avatar
Jochen Becher committed
205
        bool removed = false;
206 207 208
        for (int i = 0; i < m_clonedElements.count(); ++i) {
            Clone &clone = m_clonedElements[i];
            QMT_CHECK(!clone.m_clonedElement);
209 210
            DElement *activeElement = diagramController->findElement(clone.m_elementKey, diagram);
            QMT_CHECK(activeElement);
211
            clone.m_indexOfElement = diagram->diagramElements().indexOf(activeElement);
212
            QMT_CHECK(clone.m_indexOfElement >= 0);
213 214 215
            emit diagramController->beginRemoveElement(clone.m_indexOfElement, diagram);
            DCloneDeepVisitor cloneVisitor;
            activeElement->accept(&cloneVisitor);
216
            clone.m_clonedElement = cloneVisitor.cloned();
217 218
            diagram->removeDiagramElement(activeElement);
            emit diagramController->endRemoveElement(clone.m_indexOfElement, diagram);
Jochen Becher's avatar
Jochen Becher committed
219 220
            removed = true;
        }
221
        if (removed)
222
            diagramController->diagramModified(diagram);
Jochen Becher's avatar
Jochen Becher committed
223 224 225 226
    }

    void insert()
    {
227 228
        DiagramController *diagramController = this->diagramController();
        MDiagram *diagram = this->diagram();
Jochen Becher's avatar
Jochen Becher committed
229
        bool inserted = false;
230 231 232
        for (int i = m_clonedElements.count() - 1; i >= 0; --i) {
            Clone &clone = m_clonedElements[i];
            QMT_CHECK(clone.m_clonedElement);
233
            QMT_CHECK(clone.m_clonedElement->uid() == clone.m_elementKey);
234
            emit diagramController->beginInsertElement(clone.m_indexOfElement, diagram);
235 236
            diagram->insertDiagramElement(clone.m_indexOfElement, clone.m_clonedElement);
            clone.m_clonedElement = 0;
237
            emit diagramController->endInsertElement(clone.m_indexOfElement, diagram);
Jochen Becher's avatar
Jochen Becher committed
238 239
            inserted = true;
        }
240
        if (inserted)
241
            diagramController->diagramModified(diagram);
Jochen Becher's avatar
Jochen Becher committed
242 243
    }

244
    QList<Clone> m_clonedElements;
Jochen Becher's avatar
Jochen Becher committed
245 246
};

247
class DiagramController::AddElementsCommand : public AbstractAddRemCommand
Jochen Becher's avatar
Jochen Becher committed
248 249
{
public:
250 251
    AddElementsCommand(DiagramController *diagramController, const Uid &diagramKey, const QString &commandLabel)
        : AbstractAddRemCommand(diagramController, diagramKey, commandLabel)
Jochen Becher's avatar
Jochen Becher committed
252 253 254
    {
    }

255
    void add(const Uid &elementKey)
Jochen Becher's avatar
Jochen Becher committed
256 257 258
    {
        Clone clone;

259
        clone.m_elementKey = elementKey;
260
        m_clonedElements.append(clone);
Jochen Becher's avatar
Jochen Becher committed
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
    }

    void redo()
    {
        if (canRedo()) {
            insert();
            UndoCommand::redo();
        }
    }

    void undo()
    {
        remove();
        UndoCommand::undo();
    }
};

278
class DiagramController::RemoveElementsCommand : public AbstractAddRemCommand
Jochen Becher's avatar
Jochen Becher committed
279 280
{
public:
281 282
    RemoveElementsCommand(DiagramController *diagramController, const Uid &diagramKey, const QString &commandLabel)
        : AbstractAddRemCommand(diagramController, diagramKey, commandLabel)
Jochen Becher's avatar
Jochen Becher committed
283 284 285 286 287 288 289
    {
    }

    void add(DElement *element)
    {
        Clone clone;

290
        MDiagram *diagram = this->diagram();
291 292
        clone.m_elementKey = element->uid();
        clone.m_indexOfElement = diagram->diagramElements().indexOf(element);
293
        QMT_CHECK(clone.m_indexOfElement >= 0);
Jochen Becher's avatar
Jochen Becher committed
294 295
        DCloneDeepVisitor visitor;
        element->accept(&visitor);
296
        clone.m_clonedElement = visitor.cloned();
297 298
        QMT_CHECK(clone.m_clonedElement);
        m_clonedElements.append(clone);
Jochen Becher's avatar
Jochen Becher committed
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
    }

    void redo()
    {
        if (canRedo()) {
            remove();
            UndoCommand::redo();
        }
    }

    void undo()
    {
        insert();
        UndoCommand::undo();
    }
};

316
class DiagramController::FindDiagramsVisitor : public MChildrenVisitor
Jochen Becher's avatar
Jochen Becher committed
317 318
{
public:
319 320
    FindDiagramsVisitor(QList<MDiagram *> *allDiagrams)
        : m_allDiagrams(allDiagrams)
Jochen Becher's avatar
Jochen Becher committed
321 322 323 324 325
    {
    }

    void visitMDiagram(MDiagram *diagram)
    {
326
        m_allDiagrams->append(diagram);
Jochen Becher's avatar
Jochen Becher committed
327 328 329 330
        MChildrenVisitor::visitMDiagram(diagram);
    }

private:
331
    QList<MDiagram *> *m_allDiagrams;
Jochen Becher's avatar
Jochen Becher committed
332 333 334 335
};

DiagramController::DiagramController(QObject *parent)
    : QObject(parent),
336 337
      m_modelController(0),
      m_undoController(0)
Jochen Becher's avatar
Jochen Becher committed
338 339 340 341 342 343 344
{
}

DiagramController::~DiagramController()
{
}

345
void DiagramController::setModelController(ModelController *modelController)
Jochen Becher's avatar
Jochen Becher committed
346
{
347 348 349
    if (m_modelController) {
        disconnect(m_modelController, 0, this, 0);
        m_modelController = 0;
Jochen Becher's avatar
Jochen Becher committed
350
    }
351 352
    if (modelController) {
        m_modelController = modelController;
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
        connect(modelController, &ModelController::beginResetModel,
                this, &DiagramController::onBeginResetModel);
        connect(modelController, &ModelController::endResetModel,
                this, &DiagramController::onEndResetModel);

        connect(modelController, &ModelController::beginUpdateObject,
                this, &DiagramController::onBeginUpdateObject);
        connect(modelController, &ModelController::endUpdateObject,
                this, &DiagramController::onEndUpdateObject);
        connect(modelController, &ModelController::beginInsertObject,
                this, &DiagramController::onBeginInsertObject);
        connect(modelController, &ModelController::endInsertObject,
                this, &DiagramController::onEndInsertObject);
        connect(modelController, &ModelController::beginRemoveObject,
                this, &DiagramController::onBeginRemoveObject);
        connect(modelController, &ModelController::endRemoveObject,
                this, &DiagramController::onEndRemoveObject);
        connect(modelController, &ModelController::beginMoveObject,
                this, &DiagramController::onBeginMoveObject);
        connect(modelController, &ModelController::endMoveObject,
                this, &DiagramController::onEndMoveObject);

        connect(modelController, &ModelController::beginUpdateRelation,
                this, &DiagramController::onBeginUpdateRelation);
        connect(modelController, &ModelController::endUpdateRelation,
                this, &DiagramController::onEndUpdateRelation);
        connect(modelController, &ModelController::beginRemoveRelation,
                this, &DiagramController::onBeginRemoveRelation);
        connect(modelController, &ModelController::endRemoveRelation,
                this, &DiagramController::onEndRemoveRelation);
        connect(modelController, &ModelController::beginMoveRelation,
                this, &DiagramController::onBeginMoveRelation);
        connect(modelController, &ModelController::endMoveRelation,
                this, &DiagramController::onEndMoveRelation);
Jochen Becher's avatar
Jochen Becher committed
387 388 389
    }
}

390
void DiagramController::setUndoController(UndoController *undoController)
Jochen Becher's avatar
Jochen Becher committed
391
{
392
    m_undoController = undoController;
Jochen Becher's avatar
Jochen Becher committed
393 394
}

395
MDiagram *DiagramController::findDiagram(const Uid &diagramKey) const
Jochen Becher's avatar
Jochen Becher committed
396
{
397
    return dynamic_cast<MDiagram *>(m_modelController->findObject(diagramKey));
Jochen Becher's avatar
Jochen Becher committed
398 399 400 401
}

void DiagramController::addElement(DElement *element, MDiagram *diagram)
{
402
    int row = diagram->diagramElements().count();
Jochen Becher's avatar
Jochen Becher committed
403 404
    emit beginInsertElement(row, diagram);
    updateElementFromModel(element, diagram, false);
405
    if (m_undoController) {
406
        AddElementsCommand *undoCommand = new AddElementsCommand(this, diagram->uid(), tr("Add Object"));
407
        m_undoController->push(undoCommand);
408
        undoCommand->add(element->uid());
Jochen Becher's avatar
Jochen Becher committed
409 410 411 412 413 414 415 416 417
    }
    diagram->addDiagramElement(element);
    emit endInsertElement(row, diagram);
    diagramModified(diagram);
}

void DiagramController::removeElement(DElement *element, MDiagram *diagram)
{
    removeRelations(element, diagram);
418
    int row = diagram->diagramElements().indexOf(element);
Jochen Becher's avatar
Jochen Becher committed
419
    emit beginRemoveElement(row, diagram);
420
    if (m_undoController) {
421
        RemoveElementsCommand *undoCommand = new RemoveElementsCommand(this, diagram->uid(), tr("Remove Object"));
422 423
        m_undoController->push(undoCommand);
        undoCommand->add(element);
Jochen Becher's avatar
Jochen Becher committed
424 425 426 427 428 429 430 431 432 433 434 435 436
    }
    diagram->removeDiagramElement(element);
    emit endRemoveElement(row, diagram);
    diagramModified(diagram);
}

DElement *DiagramController::findElement(const Uid &key, const MDiagram *diagram) const
{
    QMT_CHECK(diagram);

    return diagram->findDiagramElement(key);
}

437
bool DiagramController::hasDelegate(const MElement *modelElement, const MDiagram *diagram) const
Jochen Becher's avatar
Jochen Becher committed
438 439
{
    // PERFORM smarter implementation after map is introduced
440
    return findDelegate(modelElement, diagram) != 0;
Jochen Becher's avatar
Jochen Becher committed
441 442
}

443
DElement *DiagramController::findDelegate(const MElement *modelElement, const MDiagram *diagram) const
Jochen Becher's avatar
Jochen Becher committed
444 445
{
    // PERFORM use map to increase performance
446
    foreach (DElement *diagramElement, diagram->diagramElements()) {
447
        if (diagramElement->modelUid().isValid() && diagramElement->modelUid() == modelElement->uid())
448
            return diagramElement;
Jochen Becher's avatar
Jochen Becher committed
449 450 451 452
    }
    return 0;
}

453
void DiagramController::startUpdateElement(DElement *element, MDiagram *diagram, UpdateAction updateAction)
Jochen Becher's avatar
Jochen Becher committed
454
{
455
    emit beginUpdateElement(diagram->diagramElements().indexOf(element), diagram);
456
    if (m_undoController)
457
        m_undoController->push(new UpdateElementCommand(this, diagram->uid(), element, updateAction));
Jochen Becher's avatar
Jochen Becher committed
458 459 460 461
}

void DiagramController::finishUpdateElement(DElement *element, MDiagram *diagram, bool cancelled)
{
462
    if (!cancelled)
Jochen Becher's avatar
Jochen Becher committed
463
        updateElementFromModel(element, diagram, false);
464
    emit endUpdateElement(diagram->diagramElements().indexOf(element), diagram);
465
    if (!cancelled)
Jochen Becher's avatar
Jochen Becher committed
466 467 468 469 470
        diagramModified(diagram);
}

void DiagramController::breakUndoChain()
{
471
    m_undoController->doNotMerge();
Jochen Becher's avatar
Jochen Becher committed
472 473
}

474
DContainer DiagramController::cutElements(const DSelection &diagramSelection, MDiagram *diagram)
Jochen Becher's avatar
Jochen Becher committed
475
{
476 477 478
    DContainer copiedElements = copyElements(diagramSelection, diagram);
    deleteElements(diagramSelection, diagram, tr("Cut"));
    return copiedElements;
Jochen Becher's avatar
Jochen Becher committed
479 480
}

481
DContainer DiagramController::copyElements(const DSelection &diagramSelection, const MDiagram *diagram)
Jochen Becher's avatar
Jochen Becher committed
482 483 484
{
    QMT_CHECK(diagram);

485 486
    DReferences simplifiedSelection = simplify(diagramSelection, diagram);
    DContainer copiedElements;
487
    foreach (const DElement *element, simplifiedSelection.elements()) {
Jochen Becher's avatar
Jochen Becher committed
488 489
        DCloneDeepVisitor visitor;
        element->accept(&visitor);
490
        DElement *clonedElement = visitor.cloned();
491
        copiedElements.submit(clonedElement);
Jochen Becher's avatar
Jochen Becher committed
492
    }
493
    return copiedElements;
Jochen Becher's avatar
Jochen Becher committed
494 495
}

496
void DiagramController::pasteElements(const DContainer &diagramContainer, MDiagram *diagram)
Jochen Becher's avatar
Jochen Becher committed
497 498 499 500
{
    QMT_CHECK(diagram);

    // clone all elements and renew their keys
501 502
    QHash<Uid, Uid> renewedKeys;
    QList<DElement *> clonedElements;
503
    foreach (const DElement *element, diagramContainer.elements()) {
Jochen Becher's avatar
Jochen Becher committed
504 505 506
        if (!isDelegatedElementOnDiagram(element, diagram)) {
            DCloneDeepVisitor visitor;
            element->accept(&visitor);
507
            DElement *clonedElement = visitor.cloned();
508 509
            renewElementKey(clonedElement, &renewedKeys);
            clonedElements.append(clonedElement);
Jochen Becher's avatar
Jochen Becher committed
510 511 512
        }
    }
    // fix all keys referencing between pasting elements
513 514
    foreach(DElement *clonedElement, clonedElements) {
        DRelation *relation = dynamic_cast<DRelation *>(clonedElement);
515
        if (relation)
516
            updateRelationKeys(relation, renewedKeys);
Jochen Becher's avatar
Jochen Becher committed
517
    }
518
    if (m_undoController)
519
        m_undoController->beginMergeSequence(tr("Paste"));
Jochen Becher's avatar
Jochen Becher committed
520 521
    // insert all elements
    bool added = false;
522 523
    foreach (DElement *clonedElement, clonedElements) {
        if (!dynamic_cast<DRelation *>(clonedElement)) {
524
            int row = diagram->diagramElements().size();
Jochen Becher's avatar
Jochen Becher committed
525
            emit beginInsertElement(row, diagram);
526
            if (m_undoController) {
527
                AddElementsCommand *undoCommand = new AddElementsCommand(this, diagram->uid(), tr("Paste"));
528
                m_undoController->push(undoCommand);
529
                undoCommand->add(clonedElement->uid());
Jochen Becher's avatar
Jochen Becher committed
530
            }
531
            diagram->addDiagramElement(clonedElement);
Jochen Becher's avatar
Jochen Becher committed
532 533 534 535
            emit endInsertElement(row, diagram);
            added = true;
        }
    }
536 537 538
    foreach (DElement *clonedElement, clonedElements) {
        DRelation *clonedRelation = dynamic_cast<DRelation *>(clonedElement);
        if (clonedRelation && areRelationEndsOnDiagram(clonedRelation, diagram)) {
539
            int row = diagram->diagramElements().size();
Jochen Becher's avatar
Jochen Becher committed
540
            emit beginInsertElement(row, diagram);
541
            if (m_undoController) {
542
                AddElementsCommand *undoCommand = new AddElementsCommand(this, diagram->uid(), tr("Paste"));
543
                m_undoController->push(undoCommand);
544
                undoCommand->add(clonedElement->uid());
Jochen Becher's avatar
Jochen Becher committed
545
            }
546
            diagram->addDiagramElement(clonedElement);
Jochen Becher's avatar
Jochen Becher committed
547 548 549 550
            emit endInsertElement(row, diagram);
            added = true;
        }
    }
551
    if (added)
Jochen Becher's avatar
Jochen Becher committed
552
        diagramModified(diagram);
553
    if (m_undoController)
554
        m_undoController->endMergeSequence();
Jochen Becher's avatar
Jochen Becher committed
555 556
}

557
void DiagramController::deleteElements(const DSelection &diagramSelection, MDiagram *diagram)
Jochen Becher's avatar
Jochen Becher committed
558
{
559
    deleteElements(diagramSelection, diagram, tr("Delete"));
Jochen Becher's avatar
Jochen Becher committed
560 561 562 563
}

void DiagramController::onBeginResetModel()
{
564
    m_allDiagrams.clear();
Jochen Becher's avatar
Jochen Becher committed
565 566 567 568 569 570
    emit beginResetAllDiagrams();
}

void DiagramController::onEndResetModel()
{
    updateAllDiagramsList();
571
    foreach (MDiagram *diagram, m_allDiagrams) {
Jochen Becher's avatar
Jochen Becher committed
572
        // remove all elements which are not longer part of the model
573 574 575
        foreach (DElement *element, diagram->diagramElements()) {
            if (element->modelUid().isValid()) {
                MElement *modelElement = m_modelController->findElement(element->modelUid());
576
                if (!modelElement)
Jochen Becher's avatar
Jochen Becher committed
577 578 579 580
                    removeElement(element, diagram);
            }
        }
        // update all remaining elements from model
581
        foreach (DElement *element, diagram->diagramElements())
Jochen Becher's avatar
Jochen Becher committed
582 583 584 585 586 587 588 589 590 591 592 593 594 595 596
            updateElementFromModel(element, diagram, false);
    }
    emit endResetAllDiagrams();
}

void DiagramController::onBeginUpdateObject(int row, const MObject *parent)
{
    Q_UNUSED(row);
    Q_UNUSED(parent);

    // nothing to do
}

void DiagramController::onEndUpdateObject(int row, const MObject *parent)
{
597
    MObject *modelObject = m_modelController->object(row, parent);
598 599
    QMT_CHECK(modelObject);
    MPackage *modelPackage = dynamic_cast<MPackage *>(modelObject);
600
    foreach (MDiagram *diagram, m_allDiagrams) {
601
        DObject *object = findDelegate<DObject>(modelObject, diagram);
Jochen Becher's avatar
Jochen Becher committed
602 603 604
        if (object) {
            updateElementFromModel(object, diagram, true);
        }
605
        if (modelPackage) {
Jochen Becher's avatar
Jochen Becher committed
606
            // update each element that has the updated object as its owner (for context changes)
607 608 609
            foreach (DElement *diagramElement, diagram->diagramElements()) {
                if (diagramElement->modelUid().isValid()) {
                    MObject *mobject = m_modelController->findObject(diagramElement->modelUid());
610
                    if (mobject && mobject->owner() == modelPackage)
611
                        updateElementFromModel(diagramElement, diagram, true);
Jochen Becher's avatar
Jochen Becher committed
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
                }
            }
        }
    }
}

void DiagramController::onBeginInsertObject(int row, const MObject *owner)
{
    Q_UNUSED(row);
    Q_UNUSED(owner);
}

void DiagramController::onEndInsertObject(int row, const MObject *owner)
{
    QMT_CHECK(owner);

628
    MObject *modelObject = m_modelController->object(row, owner);
629 630 631
    if (MDiagram *modelDiagram = dynamic_cast<MDiagram *>(modelObject)) {
        QMT_CHECK(!m_allDiagrams.contains(modelDiagram));
        m_allDiagrams.append(modelDiagram);
Jochen Becher's avatar
Jochen Becher committed
632 633 634 635 636 637 638
    }
}

void DiagramController::onBeginRemoveObject(int row, const MObject *parent)
{
    QMT_CHECK(parent);

639
    MObject *modelObject = m_modelController->object(row, parent);
640
    removeObjects(modelObject);
Jochen Becher's avatar
Jochen Becher committed
641 642 643 644 645 646 647 648
}

void DiagramController::onEndRemoveObject(int row, const MObject *parent)
{
    Q_UNUSED(row);
    Q_UNUSED(parent);
}

649
void DiagramController::onBeginMoveObject(int formerRow, const MObject *formerOwner)
Jochen Becher's avatar
Jochen Becher committed
650
{
651 652
    Q_UNUSED(formerRow);
    Q_UNUSED(formerOwner);
Jochen Becher's avatar
Jochen Becher committed
653 654 655 656 657 658 659
}

void DiagramController::onEndMoveObject(int row, const MObject *owner)
{
    onEndUpdateObject(row, owner);

    // if diagram was moved update all elements because of changed context
660
    MObject *modelObject = m_modelController->object(row, owner);
661 662 663 664
    QMT_CHECK(modelObject);
    MDiagram *modelDiagram = dynamic_cast<MDiagram *>(modelObject);
    if (modelDiagram) {
        emit beginResetDiagram(modelDiagram);
665
        foreach (DElement *diagramElement, modelDiagram->diagramElements())
666 667
            updateElementFromModel(diagramElement, modelDiagram, false);
        emit endResetDiagram(modelDiagram);
Jochen Becher's avatar
Jochen Becher committed
668 669 670 671 672 673 674 675 676 677 678 679 680
    }
}

void DiagramController::onBeginUpdateRelation(int row, const MObject *owner)
{
    Q_UNUSED(row);
    Q_UNUSED(owner);

    // nothing to do
}

void DiagramController::onEndUpdateRelation(int row, const MObject *owner)
{
681
    MRelation *modelRelation = owner->relations().at(row);
682
    foreach (MDiagram *diagram, m_allDiagrams) {
683
        DRelation *relation = findDelegate<DRelation>(modelRelation, diagram);
Jochen Becher's avatar
Jochen Becher committed
684 685 686 687 688 689 690 691 692 693
        if (relation) {
            updateElementFromModel(relation, diagram, true);
        }
    }
}

void DiagramController::onBeginRemoveRelation(int row, const MObject *owner)
{
    QMT_CHECK(owner);

694
    MRelation *modelRelation = owner->relations().at(row);
695
    removeRelations(modelRelation);
Jochen Becher's avatar
Jochen Becher committed
696 697 698 699 700 701 702 703
}

void DiagramController::onEndRemoveRelation(int row, const MObject *owner)
{
    Q_UNUSED(row);
    Q_UNUSED(owner);
}

704
void DiagramController::onBeginMoveRelation(int formerRow, const MObject *formerOwner)
Jochen Becher's avatar
Jochen Becher committed
705
{
706 707
    Q_UNUSED(formerRow);
    Q_UNUSED(formerOwner);
Jochen Becher's avatar
Jochen Becher committed
708 709 710 711 712 713 714 715 716

    // nothing to do
}

void DiagramController::onEndMoveRelation(int row, const MObject *owner)
{
    onEndUpdateRelation(row, owner);
}

717 718
void DiagramController::deleteElements(const DSelection &diagramSelection, MDiagram *diagram,
                                       const QString &commandLabel)
Jochen Becher's avatar
Jochen Becher committed
719 720 721
{
    QMT_CHECK(diagram);

722
    DReferences simplifiedSelection = simplify(diagramSelection, diagram);
723
    if (simplifiedSelection.elements().isEmpty())
Jochen Becher's avatar
Jochen Becher committed
724
        return;
725
    if (m_undoController)
726
        m_undoController->beginMergeSequence(commandLabel);
Jochen Becher's avatar
Jochen Becher committed
727
    bool removed = false;
728
    foreach (DElement *element, simplifiedSelection.elements()) {
Jochen Becher's avatar
Jochen Becher committed
729
        // element may have been deleted indirectly by predecessor element in loop
730
        if ((element = findElement(element->uid(), diagram))) {
Jochen Becher's avatar
Jochen Becher committed
731
            removeRelations(element, diagram);
732 733
            int row = diagram->diagramElements().indexOf(element);
            emit beginRemoveElement(diagram->diagramElements().indexOf(element), diagram);
734
            if (m_undoController) {
735
                RemoveElementsCommand *cutCommand = new RemoveElementsCommand(this, diagram->uid(), commandLabel);
736 737
                m_undoController->push(cutCommand);
                cutCommand->add(element);
Jochen Becher's avatar
Jochen Becher committed
738 739 740 741 742 743
            }
            diagram->removeDiagramElement(element);
            emit endRemoveElement(row, diagram);
            removed = true;
        }
    }
744
    if (removed)
Jochen Becher's avatar
Jochen Becher committed
745
        diagramModified(diagram);
746
    if (m_undoController)
747
        m_undoController->endMergeSequence();
Jochen Becher's avatar
Jochen Becher committed
748 749 750 751
}

DElement *DiagramController::findElementOnAnyDiagram(const Uid &uid)
{
752
    foreach (MDiagram *diagram, m_allDiagrams) {
Jochen Becher's avatar
Jochen Becher committed
753
        DElement *element = findElement(uid, diagram);
754
        if (element)
Jochen Becher's avatar
Jochen Becher committed
755 756 757 758 759
            return element;
    }
    return 0;
}

760
void DiagramController::removeObjects(MObject *modelObject)
Jochen Becher's avatar
Jochen Becher committed
761
{
762
    foreach (MDiagram *diagram, m_allDiagrams) {
763
        DElement *diagramElement = findDelegate(modelObject, diagram);
764
        if (diagramElement)
765
            removeElement(diagramElement, diagram);
766 767
        foreach (const Handle<MRelation> &relation, modelObject->relations()) {
            DElement *diagramElement = findDelegate(relation.target(), diagram);
768
            if (diagramElement)
769
                removeElement(diagramElement, diagram);
Jochen Becher's avatar
Jochen Becher committed
770 771
        }
    }
772
    foreach (const Handle<MObject> &object, modelObject->children()) {
773
        if (object.hasTarget())
774
            removeObjects(object.target());
Jochen Becher's avatar
Jochen Becher committed
775
    }
776
    if (MDiagram *diagram = dynamic_cast<MDiagram *>(modelObject)) {
Jochen Becher's avatar
Jochen Becher committed
777
        emit diagramAboutToBeRemoved(diagram);
778 779 780
        QMT_CHECK(m_allDiagrams.contains(diagram));
        m_allDiagrams.removeOne(diagram);
        QMT_CHECK(!m_allDiagrams.contains(diagram));
Jochen Becher's avatar
Jochen Becher committed
781
        // PERFORM increase performace
782 783
        while (!diagram->diagramElements().isEmpty()) {
            DElement *element = diagram->diagramElements().first();
Jochen Becher's avatar
Jochen Becher committed
784 785 786 787 788
            removeElement(element, diagram);
        }
    }
}

789
void DiagramController::removeRelations(MRelation *modelRelation)
Jochen Becher's avatar
Jochen Becher committed
790
{
791
    foreach (MDiagram *diagram, m_allDiagrams) {
792
        DElement *diagramElement = findDelegate(modelRelation, diagram);
793
        if (diagramElement)
794
            removeElement(diagramElement, diagram);
Jochen Becher's avatar
Jochen Becher committed
795 796 797 798 799
    }
}

void DiagramController::removeRelations(DElement *element, MDiagram *diagram)
{
800 801
    DObject *diagramObject = dynamic_cast<DObject *>(element);
    if (diagramObject) {
802
        foreach (DElement *diagramElement, diagram->diagramElements()) {
803
            if (DRelation *diagramRelation = dynamic_cast<DRelation *>(diagramElement)) {
804 805
                if (diagramRelation->endAUid() == diagramObject->uid()
                        || diagramRelation->endBUid() == diagramObject->uid()) {
806
                    removeElement(diagramRelation, diagram);
807
                }
Jochen Becher's avatar
Jochen Becher committed
808 809 810 811 812
            }
        }
    }
}

813
void DiagramController::renewElementKey(DElement *element, QHash<Uid, Uid> *renewedKeys)
Jochen Becher's avatar
Jochen Becher committed
814
{
815
    QMT_CHECK(renewedKeys);
Jochen Becher's avatar
Jochen Becher committed
816 817

    if (element) {
818
        DElement *existingElementOnDiagram = findElementOnAnyDiagram(element->uid());
819 820
        if (existingElementOnDiagram) {
            QMT_CHECK(existingElementOnDiagram != element);
821
            Uid oldKey = element->uid();
Jochen Becher's avatar
Jochen Becher committed
822
            element->renewUid();
823
            Uid newKey = element->uid();
824
            renewedKeys->insert(oldKey, newKey);
Jochen Becher's avatar
Jochen Becher committed
825 826 827 828
        }
    }
}

829
void DiagramController::updateRelationKeys(DRelation *relation, const QHash<Uid, Uid> &renewedKeys)
Jochen Becher's avatar
Jochen Becher committed
830
{
831
    Uid newEndAKey = renewedKeys.value(relation->endAUid(), Uid::invalidUid());
832
    if (newEndAKey.isValid())
833 834
        relation->setEndAUid(newEndAKey);
    Uid newEndBKey = renewedKeys.value(relation->endBUid(), Uid::invalidUid());
835
    if (newEndBKey.isValid())
836
        relation->setEndBUid(newEndBKey);
Jochen Becher's avatar
Jochen Becher committed
837 838
}

839
void DiagramController::updateElementFromModel(DElement *element, const MDiagram *diagram, bool emitUpdateSignal)
Jochen Becher's avatar
Jochen Becher committed
840
{
841
    if (!element->modelUid().isValid())
Jochen Becher's avatar
Jochen Becher committed
842 843 844 845
        return;

    DUpdateVisitor visitor(element, diagram);

846
    MElement *melement = m_modelController->findElement(element->modelUid());
Jochen Becher's avatar
Jochen Becher committed
847 848
    QMT_CHECK(melement);

849
    if (emitUpdateSignal) {
Jochen Becher's avatar
Jochen Becher committed
850 851
        visitor.setCheckNeedsUpdate(true);
        melement->accept(&visitor);
852
        if (visitor.isUpdateNeeded()) {
853
            int row = diagram->diagramElements().indexOf(element);
Jochen Becher's avatar
Jochen Becher committed
854 855 856 857 858 859 860 861 862 863 864 865
            emit beginUpdateElement(row, diagram);
            visitor.setCheckNeedsUpdate(false);
            melement->accept(&visitor);
            emit endUpdateElement(row, diagram);
        }
    } else {
        melement->accept(&visitor);
    }
}

void DiagramController::diagramModified(MDiagram *diagram)
{
866 867
    // the modification date is updated intentionally without signalling model controller
    // avoiding recursive change updates
Jochen Becher's avatar
Jochen Becher committed
868 869 870 871
    diagram->setLastModifiedToNow();
    emit modified(diagram);
}

872
DReferences DiagramController::simplify(const DSelection &diagramSelection, const MDiagram *diagram)
Jochen Becher's avatar
Jochen Becher committed
873 874
{
    DReferences references;
875 876
    foreach (const DSelection::Index &index, diagramSelection.indices()) {
        DElement *element = findElement(index.elementKey(), diagram);
877
        if (element)
Jochen Becher's avatar
Jochen Becher committed
878 879 880 881 882
            references.append(element);
    }
    return references;
}

883
MElement *DiagramController::delegatedElement(const DElement *element) const
Jochen Becher's avatar
Jochen Becher committed
884
{
885
    if (!element->modelUid().isValid())
Jochen Becher's avatar
Jochen Becher committed
886
        return 0;
887
    return m_modelController->findElement(element->modelUid());
Jochen Becher's avatar
Jochen Becher committed
888 889 890 891
}

bool DiagramController::isDelegatedElementOnDiagram(const DElement *element, const MDiagram *diagram) const
{
892
    MElement *modelElement = delegatedElement(element);
893
    if (!modelElement)
Jochen Becher's avatar
Jochen Becher committed
894
        return false;
895
    return hasDelegate(modelElement, diagram);
Jochen Becher's avatar
Jochen Becher committed
896 897 898 899
}

bool DiagramController::areRelationEndsOnDiagram(const DRelation *relation, const MDiagram *diagram) const
{
900
    return findElement(relation->endAUid(), diagram) && findElement(relation->endBUid(), diagram);
Jochen Becher's avatar
Jochen Becher committed
901 902 903 904
}

void DiagramController::updateAllDiagramsList()
{
905
    m_allDiagrams.clear();
906
    if (m_modelController && m_modelController->rootPackage()) {
907
        FindDiagramsVisitor visitor(&m_allDiagrams);
908
        m_modelController->rootPackage()->accept(&visitor);
Jochen Becher's avatar
Jochen Becher committed
909 910 911
    }
}

912
} // namespace qmt