00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <QMap>
00022
00023 #include "KoCommand.h"
00024 #include "KoShape.h"
00025 #include "KoShapeGroup.h"
00026 #include "KoShapeContainer.h"
00027 #include "KoShapeControllerBase.h"
00028
00029 #include <klocale.h>
00030 #include <kdebug.h>
00031
00032 KoShapeMoveCommand::KoShapeMoveCommand(const KoSelectionSet &shapes, QList<QPointF> &previousPositions, QList<QPointF> &newPositions)
00033 : m_previousPositions(previousPositions)
00034 , m_newPositions(newPositions)
00035 {
00036 m_shapes = shapes.toList();
00037 Q_ASSERT(m_shapes.count() == m_previousPositions.count());
00038 Q_ASSERT(m_shapes.count() == m_newPositions.count());
00039 }
00040
00041 KoShapeMoveCommand::KoShapeMoveCommand(const QList<KoShape*> &shapes, QList<QPointF> &previousPositions, QList<QPointF> &newPositions)
00042 : m_shapes(shapes)
00043 , m_previousPositions(previousPositions)
00044 , m_newPositions(newPositions)
00045 {
00046 Q_ASSERT(m_shapes.count() == m_previousPositions.count());
00047 Q_ASSERT(m_shapes.count() == m_newPositions.count());
00048 }
00049
00050 void KoShapeMoveCommand::execute() {
00051 for(int i=0; i < m_shapes.count(); i++) {
00052 m_shapes.at(i)->repaint();
00053 m_shapes.at(i)->setPosition( m_newPositions.at(i) );
00054 m_shapes.at(i)->repaint();
00055 }
00056 }
00057
00058 void KoShapeMoveCommand::unexecute() {
00059 for(int i=0; i < m_shapes.count(); i++) {
00060 m_shapes.at(i)->repaint();
00061 m_shapes.at(i)->setPosition( m_previousPositions.at(i) );
00062 m_shapes.at(i)->repaint();
00063 }
00064 }
00065
00066 QString KoShapeMoveCommand::name () const {
00067 return i18n( "Move shapes" );
00068 }
00069
00070
00071 KoShapeRotateCommand::KoShapeRotateCommand(const KoSelectionSet &shapes, QList<double> &previousAngles, QList<double> &newAngles)
00072 : m_previousAngles(previousAngles)
00073 , m_newAngles(newAngles)
00074 {
00075 m_shapes = shapes.toList();
00076 Q_ASSERT(m_shapes.count() == m_previousAngles.count());
00077 Q_ASSERT(m_shapes.count() == m_newAngles.count());
00078 }
00079
00080 KoShapeRotateCommand::KoShapeRotateCommand(const QList<KoShape*> &shapes, QList<double> &previousAngles, QList<double> &newAngles)
00081 : m_previousAngles(previousAngles)
00082 , m_newAngles(newAngles)
00083 {
00084 m_shapes = shapes;
00085 Q_ASSERT(m_shapes.count() == m_previousAngles.count());
00086 Q_ASSERT(m_shapes.count() == m_newAngles.count());
00087 }
00088
00089 void KoShapeRotateCommand::execute() {
00090 for(int i=0; i < m_shapes.count(); i++) {
00091 m_shapes.at(i)->repaint();
00092 m_shapes.at(i)->rotate( m_newAngles.at(i) );
00093 m_shapes.at(i)->repaint();
00094 }
00095 }
00096
00097 void KoShapeRotateCommand::unexecute() {
00098 for(int i=0; i < m_shapes.count(); i++) {
00099 m_shapes.at(i)->repaint();
00100 m_shapes.at(i)->rotate( m_previousAngles.at(i) );
00101 m_shapes.at(i)->repaint();
00102 }
00103 }
00104
00105 QString KoShapeRotateCommand::name () const {
00106 return i18n( "Rotate shapes" );
00107 }
00108
00109
00110 KoShapeShearCommand::KoShapeShearCommand(const KoSelectionSet &shapes, QList<double> &previousShearXs, QList<double> &previousShearYs, QList<double> &newShearXs, QList<double> &newShearYs)
00111 : m_previousShearXs(previousShearXs)
00112 , m_previousShearYs(previousShearYs)
00113 , m_newShearXs(newShearXs)
00114 , m_newShearYs(newShearYs)
00115 {
00116 m_shapes = shapes.toList();
00117 Q_ASSERT(m_shapes.count() == m_previousShearXs.count());
00118 Q_ASSERT(m_shapes.count() == m_previousShearYs.count());
00119 Q_ASSERT(m_shapes.count() == m_newShearXs.count());
00120 Q_ASSERT(m_shapes.count() == m_newShearYs.count());
00121 }
00122
00123 void KoShapeShearCommand::execute() {
00124 for(int i=0; i < m_shapes.count(); i++) {
00125 m_shapes.at(i)->repaint();
00126 m_shapes.at(i)->shear( m_newShearXs.at(i), m_newShearYs.at(i));
00127 m_shapes.at(i)->repaint();
00128 }
00129 }
00130
00131 void KoShapeShearCommand::unexecute() {
00132 for(int i=0; i < m_shapes.count(); i++) {
00133 m_shapes.at(i)->repaint();
00134 m_shapes.at(i)->shear( m_previousShearXs.at(i), m_previousShearYs.at(i) );
00135 m_shapes.at(i)->repaint();
00136 }
00137 }
00138
00139 QString KoShapeShearCommand::name () const {
00140 return i18n( "Shear shapes" );
00141 }
00142
00143
00144 KoShapeSizeCommand::KoShapeSizeCommand(const KoSelectionSet &shapes, QList<QSizeF> &previousSizes, QList<QSizeF> &newSizes)
00145 : m_previousSizes(previousSizes)
00146 , m_newSizes(newSizes)
00147 {
00148 m_shapes = shapes.toList();
00149 Q_ASSERT(m_shapes.count() == m_previousSizes.count());
00150 Q_ASSERT(m_shapes.count() == m_newSizes.count());
00151 }
00152
00153 KoShapeSizeCommand::KoShapeSizeCommand(const QList<KoShape*> &shapes, QList<QSizeF> &previousSizes, QList<QSizeF> &newSizes)
00154 : m_previousSizes(previousSizes)
00155 , m_newSizes(newSizes)
00156 {
00157 m_shapes = shapes;
00158 Q_ASSERT(m_shapes.count() == m_previousSizes.count());
00159 Q_ASSERT(m_shapes.count() == m_newSizes.count());
00160 }
00161
00162 void KoShapeSizeCommand::execute () {
00163 int i=0;
00164 foreach(KoShape *shape, m_shapes) {
00165 shape->repaint();
00166 shape->resize(m_newSizes[i++]);
00167 shape->repaint();
00168 }
00169 }
00170
00171 void KoShapeSizeCommand::unexecute () {
00172 int i=0;
00173 foreach(KoShape *shape, m_shapes) {
00174 shape->repaint();
00175 shape->resize(m_previousSizes[i++]);
00176 shape->repaint();
00177 }
00178 }
00179
00180 QString KoShapeSizeCommand::name () const {
00181 return i18n( "Resize shapes" );
00182 }
00183
00184
00185 KoGroupShapesCommand::KoGroupShapesCommand(KoShapeContainer *container, QList<KoShape *> shapes, QList<bool> clipped)
00186 : m_shapes(shapes)
00187 , m_clipped(clipped)
00188 , m_container(container)
00189 {
00190 Q_ASSERT(m_clipped.count() == m_shapes.count());
00191 foreach( KoShape* shape, m_shapes )
00192 m_oldParents.append( shape->parent() );
00193 }
00194
00195 KoGroupShapesCommand::KoGroupShapesCommand(KoShapeGroup *container, QList<KoShape *> shapes)
00196 : m_shapes(shapes)
00197 , m_container(container)
00198 {
00199 foreach( KoShape* shape, m_shapes )
00200 {
00201 m_clipped.append(false);
00202 m_oldParents.append( shape->parent() );
00203 }
00204 }
00205
00206 KoGroupShapesCommand::KoGroupShapesCommand() {
00207 }
00208
00209 void KoGroupShapesCommand::execute () {
00210 QList <QPointF> positions;
00211 bool boundingRectInitialized=true;
00212 QRectF bound;
00213 if(m_container->childCount() > 0)
00214 bound = m_container->boundingRect();
00215 else
00216 boundingRectInitialized = false;
00217 foreach(KoShape *shape, m_shapes) {
00218 positions.append(shape->absolutePosition());
00219 if(boundingRectInitialized)
00220 bound = bound.unite(shape->boundingRect());
00221 else {
00222 bound = shape->boundingRect();
00223 boundingRectInitialized = true;
00224 }
00225 m_container->addChild(shape);
00226 }
00227 m_container->setPosition( bound.topLeft() );
00228 m_container->resize( bound.size() );
00229 for(int i=0; i < m_shapes.count(); i++) {
00230 m_shapes[i]->setAbsolutePosition( positions[i] );
00231 }
00232
00233 kDebug() << "after group: " << m_container->position().x() << ", " << m_container->position().y() << endl;
00234 }
00235
00236 void KoGroupShapesCommand::unexecute () {
00237 QList <QPointF> positions;
00238 foreach(KoShape *shape, m_shapes)
00239 positions.append(shape->absolutePosition());
00240
00241 for(int i=0; i < m_shapes.count(); i++) {
00242 m_container->removeChild(m_shapes[i]);
00243 m_shapes[i]->setAbsolutePosition( positions[i] );
00244 if( m_oldParents.at( i ) )
00245 m_oldParents.at( i )->addChild( m_shapes[i] );
00246 }
00247 }
00248
00249 QString KoGroupShapesCommand::name () const {
00250 return i18n( "Group shapes" );
00251 }
00252
00253
00254 KoUngroupShapesCommand::KoUngroupShapesCommand(KoShapeContainer *container, QList<KoShape *> shapes)
00255 : KoGroupShapesCommand()
00256 {
00257 m_shapes = shapes;
00258 m_container = container;
00259 foreach(KoShape *shape, m_shapes) {
00260 m_clipped.append( m_container->childClipped(shape) );
00261 m_oldParents.append( m_container->parent() );
00262 }
00263 }
00264
00265 void KoUngroupShapesCommand::execute () {
00266 KoGroupShapesCommand::unexecute();
00267 }
00268
00269 void KoUngroupShapesCommand::unexecute () {
00270 KoGroupShapesCommand::execute();
00271 }
00272
00273 QString KoUngroupShapesCommand::name () const {
00274 return i18n( "Ungroup shapes" );
00275 }
00276
00277 KoShapeCreateCommand::KoShapeCreateCommand( KoShapeControllerBase *controller, KoShape *shape )
00278 : m_controller( controller )
00279 , m_shape( shape )
00280 , m_deleteShape( true )
00281 {
00282 }
00283
00284 KoShapeCreateCommand::~KoShapeCreateCommand() {
00285 if( m_shape && m_deleteShape )
00286 delete m_shape;
00287 }
00288
00289 void KoShapeCreateCommand::execute () {
00290 Q_ASSERT(m_shape);
00291 Q_ASSERT(m_controller);
00292 m_controller->addShape( m_shape );
00293 m_deleteShape = false;
00294 }
00295
00296 void KoShapeCreateCommand::unexecute () {
00297 Q_ASSERT(m_shape);
00298 Q_ASSERT(m_controller);
00299 m_controller->removeShape( m_shape );
00300 m_deleteShape = true;
00301 }
00302
00303 QString KoShapeCreateCommand::name () const {
00304 return i18n( "Create shape" );
00305 }
00306
00307 KoShapeDeleteCommand::KoShapeDeleteCommand( KoShapeControllerBase *controller, KoShape *shape )
00308 : m_controller( controller )
00309 , m_deleteShapes( false )
00310 {
00311 m_shapes.append( shape );
00312 }
00313
00314 KoShapeDeleteCommand::KoShapeDeleteCommand( KoShapeControllerBase *controller, const KoSelectionSet &shapes )
00315 : m_controller( controller )
00316 , m_deleteShapes( false )
00317 {
00318 m_shapes = shapes.toList();
00319 }
00320
00321 KoShapeDeleteCommand::~KoShapeDeleteCommand() {
00322 if( ! m_deleteShapes )
00323 return;
00324
00325 foreach (KoShape *shape, m_shapes ) {
00326 delete shape;
00327 }
00328 }
00329
00330 void KoShapeDeleteCommand::execute () {
00331 if( ! m_controller )
00332 return;
00333
00334 foreach (KoShape *shape, m_shapes ) {
00335 m_controller->removeShape( shape );
00336 }
00337 m_deleteShapes = true;
00338 }
00339
00340 void KoShapeDeleteCommand::unexecute () {
00341 if( ! m_controller )
00342 return;
00343
00344 foreach (KoShape *shape, m_shapes ) {
00345 m_controller->addShape( shape );
00346 }
00347 m_deleteShapes = false;
00348 }
00349
00350 QString KoShapeDeleteCommand::name () const {
00351 return i18n( "Delete shapes" );
00352 }
00353
00354 KoShapeBackgroundCommand::KoShapeBackgroundCommand( const KoSelectionSet &shapes, const QBrush &brush )
00355 : m_newBrush( brush )
00356 {
00357 m_shapes = shapes.toList();
00358 }
00359
00360 KoShapeBackgroundCommand::~KoShapeBackgroundCommand() {
00361 }
00362
00363 void KoShapeBackgroundCommand::execute () {
00364 foreach( KoShape *shape, m_shapes ) {
00365 m_oldBrushes.append( shape->background() );
00366 shape->setBackground( m_newBrush );
00367 shape->repaint();
00368 }
00369 }
00370
00371 void KoShapeBackgroundCommand::unexecute () {
00372 QList<QBrush>::iterator brushIt = m_oldBrushes.begin();
00373 foreach( KoShape *shape, m_shapes ) {
00374 shape->setBackground( *brushIt );
00375 shape->repaint();
00376 brushIt++;
00377 }
00378 }
00379
00380 QString KoShapeBackgroundCommand::name () const {
00381 return i18n( "Set background" );
00382 }
00383
00384 KoShapeAlignCommand::KoShapeAlignCommand( const KoSelectionSet &shapes, Align align, QRectF boundingRect )
00385 {
00386 QList<QPointF> previousPositions;
00387 QList<QPointF> newPositions;
00388 QPointF position;
00389 QPointF delta;
00390 QRectF bRect;
00391 foreach( KoShape *shape, shapes ) {
00392 if(dynamic_cast<KoShapeGroup*> (shape))
00393 kDebug() << "Found Group\n";
00394 else if(dynamic_cast<KoShapeContainer*> (shape))
00395 kDebug() << "Found Container\n";
00396 else
00397 kDebug() << "Found shape\n";
00398 position = shape->position();
00399 previousPositions << position;
00400 bRect = shape->boundingRect();
00401 switch( align )
00402 {
00403 case HorizontalLeftAlignment:
00404 delta = QPointF( boundingRect.left(), bRect.y()) - bRect.topLeft();
00405 break;
00406 case HorizontalCenterAlignment:
00407 delta = QPointF( boundingRect.center().x() - bRect.width()/2, bRect.y()) - bRect.topLeft();
00408 break;
00409 case HorizontalRightAlignment:
00410 delta = QPointF( boundingRect.right() - bRect.width(), bRect.y()) - bRect.topLeft();
00411 break;
00412 case VerticalTopAlignment:
00413 delta = QPointF( bRect.x(), boundingRect.top()) - bRect.topLeft();
00414 break;
00415 case VerticalCenterAlignment:
00416 delta = QPointF( bRect.x(), boundingRect.center().y() - bRect.height()/2) - bRect.topLeft();
00417 break;
00418 case VerticalBottomAlignment:
00419 delta = QPointF( bRect.x(), boundingRect.bottom() - bRect.height()) - bRect.topLeft();
00420 break;
00421 };
00422 newPositions << position + delta;
00423 kDebug() << "-> moving " << position.x() << "," << position.y() << " to " <<
00424 (position + delta).x() << ", " << (position+delta).y() << endl;
00425 }
00426 m_command = new KoShapeMoveCommand(shapes, previousPositions, newPositions);
00427 }
00428
00429 KoShapeAlignCommand::~KoShapeAlignCommand()
00430 {
00431 delete m_command;
00432 }
00433
00434 void KoShapeAlignCommand::execute()
00435 {
00436 m_command->execute();
00437 }
00438
00439 void KoShapeAlignCommand::unexecute()
00440 {
00441 m_command->unexecute();
00442 }
00443
00444 QString KoShapeAlignCommand::name () const {
00445 return i18n( "Align shapes" );
00446 }
00447
00448 KoShapeDistributeCommand::KoShapeDistributeCommand( const KoSelectionSet &shapes, Distribute distribute, QRectF boundingRect )
00449 : m_distribute( distribute )
00450 {
00451 QMap<double,KoShape*> sortedPos;
00452 QRectF bRect;
00453 double extent = 0.0;
00454
00455 foreach( KoShape *shape, shapes ) {
00456 bRect = shape->boundingRect();
00457 switch( m_distribute ) {
00458 case HorizontalCenterDistribution:
00459 sortedPos[bRect.center().x()] = shape;
00460 break;
00461 case HorizontalGapsDistribution:
00462 case HorizontalLeftDistribution:
00463 sortedPos[bRect.left()] = shape;
00464 extent += bRect.width();
00465 break;
00466 case HorizontalRightDistribution:
00467 sortedPos[bRect.right()] = shape;
00468 break;
00469 case VerticalCenterDistribution:
00470 sortedPos[bRect.center().y()] = shape;
00471 break;
00472 case VerticalGapsDistribution:
00473 case VerticalBottomDistribution:
00474 sortedPos[bRect.bottom()] = shape;
00475 extent += bRect.height();
00476 break;
00477 case VerticalTopDistribution:
00478 sortedPos[bRect.top()] = shape;
00479 break;
00480 }
00481 }
00482 KoShape* first = sortedPos.begin().value();
00483 KoShape* last = (--sortedPos.end()).value();
00484
00485
00486 double space = getAvailableSpace( first, last, extent, boundingRect);
00487 double pos = 0.0, step = space / double(shapes.count() - 1);
00488
00489 QList<QPointF> previousPositions;
00490 QList<QPointF> newPositions;
00491 QPointF position;
00492 QPointF delta;
00493 QMapIterator<double,KoShape*> it(sortedPos);
00494 while(it.hasNext())
00495 {
00496 it.next();
00497 position = it.value()->position();
00498 previousPositions << position;
00499
00500 bRect = it.value()->boundingRect();
00501 switch( m_distribute ) {
00502 case HorizontalCenterDistribution:
00503 delta = QPointF( boundingRect.x() + first->boundingRect().width()/2 + pos - bRect.width()/2, bRect.y() ) - bRect.topLeft();
00504 break;
00505 case HorizontalGapsDistribution:
00506 delta = QPointF( boundingRect.left() + pos, bRect.y() ) - bRect.topLeft();
00507 pos += bRect.width();
00508 break;
00509 case HorizontalLeftDistribution:
00510 delta = QPointF( boundingRect.left() + pos, bRect.y() ) - bRect.topLeft();
00511 break;
00512 case HorizontalRightDistribution:
00513 delta = QPointF( boundingRect.left() + first->boundingRect().width() + pos - bRect.width(), bRect.y() ) - bRect.topLeft();
00514 break;
00515 case VerticalCenterDistribution:
00516 delta = QPointF( bRect.x(), boundingRect.y() + first->boundingRect().height()/2 + pos - bRect.height()/2 ) - bRect.topLeft();
00517 break;
00518 case VerticalGapsDistribution:
00519 delta = QPointF( bRect.x(), boundingRect.top() + pos ) - bRect.topLeft();
00520 pos += bRect.height();
00521 break;
00522 case VerticalBottomDistribution:
00523 delta = QPointF( bRect.x(), boundingRect.top() + first->boundingRect().height() + pos - bRect.height() ) - bRect.topLeft();
00524 break;
00525 case VerticalTopDistribution:
00526 delta = QPointF( bRect.x(), boundingRect.top() + pos ) - bRect.topLeft();
00527 break;
00528 };
00529 newPositions << position + delta;
00530 pos += step;
00531 }
00532 m_command = new KoShapeMoveCommand(sortedPos.values(), previousPositions, newPositions);
00533 }
00534
00535 KoShapeDistributeCommand::~KoShapeDistributeCommand()
00536 {
00537 delete m_command;
00538 }
00539
00540 void KoShapeDistributeCommand::execute()
00541 {
00542 m_command->execute();
00543 }
00544
00545 void KoShapeDistributeCommand::unexecute()
00546 {
00547 m_command->unexecute();
00548 }
00549
00550 QString KoShapeDistributeCommand::name () const {
00551 return i18n( "Distribute shapes" );
00552 }
00553
00554 double KoShapeDistributeCommand::getAvailableSpace( KoShape *first, KoShape *last, double extent, QRectF boundingRect )
00555 {
00556 switch( m_distribute ) {
00557 case HorizontalCenterDistribution:
00558 return boundingRect.width() - last->boundingRect().width()/2 - first->boundingRect().width()/2;
00559 break;
00560 case HorizontalGapsDistribution:
00561 return boundingRect.width() - extent;
00562 break;
00563 case HorizontalLeftDistribution:
00564 return boundingRect.width() - last->boundingRect().width();
00565 break;
00566 case HorizontalRightDistribution:
00567 return boundingRect.width() - first->boundingRect().width();
00568 break;
00569 case VerticalCenterDistribution:
00570 return boundingRect.height() - last->boundingRect().height()/2 - first->boundingRect().height()/2;
00571 break;
00572 case VerticalGapsDistribution:
00573 return boundingRect.height() - extent;
00574 break;
00575 case VerticalBottomDistribution:
00576 return boundingRect.height() - first->boundingRect().height();
00577 break;
00578 case VerticalTopDistribution:
00579 return boundingRect.height() - last->boundingRect().height();
00580 break;
00581 }
00582 return 0.0;
00583 }
00584
00585 KoShapeLockCommand::KoShapeLockCommand(const KoSelectionSet &shapes, const QList<bool> &oldLock, const QList<bool> &newLock)
00586 {
00587 m_shapes = shapes.toList();
00588 m_oldLock = oldLock;
00589 m_newLock = newLock;
00590
00591 Q_ASSERT(m_shapes.count() == m_oldLock.count());
00592 Q_ASSERT(m_shapes.count() == m_newLock.count());
00593 }
00594
00595 KoShapeLockCommand::KoShapeLockCommand(const QList<KoShape*> &shapes, const QList<bool> &oldLock, const QList<bool> &newLock)
00596 {
00597 m_shapes = shapes;
00598 m_oldLock = oldLock;
00599 m_newLock = newLock;
00600
00601 Q_ASSERT(m_shapes.count() == m_oldLock.count());
00602 Q_ASSERT(m_shapes.count() == m_newLock.count());
00603 }
00604
00605 KoShapeLockCommand::~KoShapeLockCommand()
00606 {
00607 }
00608
00609 void KoShapeLockCommand::execute()
00610 {
00611 for(int i = 0; i < m_shapes.count(); ++i) {
00612 m_shapes[i]->setLocked(m_newLock[i]);
00613 }
00614 }
00615
00616 void KoShapeLockCommand::unexecute()
00617 {
00618 for(int i = 0; i < m_shapes.count(); ++i) {
00619 m_shapes[i]->setLocked(m_oldLock[i]);
00620 }
00621 }
00622
00623 QString KoShapeLockCommand::name () const
00624 {
00625 return i18n("Lock shapes");
00626 }