modelcontroller.cpp 41.3 KB
Newer Older
1
/****************************************************************************
Jochen Becher's avatar
Jochen Becher committed
2
**
3 4
** Copyright (C) 2016 Jochen Becher
** Contact: https://www.qt.io/licensing/
Jochen Becher's avatar
Jochen Becher committed
5 6 7 8 9 10 11
**
** 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
12 13 14
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
Jochen Becher's avatar
Jochen Becher committed
15
**
16 17 18 19 20 21 22
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
Jochen Becher's avatar
Jochen Becher committed
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
**
****************************************************************************/

#include "modelcontroller.h"

#include "mcontainer.h"
#include "mselection.h"
#include "mreferences.h"
#include "mclonevisitor.h"
#include "mflatassignmentvisitor.h"

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

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

#include <QDebug>

namespace qmt {

45 46 47
class ModelController::Clone
{
public:
48
    ModelController::ElementType m_elementType = ModelController::TypeUnknown;
49 50
    Uid m_elementKey;
    Uid m_ownerKey;
51 52
    int m_indexOfElement = -1;
    MElement *m_clonedElement = 0;
Jochen Becher's avatar
Jochen Becher committed
53 54
};

55
class ModelController::UpdateObjectCommand : public UndoCommand
Jochen Becher's avatar
Jochen Becher committed
56 57
{
public:
58
    UpdateObjectCommand(ModelController *modelController, MObject *object)
Jochen Becher's avatar
Jochen Becher committed
59
        : UndoCommand(tr("Change Object")),
60
          m_modelController(modelController)
Jochen Becher's avatar
Jochen Becher committed
61 62 63
    {
        MCloneVisitor visitor;
        object->accept(&visitor);
64
        m_object = dynamic_cast<MObject *>(visitor.cloned());
65
        QMT_CHECK(m_object);
Jochen Becher's avatar
Jochen Becher committed
66 67
    }

68
    ~UpdateObjectCommand() override
Jochen Becher's avatar
Jochen Becher committed
69
    {
70
        delete m_object;
Jochen Becher's avatar
Jochen Becher committed
71 72
    }

73
    bool mergeWith(const UndoCommand *other) override
Jochen Becher's avatar
Jochen Becher committed
74
    {
75
        auto updateCommand = dynamic_cast<const UpdateObjectCommand *>(other);
76
        if (!updateCommand)
Jochen Becher's avatar
Jochen Becher committed
77
            return false;
78
        if (m_object->uid() != updateCommand->m_object->uid())
Jochen Becher's avatar
Jochen Becher committed
79 80 81 82 83
            return false;
        // the last update is a complete update of all changes...
        return true;
    }

84
    void redo() override
Jochen Becher's avatar
Jochen Becher committed
85 86 87 88 89 90 91
    {
        if (canRedo()) {
            assign();
            UndoCommand::redo();
        }
    }

92
    void undo() override
Jochen Becher's avatar
Jochen Becher committed
93 94 95 96 97 98 99 100
    {
        assign();
        UndoCommand::undo();
    }

private:
    void assign()
    {
101
        MObject *object = m_modelController->findObject<MObject>(m_object->uid());
Jochen Becher's avatar
Jochen Becher committed
102 103
        QMT_CHECK(object);
        int row = 0;
104
        MObject *parent = object->owner();
Jochen Becher's avatar
Jochen Becher committed
105
        if (!parent) {
106
            QMT_CHECK(object == m_modelController->m_rootPackage);
Jochen Becher's avatar
Jochen Becher committed
107
        } else {
108
            row = object->owner()->children().indexOf(object);
Jochen Becher's avatar
Jochen Becher committed
109
        }
110
        emit m_modelController->beginUpdateObject(row, parent);
111 112
        MCloneVisitor cloneVisitor;
        object->accept(&cloneVisitor);
113
        auto newObject = dynamic_cast<MObject *>(cloneVisitor.cloned());
114 115 116
        QMT_CHECK(newObject);
        MFlatAssignmentVisitor assignVisitor(object);
        m_object->accept(&assignVisitor);
117
        delete m_object;
118
        m_object = newObject;
119 120 121
        emit m_modelController->endUpdateObject(row, parent);
        emit m_modelController->modified();
        m_modelController->verifyModelIntegrity();
Jochen Becher's avatar
Jochen Becher committed
122 123
    }

124 125
    ModelController *m_modelController = 0;
    MObject *m_object = 0;
Jochen Becher's avatar
Jochen Becher committed
126 127 128 129 130 131
};

class ModelController::UpdateRelationCommand :
        public UndoCommand
{
public:
132
    UpdateRelationCommand(ModelController *modelController, MRelation *relation)
Jochen Becher's avatar
Jochen Becher committed
133
        : UndoCommand(tr("Change Relation")),
134
          m_modelController(modelController)
Jochen Becher's avatar
Jochen Becher committed
135 136 137
    {
        MCloneVisitor visitor;
        relation->accept(&visitor);
138
        m_relation = dynamic_cast<MRelation *>(visitor.cloned());
139
        QMT_CHECK(m_relation);
Jochen Becher's avatar
Jochen Becher committed
140 141
    }

142
    ~UpdateRelationCommand() override
Jochen Becher's avatar
Jochen Becher committed
143
    {
144
        delete m_relation;
Jochen Becher's avatar
Jochen Becher committed
145 146
    }

147
    bool mergeWith(const UndoCommand *other) override
Jochen Becher's avatar
Jochen Becher committed
148
    {
149
        auto updateCommand = dynamic_cast<const UpdateRelationCommand *>(other);
150
        if (!updateCommand)
Jochen Becher's avatar
Jochen Becher committed
151
            return false;
152
        if (m_relation->uid() != updateCommand->m_relation->uid())
Jochen Becher's avatar
Jochen Becher committed
153 154 155 156 157
            return false;
        // the last update is a complete update of all changes...
        return true;
    }

158
    void redo() override
Jochen Becher's avatar
Jochen Becher committed
159 160 161 162 163 164 165
    {
        if (canRedo()) {
            assign();
            UndoCommand::redo();
        }
    }

166
    void undo() override
Jochen Becher's avatar
Jochen Becher committed
167 168 169 170 171 172 173 174
    {
        assign();
        UndoCommand::undo();
    }

private:
    void assign()
    {
175
        MRelation *relation = m_modelController->findRelation<MRelation>(m_relation->uid());
Jochen Becher's avatar
Jochen Becher committed
176
        QMT_CHECK(relation);
177
        MObject *owner = relation->owner();
Jochen Becher's avatar
Jochen Becher committed
178
        QMT_CHECK(owner);
179
        int row = owner->relations().indexOf(relation);
180
        emit m_modelController->beginUpdateRelation(row, owner);
181 182
        MCloneVisitor cloneVisitor;
        relation->accept(&cloneVisitor);
183
        auto newRelation = dynamic_cast<MRelation *>(cloneVisitor.cloned());
184 185 186
        QMT_CHECK(newRelation);
        MFlatAssignmentVisitor assignVisitor(relation);
        m_relation->accept(&assignVisitor);
187
        delete m_relation;
188
        m_relation = newRelation;
189 190 191
        emit m_modelController->endUpdateRelation(row, owner);
        emit m_modelController->modified();
        m_modelController->verifyModelIntegrity();
Jochen Becher's avatar
Jochen Becher committed
192 193
    }

194 195
    ModelController *m_modelController = 0;
    MRelation *m_relation = 0;
Jochen Becher's avatar
Jochen Becher committed
196 197
};

198
class ModelController::AddElementsCommand : public UndoCommand
Jochen Becher's avatar
Jochen Becher committed
199 200
{
public:
201 202 203
    AddElementsCommand(ModelController *modelController, const QString &commandLabel)
        : UndoCommand(commandLabel),
          m_modelController(modelController)
Jochen Becher's avatar
Jochen Becher committed
204 205 206
    {
    }

207
    ~AddElementsCommand() override
Jochen Becher's avatar
Jochen Becher committed
208
    {
209
        foreach (const Clone &clone, m_clonedElements)
210
            delete clone.m_clonedElement;
Jochen Becher's avatar
Jochen Becher committed
211 212
    }

213
    void add(ElementType elementsType, const Uid &objectKey, const Uid &ownerKey)
Jochen Becher's avatar
Jochen Becher committed
214 215
    {
        Clone clone;
216 217 218
        clone.m_elementType = elementsType;
        clone.m_elementKey = objectKey;
        clone.m_ownerKey = ownerKey;
219 220
        clone.m_indexOfElement = -1;
        m_clonedElements.append(clone);
Jochen Becher's avatar
Jochen Becher committed
221 222
    }

223
    void redo() override
Jochen Becher's avatar
Jochen Becher committed
224 225 226
    {
        if (canRedo()) {
            bool inserted = false;
227 228 229
            for (int i = m_clonedElements.count() - 1; i >= 0; --i) {
                Clone &clone = m_clonedElements[i];
                QMT_CHECK(clone.m_clonedElement);
230
                QMT_CHECK(clone.m_clonedElement->uid() == clone.m_elementKey);
231
                MObject *owner = m_modelController->findObject<MObject>(clone.m_ownerKey);
Jochen Becher's avatar
Jochen Becher committed
232
                QMT_CHECK(owner);
233 234
                QMT_CHECK(clone.m_indexOfElement >= 0);
                switch (clone.m_elementType) {
235
                case TypeObject:
Jochen Becher's avatar
Jochen Becher committed
236
                {
237
                    emit m_modelController->beginInsertObject(clone.m_indexOfElement, owner);
238
                    auto object = dynamic_cast<MObject *>(clone.m_clonedElement);
Jochen Becher's avatar
Jochen Becher committed
239
                    QMT_CHECK(object);
240 241 242 243
                    m_modelController->mapObject(object);
                    owner->insertChild(clone.m_indexOfElement, object);
                    clone.m_clonedElement = 0;
                    emit m_modelController->endInsertObject(clone.m_indexOfElement, owner);
Jochen Becher's avatar
Jochen Becher committed
244 245 246
                    inserted = true;
                    break;
                }
247
                case TypeRelation:
Jochen Becher's avatar
Jochen Becher committed
248
                {
249
                    emit m_modelController->beginInsertRelation(clone.m_indexOfElement, owner);
250
                    auto relation = dynamic_cast<MRelation *>(clone.m_clonedElement);
Jochen Becher's avatar
Jochen Becher committed
251
                    QMT_CHECK(relation);
252 253 254 255
                    m_modelController->mapRelation(relation);
                    owner->insertRelation(clone.m_indexOfElement, relation);
                    clone.m_clonedElement = 0;
                    emit m_modelController->endInsertRelation(clone.m_indexOfElement, owner);
Jochen Becher's avatar
Jochen Becher committed
256 257 258 259 260 261 262 263
                    inserted = true;
                    break;
                }
                default:
                    QMT_CHECK(false);
                    break;
                }
            }
264
            if (inserted)
265 266
                emit m_modelController->modified();
            m_modelController->verifyModelIntegrity();
Jochen Becher's avatar
Jochen Becher committed
267 268 269 270
            UndoCommand::redo();
        }
    }

271
    void undo() override
Jochen Becher's avatar
Jochen Becher committed
272 273
    {
        bool removed = false;
274 275 276 277
        for (int i = 0; i < m_clonedElements.count(); ++i) {
            Clone &clone = m_clonedElements[i];
            QMT_CHECK(!clone.m_clonedElement);
            MObject *owner = m_modelController->findObject<MObject>(clone.m_ownerKey);
Jochen Becher's avatar
Jochen Becher committed
278
            QMT_CHECK(owner);
279
            switch (clone.m_elementType) {
280
            case TypeObject:
Jochen Becher's avatar
Jochen Becher committed
281
            {
282
                MObject *object = m_modelController->findObject<MObject>(clone.m_elementKey);
Jochen Becher's avatar
Jochen Becher committed
283
                QMT_CHECK(object);
284
                clone.m_indexOfElement = owner->children().indexOf(object);
285 286
                QMT_CHECK(clone.m_indexOfElement >= 0);
                emit m_modelController->beginRemoveObject(clone.m_indexOfElement, owner);
Jochen Becher's avatar
Jochen Becher committed
287 288
                MCloneDeepVisitor visitor;
                object->accept(&visitor);
289
                clone.m_clonedElement = visitor.cloned();
290
                m_modelController->unmapObject(object);
Jochen Becher's avatar
Jochen Becher committed
291
                owner->removeChild(object);
292
                emit m_modelController->endRemoveObject(clone.m_indexOfElement, owner);
Jochen Becher's avatar
Jochen Becher committed
293 294 295
                removed = true;
                break;
            }
296
            case TypeRelation:
Jochen Becher's avatar
Jochen Becher committed
297
            {
298
                MRelation *relation = m_modelController->findRelation<MRelation>(clone.m_elementKey);
Jochen Becher's avatar
Jochen Becher committed
299
                QMT_CHECK(relation);
300
                clone.m_indexOfElement = owner->relations().indexOf(relation);
301 302
                QMT_CHECK(clone.m_indexOfElement >= 0);
                emit m_modelController->beginRemoveRelation(clone.m_indexOfElement, owner);
Jochen Becher's avatar
Jochen Becher committed
303 304
                MCloneDeepVisitor visitor;
                relation->accept(&visitor);
305
                clone.m_clonedElement = visitor.cloned();
306
                m_modelController->unmapRelation(relation);
Jochen Becher's avatar
Jochen Becher committed
307
                owner->removeRelation(relation);
308
                emit m_modelController->endRemoveRelation(clone.m_indexOfElement, owner);
Jochen Becher's avatar
Jochen Becher committed
309 310 311 312 313 314 315 316
                removed = true;
                break;
            }
            default:
                QMT_CHECK(false);
                break;
            }
        }
317
        if (removed)
318 319
            emit m_modelController->modified();
        m_modelController->verifyModelIntegrity();
Jochen Becher's avatar
Jochen Becher committed
320 321 322 323
        UndoCommand::undo();
    }

private:
324 325
    ModelController *m_modelController = 0;
    QList<ModelController::Clone> m_clonedElements;
Jochen Becher's avatar
Jochen Becher committed
326 327
};

328
class ModelController::RemoveElementsCommand : public UndoCommand
Jochen Becher's avatar
Jochen Becher committed
329 330
{
public:
331 332 333
    RemoveElementsCommand(ModelController *modelController, const QString &commandLabel)
        : UndoCommand(commandLabel),
          m_modelController(modelController)
Jochen Becher's avatar
Jochen Becher committed
334 335 336
    {
    }

337
    ~RemoveElementsCommand() override
Jochen Becher's avatar
Jochen Becher committed
338
    {
339
        foreach (const Clone &clone, m_clonedElements)
340
            delete clone.m_clonedElement;
Jochen Becher's avatar
Jochen Becher committed
341 342 343 344
    }

    void add(MElement *element, MObject *owner)
    {
345
        ModelController::Clone clone;
Jochen Becher's avatar
Jochen Becher committed
346

347 348
        clone.m_elementKey = element->uid();
        clone.m_ownerKey = owner->uid();
349
        if (auto object = dynamic_cast<MObject *>(element)) {
350
            clone.m_elementType = TypeObject;
351
            clone.m_indexOfElement = owner->children().indexOf(object);
352
            QMT_CHECK(clone.m_indexOfElement >= 0);
353
        } else if (auto relation = dynamic_cast<MRelation *>(element)) {
354
            clone.m_elementType = TypeRelation;
355
            clone.m_indexOfElement = owner->relations().indexOf(relation);
356
            QMT_CHECK(clone.m_indexOfElement >= 0);
Jochen Becher's avatar
Jochen Becher committed
357 358 359 360 361
        } else {
            QMT_CHECK(false);
        }
        MCloneDeepVisitor visitor;
        element->accept(&visitor);
362
        clone.m_clonedElement = visitor.cloned();
363 364
        QMT_CHECK(clone.m_clonedElement);
        m_clonedElements.append(clone);
Jochen Becher's avatar
Jochen Becher committed
365 366
    }

367
    void redo() override
Jochen Becher's avatar
Jochen Becher committed
368 369 370
    {
        if (canRedo()) {
            bool removed = false;
371 372 373 374
            for (int i = 0; i < m_clonedElements.count(); ++i) {
                Clone &clone = m_clonedElements[i];
                QMT_CHECK(!clone.m_clonedElement);
                MObject *owner = m_modelController->findObject<MObject>(clone.m_ownerKey);
Jochen Becher's avatar
Jochen Becher committed
375
                QMT_CHECK(owner);
376
                switch (clone.m_elementType) {
377
                case TypeObject:
Jochen Becher's avatar
Jochen Becher committed
378
                {
379
                    MObject *object = m_modelController->findObject<MObject>(clone.m_elementKey);
Jochen Becher's avatar
Jochen Becher committed
380
                    QMT_CHECK(object);
381
                    clone.m_indexOfElement = owner->children().indexOf(object);
382 383
                    QMT_CHECK(clone.m_indexOfElement >= 0);
                    emit m_modelController->beginRemoveObject(clone.m_indexOfElement, owner);
Jochen Becher's avatar
Jochen Becher committed
384 385
                    MCloneDeepVisitor visitor;
                    object->accept(&visitor);
386
                    clone.m_clonedElement = visitor.cloned();
387
                    m_modelController->unmapObject(object);
Jochen Becher's avatar
Jochen Becher committed
388
                    owner->removeChild(object);
389
                    emit m_modelController->endRemoveObject(clone.m_indexOfElement, owner);
Jochen Becher's avatar
Jochen Becher committed
390 391 392
                    removed = true;
                    break;
                }
393
                case TypeRelation:
Jochen Becher's avatar
Jochen Becher committed
394
                {
395
                    MRelation *relation = m_modelController->findRelation<MRelation>(clone.m_elementKey);
Jochen Becher's avatar
Jochen Becher committed
396
                    QMT_CHECK(relation);
397
                    clone.m_indexOfElement = owner->relations().indexOf(relation);
398 399
                    QMT_CHECK(clone.m_indexOfElement >= 0);
                    emit m_modelController->beginRemoveRelation(clone.m_indexOfElement, owner);
Jochen Becher's avatar
Jochen Becher committed
400 401
                    MCloneDeepVisitor visitor;
                    relation->accept(&visitor);
402
                    clone.m_clonedElement = visitor.cloned();
403
                    m_modelController->unmapRelation(relation);
Jochen Becher's avatar
Jochen Becher committed
404
                    owner->removeRelation(relation);
405
                    emit m_modelController->endRemoveRelation(clone.m_indexOfElement, owner);
Jochen Becher's avatar
Jochen Becher committed
406 407 408 409 410 411 412 413
                    removed = true;
                    break;
                }
                default:
                    QMT_CHECK(false);
                    break;
                }
            }
414
            if (removed)
415 416
                emit m_modelController->modified();
            m_modelController->verifyModelIntegrity();
Jochen Becher's avatar
Jochen Becher committed
417 418 419 420
            UndoCommand::redo();
        }
    }

421
    void undo() override
Jochen Becher's avatar
Jochen Becher committed
422 423
    {
        bool inserted = false;
424 425 426 427
        for (int i = m_clonedElements.count() - 1; i >= 0; --i) {
            Clone &clone = m_clonedElements[i];
            QMT_CHECK(clone.m_clonedElement);
            MObject *owner = m_modelController->findObject<MObject>(clone.m_ownerKey);
Jochen Becher's avatar
Jochen Becher committed
428
            QMT_CHECK(owner);
429 430
            QMT_CHECK(clone.m_indexOfElement >= 0);
            switch (clone.m_elementType) {
431
            case TypeObject:
Jochen Becher's avatar
Jochen Becher committed
432
            {
433
                emit m_modelController->beginInsertObject(clone.m_indexOfElement, owner);
434
                auto object = dynamic_cast<MObject *>(clone.m_clonedElement);
Jochen Becher's avatar
Jochen Becher committed
435
                QMT_CHECK(object);
436 437 438 439
                m_modelController->mapObject(object);
                owner->insertChild(clone.m_indexOfElement, object);
                clone.m_clonedElement = 0;
                emit m_modelController->endInsertObject(clone.m_indexOfElement, owner);
Jochen Becher's avatar
Jochen Becher committed
440 441 442
                inserted = true;
                break;
            }
443
            case TypeRelation:
Jochen Becher's avatar
Jochen Becher committed
444
            {
445
                emit m_modelController->beginInsertRelation(clone.m_indexOfElement, owner);
446
                auto relation = dynamic_cast<MRelation *>(clone.m_clonedElement);
Jochen Becher's avatar
Jochen Becher committed
447
                QMT_CHECK(relation);
448 449 450 451
                m_modelController->mapRelation(relation);
                owner->insertRelation(clone.m_indexOfElement, relation);
                clone.m_clonedElement = 0;
                emit m_modelController->endInsertRelation(clone.m_indexOfElement, owner);
Jochen Becher's avatar
Jochen Becher committed
452 453 454 455 456 457 458 459
                inserted = true;
                break;
            }
            default:
                QMT_CHECK(false);
                break;
            }
        }
460
        if (inserted)
461 462
            emit m_modelController->modified();
        m_modelController->verifyModelIntegrity();
Jochen Becher's avatar
Jochen Becher committed
463 464 465 466
        UndoCommand::undo();
    }

private:
467 468
    ModelController *m_modelController = 0;
    QList<ModelController::Clone> m_clonedElements;
Jochen Becher's avatar
Jochen Becher committed
469 470
};

471
class ModelController::MoveObjectCommand : public UndoCommand
Jochen Becher's avatar
Jochen Becher committed
472 473
{
public:
474
    MoveObjectCommand(ModelController *modelController, MObject *object)
Jochen Becher's avatar
Jochen Becher committed
475
        : UndoCommand(tr("Move Object")),
476
          m_modelController(modelController),
477 478 479
          m_objectKey(object->uid()),
          m_ownerKey(object->owner()->uid()),
          m_indexOfElement(object->owner()->children().indexOf(object))
Jochen Becher's avatar
Jochen Becher committed
480 481 482
    {
    }

483
    ~MoveObjectCommand() override
Jochen Becher's avatar
Jochen Becher committed
484 485 486
    {
    }

487
    void redo() override
Jochen Becher's avatar
Jochen Becher committed
488 489 490 491 492 493 494
    {
        if (canRedo()) {
            swap();
            UndoCommand::redo();
        }
    }

495
    void undo() override
Jochen Becher's avatar
Jochen Becher committed
496 497 498 499 500 501 502 503
    {
        swap();
        UndoCommand::undo();
    }

private:
    void swap()
    {
504
        MObject *object = m_modelController->findObject(m_objectKey);
Jochen Becher's avatar
Jochen Becher committed
505
        QMT_CHECK(object);
506 507
        MObject *formerOwner = object->owner();
        int formerRow = formerOwner->children().indexOf(object);
508 509 510 511 512
        emit m_modelController->beginMoveObject(formerRow, formerOwner);
        formerOwner->decontrolChild(object);
        MObject *newOwner = m_modelController->findObject(m_ownerKey);
        newOwner->insertChild(m_indexOfElement, object);
        int newRow = m_indexOfElement;
513
        m_ownerKey = formerOwner->uid();
514 515
        m_indexOfElement = formerRow;
        emit m_modelController->endMoveObject(newRow, newOwner);
516 517
        emit m_modelController->modified();
        m_modelController->verifyModelIntegrity();
Jochen Becher's avatar
Jochen Becher committed
518 519
    }

520
    ModelController *m_modelController = 0;
521 522
    Uid m_objectKey;
    Uid m_ownerKey;
523
    int m_indexOfElement = -1;
Jochen Becher's avatar
Jochen Becher committed
524 525
};

526
class ModelController::MoveRelationCommand : public UndoCommand
Jochen Becher's avatar
Jochen Becher committed
527 528
{
public:
529
    MoveRelationCommand(ModelController *modelController, MRelation *relation)
Jochen Becher's avatar
Jochen Becher committed
530
        : UndoCommand(tr("Move Relation")),
531
          m_modelController(modelController),
532 533 534
          m_relationKey(relation->uid()),
          m_ownerKey(relation->owner()->uid()),
          m_indexOfElement(relation->owner()->relations().indexOf(relation))
Jochen Becher's avatar
Jochen Becher committed
535 536 537
    {
    }

538
    ~MoveRelationCommand() override
Jochen Becher's avatar
Jochen Becher committed
539 540 541
    {
    }

542
    void redo() override
Jochen Becher's avatar
Jochen Becher committed
543 544 545 546 547 548 549
    {
        if (canRedo()) {
            swap();
            UndoCommand::redo();
        }
    }

550
    void undo() override
Jochen Becher's avatar
Jochen Becher committed
551 552 553 554 555 556 557 558
    {
        swap();
        UndoCommand::undo();
    }

private:
    void swap()
    {
559
        MRelation *relation = m_modelController->findRelation(m_relationKey);
Jochen Becher's avatar
Jochen Becher committed
560
        QMT_CHECK(relation);
561 562
        MObject *formerOwner = relation->owner();
        int formerRow = formerOwner->relations().indexOf(relation);
563 564 565 566 567
        emit m_modelController->beginMoveRelation(formerRow, formerOwner);
        formerOwner->decontrolRelation(relation);
        MObject *newOwner = m_modelController->findObject(m_ownerKey);
        newOwner->insertRelation(m_indexOfElement, relation);
        int newRow = m_indexOfElement;
568
        m_ownerKey = formerOwner->uid();
569 570
        m_indexOfElement = formerRow;
        emit m_modelController->endMoveRelation(newRow, newOwner);
571 572
        emit m_modelController->modified();
        m_modelController->verifyModelIntegrity();
Jochen Becher's avatar
Jochen Becher committed
573 574
    }

575
    ModelController *m_modelController = 0;
576 577
    Uid m_relationKey;
    Uid m_ownerKey;
578
    int m_indexOfElement = -1;
Jochen Becher's avatar
Jochen Becher committed
579 580 581 582
};

ModelController::ModelController(QObject *parent)
    : QObject(parent),
583 584
      m_rootPackage(0),
      m_undoController(0),
585
      m_isResettingModel(false)
Jochen Becher's avatar
Jochen Becher committed
586 587 588 589 590
{
}

ModelController::~ModelController()
{
591
    delete m_rootPackage;
Jochen Becher's avatar
Jochen Becher committed
592 593
}

594
void ModelController::setRootPackage(MPackage *rootPackage)
Jochen Becher's avatar
Jochen Becher committed
595 596
{
    startResetModel();
597
    unmapObject(m_rootPackage);
598
    m_rootPackage = rootPackage;
599
    mapObject(m_rootPackage);
Jochen Becher's avatar
Jochen Becher committed
600 601 602
    finishResetModel(false);
}

603
void ModelController::setUndoController(UndoController *undoController)
Jochen Becher's avatar
Jochen Becher committed
604
{
605
    m_undoController = undoController;
Jochen Becher's avatar
Jochen Becher committed
606 607
}

608
Uid ModelController::ownerKey(const MElement *element) const
Jochen Becher's avatar
Jochen Becher committed
609 610
{
    QMT_CHECK(element);
611
    MObject *owner = element->owner();
612
    if (!owner)
Jochen Becher's avatar
Jochen Becher committed
613
        return Uid();
614
    return owner->uid();
Jochen Becher's avatar
Jochen Becher committed
615 616 617 618
}

MElement *ModelController::findElement(const Uid &key)
{
619
    if (MObject *object = findObject(key))
Jochen Becher's avatar
Jochen Becher committed
620
        return object;
621
    else if (MRelation *relation = findRelation(key))
Jochen Becher's avatar
Jochen Becher committed
622 623 624 625 626 627
        return relation;
    return 0;
}

void ModelController::startResetModel()
{
628 629
    QMT_CHECK(!m_isResettingModel);
    m_isResettingModel = true;
Jochen Becher's avatar
Jochen Becher committed
630
    emit beginResetModel();
631
    QMT_CHECK(m_isResettingModel);
Jochen Becher's avatar
Jochen Becher committed
632 633 634 635
}

void ModelController::finishResetModel(bool modified)
{
636
    QMT_CHECK(m_isResettingModel);
Jochen Becher's avatar
Jochen Becher committed
637
    emit endResetModel();
638
    if (modified)
Jochen Becher's avatar
Jochen Becher committed
639
        emit this->modified();
640 641
    QMT_CHECK(m_isResettingModel);
    m_isResettingModel = false;
Jochen Becher's avatar
Jochen Becher committed
642 643
}

644
MObject *ModelController::object(int row, const MObject *owner) const
Jochen Becher's avatar
Jochen Becher committed
645 646 647
{
    if (!owner) {
        QMT_CHECK(row == 0);
648
        return m_rootPackage;
Jochen Becher's avatar
Jochen Becher committed
649
    }
650 651
    QMT_CHECK(row >= 0 && row < owner->children().size());
    return owner->children().at(row);
Jochen Becher's avatar
Jochen Becher committed
652 653 654 655
}

MObject *ModelController::findObject(const Uid &key) const
{
656
    return m_objectsMap.value(key);
Jochen Becher's avatar
Jochen Becher committed
657 658
}

659
void ModelController::addObject(MPackage *parentPackage, MObject *object)
Jochen Becher's avatar
Jochen Becher committed
660
{
661
    QMT_CHECK(parentPackage);
Jochen Becher's avatar
Jochen Becher committed
662
    QMT_CHECK(object);
663
    int row = parentPackage->children().size();
664
    if (!m_isResettingModel)
665
        emit beginInsertObject(row, parentPackage);
Jochen Becher's avatar
Jochen Becher committed
666
    mapObject(object);
667
    if (m_undoController) {
668
        auto undoCommand = new AddElementsCommand(this, tr("Add Object"));
669
        m_undoController->push(undoCommand);
670
        undoCommand->add(TypeObject, object->uid(), parentPackage->uid());
Jochen Becher's avatar
Jochen Becher committed
671
    }
672
    parentPackage->addChild(object);
673
    if (!m_isResettingModel) {
674
        emit endInsertObject(row, parentPackage);
Jochen Becher's avatar
Jochen Becher committed
675 676 677 678 679 680 681 682
        emit modified();
    }
    verifyModelIntegrity();
}

void ModelController::removeObject(MObject *object)
{
    QMT_CHECK(object);
683
    if (m_undoController)
684
        m_undoController->beginMergeSequence(tr("Delete Object"));
Jochen Becher's avatar
Jochen Becher committed
685 686
    removeRelatedRelations(object);
    // remove object
687 688 689
    QMT_CHECK(object->owner());
    int row = object->owner()->children().indexOf(object);
    MObject *owner = object->owner();
690
    if (!m_isResettingModel)
Jochen Becher's avatar
Jochen Becher committed
691
        emit beginRemoveObject(row, owner);
692
    if (m_undoController) {
693
        auto undoCommand = new RemoveElementsCommand(this, tr("Delete Object"));
694
        m_undoController->push(undoCommand);
695
        undoCommand->add(object, object->owner());
Jochen Becher's avatar
Jochen Becher committed
696 697 698
    }
    unmapObject(object);
    owner->removeChild(object);
699
    if (!m_isResettingModel) {
Jochen Becher's avatar
Jochen Becher committed
700 701 702
        emit endRemoveObject(row, owner);
        emit modified();
    }
703
    if (m_undoController)
704
        m_undoController->endMergeSequence();
Jochen Becher's avatar
Jochen Becher committed
705 706 707 708 709 710 711
    verifyModelIntegrity();
}

void ModelController::startUpdateObject(MObject *object)
{
    QMT_CHECK(object);
    int row = 0;
712
    MObject *parent = object->owner();
Jochen Becher's avatar
Jochen Becher committed
713
    if (!parent) {
714
        QMT_CHECK(object == m_rootPackage);
Jochen Becher's avatar
Jochen Becher committed
715
    } else {
716
        row = parent->children().indexOf(object);
Jochen Becher's avatar
Jochen Becher committed
717
    }
718
    if (auto package = dynamic_cast<MPackage *>(object))
719
        m_oldPackageName = package->name();
720
    if (!m_isResettingModel)
Jochen Becher's avatar
Jochen Becher committed
721
        emit beginUpdateObject(row, parent);
722
    if (m_undoController)
723
        m_undoController->push(new UpdateObjectCommand(this, object));
Jochen Becher's avatar
Jochen Becher committed
724 725 726 727 728 729 730
}

void ModelController::finishUpdateObject(MObject *object, bool cancelled)
{
    QMT_CHECK(object);

    int row = 0;
731
    MObject *parent = object->owner();
Jochen Becher's avatar
Jochen Becher committed
732
    if (!parent) {
733
        QMT_CHECK(object == m_rootPackage);
Jochen Becher's avatar
Jochen Becher committed
734
    } else {
735
        row = parent->children().indexOf(object);
Jochen Becher's avatar
Jochen Becher committed
736
    }
737
    if (!m_isResettingModel) {
Jochen Becher's avatar
Jochen Becher committed
738 739 740
        emit endUpdateObject(row, parent);
        if (!cancelled) {
            QList<MRelation *> relations = findRelationsOfObject(object);
741
            foreach (MRelation *relation, relations)
Jochen Becher's avatar
Jochen Becher committed
742
                emit relationEndChanged(relation, object);
743
            if (auto package = dynamic_cast<MPackage *>(object)) {
744
                if (m_oldPackageName != package->name())
745
                    emit packageNameChanged(package, m_oldPackageName);
Jochen Becher's avatar
Jochen Becher committed
746 747 748 749 750 751 752
            }
            emit modified();
        }
    }
    verifyModelIntegrity();
}

753
void ModelController::moveObject(MPackage *newOwner, MObject *object)
Jochen Becher's avatar
Jochen Becher committed
754
{
755
    QMT_CHECK(newOwner);
Jochen Becher's avatar
Jochen Becher committed
756
    QMT_CHECK(object);
757
    QMT_CHECK(object != m_rootPackage);
Jochen Becher's avatar
Jochen Becher committed
758

759
    if (newOwner != object->owner()) {
760
        int formerRow = 0;
761
        MObject *formerOwner = object->owner();
762
        QMT_CHECK(formerOwner);
763
        formerRow = formerOwner->children().indexOf(object);
764
        if (!m_isResettingModel)
765
            emit beginMoveObject(formerRow, formerOwner);
766
        if (m_undoController) {
767
            auto undoCommand = new MoveObjectCommand(this, object);
768
            m_undoController->push(undoCommand);
Jochen Becher's avatar
Jochen Becher committed
769
        }
770 771
        formerOwner->decontrolChild(object);
        newOwner->addChild(object);
772
        int row = newOwner->children().indexOf(object);
773
        if (!m_isResettingModel) {
774
            emit endMoveObject(row, newOwner);
Jochen Becher's avatar
Jochen Becher committed
775 776 777 778 779 780 781 782
            emit modified();
        }
    }
    verifyModelIntegrity();
}

MRelation *ModelController::findRelation(const Uid &key) const
{
783
    return m_relationsMap.value(key);
Jochen Becher's avatar
Jochen Becher committed
784 785 786 787 788 789
}

void ModelController::addRelation(MObject *owner, MRelation *relation)
{
    QMT_CHECK(owner);
    QMT_CHECK(relation);
790 791
    QMT_CHECK(findObject(relation->endAUid()));
    QMT_CHECK(findObject(relation->endBUid()));
Jochen Becher's avatar
Jochen Becher committed
792

793
    int row = owner->relations().size();
794
    if (!m_isResettingModel)
Jochen Becher's avatar
Jochen Becher committed
795 796
        emit beginInsertRelation(row, owner);
    mapRelation(relation);
797
    if (m_undoController) {
798
        auto undoCommand = new AddElementsCommand(this, tr("Add Relation"));
799
        m_undoController->push(undoCommand);
800
        undoCommand->add(TypeRelation, relation->uid(), owner->uid());
Jochen Becher's avatar
Jochen Becher committed
801 802
    }
    owner->addRelation(relation);
803
    if (!m_isResettingModel) {
Jochen Becher's avatar
Jochen Becher committed
804 805 806 807 808 809 810 811 812
        emit endInsertRelation(row, owner);
        emit modified();
    }
    verifyModelIntegrity();
}

void ModelController::removeRelation(MRelation *relation)
{
    QMT_CHECK(relation);
813
    MObject *owner = relation->owner();
Jochen Becher's avatar
Jochen Becher committed
814
    QMT_CHECK(owner);
815
    int row = owner->relations().indexOf(relation);
816
    if (!m_isResettingModel)
Jochen Becher's avatar
Jochen Becher committed
817
        emit beginRemoveRelation(row, owner);
818
    if (m_undoController) {
819
        auto undoCommand = new RemoveElementsCommand(this, tr("Delete Relation"));
820 821
        m_undoController->push(undoCommand);
        undoCommand->add(relation, owner);
Jochen Becher's avatar
Jochen Becher committed
822 823 824
    }
    unmapRelation(relation);
    owner->removeRelation(relation);
825
    if (!m_isResettingModel) {
Jochen Becher's avatar
Jochen Becher committed
826 827 828 829 830 831 832 833 834
        emit endRemoveRelation(row, owner);
        emit modified();
    }
    verifyModelIntegrity();
}

void ModelController::startUpdateRelation(MRelation *relation)
{
    QMT_CHECK(relation);
835
    MObject *owner = relation->owner();
Jochen Becher's avatar
Jochen Becher committed
836
    QMT_CHECK(owner);
837
    if (!m_isResettingModel)
838
        emit beginUpdateRelation(owner->relations().indexOf(relation), owner);
839
    if (m_undoController)
840
        m_undoController->push(new UpdateRelationCommand(this, relation));
Jochen Becher's avatar
Jochen Becher committed
841 842 843 844 845
}

void ModelController::finishUpdateRelation(MRelation *relation, bool cancelled)
{
    QMT_CHECK(relation);
846 847 848
    QMT_CHECK(findObject(relation->endAUid()));
    QMT_CHECK(findObject(relation->endBUid()));
    MObject *owner = relation->owner();
Jochen Becher's avatar
Jochen Becher committed
849
    QMT_CHECK(owner);
850
    if (!m_isResettingModel) {
851
        emit endUpdateRelation(owner->relations().indexOf(relation), owner);
852
        if (!cancelled)
Jochen Becher's avatar
Jochen Becher committed
853 854 855 856 857
            emit modified();
    }
    verifyModelIntegrity();
}

858
void ModelController::moveRelation(MObject *newOwner, MRelation *relation)
Jochen Becher's avatar
Jochen Becher committed
859
{
860
    QMT_CHECK(newOwner);
Jochen Becher's avatar
Jochen Becher committed
861 862
    QMT_CHECK(relation);

863
    if (newOwner != relation->owner()) {
864
        int formerRow = 0;
865
        MObject *formerOwner = relation->owner();
866
        QMT_CHECK(formerOwner);
867
        formerRow = formerOwner->relations().indexOf(relation);
868
        if (!m_isResettingModel)
869
            emit beginMoveRelation(formerRow, formerOwner);
870
        if (m_undoController) {
871
            auto undoCommand = new MoveRelationCommand(this, relation);
872
            m_undoController->push(undoCommand);
Jochen Becher's avatar
Jochen Becher committed
873
        }
874 875
        formerOwner->decontrolRelation(relation);
        newOwner->addRelation(relation);
876
        int row = newOwner->relations().indexOf(relation);
877
        if (!m_isResettingModel) {
878
            emit endMoveRelation(row, newOwner);
Jochen Becher's avatar
Jochen Becher committed
879 880 881 882 883 884 885 886 887
            emit modified();
        }
    }
    verifyModelIntegrity();
}

QList<MRelation *> ModelController::findRelationsOfObject(const MObject *object) const
{
    QMT_CHECK(object);
888
    return m_objectRelationsMap.values(object->uid());
Jochen Becher's avatar
Jochen Becher committed
889 890
}

891
MContainer ModelController::cutElements(const MSelection &modelSelection)
Jochen Becher's avatar
Jochen Becher committed
892
{