Commit Graph

9 Commits

Author SHA1 Message Date
ispyisail aaeaff55cc Add a hidapi 3D mouse backend that needs no 3Dconnexion driver
The 3D mouse only worked on Linux, through spacenavd. This adds a second
backend that reads the device directly over USB through hidapi, with no
3Dconnexion driver or SDK: the route to Windows and macOS (discussion
#599), and usable on Linux without spacenavd.

SpaceMouseHid decodes the raw reports from the device's own report
descriptor -- where each axis and button sits, its range, absolute or
relative -- so no per-model table is needed, with the classic report
1/2/3 layout as a fallback when the descriptor cannot be read and the
0x1c button list newer devices send. Absolute axes are rescaled to
+-500 exactly as spacenavd does, so both backends give QET the same
values. HidBackend polls from the main thread (fast while moving, slow
when still), emits one sample per poll, and looks for a device every 3 s
so plugging one in or back in needs no restart.

QET_SPACEMOUSE_BACKEND (auto, spnav, hid) picks the backend; auto keeps
libspnav on Linux when it is found and uses hidapi otherwise. hidapi is
found through pkg-config as hidapi-hidraw (Linux) or hidapi (MSYS2,
Homebrew).

A sample arriving in the same millisecond as the previous one now counts
for no time instead of a full period, so a burst of queued samples no
longer moves the view further than the time it covers.

Tested without a device: tst_spacemousehid (descriptor parsing, broken
and hostile descriptors, every report form, recordings from real devices
once they are added to fixtures/spacemouse), and end to end on Linux
through a virtual USB device created with /dev/uhid: the same moves give
byte-identical screenshots through the hidapi and libspnav backends, an
absolute axis is rescaled as spacenavd does, buttons trigger their
bound action, and unplugging and replugging while QET runs (including
with a dialog open that a device button opened) reconnects cleanly.
Not tested on Windows, macOS or real hardware.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 10:55:30 +12:00
ispyisail bf7f49f334 Merge remote-tracking branch 'upstream/master' into review-635-fix
# Conflicts:
#	CMakeLists.txt
#	cmake/developer_options.cmake
#	cmake/qet_compilation_vars.cmake
#	sources/qetapp.cpp
2026-09-22 23:10:34 +12:00
Andre Rummler 8606cc5328 Removing Qt5/KF5 from build system. 2026-09-17 00:07:46 +02:00
Andre Rummler c14d6a6dd6 In order to migrate to Qt6 all options for KF6 were added:
a) using a system provided KF6
b) downloading and compiling KF6
c) using the vendored-in re-creation of the functionality

The behaviour for both Qt5 and Qt6 is steered with the same two variables which were renamed to become version agnostic:
a) BUILD_WITH_KF=ON BUILD_KF=OFF
b) BUILD_WITH_KF=ON BUILD_KF=ON
c) BUILD_WITH_KF=OFF

The version is automatically derived from the chosen Qt major version.
2026-08-12 12:29:56 +02:00
ispyisail 4caefc048f Add optional precompiled headers behind QET_ENABLE_PCH (default OFF)
Building QET is dominated by re-parsing Qt's headers. A 214-line source
file expands to roughly 198,000 preprocessed lines, and compiling one
translation unit costs ~4.1 s, of which only ~0.35 s is optimisation --
switching -O3 to -O0 saves just 8%, so the usual "build Debug for faster
compiles" advice does not help here. A precompiled header caches the
parsed header state, which is the part that actually costs.

Measured on a 24-thread Xeon E5-2650 v4 with Qt 5.15.18 and GCC 15.2,
same build tree, only the option differing:

  compile one translation unit   4.12 s -> 1.21 s
  edit one .cpp -> linked binary 5.22 s -> 1.65 s

Deliberately OFF by default. A PCH satisfies includes that a source file
neglected to make for itself, so code written with it enabled can fail to
compile for everyone else. Leaving the default off keeps CI and
contributors on the strict behaviour; only developers who opt in trade
that away for the speed.

Two details in the implementation are load-bearing:

- The generator expressions are not decoration. This target also compiles
  the 18 C files of the bundled LZMA decoder, and an unguarded header list
  applies to every language in the target, so the Qt headers would be fed
  to the C compiler and fail with "unknown type name 'namespace'".
  $<ANGLE-R> is needed because a literal '>' would end the generator
  expression.
