Files
vdm/gui/CMakeLists.txt
T
samiandClaude Sonnet 5 c2eef96175 gui: floating drop target, clipboard global shortcut, theming, UI watchdog
Continues the build order past Options/Scheduler/Speed Limiter/Batch/
Grabber/tray.

- DropTargetWidget: frameless always-on-top drop target (docs/03-gui-spec.md
  §5), position persisted, accepts a dropped http(s) URL or link text and
  opens FileInfoDialog directly (skipping Add URL, since the URL is already
  known). Shown/hidden from general.showDropTarget, live via
  event.settings.changed, same pattern MainWindow already used for
  general.minimizeToTray.
- Clipboard, explicit path #2 (docs/06-risks-and-spikes.md R2):
  GlobalShortcut wraps org.freedesktop.portal.GlobalShortcuts
  (CreateSession -> BindShortcuts -> Activated), triggering the same Add URL
  flow. Guarded end-to-end on `if(TARGET Qt6::DBus)` / VELOX_GUI_HAVE_DBUS
  so a build without the component degrades to "feature skipped," not
  broken (gui/docs/pkg-qa-requests-m1.md R4). Best-effort by design per the
  risk doc: fails silent, never advertised.

  Verified live against the real portal (a real Wayland session, not just
  offscreen): `CreateSession` refuses every caller with "An app id is
  required" — reproduced identically via a bare `busctl` call with no Qt
  involved at all, so this is the portal requiring a sandboxed caller
  identity, not something fixable from an unconfined process. Recorded as
  a partial Spike S2 answer in docs/06-risks-and-spikes.md: this explicit
  path likely doesn't work for Velox as a traditionally-packaged app on
  stock GNOME, only if/when it ships confined. Also fixed a real leak this
  verification caught: QDBusInterface's introspection cache reads as a
  LeakSanitizer leak the first time anything touches D-Bus (tst_rtl went
  red under ASan) — switched to QDBusMessage::createMethodCall, which
  needs no introspection.
- Theming (docs/03-gui-spec.md §7): gui/resources/qss/{idm-like,dark}.qss,
  each with a documented palette block up top (QSS itself has no variable
  syntax), applied by ThemeManager and kept live via
  QStyleHints::colorSchemeChanged. util/Theme.hpp gives the handful of
  inline C++ styles (status dot, offline banner, the eleven identical
  error-label styles across dialogs) named constants instead of a twelfth
  copy of the same hex.
- UiThreadWatchdog: the M1 DoD's 200 ms debug-build watchdog. A background
  std::thread pings the UI thread every 50 ms via a queued invokeMethod and
  warns once (not per-poll) if a ping goes unanswered past 200 ms; no
  QThread, no Qt event loop of its own, so the watchdog itself can never be
  what blocks the thread it watches. No-op in a release build. Proven both
  ways in tst_uithreadwatchdog: fires on a genuinely blocked UI thread
  (synchronous sleep, no processEvents) and stays silent on a responsive
  one.

Full non-conformance suite (55 tests across every lane, `ctest -LE
conformance`) passes clean at this point, including the whole gui label
under ASan+UBSan.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NSCdCWFXBTSBBK3MzWtJiC
2026-09-12 21:30:13 +04:00

93 lines
3.8 KiB
CMake

