diff --git a/sources/qetgraphicsitem/diagramtextitem.cpp b/sources/qetgraphicsitem/diagramtextitem.cpp index cc44c6b0c..08fdfafb8 100644 --- a/sources/qetgraphicsitem/diagramtextitem.cpp +++ b/sources/qetgraphicsitem/diagramtextitem.cpp @@ -22,6 +22,8 @@ #include "../qetapp.h" #include "../richtext/richtexteditor_p.h" #include "../textanchor.h" +#include "../utils/qetutils.h" +#include "../QetGraphicsItemModeler/textresizehandles.h" /** @brief DiagramTextItem::DiagramTextItem @@ -335,6 +337,7 @@ void DiagramTextItem::focusInEvent(QFocusEvent *event) m_previous_html_text = toHtml(); m_previous_text = toPlainText(); + refreshTextResizeHandles(); } /** @@ -357,6 +360,89 @@ void DiagramTextItem::focusOutEvent(QFocusEvent *event) setFlag(QGraphicsItem::ItemIsMovable, true); setFlag(QGraphicsTextItem::ItemIsFocusable, false); + refreshTextResizeHandles(); +} + +/** + @brief DiagramTextItem::itemChange + Show or hide the resize handles with the selection and the scene. + @param change + @param value + @return +*/ +QVariant DiagramTextItem::itemChange(GraphicsItemChange change, const QVariant &value) +{ + //Also when the text comes back to a scene: Qt keeps it selected + //across removeItem()/addItem() (undoing a delete) and sends no + //selection change, and its handles were removed with the scene. + if (change == QGraphicsItem::ItemSelectedHasChanged + || change == QGraphicsItem::ItemSceneHasChanged) + refreshTextResizeHandles(); + + return QGraphicsTextItem::itemChange(change, value); +} + +/** + @brief DiagramTextItem::textResizeHandlesWanted + @return true when the corner handles to change the width of this text + should be shown. A text without a "textWidth" property never has them. +*/ +bool DiagramTextItem::textResizeHandlesWanted() const +{ + return false; +} + +/** + @brief DiagramTextItem::isEditing + @return true while the text itself is being typed in +*/ +bool DiagramTextItem::isEditing() const +{ + return textInteractionFlags() & Qt::TextEditable; +} + +/** + @brief DiagramTextItem::refreshTextResizeHandles + Create or remove the corner handles to change the width of this text, + according to textResizeHandlesWanted(). + Called from itemChange() and when the edition starts or ends, not from + paint(): moving items from paint() left fragments behind + (qelectrotech#1002). +*/ +void DiagramTextItem::refreshTextResizeHandles() +{ + const bool wanted = scene() && textResizeHandlesWanted(); + if (wanted && !m_resize_handles) + { + m_resize_handles = new TextResizeHandles(this, QETUtils::graphicsHandlerSize(this)); + connect(m_resize_handles, &TextResizeHandles::resizeFinished, + this, &DiagramTextItem::pushResizeCommand); + } + else if (!wanted && m_resize_handles) { + removeTextResizeHandles(); + } +} + +/** + @brief DiagramTextItem::removeTextResizeHandles +*/ +void DiagramTextItem::removeTextResizeHandles() +{ + delete m_resize_handles; + m_resize_handles = nullptr; +} + +/** + @brief DiagramTextItem::pushResizeCommand + Make the width change done with the resize handles undoable. The change + is already applied, live during the drag. +*/ +void DiagramTextItem::pushResizeCommand(qreal old_width, qreal new_width, + QPointF old_pos, QPointF new_pos) +{ + if (Diagram *diagram_ = diagram()) + diagram_->undoStack().push(new TextResizeCommand(this, old_width, new_width, + old_pos, new_pos)); } /** diff --git a/sources/qetgraphicsitem/diagramtextitem.h b/sources/qetgraphicsitem/diagramtextitem.h index 323c0db56..3a5d5ca4d 100644 --- a/sources/qetgraphicsitem/diagramtextitem.h +++ b/sources/qetgraphicsitem/diagramtextitem.h @@ -24,6 +24,7 @@ class Diagram; class QDomElement; class QDomDocument; +class TextResizeHandles; /** This class represents a selectable, movable and editable text field on a @@ -91,11 +92,15 @@ class DiagramTextItem : public QGraphicsTextItem bool isHtml() const; protected: + void refreshTextResizeHandles(); + TextResizeHandles *textResizeHandles() const {return m_resize_handles;} + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override; void focusInEvent(QFocusEvent *) override; void focusOutEvent(QFocusEvent *) override; + QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; void mouseDoubleClickEvent (QGraphicsSceneMouseEvent *event) override; void mousePressEvent (QGraphicsSceneMouseEvent *event) override; @@ -110,7 +115,10 @@ class DiagramTextItem : public QGraphicsTextItem void prepareAlignment(); void finishAlignment(); + virtual bool textResizeHandlesWanted() const; virtual bool hasUserTextWidth() const {return false;} + bool isEditing() const; + void removeTextResizeHandles(); protected: @@ -128,7 +136,11 @@ class DiagramTextItem : public QGraphicsTextItem QPointF m_mouse_to_origin_movement; private: + void pushResizeCommand(qreal old_width, qreal new_width, + QPointF old_pos, QPointF new_pos); + QRectF m_alignment_rect; + TextResizeHandles *m_resize_handles = nullptr; Qt::Alignment m_alignment = (Qt::AlignTop | Qt::AlignLeft); }; #endif diff --git a/sources/qetgraphicsitem/independenttextitem.cpp b/sources/qetgraphicsitem/independenttextitem.cpp index 8e5d03ef4..833b8dd48 100644 --- a/sources/qetgraphicsitem/independenttextitem.cpp +++ b/sources/qetgraphicsitem/independenttextitem.cpp @@ -148,6 +148,16 @@ void IndependentTextItem::setTextWidth(qreal width) emit textWidthChanged(width); } +/** + @brief IndependentTextItem::textResizeHandlesWanted + @return true when this text is selected and not being typed in: the + corner handles then change its width. +*/ +bool IndependentTextItem::textResizeHandlesWanted() const +{ + return isSelected() && !isEditing(); +} + void IndependentTextItem::focusOutEvent(QFocusEvent *event) { DiagramTextItem::focusOutEvent(event); diff --git a/sources/qetgraphicsitem/independenttextitem.h b/sources/qetgraphicsitem/independenttextitem.h index 571c9eeea..bc2083e6a 100644 --- a/sources/qetgraphicsitem/independenttextitem.h +++ b/sources/qetgraphicsitem/independenttextitem.h @@ -63,6 +63,7 @@ class IndependentTextItem : public DiagramTextItem protected: void focusOutEvent(QFocusEvent *event) override; + bool textResizeHandlesWanted() const override; bool hasUserTextWidth() const override {return m_text_width > 0;} private: