Files
qelectrotech-source-mirror/sources/undocommand/rotatetextscommand.cpp
T
ispyisail 6c76b1f6a8 Fix bugtracker #312: wire text rotation not preserved on reload
RotateTextsCommand::undo()/redo() called cti->forceMovedByUser(...)
instead of cti->forceRotateByUser(...) for ConductorTextItem entries
- a copy-paste mix-up between the two parallel user-override flags
that track independently whether a conductor's text was manually
moved vs manually rotated.

Because rotate_by_user_ was never actually set to true, the rotation
attribute-writing gate in Conductor::toXml() (which checks
wasRotatedByUser()) never fired, so a manual rotation applied via
"Orienter les textes" (Edit > Orienter les textes / Ctrl+Space) was
silently dropped on save: the rotation displayed correctly until the
project was closed and reopened, at which point it reverted to
default orientation.

Fix swaps both calls to forceRotateByUser(...), matching what the
constructor reads via wasRotatedByUser() when building m_cond_texts.

Verified: clean rebuild (506/506, no new warnings). Live-verified
under Xvfb that RotateTextsCommand's rotation correctly animates and
applies to ConductorTextItem text (confirmed via the "Orienter les
textes" dialog). A full save/close/reopen round-trip on a from-scratch
two-element wire was attempted but not completed due to unreliable
terminal-to-terminal wire drawing via synthetic mouse events in the
window-manager-less Xvfb sandbox; confidence in the fix instead rests
on tracing the exact save-gate code path (Conductor::toXml() gates
solely on wasRotatedByUser(), which the constructor/undo/redo all
already correctly reference elsewhere for the parallel
moved-by-user flag).
2026-08-10 22:37:23 +12:00

150 lines
4.4 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 "rotatetextscommand.h"
#include "../diagram.h"
#include "../diagramcontent.h"
#include "../qetapp.h"
#include "../qetgraphicsitem/conductortextitem.h"
#include "../qetgraphicsitem/diagramtextitem.h"
#include "../qetgraphicsitem/elementtextitemgroup.h"
#include "../qtextorientationspinboxwidget.h"
/**
@brief RotateTextsCommand::RotateTextsCommand
@param diagram : Apply the rotation to the selected texts and group of texts
of diagram at construction time.
@param parent : undo parent
*/
RotateTextsCommand::RotateTextsCommand(Diagram *diagram, QUndoCommand *parent) :
QUndoCommand(parent),
m_diagram(diagram)
{
DiagramContent dc(m_diagram);
QList <DiagramTextItem *> texts_list;
QList <ElementTextItemGroup *> groups_list;
for(DiagramTextItem *dti : dc.selectedTexts())
{
texts_list << dti;
if(dti->type() == ConductorTextItem::Type)
{
ConductorTextItem *cti = static_cast<ConductorTextItem *>(dti);
m_cond_texts.insert(cti, cti->wasRotatedByUser());
}
}
for(ElementTextItemGroup *etig : dc.selectedTextsGroup())
groups_list << etig;
if(texts_list.count() || groups_list.count())
{
openDialog();
QString text;
if(texts_list.count())
text.append(QObject::tr("Pivoter %1 textes").arg(texts_list.count()));
if(groups_list.count())
{
if(text.isEmpty())
text.append(QObject::tr("Pivoter"));
else
text.append(QObject::tr(" et"));
text.append(QObject::tr(" %1 groupes de textes").arg(groups_list.count()));
}
if(!text.isNull())
setText(text);
for(DiagramTextItem *dti : texts_list)
setupAnimation(dti, "rotation", dti->rotation(), m_rotation);
for(ElementTextItemGroup *grp : groups_list)
setupAnimation(grp, "rotation", grp->rotation(), m_rotation);
}
else
setObsolete(true);
}
void RotateTextsCommand::undo()
{
if(m_diagram)
m_diagram.data()->showMe();
m_anim_group->setDirection(QAnimationGroup::Backward);
m_anim_group->start();
for(ConductorTextItem *cti : m_cond_texts.keys())
cti->forceRotateByUser(m_cond_texts.value(cti));
}
void RotateTextsCommand::redo()
{
if(m_diagram)
m_diagram.data()->showMe();
m_anim_group->setDirection(QAnimationGroup::Forward);
m_anim_group->start();
for(ConductorTextItem *cti : m_cond_texts.keys())
cti->forceRotateByUser(true);
}
void RotateTextsCommand::openDialog()
{
//Open the dialog
QDialog ori_text_dialog;
ori_text_dialog.setSizeGripEnabled(false);
#ifdef Q_OS_MACOS
ori_text_dialog.setWindowFlags(Qt::Sheet);
#endif
ori_text_dialog.setWindowTitle(QObject::tr("Orienter les textes sélectionnés", "window title"));
QTextOrientationSpinBoxWidget *ori_widget = QETApp::createTextOrientationSpinBoxWidget();
ori_widget->setParent(&ori_text_dialog);
ori_widget->spinBox()->selectAll();
QDialogButtonBox buttons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
QObject::connect(&buttons, &QDialogButtonBox::accepted, &ori_text_dialog, &QDialog::accept);
QObject::connect(&buttons, &QDialogButtonBox::rejected, &ori_text_dialog, &QDialog::reject);
QVBoxLayout layout_v(&ori_text_dialog);
layout_v.setSizeConstraint(QLayout::SetFixedSize);
layout_v.addWidget(ori_widget);
layout_v.addStretch();
layout_v.addWidget(&buttons);
if (ori_text_dialog.exec() == QDialog::Accepted)
m_rotation = ori_widget->orientation();
else
setObsolete(true);
}
void RotateTextsCommand::setupAnimation(QObject *target, const QByteArray &propertyName, const QVariant& start, const QVariant& end)
{
if(m_anim_group == nullptr)
m_anim_group = new QParallelAnimationGroup();
QPropertyAnimation *animation = new QPropertyAnimation(target, propertyName);
animation->setDuration(300);
animation->setStartValue(start);
animation->setEndValue(end);
animation->setEasingCurve(QEasingCurve::OutQuad);
m_anim_group->addAnimation(animation);
}