mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-15 01:54:14 +02:00
Make the 3D mouse pan and zoom the element editor too
The 3D mouse only acted on the diagram editor: SpaceMouseListener ignored every other window, so the element editor did not move at all (reported by scorpio810 in PR #635 with a SpacePilot Pro). applyMotion() now also handles a QETElementEditor, driving its ElementView through the same scrollbar pan and a new ElementView::zoom(factor), which keeps the wheel zoom's clamping. The element editor's scene rect only covers what is on screen, so it is grown before each pan sample, as its middle-button pan does; without that the scrollbars have no range and the pan does nothing. Verified under Xvfb with an LD_PRELOAD stand-in for libspnav feeding recorded motion samples: element editor zooms 1.63x for ten z=50 samples and pans; diagram editor screenshots are byte-identical to master's for the same input. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -117,6 +117,18 @@ void ElementView::scaleClamped(qreal factor)
|
||||
scale(factor, factor);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief ElementView::zoom
|
||||
Zoom by an arbitrary factor, for a continuous input such as a 3D mouse.
|
||||
Same clamping as the wheel zoom.
|
||||
@param zoom_factor : > 1 zooms in, < 1 zooms out
|
||||
*/
|
||||
void ElementView::zoom(qreal zoom_factor)
|
||||
{
|
||||
adjustSceneRect();
|
||||
scaleClamped(zoom_factor);
|
||||
}
|
||||
|
||||
/**
|
||||
Agrandit le schema (+33% = inverse des -25 % de zoomMoins())
|
||||
*/
|
||||
|
||||
@@ -41,6 +41,7 @@ class ElementView : public QGraphicsView {
|
||||
ElementScene *scene() const;
|
||||
void setScene(ElementScene *);
|
||||
QRectF viewedSceneRect() const;
|
||||
void zoom(qreal zoom_factor);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *) override;
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#endif
|
||||
|
||||
#include "../diagramview.h"
|
||||
#include "../editor/elementview.h"
|
||||
#include "../editor/ui/qetelementeditor.h"
|
||||
#include "../projectview.h"
|
||||
#include "../qetdiagrameditor.h"
|
||||
#include "../shortcutmanager.h"
|
||||
@@ -47,6 +49,16 @@ namespace {
|
||||
//one-line fix once someone with a device tries it.
|
||||
constexpr qreal ZOOM_DIVISOR = 1000.0;
|
||||
constexpr qreal PAN_SCALE = 1.0;
|
||||
|
||||
//Pan a view by one motion sample, through its scrollbars -- the same
|
||||
//way both editors' own middle-button drag pans them.
|
||||
void panView(QGraphicsView *view, int dx, int dy)
|
||||
{
|
||||
view->horizontalScrollBar()->setValue(
|
||||
view->horizontalScrollBar()->value() - qRound(dx * PAN_SCALE));
|
||||
view->verticalScrollBar()->setValue(
|
||||
view->verticalScrollBar()->value() - qRound(dy * PAN_SCALE));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,11 +108,12 @@ qreal SpaceMouseListener::zoomFactorForZAxis(int z)
|
||||
|
||||
/**
|
||||
@brief SpaceMouseListener::applyMotion
|
||||
Apply one motion sample to whichever DiagramView is currently active.
|
||||
Apply one motion sample to the view of the active window: the current
|
||||
folio of a diagram editor, or the drawing of an element editor.
|
||||
X/Y translation pans it, Z translation zooms it -- the same two
|
||||
primitives (scrollbars, DiagramView::zoom()) DiagramView::wheelEvent()
|
||||
already drives from a physical wheel, so there is no new navigation
|
||||
logic here, only a new input source feeding the existing one.
|
||||
primitives (scrollbars, zoom()) each view's wheelEvent() already drives
|
||||
from a physical wheel, so there is no new navigation logic here, only a
|
||||
new input source feeding the existing one.
|
||||
|
||||
Which of a device's three translation axes is "left/right" vs
|
||||
"forward/back" vs "up/down", and their sign, is a hardware convention
|
||||
@@ -112,31 +125,46 @@ qreal SpaceMouseListener::zoomFactorForZAxis(int z)
|
||||
*/
|
||||
void SpaceMouseListener::applyMotion(int dx, int dy, int dz)
|
||||
{
|
||||
auto *editor = qobject_cast<QETDiagramEditor *>(qApp->activeWindow());
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
QWidget *window = qApp->activeWindow();
|
||||
|
||||
ProjectView *project_view = editor->currentProjectView();
|
||||
if (!project_view) {
|
||||
return;
|
||||
}
|
||||
|
||||
DiagramView *view = project_view->currentDiagram();
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dx || dy)
|
||||
if (auto *editor = qobject_cast<QETDiagramEditor *>(window))
|
||||
{
|
||||
view->horizontalScrollBar()->setValue(
|
||||
view->horizontalScrollBar()->value() - qRound(dx * PAN_SCALE));
|
||||
view->verticalScrollBar()->setValue(
|
||||
view->verticalScrollBar()->value() - qRound(dy * PAN_SCALE));
|
||||
}
|
||||
ProjectView *project_view = editor->currentProjectView();
|
||||
if (!project_view) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dz) {
|
||||
view->zoom(zoomFactorForZAxis(dz));
|
||||
DiagramView *view = project_view->currentDiagram();
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dx || dy) {
|
||||
panView(view, dx, dy);
|
||||
}
|
||||
if (dz) {
|
||||
view->zoom(zoomFactorForZAxis(dz));
|
||||
}
|
||||
}
|
||||
else if (auto *element_editor = qobject_cast<QETElementEditor *>(window))
|
||||
{
|
||||
ElementView *view = element_editor->elementView();
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dx || dy)
|
||||
{
|
||||
//The element editor's scene rect only just covers what is
|
||||
//on screen, so grow it before each sample, as its own
|
||||
//middle-button pan does on release -- otherwise the
|
||||
//scrollbars have no range and the pan does nothing.
|
||||
view->adjustSceneRect();
|
||||
panView(view, dx, dy);
|
||||
}
|
||||
if (dz) {
|
||||
view->zoom(zoomFactorForZAxis(dz));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,16 +25,16 @@ class SpaceMouseBackend;
|
||||
/**
|
||||
@brief The SpaceMouseListener class
|
||||
https://github.com/qelectrotech/qelectrotech-source-mirror/discussions/599 :
|
||||
bridges a 3Dconnexion SpaceMouse/SpacePilot 6-DOF device to
|
||||
DiagramView's existing pan/zoom primitives (the same
|
||||
horizontalScrollBar()/verticalScrollBar()/zoom() calls
|
||||
DiagramView::wheelEvent() already uses for a physical wheel), and its
|
||||
bridges a 3Dconnexion SpaceMouse/SpacePilot 6-DOF device to the
|
||||
existing pan/zoom primitives of DiagramView and ElementView (the same
|
||||
horizontalScrollBar()/verticalScrollBar()/zoom() calls their
|
||||
wheelEvent() already uses for a physical wheel), and its
|
||||
buttons to named QET actions via ShortcutManager -- the same registry
|
||||
keyboard shortcuts already use, so a device button can trigger anything
|
||||
in that registry (undo, redo, rotate selection, ...) without QET having
|
||||
a second, device-specific action list.
|
||||
|
||||
Everything here is platform-independent: which DiagramView to apply
|
||||
Everything here is platform-independent: which view to apply
|
||||
motion to, the pan/zoom calls, the Z-to-zoom-factor mapping, and button
|
||||
dispatch via SpaceMouseButtonMap + ShortcutManager. Talking to the
|
||||
actual device driver is a SpaceMouseBackend's job (see its class
|
||||
@@ -73,7 +73,7 @@ class SpaceMouseListener : public QObject
|
||||
|
||||
private slots:
|
||||
/// Apply one motion sample -- from whichever backend is in use
|
||||
/// -- to whichever DiagramView is currently active.
|
||||
/// -- to the view of the active diagram or element editor.
|
||||
void applyMotion(int dx, int dy, int dz);
|
||||
|
||||
/// Look up which action id, if any, SpaceMouseButtonMap binds
|
||||
|
||||
Reference in New Issue
Block a user