modelcontroller.cpp 41.4 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
        MObject *newOwner = m_modelController->findObject(m_ownerKey);
        QMT_CHECK(newOwner);
510 511 512 513
        emit m_modelController->beginMoveObject(formerRow, formerOwner);
        formerOwner->decontrolChild(object);
        newOwner->insertChild(m_indexOfElement, object);
        int newRow = m_indexOfElement;
514
        m_ownerKey = formerOwner->uid();
515 516
        m_indexOfElement = formerRow;
        emit m_modelController->endMoveObject(newRow, newOwner);
517 518
        emit m_modelController->modified();
        m_modelController->verifyModelIntegrity();
Jochen Becher's avatar
Jochen Becher committed
519 520
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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