File indexing completed on 2024-06-09 04:20:46
0001 /* This file is part of the KDE project 0002 * SPDX-FileCopyrightText: 2006 Thomas Zander <zander@kde.org> 0003 * SPDX-FileCopyrightText: 2006 Jan Hambrecht <jaham@gmx.net> 0004 * 0005 * SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "KoShapeUngroupCommand.h" 0009 #include "KoShapeContainer.h" 0010 #include "KoShapeReorderCommand.h" 0011 0012 #include <klocalizedstring.h> 0013 #include "kis_assert.h" 0014 0015 0016 struct KoShapeUngroupCommand::Private 0017 { 0018 Private(KoShapeContainer *_container, 0019 const QList<KoShape *> &_shapes, 0020 const QList<KoShape*> &_topLevelShapes) 0021 : container(_container), 0022 shapes(_shapes), 0023 topLevelShapes(_topLevelShapes) 0024 { 0025 std::stable_sort(shapes.begin(), shapes.end(), KoShape::compareShapeZIndex); 0026 std::sort(topLevelShapes.begin(), topLevelShapes.end(), KoShape::compareShapeZIndex); 0027 } 0028 0029 0030 KoShapeContainer *container; 0031 QList<KoShape*> shapes; 0032 QList<KoShape*> topLevelShapes; 0033 QScopedPointer<KUndo2Command> shapesReorderCommand; 0034 0035 }; 0036 0037 KoShapeUngroupCommand::KoShapeUngroupCommand(KoShapeContainer *container, const QList<KoShape *> &shapes, 0038 const QList<KoShape*> &topLevelShapes, KUndo2Command *parent) 0039 : KUndo2Command(parent), 0040 m_d(new Private(container, shapes, topLevelShapes)) 0041 { 0042 setText(kundo2_i18n("Ungroup shapes")); 0043 } 0044 0045 KoShapeUngroupCommand::~KoShapeUngroupCommand() 0046 { 0047 } 0048 0049 void KoShapeUngroupCommand::redo() 0050 { 0051 using IndexedShape = KoShapeReorderCommand::IndexedShape; 0052 0053 KoShapeContainer *newParent = m_d->container->parent(); 0054 0055 QList<IndexedShape> indexedSiblings; 0056 QList<KoShape*> perspectiveSiblings; 0057 0058 if (newParent) { 0059 perspectiveSiblings = newParent->shapes(); 0060 std::sort(perspectiveSiblings.begin(), perspectiveSiblings.end(), KoShape::compareShapeZIndex); 0061 } else { 0062 perspectiveSiblings = m_d->topLevelShapes; 0063 } 0064 0065 Q_FOREACH (KoShape *shape, perspectiveSiblings) { 0066 indexedSiblings.append(shape); 0067 } 0068 0069 // find the place where the ungrouped shapes should be inserted 0070 // (right on the top of their current container) 0071 auto insertIt = std::upper_bound(indexedSiblings.begin(), 0072 indexedSiblings.end(), 0073 IndexedShape(m_d->container)); 0074 0075 std::copy(m_d->shapes.begin(), m_d->shapes.end(), 0076 std::inserter(indexedSiblings, insertIt)); 0077 0078 indexedSiblings = KoShapeReorderCommand::homogenizeZIndexesLazy(indexedSiblings); 0079 0080 const QTransform ungroupTransform = m_d->container->absoluteTransformation(); 0081 for (auto it = m_d->shapes.begin(); it != m_d->shapes.end(); ++it) { 0082 KoShape *shape = *it; 0083 KIS_SAFE_ASSERT_RECOVER(shape->parent() == m_d->container) { continue; } 0084 0085 shape->setParent(newParent); 0086 shape->applyAbsoluteTransformation(ungroupTransform); 0087 } 0088 0089 if (!indexedSiblings.isEmpty()) { 0090 m_d->shapesReorderCommand.reset(new KoShapeReorderCommand(indexedSiblings)); 0091 m_d->shapesReorderCommand->redo(); 0092 } 0093 } 0094 0095 void KoShapeUngroupCommand::undo() 0096 { 0097 const QTransform groupTransform = m_d->container->absoluteTransformation().inverted(); 0098 for (auto it = m_d->shapes.begin(); it != m_d->shapes.end(); ++it) { 0099 KoShape *shape = *it; 0100 0101 shape->setParent(m_d->container); 0102 shape->applyAbsoluteTransformation(groupTransform); 0103 } 0104 0105 if (m_d->shapesReorderCommand) { 0106 m_d->shapesReorderCommand->undo(); 0107 m_d->shapesReorderCommand.reset(); 0108 } 0109 }