Krita Source Code Documentation
Loading...
Searching...
No Matches
KoShapeReorderCommand Class Reference

This command allows you to change the zIndex of a number of shapes. More...

#include <KoShapeReorderCommand.h>

+ Inheritance diagram for KoShapeReorderCommand:

Classes

struct  IndexedShape
 

Public Types

enum  MoveShapeType { RaiseShape , LowerShape , BringToFront , SendToBack }
 An enum for defining what kind of reordering to use. More...
 

Public Member Functions

 KoShapeReorderCommand (const QList< IndexedShape > &shapes, KUndo2Command *parent=0)
 
 KoShapeReorderCommand (const QList< KoShape * > &shapes, QList< int > &newIndexes, KUndo2Command *parent=0)
 
void redo () override
 redo the command
 
void undo () override
 revert the actions done in redo
 
 ~KoShapeReorderCommand () override
 
- Public Member Functions inherited from KUndo2Command
QString actionText () const
 
virtual bool canAnnihilateWith (const KUndo2Command *other) const
 
const KUndo2Commandchild (int index) const
 
int childCount () const
 
virtual QTime endTime () const
 
KUndo2CommandExtraDataextraData () const
 
bool hasParent () const
 
virtual int id () const
 
virtual bool isMerged () const
 
 KUndo2Command (const KUndo2MagicString &text, KUndo2Command *parent=0)
 
 KUndo2Command (KUndo2Command *parent=0)
 
virtual QVector< KUndo2Command * > mergeCommandsVector () const
 
virtual bool mergeWith (const KUndo2Command *other)
 
virtual void redoMergedCommands ()
 
void setEndTime ()
 
virtual void setEndTime (const QTime &time)
 
void setExtraData (KUndo2CommandExtraData *data)
 
void setText (const KUndo2MagicString &text)
 
void setTime ()
 
virtual void setTime (const QTime &time)
 
virtual void setTimedID (int timedID)
 
KUndo2MagicString text () const
 
virtual QTime time () const
 
virtual int timedId () const
 
virtual bool timedMergeWith (KUndo2Command *other)
 
virtual void undoMergedCommands ()
 
virtual ~KUndo2Command ()
 

Static Public Member Functions

static KoShapeReorderCommandcreateCommand (const QList< KoShape * > &shapes, KoShapeManager *manager, MoveShapeType move, KUndo2Command *parent=0)
 
static QList< KoShapeReorderCommand::IndexedShapehomogenizeZIndexes (QList< IndexedShape > shapes)
 
static QList< KoShapeReorderCommand::IndexedShapehomogenizeZIndexesLazy (QList< IndexedShape > shapes)
 
static QList< IndexedShapemergeDownShapes (QList< KoShape * > shapesBelow, QList< KoShape * > shapesAbove)
 
static KoShapeReorderCommandmergeInShape (QList< KoShape * > shapes, KoShape *newShape, KUndo2Command *parent=0)
 mergeInShape adjust zIndex of all the shapes and newShape to avoid collisions between shapes and newShape.
 

Private Attributes

KoShapeReorderCommandPrivate *const d
 

Detailed Description

This command allows you to change the zIndex of a number of shapes.

Definition at line 21 of file KoShapeReorderCommand.h.

Member Enumeration Documentation

◆ MoveShapeType

An enum for defining what kind of reordering to use.

Enumerator
RaiseShape 

raise the selected shape to the level that it is above the shape that is on top of it.

LowerShape 

Lower the selected shape to the level that it is below the shape that is below it.

BringToFront 

Raise the selected shape to be on top of all shapes.

SendToBack 

Lower the selected shape to be below all other shapes.

Definition at line 48 of file KoShapeReorderCommand.h.

48 {
53 };
@ RaiseShape
raise the selected shape to the level that it is above the shape that is on top of it.
@ SendToBack
Lower the selected shape to be below all other shapes.
@ LowerShape
Lower the selected shape to the level that it is below the shape that is below it.
@ BringToFront
Raise the selected shape to be on top of all shapes.

Constructor & Destructor Documentation

◆ KoShapeReorderCommand() [1/2]

KoShapeReorderCommand::KoShapeReorderCommand ( const QList< KoShape * > & shapes,
QList< int > & newIndexes,
KUndo2Command * parent = 0 )

Constructor.

Parameters
shapesthe set of objects that are moved.
newIndexesthe new indexes for the shapes. this list naturally must have the same amount of items as the shapes set.
parentthe parent command used for macro commands

