The window drew its icons with unicode glyphs -- a clip emoji for attach, a
gear, a hamburger, a chevron, a multiplication sign for delete. Those render
in whichever font happens to cover them (colour emoji in a grey toolbar) and
are a box on a machine without that glyph. They now come from the icon theme,
the way every other desktop app gets them.
Icons
- app/src/ui/ThemeIcons.{h,cpp}: a QQuickImageProvider for
image://csttheme/<name>?color=%23rrggbb -- QIcon::fromTheme() in the
desktop's theme (whatever the platform theme set, else breeze-dark, breeze,
hicolor), tinted with QPainter's SourceIn and rasterised at the requested
size and the screen's device pixel ratio. Qt only builds its theme search
paths from XDG once a theme name is set, so the provider fills them itself
(GenericDataLocation/icons, ~/.icons and, on NixOS,
/run/current-system/sw/share/icons, for a shell started outside the desktop
session). An unknown name yields a null image, which QML reports as
Image.Error.
- app/qml/ThemeIcon.qml: the one component that asks for an icon. Every use
still names the old character as `glyph:`, so a host with no icon theme
degrades to exactly what the window looked like before instead of going
blank. installThemeIcons() is called by main() and by --uitest, so the test
loads the same icons the app does.
- Replaced: nav (application-menu), settings (settings-configure), attach
(mail-attachment), copy (edit-copy), session delete (edit-delete), new
session (list-add), expand/collapse (arrow-right/arrow-down), jump to the end
(go-down), the plan checklist (task-complete/box). A tool card also shows
what kind of tool ran -- Theme.toolIcon(): pencil for patch/write, text page
for read, folder for list/glob, magnifier for grep, braces for a shell,
globe for web, list for a plan. Toolbar icons are 22 px (Breeze's toolbar
size), card and row icons 14-16 px.
Colours (the "some text is unreadable" part)
- textFaint #6d757b -> #8d959c: ~3.4:1 -> ~5:1 on the card fill. It carries
hints, provider URLs, session metadata and placeholders, so it is text, not
decoration.
- A selected provider row and the open session row write on the accent fill;
they now use accentText / accentTextDim / okOnAccent instead of faint grey
and green on blue (named "accentText", not "onAccent": QML reads any `onFoo`
property as a signal handler and refuses the assignment).
- The filled buttons (Send, Use this) take their ink from Theme.accentInk.
Composer
- The frame is one Theme.pad around its column on every side (anchors.fill,
implicitHeight + 2*pad). With the top margin alone the last row -- the clip
and Send -- hung over the lower border, which is what put the clip on the
frame instead of inside it.
app/README.md gains an "Icons, colors" section (the provider, why the theme
search paths are filled by hand, the qtsvg requirement for rasterising Breeze,
the tool map, and the contrast rules).
Verified: --uitest 52/52, --selftest OK, and the 0.8.14 window relaunched in
the Plasma session (no QML warnings).
Version 0.8.14.
mode = coding
132 lines
5.4 KiB
CMake
132 lines
5.4 KiB
CMake
cmake_minimum_required(VERSION 3.16)
|
|
project(cst-agent-app LANGUAGES C CXX VERSION 0.1.0)
|
|
|
|
# The Qt front end (app/) embeds the C engine in-process: it links libcstcore
|
|
# and never opens a port. Two targets:
|
|
#
|
|
# cst-app-selftest pure C smoke test of the embedding path (no Qt), so the
|
|
# C side is still guarded on machines without Qt Quick
|
|
# cst-agent-app the GUI (Qt 6 Quick + QML), built when the Qt modules
|
|
# are there
|
|
#
|
|
# Standalone build (builds the engine from ../ too):
|
|
# cmake -S app -B build-app -DCMAKE_BUILD_TYPE=Debug && cmake --build build-app -j
|
|
# Inside the repo build (the parent defines the cstcore target, shared with the CLI):
|
|
# cmake -B build -DCST_BUILD_APP=ON && cmake --build build --target cst-agent-app
|
|
#
|
|
# Extra QML import paths, e.g. a Kirigami installed away from the Qt prefix:
|
|
# -DCST_APP_QML_IMPORT=... (added to QML2_IMPORT_PATH / the app's runtime)
|
|
|
|
option(CST_APP_GUI "build the Qt GUI (needs Qt6 Quick, Qml, QuickControls2)" ON)
|
|
option(CST_APP_SELFTEST "build the C embedding smoke test" ON)
|
|
|
|
# --- the engine ----------------------------------------------------------
|
|
# Used as a subproject (../CMakeLists.txt already defined cstcore, engine
|
|
# compiled once for CLI and app) or built here from the sources next door.
|
|
if(NOT TARGET cstcore)
|
|
set(CST_APP_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
|
include_directories("${CST_APP_ROOT}/include" "${CST_APP_ROOT}/vendor/cjson")
|
|
file(GLOB CST_APP_CORE_SRC
|
|
"${CST_APP_ROOT}/src/*.c"
|
|
"${CST_APP_ROOT}/src/tools/*.c"
|
|
"${CST_APP_ROOT}/vendor/cjson/cJSON.c")
|
|
list(REMOVE_ITEM CST_APP_CORE_SRC
|
|
"${CST_APP_ROOT}/src/main.c"
|
|
"${CST_APP_ROOT}/src/tui.c"
|
|
"${CST_APP_ROOT}/src/tui_stub.c"
|
|
"${CST_APP_ROOT}/src/textsel.c")
|
|
# The HTTP front end is not part of an in-process app: no server, no port.
|
|
list(REMOVE_ITEM CST_APP_CORE_SRC
|
|
"${CST_APP_ROOT}/src/net.c"
|
|
"${CST_APP_ROOT}/src/http_srv.c"
|
|
"${CST_APP_ROOT}/src/webui.c"
|
|
"${CST_APP_ROOT}/src/web_md.c")
|
|
if(EXISTS "${CST_APP_ROOT}/.gen/models_builtin.inc")
|
|
include_directories("${CST_APP_ROOT}/.gen")
|
|
endif()
|
|
add_library(cstcore STATIC ${CST_APP_CORE_SRC})
|
|
target_compile_definitions(cstcore PRIVATE CST_NO_WEBUI=1)
|
|
find_package(CURL REQUIRED)
|
|
find_package(Threads REQUIRED)
|
|
target_link_libraries(cstcore PUBLIC ${CURL_LIBRARIES} Threads::Threads m)
|
|
message(STATUS "app: building the engine from ${CST_APP_ROOT}")
|
|
else()
|
|
message(STATUS "app: linking the cstcore target of the parent build")
|
|
endif()
|
|
|
|
# --- the C smoke test ----------------------------------------------------
|
|
if(CST_APP_SELFTEST)
|
|
add_executable(cst-app-selftest tools/selftest.c)
|
|
target_link_libraries(cst-app-selftest PRIVATE cstcore)
|
|
enable_testing()
|
|
add_test(NAME cst-app-selftest COMMAND cst-app-selftest)
|
|
endif()
|
|
|
|
# --- the GUI -------------------------------------------------------------
|
|
if(CST_APP_GUI)
|
|
find_package(Qt6 6.4 COMPONENTS Core Gui Qml Quick QuickControls2 Test QUIET)
|
|
if(NOT Qt6_FOUND)
|
|
message(WARNING
|
|
"app: Qt 6 Quick/Qml not found, skipping cst-agent-app "
|
|
"(the C selftest still builds; install e.g. qt6.qtdeclarative / "
|
|
"qt6.qtquickcontrols2 and reconfigure)")
|
|
else()
|
|
qt_standard_project_setup()
|
|
# Qt 6.5+ policies: keep the module resource at :/qt/qml/<URI>/ (what
|
|
# main.cpp loads) and let CMake generate the qmldir of qml/ for us.
|
|
qt_policy(SET QTP0001 NEW)
|
|
qt_policy(SET QTP0004 NEW)
|
|
qt_add_executable(cst-agent-app
|
|
src/main.cpp
|
|
src/core/AgentCore.cpp
|
|
src/core/ToolProvider.cpp
|
|
src/ui/UiTest.cpp
|
|
src/ui/ThemeIcons.cpp
|
|
src/platform/linux/NotifyTool.cpp)
|
|
target_include_directories(cst-agent-app PRIVATE
|
|
src "${CMAKE_CURRENT_SOURCE_DIR}/../include")
|
|
target_compile_definitions(cst-agent-app PRIVATE CST_APP_VERSION="${PROJECT_VERSION}")
|
|
if(CST_APP_QML_IMPORT)
|
|
target_compile_definitions(cst-agent-app PRIVATE
|
|
CST_APP_QML_IMPORT="${CST_APP_QML_IMPORT}")
|
|
endif()
|
|
target_link_libraries(cst-agent-app PRIVATE
|
|
Qt6::Core Qt6::Gui Qt6::Qml Qt6::Quick Qt6::QuickControls2 Qt6::Test cstcore)
|
|
if(WIN32)
|
|
set_target_properties(cst-agent-app PROPERTIES WIN32_EXECUTABLE TRUE)
|
|
endif()
|
|
|
|
# Theme is read by every component, so it is a QML singleton (one instance,
|
|
# no object needed in the tree).
|
|
set_source_files_properties(qml/Theme.qml PROPERTIES QT_QML_SINGLETON_TYPE TRUE)
|
|
# Keep the module flat in the resource tree (:qt/qml/CstAgent/Main.qml).
|
|
# Sources live in qml/, but a module whose files sit in a subdirectory of
|
|
# the URI makes Qt register the types with relative URLs ("qmlRegisterType
|
|
# requires absolute URLs" on every start).
|
|
foreach(_qml Main ChatView Sidebar SessionRow MessageCard ToolCard ThinkBlock
|
|
NoteLine TodoPanel Composer ConsentDialog AskDialog SettingsDialog
|
|
ThemeIcon Theme)
|
|
set_source_files_properties(qml/${_qml}.qml PROPERTIES QT_RESOURCE_ALIAS ${_qml}.qml)
|
|
endforeach()
|
|
qt_add_qml_module(cst-agent-app
|
|
URI CstAgent
|
|
VERSION 1.0
|
|
QML_FILES
|
|
qml/Main.qml
|
|
qml/ChatView.qml
|
|
qml/Sidebar.qml
|
|
qml/SessionRow.qml
|
|
qml/MessageCard.qml
|
|
qml/ToolCard.qml
|
|
qml/ThinkBlock.qml
|
|
qml/NoteLine.qml
|
|
qml/TodoPanel.qml
|
|
qml/Composer.qml
|
|
qml/ConsentDialog.qml
|
|
qml/AskDialog.qml
|
|
qml/SettingsDialog.qml
|
|
qml/ThemeIcon.qml
|
|
qml/Theme.qml)
|
|
endif()
|
|
endif()
|