Files
qelectrotech-source-mirror/sources/qetgraphicsitem/dynamicelementtextitem.h
T
ispyisail fcc11bff74 Keep a right-aligned text where it was when lazy folios refill it
A report symbol's right-aligned text (the function of its partner's
wire) was saved at another x than with every folio built after deleting
a coil on its folio: moved left by its own width. Cosmetic, nothing lost.

setPlainText() keeps a right-aligned text's right edge, except while the
project is being opened (ProjectParsingRunning) or the symbol is built.
With lazy folios the text is emptied outside that state (the partner's
folio is not built, so no wire is watched) and the edge is kept, then
filled again while the late folios are built, which holds the project in
the opening state: the edge was not kept, and x stayed where emptying
moved it. With every folio built both happen during the opening.

A text emptied with its alignment kept is now filled again the same way,
whatever the project state; a text set while the project is opened and
never emptied that way is untouched, so what a plain opening writes does
not change.

Evidence: forum f1537 (resaved with every folio built), deleting coil
{794d8944} on folio 9 saved x=11.7969 lazily, x=60 eagerly; both 60
now. Resave of the 342 corpus projects, lazy and eager, identical to
before. tst_reporttextlatefolio fails without the fix (x=28.6875 lazily).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 12:57:17 +13:00

215 lines
7.9 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/>.
*/
#ifndef DYNAMICELEMENTTEXTITEM_H
#define DYNAMICELEMENTTEXTITEM_H
#include "../properties/xrefproperties.h"
#include "diagramtextitem.h"
#include "element.h"
#include <QPointer>
#include <QUuid>
class Element;
class Conductor;
class ElementTextItemGroup;
class CrossRefItem;
class QetGraphicsHandlerItem;
/**
@brief The DynamicElementTextItem class
This class provide a simple text field of element who can be added or removed directly from the diagram editor.
This text is created to compensate a big lack of the ElementTextItem : ElementTextItem can't be added or removed directly in the diagram editor
*/
class DynamicElementTextItem : public DiagramTextItem
{
friend class DynamicTextItemDelegate;
friend class CompositeTextEditDialog;
friend class Element;
Q_OBJECT
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
Q_PROPERTY(TextFrom textFrom READ textFrom WRITE setTextFrom NOTIFY textFromChanged)
Q_PROPERTY(QString infoName READ infoName WRITE setInfoName NOTIFY infoNameChanged)
Q_PROPERTY(QString compositeText READ compositeText WRITE setCompositeText NOTIFY compositeTextChanged)
Q_PROPERTY(bool frame READ frame WRITE setFrame NOTIFY frameChanged)
Q_PROPERTY(qreal textWidth READ textWidth WRITE setTextWidth NOTIFY textWidthChanged)
Q_PROPERTY(bool keepVisualRotation READ keepVisualRotation WRITE setKeepVisualRotation NOTIFY keepVisualRotationChanged)
Q_PROPERTY(bool rotationPointCenter READ rotationPointCenter WRITE setRotationPointCenter NOTIFY rotationPointCenterChanged)
public:
enum TextFrom {
UserText,
ElementInfo,
CompositeText
};
Q_ENUM (TextFrom)
enum {Type = UserType + 1010};
int type() const override {return Type;}
signals:
void textChanged(QString text);
void textFromChanged(DynamicElementTextItem::TextFrom text_from);
void infoNameChanged(QString info);
void compositeTextChanged(QString text);
void frameChanged(bool frame);
void plainTextChanged();
void textWidthChanged(qreal width);
void keepVisualRotationChanged(bool keep);
void rotationPointCenterChanged(bool center);
public:
DynamicElementTextItem(Element *parent_element);
~DynamicElementTextItem() override;
static QMetaEnum textFromMetaEnum();
private:
DynamicElementTextItem ();
DynamicElementTextItem(const DynamicElementTextItem &);
public:
QDomElement toXml(QDomDocument &dom_doc) const override;
void fromXml(const QDomElement &dom_elmt) override;
Element *parentElement() const;
/// PDF export: slave cross-reference text item ("(folio-pos)") and its master target.
QGraphicsTextItem *slaveXrefItem() const { return m_slave_Xref_item; }
/// DXF export: the master-side cross-reference item (the table/cross
/// drawn next to a report/master element), if this text item has one.
CrossRefItem *masterXrefItem() const { return m_Xref_item; }
Element *masterElement() const;
ElementTextItemGroup *parentGroup() const;
Element *elementUseForInfo() const;
void refreshLabelConnection();
DynamicElementTextItem::TextFrom textFrom() const;
void setTextFrom (DynamicElementTextItem::TextFrom text_from);
QString text() const;
void setText(const QString &text);
static QString xmlTagName() {return QString("dynamic_elmt_text");}
void setInfoName(const QString &info_name);
QString infoName() const;
void setCompositeText(const QString &text);
QString compositeText() const;
void setFrame(const bool frame);
bool frame() const;
QUuid uuid() const;
void updateXref();
void setPlainText(const QString &text);
//Hide QGraphicsTextItem::textWidth(): with the width on "auto"
//the document is given the text's own width so its lines can be
//centred or right-aligned, but the width is still "auto" (-1).
qreal textWidth() const {return m_text_width;}
void setTextWidth(qreal width);
void setXref_item(Qt::AlignmentFlag m_exHrefPos, int slave_offset = 0);
void setKeepVisualRotation(bool set);
bool keepVisualRotation() const;
void setRotationPointCenter(bool set);
bool rotationPointCenter() const;
//Called by Element::itemChange() when the PARENT's selection
//changes, so the parent can keep each of its texts' resize
//handles in sync with its own selection state. Public for that;
//see the .cpp for why it exists.
void refreshResizeHandlesVisibility();
protected:
void keyPressEvent(QKeyEvent *event) override;
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) override;
private:
void elementInfoChanged();
void masterChanged();
void reportChanged();
void reportFormulaChanged();
void setConnectionForReportFormula(const QString &formula);
void removeConnectionForReportFormula(const QString &formula);
void setupFormulaConnection();
void clearFormulaConnection();
void updateReportFormulaConnection();
void updateReportText();
void updateLabel();
void conductorWasAdded(Conductor *conductor);
void conductorWasRemoved(Conductor *conductor);
void setPotentialConductor();
void conductorPropertiesChanged();
QString reportReplacedCompositeText() const;
void zoomToLinkedElement();
void parentElementRotationChanged();
void thisRotationChanged();
void addResizeHandles();
void removeResizeHandles();
void updateResizeHandlesPos();
void fitAutoTextWidth();
void handlerMousePressEvent(QetGraphicsHandlerItem *handle, QGraphicsSceneMouseEvent *event);
void handlerMouseMoveEvent(QetGraphicsHandlerItem *handle, QGraphicsSceneMouseEvent *event);
void handlerMouseReleaseEvent(QetGraphicsHandlerItem *handle, QGraphicsSceneMouseEvent *event);
private:
QPointer <Element>
m_parent_element,
m_master_element,
m_other_report;
QPointer <Conductor> m_watched_conductor;
QString
m_text,
m_info_name,
m_composite_text,
m_report_formula,
m_F_str;
DynamicElementTextItem::TextFrom m_text_from = UserText;
QUuid m_uuid;
QMetaObject::Connection m_report_formula_con;
QList<QMetaObject::Connection>
m_formula_connection,
m_update_slave_Xref_connection;
QColor m_user_color;
bool
m_frame = false,
m_first_scene_change = true;
CrossRefItem *m_Xref_item = nullptr;
QGraphicsTextItem *m_slave_Xref_item = nullptr;
qreal m_text_width = -1;
/// The text was emptied with its alignment kept (setPlainText())
bool m_emptied_aligned = false;
QPointF m_initial_position;
bool m_keep_visual_rotation = true;
bool m_rotation_point_center = false;
qreal m_visual_rotation_ref = 0;
bool m_move_parent = true;
QetGraphicsHandlerItem *m_left_resize_handle = nullptr;
QetGraphicsHandlerItem *m_right_resize_handle = nullptr;
qreal m_resize_original_width = -1;
qreal m_resize_baseline_width = -1;
qreal m_resize_start_local_x = 0;
QMetaObject::Connection m_resize_handles_con;
};
#endif // DYNAMICELEMENTTEXTITEM_H