Definition at line 45 of file KoShapeReorderCommand.cpp.

46 : KUndo2Command(parent),
47 d(new KoShapeReorderCommandPrivate(shapes, newIndexes))
48{
49 Q_ASSERT(shapes.count() == newIndexes.count());
50 foreach (KoShape *shape, shapes)
51 d->previousIndexes.append(shape->zIndex());
52
53 setText(kundo2_i18n("Reorder shapes"));
54}
void setText(const KUndo2MagicString &text)
KUndo2Command(KUndo2Command *parent=0)
KoShapeReorderCommandPrivate *const d
qint16 zIndex() const
Definition KoShape.cpp:600
KUndo2MagicString kundo2_i18n(const char *text)

References d, kundo2_i18n(), KoShapeReorderCommandPrivate::previousIndexes, KUndo2Command::setText(), and KoShape::zIndex().

◆ KoShapeReorderCommand() [2/2]

KoShapeReorderCommand::KoShapeReorderCommand ( const QList< IndexedShape > & shapes,
KUndo2Command * parent = 0 )

Definition at line 56 of file KoShapeReorderCommand.cpp.

57 : KUndo2Command(parent),
59{
60 Q_FOREACH (const IndexedShape &index, shapes) {
61 d->shapes.append(index.shape);
62 d->newIndexes.append(index.zIndex);
63 d->previousIndexes.append(index.shape->zIndex());
64 }
65
66 setText(kundo2_i18n("Reorder shapes"));
67}

References d, kundo2_i18n(), KoShapeReorderCommandPrivate::newIndexes, KoShapeReorderCommandPrivate::previousIndexes, KUndo2Command::setText(), KoShapeReorderCommand::IndexedShape::shape, KoShapeReorderCommandPrivate::shapes, KoShapeReorderCommand::IndexedShape::zIndex, and KoShape::zIndex().

◆ ~KoShapeReorderCommand()

KoShapeReorderCommand::~KoShapeReorderCommand ( )
override

Definition at line 69 of file KoShapeReorderCommand.cpp.

70{
71 delete d;
72}

References d.

Member Function Documentation

◆ createCommand()

KoShapeReorderCommand * KoShapeReorderCommand::createCommand ( const QList< KoShape * > & shapes,
KoShapeManager * manager,
MoveShapeType move,
KUndo2Command * parent = 0 )
static

Create a new KoShapeReorderCommand by calculating the new indexes required to move the shapes according to the move parameter.

Parameters
shapesall the shapes that should be moved.
managerthe shapeManager that contains all the shapes that could have their indexes changed.
movethe moving type.
parentthe parent command for grouping purposes.
Returns
command for reordering the shapes or 0 if no reordering happened

TODO: this method doesn't handle the case when one of the shapes has maximum or minimum zIndex value (which is 16-bit in our case)!

Definition at line 142 of file KoShapeReorderCommand.cpp.

143{
149 QList<int> newIndexes;
150 QList<KoShape*> changedShapes;
151 QMap<KoShape*, QList<KoShape*> > newOrder;
152 QList<KoShape*> sortedShapes(shapes);
153 std::sort(sortedShapes.begin(), sortedShapes.end(), KoShape::compareShapeZIndex);
154 if (move == BringToFront || move == LowerShape) {
155 for (int i = 0; i < sortedShapes.size(); ++i) {
156 prepare(sortedShapes.at(i), newOrder, manager, move);
157 }
158 }
159 else {
160 for (int i = sortedShapes.size() - 1; i >= 0; --i) {
161 prepare(sortedShapes.at(i), newOrder, manager, move);
162 }
163 }
164
165 QMap<KoShape*, QList<KoShape*> >::iterator newIt(newOrder.begin());
166 for (; newIt != newOrder.end(); ++newIt) {
167 QList<KoShape*> order(newIt.value());
168 order.removeAll(nullptr);
169 int index = -KoShape::maxZIndex - 1; // set minimum zIndex
170 int pos = 0;
171 for (; pos < order.size(); ++pos) {
172 if (order[pos]->zIndex() > index) {
173 index = order[pos]->zIndex();
174 }
175 else {
176 break;
177 }
178 }
179
180 if (pos == order.size()) {
181 //nothing needs to be done
182 continue;
183 }
184 else if (pos <= order.size() / 2) {
185 // new index for the front
186 int startIndex = order[pos]->zIndex() - pos;
187 for (int i = 0; i < pos; ++i) {
188 changedShapes.append(order[i]);
189 newIndexes.append(startIndex++);
190 }
191 }
192 else {
193 //new index for the end
194 for (int i = pos; i < order.size(); ++i) {
195 changedShapes.append(order[i]);
196 newIndexes.append(++index);
197 }
198 }
199 }
200 Q_ASSERT(changedShapes.count() == newIndexes.count());
201 return changedShapes.isEmpty() ? 0: new KoShapeReorderCommand(changedShapes, newIndexes, parent);
202}
static void prepare(KoShape *s, QMap< KoShape *, QList< KoShape * > > &newOrder, KoShapeManager *manager, KoShapeReorderCommand::MoveShapeType move)
KoShapeReorderCommand(const QList< KoShape * > &shapes, QList< int > &newIndexes, KUndo2Command *parent=0)
static bool compareShapeZIndex(KoShape *s1, KoShape *s2)
Definition KoShape.cpp:434
static const qint16 maxZIndex
Definition KoShape.h:502