# velox-gui — the Qt 6 Widgets client. Lane GUI.
#
# CLAUDE.md §3: zero download logic here. This target links libveloxproto (the wire
# types, ADR 0009) and NEVER libveloxcore — enforced by tests/ (see the
# gui_no_download_logic test).
#
# The root CMakeLists.txt add_subdirectory()s this unconditionally once the file exists,
# so it must stay configurable even if veloxproto is ever absent again. Until that target
# exists we announce and bail.
if(NOT TARGET veloxproto)
message(STATUS "velox-gui: libveloxproto target missing — GUI target skipped. "
"It builds automatically once core/ provides the veloxproto target (ADR 0009).")
return()
endif()
set(CMAKE_AUTOMOC ON)
# Everything except main() lives in a static lib so the tests can link the real widgets
# and models rather than a reimplementation.
add_library(velox-gui-lib STATIC
src/rpc/RpcConnection.cpp
src/rpc/RpcClient.cpp
src/models/DownloadTableModel.cpp
src/models/DownloadFilterProxy.cpp
src/widgets/ProgressDelegate.cpp
src/widgets/SegmentBarsWidget.cpp
src/widgets/SpeedGraphWidget.cpp
src/dialogs/AddUrlDialog.cpp
src/dialogs/FileInfoDialog.cpp
src/dialogs/ProgressDialog.cpp
src/dialogs/OptionsDialog.cpp
src/dialogs/SchedulerDialog.cpp
src/dialogs/SpeedLimiterDialog.cpp
src/dialogs/BatchDialog.cpp
src/dialogs/GrabberWizard.cpp
src/tray/TrayIcon.cpp
src/widgets/DropTargetWidget.cpp
src/util/ThemeManager.cpp
src/util/UiThreadWatchdog.cpp
src/mainwindow/CategoryPanel.cpp
src/mainwindow/MainWindow.cpp
)
# docs/03-gui-spec.md §7: the two QSS skins ThemeManager picks between, embedded so the
# app needs no external file at runtime.
qt_add_resources(velox-gui-lib "theme"
PREFIX "/qss"
BASE "resources/qss"
FILES resources/qss/idm-like.qss resources/qss/dark.qss
)
target_include_directories(velox-gui-lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_compile_features(velox-gui-lib PUBLIC cxx_std_23)
target_compile_options(velox-gui-lib PRIVATE -Wall -Wextra -Wpedantic -Werror)
target_link_libraries(velox-gui-lib PUBLIC
velox::proto
Qt6::Widgets
Qt6::Svg
Qt6::Network
Threads::Threads
)
# docs/06-risks-and-spikes.md R2's explicit path #2 (a global shortcut via
# org.freedesktop.portal.GlobalShortcuts) needs Qt6::DBus, which the root CMakeLists.txt
# does not request yet (gui/docs/pkg-qa-requests-m1.md R4 — PKG/QA's file, not ours).
# Guarded exactly like the veloxproto check above: compiles in automatically the moment
# that lands, and MainWindow only wires it up when VELOX_GUI_HAVE_DBUS is defined.
if(TARGET Qt6::DBus)
target_sources(velox-gui-lib PRIVATE src/clipboard/GlobalShortcut.cpp)
target_link_libraries(velox-gui-lib PUBLIC Qt6::DBus)
target_compile_definitions(velox-gui-lib PUBLIC VELOX_GUI_HAVE_DBUS)
else()
message(STATUS "velox-gui: Qt6::DBus not available — the clipboard global-shortcut "
"path (gui/docs/pkg-qa-requests-m1.md R4) is skipped, not broken.")
endif()
add_executable(velox-gui src/main.cpp)
target_compile_options(velox-gui PRIVATE -Wall -Wextra -Wpedantic -Werror)
target_link_libraries(velox-gui PRIVATE velox-gui-lib)
set_target_properties(velox-gui PROPERTIES WIN32_EXECUTABLE OFF MACOSX_BUNDLE OFF)
# --- i18n -------------------------------------------------------------------------------
# Every string in the GUI goes through tr(); the Arabic stub exists to prove the RTL
# layout survives (GUI DoD), exercised by tests/tst_rtl. lrelease also drops the .qm at
# ${CMAKE_CURRENT_BINARY_DIR}/velox_ar.qm, which the RTL test loads by path.
qt_add_translations(velox-gui TS_FILES i18n/velox_ar.ts)
# --- tests ---------------------------------------------------------------------------
if(VELOX_BUILD_TESTS)
add_subdirectory(tests)
endif()