mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-07 04:04:14 +02:00
Keep the text resize handles working after a scene change
A scene drops the event filters of an item that leaves it. The handles installed theirs once, in the constructor, and only if the text was in a scene: after the text was removed and added back (undoing a delete does that), or when the handles were made before the text was in a scene, they no longer reacted, and a drag moved the text instead. TextResizeHandles now installs the filters again whenever it enters a scene. Tests: dragAfterLeavingTheScene, dragWhenCreatedOutsideAScene (both fail before). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,11 +26,12 @@
|
||||
#include <QTextDocument>
|
||||
|
||||
#include <cmath>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
@brief TextResizeHandles::TextResizeHandles
|
||||
@param text : the text to resize, becomes the parent of the handles.
|
||||
It must be in a scene, the handles filter their own events.
|
||||
The text may be in a scene or not yet.
|
||||
@param handle_size : see QETUtils::graphicsHandlerSize()
|
||||
*/
|
||||
TextResizeHandles::TextResizeHandles(QGraphicsTextItem *text, qreal handle_size) :
|
||||
@@ -48,10 +49,9 @@ TextResizeHandles::TextResizeHandles(QGraphicsTextItem *text, qreal handle_size)
|
||||
"double-cliquer pour une largeur automatique"));
|
||||
handle->setCursor(i == TextResize::TopLeft || i == TextResize::BottomRight
|
||||
? Qt::SizeFDiagCursor : Qt::SizeBDiagCursor);
|
||||
if (scene())
|
||||
handle->installSceneEventFilter(this);
|
||||
m_handles << handle;
|
||||
}
|
||||
installHandleFilters();
|
||||
|
||||
m_size_connection = connect(text->document()->documentLayout(),
|
||||
&QAbstractTextDocumentLayout::documentSizeChanged,
|
||||
@@ -90,6 +90,34 @@ void TextResizeHandles::updateHandlesPos()
|
||||
m_handles.at(i)->setPos(TextResize::cornerOf(rect, TextResize::Corner(i)));
|
||||
}
|
||||
|
||||
/**
|
||||
@brief TextResizeHandles::itemChange
|
||||
A scene drops the event filters of an item that leaves it, so the
|
||||
handles stop reacting to the mouse when the text is removed from its
|
||||
scene and added back (undoing a delete does that), or when they were
|
||||
created before the text was in a scene. Install them again each time
|
||||
these handles enter a scene.
|
||||
*/
|
||||
QVariant TextResizeHandles::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
{
|
||||
if (change == QGraphicsItem::ItemSceneHasChanged)
|
||||
installHandleFilters();
|
||||
return QGraphicsObject::itemChange(change, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief TextResizeHandles::installHandleFilters
|
||||
Filter the mouse events of the handles, when they are in a scene.
|
||||
*/
|
||||
void TextResizeHandles::installHandleFilters()
|
||||
{
|
||||
if (!scene())
|
||||
return;
|
||||
for (QetGraphicsHandlerItem *handle : std::as_const(m_handles))
|
||||
if (handle->scene() == scene())
|
||||
handle->installSceneEventFilter(this);
|
||||
}
|
||||
|
||||
bool TextResizeHandles::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
|
||||
{
|
||||
const int index = m_handles.indexOf(static_cast<QetGraphicsHandlerItem *>(watched));
|
||||
|
||||
@@ -65,8 +65,10 @@ class TextResizeHandles : public QGraphicsObject
|
||||
|
||||
protected:
|
||||
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) override;
|
||||
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
|
||||
|
||||
private:
|
||||
void installHandleFilters();
|
||||
void pressed(TextResize::Corner corner, const QPointF &scene_pos);
|
||||
void moved(const QPointF &scene_pos);
|
||||
void released();
|
||||
|
||||
@@ -215,6 +215,38 @@ private slots:
|
||||
}
|
||||
}
|
||||
|
||||
// The handles still work after the text left its scene and came back,
|
||||
// as undoing a delete does: Qt drops scene event filters on removal.
|
||||
void dragAfterLeavingTheScene()
|
||||
{
|
||||
QGraphicsScene scene;
|
||||
auto *text = new WidthText(QStringLiteral("Motor protection switch Q12"));
|
||||
scene.addItem(text);
|
||||
auto *handles = new TextResizeHandles(text);
|
||||
|
||||
scene.removeItem(text);
|
||||
scene.addItem(text);
|
||||
|
||||
const QPointF start_pos = text->pos();
|
||||
drag(scene, *handles, *text, TextResize::BottomRight, QPointF(-40, 0));
|
||||
QVERIFY(text->textWidth() > 0);
|
||||
QCOMPARE(text->pos(), start_pos);
|
||||
delete text;
|
||||
}
|
||||
|
||||
// The handles also work when they are created before the text is in a
|
||||
// scene.
|
||||
void dragWhenCreatedOutsideAScene()
|
||||
{
|
||||
QGraphicsScene scene;
|
||||
auto *text = new WidthText(QStringLiteral("Motor protection switch Q12"));
|
||||
auto *handles = new TextResizeHandles(text);
|
||||
scene.addItem(text);
|
||||
|
||||
drag(scene, *handles, *text, TextResize::BottomRight, QPointF(-40, 0));
|
||||
QVERIFY(text->textWidth() > 0);
|
||||
}
|
||||
|
||||
// A text is never made narrower than its longest word.
|
||||
void dragStopsAtTheLongestWord()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user