References BringToFront, KoShape::compareShapeZIndex(), KoShapeReorderCommand(), LowerShape, KoShape::maxZIndex, and prepare().

◆ homogenizeZIndexes()

QList< KoShapeReorderCommand::IndexedShape > KoShapeReorderCommand::homogenizeZIndexes ( QList< IndexedShape > shapes)
static

Recalculates the attached z-indexes of shapes so that all indexes go strictly in ascending order and no shapes have repetitive indexes. The physical order of the shapes in the array is not changed, on the indexes in IndexedShape are corrected.

Definition at line 243 of file KoShapeReorderCommand.cpp.

244{
245 if (shapes.isEmpty()) return shapes;
246
247 // the shapes are expected to be sorted, we just need to adjust the indexes
248
249 int lastIndex = shapes.begin()->zIndex;
250
251 auto it = shapes.begin() + 1;
252 while (it != shapes.end()) {
253 if (it->zIndex <= lastIndex) {
254 it->zIndex = lastIndex + 1;
255 }
256 lastIndex = it->zIndex;
257 ++it;
258 }
259
260 const int overflowSize = shapes.last().zIndex - int(std::numeric_limits<qint16>::max());
261
262 if (overflowSize > 0) {
263 if (shapes.first().zIndex - overflowSize > int(std::numeric_limits<qint16>::min())) {
264 for (auto it = shapes.begin(); it != shapes.end(); ++it) {
265 it->zIndex -= overflowSize;
266 }
267 } else {
268 int index = shapes.size() < int(std::numeric_limits<qint16>::max()) ?
269 0 :
270 int(std::numeric_limits<qint16>::max()) - shapes.size();
271
272 for (auto it = shapes.begin(); it != shapes.end(); ++it) {
273 it->zIndex = index;
274 index++;
275 }
276 }
277 }
278
279 return shapes;
280}

◆ homogenizeZIndexesLazy()

QList< KoShapeReorderCommand::IndexedShape > KoShapeReorderCommand::homogenizeZIndexesLazy ( QList< IndexedShape > shapes)
static

Convenience version of homogenizeZIndexes() that removes all the IndexedShape objects, which z-index didn't change during homogenization. In a result you get a list that can be passed to KoShapeReorderCommand directly.

Definition at line 283 of file KoShapeReorderCommand.cpp.

284{
285 shapes = homogenizeZIndexes(shapes);
286 // remove shapes that didn't change
287 for (auto it = shapes.begin(); it != shapes.end();) {
288 if (it->zIndex == it->shape->zIndex()) {
289 it = shapes.erase(it);
290 } else {
291 ++it;
292 }
293 }
294
295 return shapes;
296}
static QList< KoShapeReorderCommand::IndexedShape > homogenizeZIndexes(QList< IndexedShape > shapes)

References homogenizeZIndexes().

◆ mergeDownShapes()

QList< KoShapeReorderCommand::IndexedShape > KoShapeReorderCommand::mergeDownShapes ( QList< KoShape * > shapesBelow,
QList< KoShape * > shapesAbove )
static

Put all the shapes in shapesAbove above the shapes in shapesBelow, adjusting their z-index values.

Definition at line 299 of file KoShapeReorderCommand.cpp.

300{
301 std::sort(shapesBelow.begin(), shapesBelow.end(), KoShape::compareShapeZIndex);
302 std::sort(shapesAbove.begin(), shapesAbove.end(), KoShape::compareShapeZIndex);
303
304 QList<IndexedShape> shapes;
305 Q_FOREACH (KoShape *shape, shapesBelow) {
306 shapes.append(IndexedShape(shape));
307 }
308
309 Q_FOREACH (KoShape *shape, shapesAbove) {
310 shapes.append(IndexedShape(shape));
311 }
312
313 return homogenizeZIndexesLazy(shapes);
314}
static QList< KoShapeReorderCommand::IndexedShape > homogenizeZIndexesLazy(QList< IndexedShape > shapes)

References KoShape::compareShapeZIndex(), and homogenizeZIndexesLazy().

◆ mergeInShape()

KoShapeReorderCommand * KoShapeReorderCommand::mergeInShape ( QList< KoShape * > shapes,
KoShape * newShape,
KUndo2Command * parent = 0 )
static

mergeInShape adjust zIndex of all the shapes and newShape to avoid collisions between shapes and newShape.

Note1: newShape may or may not be contained in shapes, there is no difference. Note2: the collisions inside shapes are ignored. They are just adjusted to avoid collisions with newShape only

Parameters
shapeslist of shapes
newShapethe new shape
parentthe parent command for grouping purposes.
Returns
command for reordering the shapes or 0 if no reordering happened

Definition at line 204 of file KoShapeReorderCommand.cpp.

205{
206 std::sort(shapes.begin(), shapes.end(), KoShape::compareShapeZIndex);
207
208 QList<KoShape*> reindexedShapes;
209 QList<int> reindexedIndexes;
210
211 const int originalShapeZIndex = newShape->zIndex();
212 int newShapeZIndex = originalShapeZIndex;
213 int lastOccupiedShapeZIndex = originalShapeZIndex + 1;
214
215 Q_FOREACH (KoShape *shape, shapes) {
216 if (shape == newShape) continue;
217
218 const int zIndex = shape->zIndex();
219
220 if (newShapeZIndex == originalShapeZIndex) {
221 if (zIndex == originalShapeZIndex) {
222 newShapeZIndex = originalShapeZIndex + 1;
223 lastOccupiedShapeZIndex = newShapeZIndex;
224
225 reindexedShapes << newShape;
226 reindexedIndexes << newShapeZIndex;
227 }
228 } else {
229 if (zIndex >= newShapeZIndex &&
230 zIndex <= lastOccupiedShapeZIndex) {
231
232 lastOccupiedShapeZIndex = zIndex + 1;
233 reindexedShapes << shape;
234 reindexedIndexes << lastOccupiedShapeZIndex;
235 }
236 }
237 }
238
239 return !reindexedShapes.isEmpty() ? new KoShapeReorderCommand(reindexedShapes, reindexedIndexes, parent) : 0;
240}

References KoShape::compareShapeZIndex(), KoShapeReorderCommand(), and KoShape::zIndex().

◆ redo()

void KoShapeReorderCommand::redo ( )
overridevirtual

redo the command

Reimplemented from KUndo2Command.

Definition at line 74 of file KoShapeReorderCommand.cpp.

75{
77 for (int i = 0; i < d->shapes.count(); i++) {
78 // z-index cannot change the bounding rect of the shape, so
79 // no united updates needed
80 d->shapes.at(i)->setZIndex(d->newIndexes.at(i));
81 d->shapes.at(i)->update();
82 }
83}
virtual void redo()

References d, KoShapeReorderCommandPrivate::newIndexes, KUndo2Command::redo(), and KoShapeReorderCommandPrivate::shapes.

◆ undo()

void KoShapeReorderCommand::undo ( )
overridevirtual

revert the actions done in redo

Reimplemented from KUndo2Command.

Definition at line 85 of file KoShapeReorderCommand.cpp.

86{
88 for (int i = 0; i < d->shapes.count(); i++) {
89 // z-index cannot change the bounding rect of the shape, so
90 // no united updates needed
91 d->shapes.at(i)->setZIndex(d->previousIndexes.at(i));
92 d->shapes.at(i)->update();
93 }
94}
virtual void undo()

References d, KoShapeReorderCommandPrivate::previousIndexes, KoShapeReorderCommandPrivate::shapes, and KUndo2Command::undo().

Member Data Documentation

◆ d

KoShapeReorderCommandPrivate* const KoShapeReorderCommand::d
private

Definition at line 114 of file KoShapeReorderCommand.h.


The documentation for this class was generated from the following files: