modelcontroller.cpp 41.6 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
/***************************************************************************
**
** 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 "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 {

50 51 52
class ModelController::Clone
{
public:
53
    ModelController::ElementType m_elementType = ModelController::TypeUnknown;
54 55
    Uid m_elementKey;
    Uid m_ownerKey;
56 57
    int m_indexOfElement = -1;
    MElement *m_clonedElement = 0;
Jochen Becher's avatar
Jochen Becher committed
58 59
};

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

73
    ~UpdateObjectCommand() override
Jochen Becher's avatar
Jochen Becher committed
74
    {
75
        delete m_object;
Jochen Becher's avatar
Jochen Becher committed
76 77
    }

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

89
    void redo() override
Jochen Becher's avatar
Jochen Becher committed
90 91 92 93 94 95 96
    {
        if (canRedo()) {
            assign();
            UndoCommand::redo();
        }
    }

97
    void undo() override
Jochen Becher's avatar
Jochen Becher committed
98 99 100 101 102 103 104 105
    {
        assign();
        UndoCommand::undo();
    }

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

129 130
    ModelController *m_modelController = 0;
    MObject *m_object = 0;
Jochen Becher's avatar
Jochen Becher committed
131 132 133 134 135 136
};

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

147
    ~UpdateRelationCommand() override
Jochen Becher's avatar
Jochen Becher committed
148
    {
149
        delete m_relation;
Jochen Becher's avatar
Jochen Becher committed
150 151
    }

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

163
    void redo() override
Jochen Becher's avatar
Jochen Becher committed
164 165 166 167 168 169 170
    {
        if (canRedo()) {
            assign();
            UndoCommand::redo();
        }
    }

171
    void undo() override
Jochen Becher's avatar
Jochen Becher committed
172 173 174 175 176 177 178 179
    {
        assign();
        UndoCommand::undo();
    }

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

199 200
    ModelController *m_modelController = 0;
    MRelation *m_relation = 0;
Jochen Becher's avatar
Jochen Becher committed
201 202
};

203
class ModelController::AddElementsCommand : public UndoCommand
Jochen Becher's avatar
Jochen Becher committed
204 205
{
public:
206 207 208
    AddElementsCommand(ModelController *modelController, const QString &commandLabel)
        : UndoCommand(commandLabel),
          m_modelController(modelController)
Jochen Becher's avatar
Jochen Becher committed
209 210 211
    {
    }

212
    ~AddElementsCommand() override
Jochen Becher's avatar
Jochen Becher committed
213
    {
214
        foreach (const Clone &clone, m_clonedElements)
215
            delete clone.m_clonedElement;
Jochen Becher's avatar
Jochen Becher committed
216 217
    }

218
    void add(ElementType elementsType, const Uid &objectKey, const Uid &ownerKey)
Jochen Becher's avatar
Jochen Becher committed
219 220
    {
        Clone clone;
221 222 223
        clone.m_elementType = elementsType;
        clone.m_elementKey = objectKey;
        clone.m_ownerKey = ownerKey;
224 225
        clone.m_indexOfElement = -1;
        m_clonedElements.append(clone);
Jochen Becher's avatar
Jochen Becher committed
226 227
    }

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

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

private:
329 330
    ModelController *m_modelController = 0;
    QList<ModelController::Clone> m_clonedElements;
Jochen Becher's avatar
Jochen Becher committed
331 332
};

333
class ModelController::RemoveElementsCommand : public UndoCommand
Jochen Becher's avatar
Jochen Becher committed
334 335
{
public:
336 337 338
    RemoveElementsCommand(ModelController *modelController, const QString &commandLabel)
        : UndoCommand(commandLabel),
          m_modelController(modelController)
Jochen Becher's avatar
Jochen Becher committed
339 340 341
    {
    }

342
    ~RemoveElementsCommand() override
Jochen Becher's avatar
Jochen Becher committed
343
    {
344
        foreach (const Clone &clone, m_clonedElements)
345
            delete clone.m_clonedElement;
Jochen Becher's avatar
Jochen Becher committed
346 347 348 349
    }

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

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

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

426
    void undo() override
Jochen Becher's avatar
Jochen Becher committed
427 428
    {
        bool inserted = false;
429 430 431 432
        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
433
            QMT_CHECK(owner);
434 435
            QMT_CHECK(clone.m_indexOfElement >= 0);
            switch (clone.m_elementType) {
436
            case TypeObject:
Jochen Becher's avatar
Jochen Becher committed
437
            {
438
                emit m_modelController->beginInsertObject(clone.m_indexOfElement, owner);
439
                auto object = dynamic_cast<MObject *>(clone.m_clonedElement);
Jochen Becher's avatar
Jochen Becher committed
440
                QMT_CHECK(object);
441 442 443 444
                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
445 446 447
                inserted = true;
                break;
            }
448
            case TypeRelation:
Jochen Becher's avatar
Jochen Becher committed
449
            {
450
                emit m_modelController->beginInsertRelation(clone.m_indexOfElement, owner);
451
                auto relation = dynamic_cast<MRelation *>(clone.m_clonedElement);
Jochen Becher's avatar
Jochen Becher committed
452
                QMT_CHECK(relation);
453 454 455 456
                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
457 458 459 460 461 462 463 464
                inserted = true;
                break;
            }
            default:
                QMT_CHECK(false);
                break;
            }
        }
465
        if (inserted)
466 467
            emit m_modelController->modified();
        m_modelController->verifyModelIntegrity();
Jochen Becher's avatar
Jochen Becher committed
468 469 470 471
        UndoCommand::undo();
    }

private:
472 473
    ModelController *m_modelController = 0;
    QList<ModelController::Clone> m_clonedElements;
Jochen Becher's avatar
Jochen Becher committed
474 475
};

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

488
    ~MoveObjectCommand() override
Jochen Becher's avatar
Jochen Becher committed
489 490 491
    {
    }

492
    void redo() override
Jochen Becher's avatar
Jochen Becher committed
493 494 495 496 497 498 499
    {
        if (canRedo()) {
            swap();
            UndoCommand::redo();
        }
    }

500
    void undo() override
Jochen Becher's avatar
Jochen Becher committed
501 502 503 504 505 506 507 508
    {
        swap();
        UndoCommand::undo();
    }

private:
    void swap()
    {
509
        MObject *object = m_modelController->findObject(m_objectKey);
Jochen Becher's avatar
Jochen Becher committed
510
        QMT_CHECK(object);
511 512
        MObject *formerOwner = object->owner();
        int formerRow = formerOwner->children().indexOf(object);
513 514 515 516 517
        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;
518
        m_ownerKey = formerOwner->uid();
519 520
        m_indexOfElement = formerRow;
        emit m_modelController->endMoveObject(newRow, newOwner);
521 522
        emit m_modelController->modified();
        m_modelController->verifyModelIntegrity();
Jochen Becher's avatar
Jochen Becher committed
523 524
    }

525
    ModelController *m_modelController = 0;
526 527
    Uid m_objectKey;
    Uid m_ownerKey;
528
    int m_indexOfElement = -1;
Jochen Becher's avatar
Jochen Becher committed
529 530
};

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

543
    ~MoveRelationCommand() override
Jochen Becher's avatar
Jochen Becher committed
544 545 546
    {
    }

547
    void redo() override
Jochen Becher's avatar
Jochen Becher committed
548 549 550 551 552 553 554
    {
        if (canRedo()) {
            swap();
            UndoCommand::redo();
        }
    }

555
    void undo() override
Jochen Becher's avatar
Jochen Becher committed
556 557 558 559 560 561 562 563
    {
        swap();
        UndoCommand::undo();
    }

private:
    void swap()
    {
564
        MRelation *relation = m_modelController->findRelation(m_relationKey);
Jochen Becher's avatar
Jochen Becher committed
565
        QMT_CHECK(relation);
566 567
        MObject *formerOwner = relation->owner();
        int formerRow = formerOwner->relations().indexOf(relation);
568 569 570 571 572
        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;
573
        m_ownerKey = formerOwner->uid();
574 575
        m_indexOfElement = formerRow;
        emit m_modelController->endMoveRelation(newRow, newOwner);
576 577
        emit m_modelController->modified();
        m_modelController->verifyModelIntegrity();
Jochen Becher's avatar
Jochen Becher committed
578 579
    }

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

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

ModelController::~ModelController()
{
596
    delete m_rootPackage;
Jochen Becher's avatar
Jochen Becher committed
597 598
}

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

608
void ModelController::setUndoController(UndoController *undoController)
Jochen Becher's avatar
Jochen Becher committed
609
{
610
    m_undoController = undoController;
Jochen Becher's avatar
Jochen Becher committed
611 612
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

863
void ModelController::moveRelation(MObject *newOwner, MRelation *relation)
Jochen Becher's avatar
Jochen Becher committed
864
{
865
    QMT_CHECK(newOwner);
Jochen Becher's avatar
Jochen Becher committed
866 867
    QMT_CHECK(relation);

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

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

896
MContainer ModelController::cutElements(const MSelection &modelSelection)
Jochen Becher's avatar
Jochen Becher committed
897
{
898 899 900 901
    // PERFORM avoid duplicate call of simplify(modelSelection)
    MContainer copiedElements = copyElements(modelSelection);
    deleteElements(modelSelection, tr("Cut"));
    return copiedElements;
Jochen Becher's avatar
Jochen Becher committed
902 903
}

904