Merge pull request #1342 from bhangart/feature/free-text-resize-handles

Resize free texts by dragging a corner
This commit is contained in:
Laurent Trinques
2026-10-07 06:36:06 +02:00
committed by GitHub
4 changed files with 109 additions and 0 deletions
@@ -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));
}
/**
+12
View File
@@ -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
@@ -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);
@@ -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: