Files
qelectrotech-source-mirror/sources/editor/editorcommands.cpp
Jeff Patterson 825a1a594d Fix element editor Mirror and Flip to reflect the selection in place
Mirror (M) and Flip (F) in the element editor reflected the selected
parts across the element origin: every part's mirror() and flip()
negated the scene x or y coordinate. A part drawn to the right of the
origin landed the same distance to the left, so the selection jumped
to the other side of the canvas instead of turning around.

MirrorElementsCommand and FlipElementsCommand now compute the united
scene bounding rectangle of the selected items and reflect across the
vertical or horizontal line through its center. The center is snapped
to the nearest half of the diagram grid, so points that were on the
grid stay on the grid after the reflection. Terminals in particular
keep their grid alignment.

Each part's mirror() and flip() takes the axis coordinate as a
parameter with a default of 0, so the previous behavior remains
available to any other caller. The command stores the axis when it is
created and undo reapplies the same reflection, which is its own
inverse, so the existing undo path is unchanged.

Parts covered: PartArc, PartDynamicTextField, PartEllipse, PartLine,
PartPolygon, PartRectangle, PartTerminal, PartText.

Fixes #812
2026-09-06 06:48:45 -05:00

788 lines
22 KiB
C++

/*
Copyright 2006-2026 The QElectroTech Team
This file is part of QElectroTech.
QElectroTech is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
QElectroTech is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "editorcommands.h"
#include "../diagram.h"
/**
@brief ElementEditionCommand::ElementEditionCommand
Constructs an ElementEditionCommand,
thus embedding the provided \a scene and \a view.
@param scene
@param view
@param parent : Parent command
*/
ElementEditionCommand::ElementEditionCommand(ElementScene *scene,
ElementView *view,
QUndoCommand *parent):
QUndoCommand(parent),
m_scene(scene),
m_view(view)
{
}
/**
@brief ElementEditionCommand::ElementEditionCommand
Constructs an ElementEditionCommand,
thus embedding the provided \a scene and \a view.
@param text : Text describing the effect of the command
@param scene
@param view
@param parent : Parent command
*/
ElementEditionCommand::ElementEditionCommand(const QString &text,
ElementScene *scene,
ElementView *view,
QUndoCommand *parent):
QUndoCommand(text, parent),
m_scene(scene),
m_view(view)
{
}
/**
Destructor
*/
ElementEditionCommand::~ElementEditionCommand()
{
}
/**
@return the element editor/scene the command should take place on
*/
ElementScene *ElementEditionCommand::elementScene() const
{
return(m_scene);
}
/**
Define \a scene as the element editor/scene the command should take place
*/
void ElementEditionCommand::setElementScene(ElementScene *scene) {
m_scene = scene;
}
/**
@return the view the effect of the command should be rendered on
*/
ElementView *ElementEditionCommand::elementView() const
{
return(m_view);
}
/**
Define \a view as the view the effect of the command should be rendered on
*/
void ElementEditionCommand::setElementView(ElementView *view) {
m_view = view;
}
/*** CutPartsCommand ***/
/**
Constructeur
@param scene ElementScene concernee
@param parts Liste des parties coupees
@param parent QUndoCommand parent
*/
CutPartsCommand::CutPartsCommand(
ElementScene *scene,
const QList<QGraphicsItem *>& parts,
QUndoCommand *parent
) :
DeletePartsCommand(scene, parts.toVector(), parent)
{
setText(QString(QObject::tr("couper des parties", "undo caption")));
}
/// Destructeur
CutPartsCommand::~CutPartsCommand()
{
}
/*** MovePartsCommand ***/
/**
Constructeur
@param m Mouvement sous forme de QPointF
@param scene ElementScene concernee
@param parts Liste des parties deplacees
@param parent QUndoCommand parent
*/
MovePartsCommand::MovePartsCommand(
const QPointF &m,
ElementScene *scene,
const QList<QGraphicsItem *>& parts,
QUndoCommand *parent
) :
ElementEditionCommand(QObject::tr("déplacement", "undo caption"), scene, nullptr, parent),
movement(m),
first_redo(true)
{
moved_parts = parts;
}
/// Destructeur
MovePartsCommand::~MovePartsCommand()
{
}
/// Annule le deplacement
void MovePartsCommand::undo()
{
foreach(QGraphicsItem *qgi, moved_parts) qgi -> moveBy(-movement.x(), -movement.y());
}
/// Refait le deplacement
void MovePartsCommand::redo()
{
// le premier appel a redo, lors de la construction de l'objet, ne doit pas se faire
if (first_redo) {
first_redo = false;
return;
}
foreach(QGraphicsItem *qgi, moved_parts) qgi -> moveBy(movement.x(), movement.y());
}
/**
Constructeur
@param element_scene Element edite
@param before Listes des noms avant changement
@param after Listes des noms apres changement
@param parent QUndoCommand parent
*/
ChangeNamesCommand::ChangeNamesCommand(
ElementScene *element_scene,
const NamesList &before,
const NamesList &after,
QUndoCommand *parent
) :
ElementEditionCommand(QObject::tr("modification noms", "undo caption"), element_scene, nullptr, parent),
names_before(before),
names_after(after)
{
}
/// Destructeur
ChangeNamesCommand::~ChangeNamesCommand()
{
}
/// Annule le changement
void ChangeNamesCommand::undo()
{
auto data = m_scene->elementData();
data.m_names_list = names_before;
m_scene->setElementData(data);
}
/// Refait le changement
void ChangeNamesCommand::redo()
{
auto data = m_scene->elementData();
data.m_names_list = names_after;
m_scene->setElementData(data);
}
/**
Constructeur
@param elmt ElementScene concernee
@param o Option decrivant le type de traitement applique aux zValues des parties de l'element
@param parent QUndoCommand parent
*/
ChangeZValueCommand::ChangeZValueCommand(
ElementScene *elmt,
QET::DepthOption o,
QUndoCommand *parent
) :
ElementEditionCommand(elmt, nullptr, parent),
m_option(o)
{
// retrieve all primitives but terminals
QList<QGraphicsItem *> items_list = m_scene -> zItems(ElementScene::SortByZValue | ElementScene::SelectedOrNot);
// prend un snapshot des zValues
foreach(QGraphicsItem *qgi, items_list) undo_hash.insert(qgi, qgi -> zValue());
// choisit le nom en fonction du traitement
if (m_option == QET::BringForward) {
setText(QObject::tr("amener au premier plan", "undo caption"));
applyBringForward(items_list);
} else if (m_option == QET::Raise) {
setText(QObject::tr("rapprocher", "undo caption"));
applyRaise(items_list);
} else if (m_option == QET::Lower) {
setText(QObject::tr("éloigner", "undo caption"));
applyLower(items_list);
} else if (m_option == QET::SendBackward) {
setText(QObject::tr("envoyer au fond", "undo caption"));
applySendBackward(items_list);
}
}
/// Destructeur
ChangeZValueCommand::~ChangeZValueCommand()
{
}
/// Annule les changements de zValue
void ChangeZValueCommand::undo()
{
foreach(QGraphicsItem *qgi, undo_hash.keys()) qgi -> setZValue(undo_hash[qgi]);
}
/// Refait les changements de zValue
void ChangeZValueCommand::redo()
{
foreach(QGraphicsItem *qgi, redo_hash.keys()) qgi -> setZValue(redo_hash[qgi]);
}
/**
Amene les elements selectionnes au premier plan
@param items_list Liste des elements (selectionnes et non selectionnes)
*/
void ChangeZValueCommand::applyBringForward(const QList<QGraphicsItem *> &items_list) {
QList<QGraphicsItem *> non_selected_items = items_list;
QList<QGraphicsItem *> selected_items;
foreach(QGraphicsItem *qgi, non_selected_items) {
if (qgi -> isSelected()) {
selected_items << qgi;
non_selected_items.removeAt(non_selected_items.indexOf(qgi));
}
}
int z = 1;
foreach(QGraphicsItem *qgi, non_selected_items) redo_hash.insert(qgi, z ++);
foreach(QGraphicsItem *qgi, selected_items) redo_hash.insert(qgi, z ++);
}
/**
Remonte les elements selectionnes d'un plan
@param items_list Liste des elements (selectionnes et non selectionnes)
*/
void ChangeZValueCommand::applyRaise(const QList<QGraphicsItem *> &items_list) {
QList<QGraphicsItem *> my_items_list = items_list;
for (int i = my_items_list.count() - 2 ; i >= 0 ; -- i) {
if (my_items_list[i] -> isSelected()) {
if (!my_items_list[i +1] -> isSelected()) {
my_items_list.swapItemsAt(i, i + 1);
}
}
}
int z = 1;
foreach(QGraphicsItem *qgi, my_items_list) redo_hash.insert(qgi, z ++);
}
/**
Descend les elements selectionnes d'un plan
@param items_list Liste des elements (selectionnes et non selectionnes)
*/
void ChangeZValueCommand::applyLower(const QList<QGraphicsItem *> &items_list) {
QList<QGraphicsItem *> my_items_list = items_list;
for (int i = 1 ; i < my_items_list.count() ; ++ i) {
if (my_items_list[i] -> isSelected()) {
if (!my_items_list[i - 1] -> isSelected()) {
my_items_list.swapItemsAt(i, i - 1);
}
}
}
int z = 1;
foreach(QGraphicsItem *qgi, my_items_list) redo_hash.insert(qgi, z ++);
}
/**
Envoie les elements selectionnes au fond
@param items_list Liste des elements (selectionnes et non selectionnes)
*/
void ChangeZValueCommand::applySendBackward(const QList<QGraphicsItem *> &items_list) {
QList<QGraphicsItem *> non_selected_items = items_list;
QList<QGraphicsItem *> selected_items;
foreach(QGraphicsItem *qgi, non_selected_items) {
if (qgi -> isSelected()) {
selected_items << qgi;
non_selected_items.removeAt(non_selected_items.indexOf(qgi));
}
}
int z = 1;
foreach(QGraphicsItem *qgi, selected_items) redo_hash.insert(qgi, z ++);
foreach(QGraphicsItem *qgi, non_selected_items) redo_hash.insert(qgi, z ++);
}
/**
Constructeur
@param elmt ElementScene concernee
@param old_infos Informations complementaires precedentes
@param new_infos Nouvelles informations complementaires
@param parent QUndoCommand parent
*/
ChangeInformationsCommand::ChangeInformationsCommand(ElementScene *elmt, const QString &old_infos, const QString &new_infos, QUndoCommand *parent) :
ElementEditionCommand(QObject::tr("modification informations complementaires", "undo caption"), elmt, nullptr, parent),
old_informations_(old_infos),
new_informations_(new_infos)
{
}
/// Destructeur
ChangeInformationsCommand::~ChangeInformationsCommand()
{
}
/// Annule le changement d'autorisation pour les connexions internes
void ChangeInformationsCommand::undo()
{
auto data = m_scene->elementData();
data.m_drawing_information = old_informations_;
m_scene->setElementData(data);
}
/// Refait le changement d'autorisation pour les connexions internes
void ChangeInformationsCommand::redo()
{
auto data = m_scene->elementData();
data.m_drawing_information = new_informations_;
m_scene->setElementData(data);
}
/**
Constructor
@param scene Modified ElementScene
@param parent Parent QUndoCommand
*/
ScalePartsCommand::ScalePartsCommand(ElementScene *scene, QUndoCommand * parent) :
ElementEditionCommand(scene, nullptr, parent),
first_redo(true)
{}
/**
Destructor
*/
ScalePartsCommand::~ScalePartsCommand()
{
}
/**
Undo the scaling operation
*/
void ScalePartsCommand::undo()
{
scale(new_rect_, original_rect_);
}
/**
Redo the scaling operation
*/
void ScalePartsCommand::redo()
{
if (first_redo) {
first_redo = false;
return;
}
scale(original_rect_, new_rect_);
}
/**
@return the element editor/scene the command should take place on
*/
ElementScene *ScalePartsCommand::elementScene() const
{
return(m_scene);
}
/**
Set \a primitives as the list of primitives to be scaled by this command
*/
void ScalePartsCommand::setScaledPrimitives(const QList<CustomElementPart *> &primitives) {
scaled_primitives_ = primitives;
adjustText();
}
/**
@return the list of primitives to be scaled by this command
*/
QList<CustomElementPart *> ScalePartsCommand::scaledPrimitives() const
{
return(scaled_primitives_);
}
/**
@brief ScalePartsCommand::setTransformation
Define the transformation applied by this command
@param original_rect :
Bounding rectangle for all scaled primitives before the operation
@param new_rect :
Bounding rectangle for all scaled primitives after the operation
*/
void ScalePartsCommand::setTransformation(const QRectF &original_rect,
const QRectF &new_rect) {
original_rect_ = original_rect;
new_rect_ = new_rect;
}
/**
@return the transformation applied by this command. The returned rectangles
are the bounding rectangles for all scaled primitives respectively before
and after the operation.
*/
QPair<QRectF, QRectF> ScalePartsCommand::transformation()
{
return(QPair<QRectF, QRectF>(original_rect_, new_rect_));
}
/**
Apply the scaling operation from \a before to \a after.
*/
void ScalePartsCommand::scale(const QRectF &before, const QRectF &after) {
if (!scaled_primitives_.count()) return;
if (before == after) return;
if (!before.width() || !before.height()) return; // cowardly flee division by zero FIXME?
foreach (CustomElementPart *part_item, scaled_primitives_) {
part_item -> startUserTransformation(before);
part_item -> handleUserTransformation(before, after);
}
}
/**
Generate the text describing what this command does exactly.
*/
void ScalePartsCommand::adjustText()
{
if (scaled_primitives_.count() == 1) {
setText(QObject::tr("redimensionnement %1", "undo caption -- %1 is the resized primitive type name").arg(scaled_primitives_.first() -> name()));
} else {
setText(QObject::tr("redimensionnement de %1 primitives", "undo caption -- %1 always > 1").arg(scaled_primitives_.count()));
}
}
/**
* @brief changeElementDataCommand::changeElementDataCommand
* Change the properties of the drawn element
* @param scene : scene belonging to the property
* @param old_data : old data
* @param new_data : new data
* @param parent : parent undo command
*/
changeElementDataCommand::changeElementDataCommand(ElementScene *scene,
ElementData old_data,
ElementData new_data,
QUndoCommand *parent) :
ElementEditionCommand(scene, nullptr, parent),
m_old(old_data),
m_new(new_data)
{
setText(QObject::tr("Modifier les propriétées de l'élément"));
}
void changeElementDataCommand::undo() {
m_scene->setElementData(m_old);
QUndoCommand::undo();
}
void changeElementDataCommand::redo() {
m_scene->setElementData(m_new);
QUndoCommand::redo();
}
RotateElementsCommand::RotateElementsCommand(ElementScene *scene, QUndoCommand *parent) :
ElementEditionCommand(QObject::tr("Pivoter la selection", "undo caption"), scene, nullptr, parent)
{
m_items = scene->selectedItems();
}
/**
@brief RotateElementsCommand::undo
*/
void RotateElementsCommand::undo()
{
for (QGraphicsItem *item : m_items)
{
if (item->type() == PartTerminal::Type) {
PartTerminal* term = qgraphicsitem_cast<PartTerminal*>(item);
if(m_items.size() == 1) {
term->previousOrientation();
} else {
term->setRotation(term->rotation()-90);
}
}
else if (item->type() == PartRectangle::Type) {
PartRectangle* rect = qgraphicsitem_cast<PartRectangle*>(item);
rect->setRotation(rect->rotation()-90);
}
else if (item->type() == PartArc::Type) {
PartArc* arc = qgraphicsitem_cast<PartArc*>(item);
arc->setRotation(arc->rotation()-90);
}
else if (item->type() == PartEllipse::Type) {
PartEllipse* ellipse = qgraphicsitem_cast<PartEllipse*>(item);
ellipse->setRotation(ellipse->rotation()-90);
}
else if (item->type() == PartLine::Type) {
PartLine* line = qgraphicsitem_cast<PartLine*>(item);
line->setRotation(line->rotation()-90);
}
else if (item->type() == PartPolygon::Type) {
PartPolygon* poly = qgraphicsitem_cast<PartPolygon*>(item);
poly->setRotation(poly->rotation()-90);
}
else if (item->type() == PartText::Type) {
PartText* text = qgraphicsitem_cast<PartText*>(item);
text->setRotation(text->rotation()-90);
}
else if (item->type() == PartDynamicTextField::Type) {
PartDynamicTextField* dyntext = qgraphicsitem_cast<PartDynamicTextField*>(item);
dyntext->setRotation(dyntext->rotation()-90);
}
else {
item->setRotation(item->rotation()-90);
}
}
}
/**
@brief RotateElementsCommand::redo
*/
void RotateElementsCommand::redo()
{
for (QGraphicsItem *item : m_items)
{
if (item->type() == PartTerminal::Type) {
PartTerminal* term = qgraphicsitem_cast<PartTerminal*>(item);
if (m_items.size() == 1) {
term->nextOrientation();
} else {
term->setRotation(term->rotation()+90);
}
}
else if (item->type() == PartRectangle::Type) {
PartRectangle* rect = qgraphicsitem_cast<PartRectangle*>(item);
rect->setRotation(rect->rotation()+90);
}
else if (item->type() == PartArc::Type) {
PartArc* arc = qgraphicsitem_cast<PartArc*>(item);
arc->setRotation(arc->rotation()+90);
}
else if (item->type() == PartEllipse::Type) {
PartEllipse* ellipse = qgraphicsitem_cast<PartEllipse*>(item);
ellipse->setRotation(ellipse->rotation()+90);
}
else if (item->type() == PartLine::Type) {
PartLine* line = qgraphicsitem_cast<PartLine*>(item);
line->setRotation(line->rotation()+90);
}
else if (item->type() == PartPolygon::Type) {
PartPolygon* poly = qgraphicsitem_cast<PartPolygon*>(item);
poly->setRotation(poly->rotation()+90);
}
else if (item->type() == PartText::Type) {
PartText* text = qgraphicsitem_cast<PartText*>(item);
text->setRotation(text->rotation()+90);
}
else if (item->type() == PartDynamicTextField::Type) {
PartDynamicTextField* dyntext = qgraphicsitem_cast<PartDynamicTextField*>(item);
dyntext->setRotation(dyntext->rotation()+90);
}
else {
item->setRotation(item->rotation()+90);
}
}
}
RotateFineElementsCommand::RotateFineElementsCommand(ElementScene *scene, QUndoCommand *parent) :
ElementEditionCommand(QObject::tr("Pivoter la selection", "undo caption"), scene, nullptr, parent)
{
m_items = scene->selectedItems();
}
/**
@brief RotateFineElementsCommand::undo
*/
void RotateFineElementsCommand::undo()
{
for (QGraphicsItem *item : m_items)
{
if (item->type() == PartLine::Type) {
PartLine* line = qgraphicsitem_cast<PartLine*>(item);
line->setRotation(line->rotation()-5);
}
else if (item->type() == PartPolygon::Type) {
PartPolygon* poly = qgraphicsitem_cast<PartPolygon*>(item);
poly->setRotation(poly->rotation()-5);
}
else if (item->type() == PartText::Type) {
PartText* text = qgraphicsitem_cast<PartText*>(item);
text->setRotation(text->rotation()-5);
}
else if (item->type() == PartDynamicTextField::Type) {
PartDynamicTextField* dyntext = qgraphicsitem_cast<PartDynamicTextField*>(item);
dyntext->setRotation(dyntext->rotation()-5);
}
else {
//item->setRotation(item->rotation()-5);
}
}
}
/**
@brief RotateFineElementsCommand::redo
*/
void RotateFineElementsCommand::redo()
{
for (QGraphicsItem *item : m_items)
{
if (item->type() == PartLine::Type) {
PartLine* line = qgraphicsitem_cast<PartLine*>(item);
line->setRotation(line->rotation()+5);
}
else if (item->type() == PartPolygon::Type) {
PartPolygon* poly = qgraphicsitem_cast<PartPolygon*>(item);
poly->setRotation(poly->rotation()+5);
}
else if (item->type() == PartText::Type) {
PartText* text = qgraphicsitem_cast<PartText*>(item);
text->setRotation(text->rotation()+5);
}
else if (item->type() == PartDynamicTextField::Type) {
PartDynamicTextField* dyntext = qgraphicsitem_cast<PartDynamicTextField*>(item);
dyntext->setRotation(dyntext->rotation()+5);
}
else {
//item->setRotation(item->rotation()+5);
}
}
}
/**
@brief selectionCenter
@param items
@return the center of the united scene bounding rect of items,
snapped to the nearest half of the diagram grid. Mirroring across a
half-grid line keeps points that were on the grid on the grid.
*/
static QPointF selectionCenter(const QList<QGraphicsItem *> &items)
{
QRectF bounding;
for (auto *item : items) {
bounding = bounding.united(item->sceneBoundingRect());
}
QPointF center = bounding.center();
const qreal half_x = Diagram::xGrid / 2.0;
const qreal half_y = Diagram::yGrid / 2.0;
center.setX(qRound(center.x() / half_x) * half_x);
center.setY(qRound(center.y() / half_y) * half_y);
return center;
}
MirrorElementsCommand::MirrorElementsCommand(ElementScene *scene, QUndoCommand *parent) :
ElementEditionCommand(QObject::tr("Miroir de sélection", "undo caption"), scene, nullptr, parent)
{
m_items = scene->selectedItems();
m_axis_x = selectionCenter(m_items).x();
}
/**
@brief MirrorElementsCommand::redo
*/
void MirrorElementsCommand::redo()
{
foreach (auto *item, m_items) {
if (item->type() == PartText::Type) {
PartText* staticText = qgraphicsitem_cast<PartText*>(item);
staticText->mirror(m_axis_x);
} else if (item->type() == PartDynamicTextField::Type) {
PartDynamicTextField* dyntext = qgraphicsitem_cast<PartDynamicTextField*>(item);
dyntext->mirror(m_axis_x);
} else if (item->type() == PartArc::Type) {
PartArc* arc = qgraphicsitem_cast<PartArc*>(item);
arc->mirror(m_axis_x);
} else if (item->type() == PartEllipse::Type) {
PartEllipse* ellipse = qgraphicsitem_cast<PartEllipse*>(item);
ellipse->mirror(m_axis_x);
} else if (item->type() == PartLine::Type) {
PartLine* line = qgraphicsitem_cast<PartLine*>(item);
line->mirror(m_axis_x);
} else if (item->type() == PartPolygon::Type) {
PartPolygon* poly = qgraphicsitem_cast<PartPolygon*>(item);
poly->mirror(m_axis_x);
} else if (item->type() == PartRectangle::Type) {
PartRectangle* rect = qgraphicsitem_cast<PartRectangle*>(item);
rect->mirror(m_axis_x);
} else if (item->type() == PartTerminal::Type) {
PartTerminal* term = qgraphicsitem_cast<PartTerminal*>(item);
term->mirror(m_axis_x);
}
}
}
/**
@brief MirrorElementsCommand::undo
*/
void MirrorElementsCommand::undo()
{
redo();
}
FlipElementsCommand::FlipElementsCommand(ElementScene *scene, QUndoCommand *parent) :
ElementEditionCommand(QObject::tr("Retourner la sélection", "undo caption"), scene, nullptr, parent)
{
m_items = scene->selectedItems();
m_axis_y = selectionCenter(m_items).y();
}
/**
@brief FlipElementsCommand::redo
*/
void FlipElementsCommand::redo()
{
foreach (auto *item, m_items) {
if (item->type() == PartText::Type) {
PartText* staticText = qgraphicsitem_cast<PartText*>(item);
staticText->flip(m_axis_y);
} else if (item->type() == PartDynamicTextField::Type) {
PartDynamicTextField* dyntext = qgraphicsitem_cast<PartDynamicTextField*>(item);
dyntext->flip(m_axis_y);
} else if (item->type() == PartArc::Type) {
PartArc* arc = qgraphicsitem_cast<PartArc*>(item);
arc->flip(m_axis_y);
} else if (item->type() == PartEllipse::Type) {
PartEllipse* ellipse = qgraphicsitem_cast<PartEllipse*>(item);
ellipse->flip(m_axis_y);
} else if (item->type() == PartLine::Type) {
PartLine* line = qgraphicsitem_cast<PartLine*>(item);
line->flip(m_axis_y);
} else if (item->type() == PartPolygon::Type) {
PartPolygon* poly = qgraphicsitem_cast<PartPolygon*>(item);
poly->flip(m_axis_y);
} else if (item->type() == PartRectangle::Type) {
PartRectangle* rect = qgraphicsitem_cast<PartRectangle*>(item);
rect->flip(m_axis_y);
} else if (item->type() == PartTerminal::Type) {
PartTerminal* term = qgraphicsitem_cast<PartTerminal*>(item);
term->flip(m_axis_y);
}
}
}
/**
@brief FlipElementsCommand::undo
*/
void FlipElementsCommand::undo()
{
redo();
}