- target_precompile_headers() requires CMake 3.16 while the project still
  declares a 3.5 minimum, so the block warns and skips rather than raising
  the project-wide requirement for an opt-in developer feature.

Verified both ways: with the option off no PCH artefacts are generated and
the build is byte-for-byte the previous behaviour; with it on, all 18 C
files still compile, the generated PCH is C++-only (cmake_pch.hxx, with no
cmake_pch.h), the C compile commands carry no PCH, and the resulting
binary runs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 21:10:46 +12:00
ispyisail 2e4bb486bb Add 3D mouse (SpaceMouse/SpacePilot) pan/zoom support via libspnav
Implements discussion #599's phase 1 (Linux, libspnav): a 3Dconnexion
6-DOF device pans and zooms the active diagram view, via spacenavd.

## Off by default, zero cost when off

QET_ENABLE_SPACEMOUSE (cmake/developer_options.cmake) is OFF. Verified in
two separate build directories from a clean configure: with it off, the
new cmake/find_spacemouse.cmake step runs and does nothing (no library
lookup, no definition, no new source files compiled), and qetapp.cpp/.h
produce zero new object code -- both are entirely #ifdef'd out. The
default build is byte-for-byte the same shape as before this commit.

With it on, libspnav is located via its pkg-config file (spnav.pc, shipped
by libspnav-dev on Debian/Ubuntu and equivalent packages elsewhere). If the
option is on but the library isn't found, this does not hard-fail
configure: it downgrades back to off with a warning, so an opt-in feature
never blocks a developer who doesn't have the library installed.

## No new navigation logic -- a new input source for the existing one

DiagramView::wheelEvent() already turns a physical wheel's delta into
horizontalScrollBar()/verticalScrollBar() calls for pan and a
zoom(1 + value/1000) call for zoom -- see diagramview.cpp:661-687.
SpaceMouseListener calls exactly those same primitives from spnav motion
events instead of wheel events. It does not reimplement panning or
zooming.

## Safe by construction even when compiled in

The overwhelming majority of users of a build with the option on still
won't have spacenavd running or a device attached -- that must never
surface as an error dialog or a startup warning. SpaceMouseListener::
isAvailable() reflects this: spnav_open() failing is treated as the
ordinary case, not an error, and the object then does nothing at all.
Verified for real in this environment, which genuinely has no spacenavd
running: built with the option on, ran the resulting binary to completion,
and confirmed zero crashes and zero spnav-related output of any kind --
the silence is the point.

Motion is read via a QSocketNotifier on spnav_fd() (event-driven, no
polling loop, no idle cost) and applied to whichever DiagramView is
currently active, found via qApp->activeWindow() -> QETDiagramEditor ->
currentProjectView() -> currentDiagram(): a 6-DOF device is one ambient
input source for the whole application, not something tied to a
particular window, so there is exactly one listener, owned by QETApp.

## What could not be verified without hardware

The Z-axis-to-zoom-factor mapping (SpaceMouseListener::zoomFactorForZAxis)
is a pure function specifically so it could be tested without a live
device: confirmed a centered device (z=0) yields exactly 1.0 (an exact
no-op, not an epsilon-off value that could trip DiagramView::zoom()'s
>=1 branch), and that push/pull produce symmetric zoom-in/out factors.

What genuinely cannot be checked in this environment: which physical axis
is "left/right" vs "up/down" vs "push/forward", their sign, and whether
the ZOOM_DIVISOR/PAN_SCALE constants feel right on real hardware. Both are
named constants specifically so recalibrating them is a one-line change
once someone with a device tries it -- flagged plainly in the PR rather
than presented as verified.

## Not in this commit

Windows/macOS (proprietary 3DxWare SDK, materially bigger lift) and
device button mapping are both explicitly out of scope for this phase per
the discussion.
2026-08-02 21:04:57 +12:00
Simon De Backer 2000b6cd2b Update Cmake and disable fail to compile if it uses deprecated APIs. 2021-01-04 20:38:57 +01:00
Simon De Backer cb37c1c2fe Add switch for KF5 (QT6) and Mod Cmake
if we want to test QET on QT6, KF5 must be removed from the code,
this switch is for that,

this is for testing only
2020-12-16 23:06:08 +01:00
Simon De Backer c88d1ef6bb Refactoring Cmake
cleaning up the Cmake code
2020-12-13 00:40:43 +01:00