Merge pull request #1414 from bhangart/fix/image-handle-escape

Cancel a picture's handle drag with Escape
This commit is contained in:
ispyisail
2026-10-09 22:39:22 +13:00
committed by GitHub
4 changed files with 92 additions and 2 deletions
+6
View File
@@ -118,6 +118,7 @@ class Diagram : public QGraphicsScene
ElementTextsMover m_element_texts_mover;
QGIManager *qgi_manager_;
QETProject *m_project;
QPointer<QGraphicsObject> m_keyboard_item;
QDomDocument xml_document_;
@@ -274,6 +275,11 @@ class Diagram : public QGraphicsScene
QUndoStack &undoStack();
QGIManager &qgiManager();
/// The item that gets keys before the view's own shortcuts, while
/// it is in a state Escape must end (a picture whose handle is
/// dragged). nullptr the rest of the time.
void setKeyboardItem(QGraphicsObject *item) { m_keyboard_item = item; }
QGraphicsObject *keyboardItem() const { return m_keyboard_item; }
//methods related to element label Update Policy
void freezeElements(bool freeze);
+11
View File
@@ -1155,6 +1155,17 @@ void DiagramView::keyPressEvent(QKeyEvent *e)
if (m_event_interface && m_event_interface->keyPressEvent(e))
return;
//An item in a state Escape must end -- a picture while one of its
//handles is dragged -- sees each key before the shortcuts below,
//which would otherwise clear the selection under it.
QGraphicsObject *keyboard_item = m_diagram ? m_diagram->keyboardItem() : nullptr;
if (keyboard_item && keyboard_item->scene() == m_diagram) {
e->ignore();
m_diagram->sendEvent(keyboard_item, e);
if (e->isAccepted())
return;
}
ProjectView *current_project = this->diagramEditor()->currentProjectView();
DiagramContent dc(m_diagram);
switch(e -> key())
+71 -2
View File
@@ -33,6 +33,7 @@
#include "../utils/qetutils.h"
#include "../QetGraphicsItemModeler/qetgraphicshandleritem.h"
#include <QKeyEvent>
#include <QAction>
#include <QBuffer>
#include <QFileDialog>
@@ -599,6 +600,10 @@ void DiagramImageItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
*/
void DiagramImageItem::clearHandles()
{
// The handles go (deselected, or another handle mode): a drag of one
// of them cannot end with its release any more.
if (m_vector_index != -1)
endHandleDrag();
if (!m_handler_vector.isEmpty())
{
qDeleteAll(m_handler_vector);
@@ -726,17 +731,22 @@ bool DiagramImageItem::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
if (event->type() == QEvent::GraphicsSceneMousePress)
{
m_drag_cancelled = false;
handlerMousePressEvent(index, static_cast<QGraphicsSceneMouseEvent *>(event)->modifiers());
return true;
}
if (event->type() == QEvent::GraphicsSceneMouseMove)
{
handlerMouseMoveEvent(index, static_cast<QGraphicsSceneMouseEvent *>(event));
if (!m_drag_cancelled)
handlerMouseMoveEvent(index, static_cast<QGraphicsSceneMouseEvent *>(event));
return true;
}
if (event->type() == QEvent::GraphicsSceneMouseRelease)
{
handlerMouseReleaseEvent(index);
if (m_drag_cancelled)
m_drag_cancelled = false;
else
handlerMouseReleaseEvent(index);
return true;
}
if (event->type() == QEvent::GraphicsSceneHoverEnter)
@@ -806,6 +816,12 @@ void DiagramImageItem::handlerMousePressEvent(int index, Qt::KeyboardModifiers m
m_original_pos = pos();
m_original_transform = m_transform;
m_original_pivotIsCustom = m_pivotIsCustom;
// The handle has the mouse, not the keyboard: ask the view for the
// keys for the length of the drag, so that Escape reaches
// keyPressEvent() and not the view's own Escape, which clears the
// selection.
if (diagram())
diagram()->setKeyboardItem(this);
if (m_handleRoles.at(index) == HandleRole::Resize)
{
@@ -959,7 +975,60 @@ void DiagramImageItem::handlerMouseReleaseEvent(int index)
}
}
endHandleDrag();
}
/**
@brief DiagramImageItem::keyPressEvent
The view sends keys here only while one of the picture's handles is
dragged (see handlerMousePressEvent()): Escape cancels that drag. Any
other key is left to the view.
*/
void DiagramImageItem::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Escape && m_vector_index != -1)
{
cancelHandleDrag();
event->accept();
return;
}
QetGraphicsItem::keyPressEvent(event);
}
/**
@brief DiagramImageItem::endHandleDrag
The drag is over: no handle is dragged any more, and the keyboard
goes back to the view.
*/
void DiagramImageItem::endHandleDrag()
{
m_vector_index = -1;
if (diagram() && diagram()->keyboardItem() == this)
diagram()->setKeyboardItem(nullptr);
}
/**
@brief DiagramImageItem::cancelHandleDrag
Put the picture back exactly as it was when the handle was pressed --
transform, pivot (Resize moves it for the drag) and position -- and
ignore the rest of the mouse gesture, so its release pushes no undo
command.
*/
void DiagramImageItem::cancelHandleDrag()
{
prepareGeometryChange();
m_deferHandleReposition = true;
m_transform = m_original_transform;
m_pivotIsCustom = m_original_pivotIsCustom; // a pivot drag marks it as hand-placed
// Not the snapping setPos(): see handlerMousePressEvent().
QGraphicsObject::setPos(m_original_pos);
setTransform(m_transform.toMatrix());
m_deferHandleReposition = false;
emit transformChanged();
repositionHandles();
endHandleDrag();
m_drag_cancelled = true;
clearStatusHint();
}
/**
@@ -174,6 +174,7 @@ class DiagramImageItem : public QetGraphicsItem {
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
private:
@@ -203,6 +204,8 @@ class DiagramImageItem : public QetGraphicsItem {
void handlerMousePressEvent(int index, Qt::KeyboardModifiers mods);
void handlerMouseMoveEvent(int index, QGraphicsSceneMouseEvent *event);
void handlerMouseReleaseEvent(int index);
void cancelHandleDrag();
void endHandleDrag();
void dragResize(int index, const QPointF &localPos, Qt::KeyboardModifiers mods);
void dragRotateHandle(int cornerIndex, const QPointF &scenePos, Qt::KeyboardModifiers mods);
void dragSkewHandle(int edgeIndex, const QPointF &scenePos, Qt::KeyboardModifiers mods);
@@ -264,6 +267,7 @@ class DiagramImageItem : public QetGraphicsItem {
QVector<HandleRole> m_handleRoles;
int m_vector_index = -1;
QPointF m_original_pos; // scene position at the start of a resize/rotate/pivot drag, for Escape-to-cancel
bool m_drag_cancelled = false; // Escape pressed: ignore the rest of this mouse gesture
ShapeTransform m_original_transform;
bool m_original_pivotIsCustom = false;
bool m_deferHandleReposition = false; // see setPivot()'s comment