mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-09 13:34:14 +02:00
Cancel a picture's handle drag with Escape
Pressing Escape while a handle of a picture was dragged went to DiagramView, which clears the selection. That removed the handles under the mouse, so the drag stopped where it was: the picture kept the new size, angle or pivot, and since the release never arrived, no undo step was recorded and the change could not be undone. Diagram gets a keyboardItem: an item in a state Escape must end. While a resize, rotate, skew or pivot handle is dragged, the picture is that item; DiagramView sends each key to it first, and only keys it does not take reach the view's own shortcuts. Escape puts the picture back as it was when the handle was pressed (position, transform, and whether the pivot was placed by hand) and ignores the rest of the gesture, so no undo step is recorded. The drag also ends when the handles go away. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user