155 lines
6.6 KiB
Markdown
155 lines
6.6 KiB
Markdown
# qwfassoc (suite)
|
|
|
|
A Qt Widgets based GUI for the [wfassoc](../../wfassoc) library, split into a
|
|
reusable shared library and a small standalone executable that exercises it.
|
|
|
|
The project is organized as two CMake subprojects:
|
|
|
|
```
|
|
qwfassoc/ Parent directory (this README)
|
|
├── CMakeLists.txt Top-level CMake; add_subdirectory's both
|
|
│ subprojects and finds Qt, wfassoc, toml11
|
|
├── cmake/
|
|
│ ├── Findwfassoc.cmake Verbatim copy of wfassoc's Find module
|
|
│ └── README.md Provenance notes for the copy
|
|
├── qwfassoc/ Shared library subproject
|
|
│ ├── CMakeLists.txt
|
|
│ ├── i18n/
|
|
│ │ └── qwfassoc_zh_CN.ts Empty placeholder translation file
|
|
│ └── src/
|
|
│ ├── qwfassoc_global.h QWFASSOC_EXPORT macro
|
|
│ ├── scope.h Shared TargetScope enum
|
|
│ ├── manifest.h Manifest data struct (no TOML dependency)
|
|
│ ├── icon_utils.h/.cpp wfassocpp::HICON -> QPixmap conversion
|
|
│ ├── application_widget.h/.cpp/.ui
|
|
│ │ Install / uninstall widget
|
|
│ └── association_widget.h/.cpp/.ui
|
|
│ File associations widget
|
|
└── qwfassoc-standalone/ Executable subproject
|
|
├── CMakeLists.txt
|
|
├── i18n/
|
|
│ └── qwfassoc-standalone_zh_CN.ts
|
|
│ Empty placeholder translation file
|
|
└── src/
|
|
├── main.cpp Entry point, CLI parsing, translator loading
|
|
├── main_window.h/.cpp/.ui
|
|
│ QDialog hosting the two widgets in a tab widget
|
|
└── manifest_parser.h/.cpp
|
|
TOML -> Manifest, Manifest -> Schema
|
|
```
|
|
|
|
## Subprojects at a glance
|
|
|
|
### `qwfassoc` (shared library)
|
|
|
|
Exports two reusable widgets that wrap wfassoc:
|
|
|
|
* `qwfassoc::ApplicationWidget` — install / uninstall the program in the
|
|
configured scope.
|
|
* `qwfassoc::AssociationWidget` — stage and apply per-extension link / unlink
|
|
operations.
|
|
|
|
Both widgets follow the **two-phase initialization** pattern expected by Qt
|
|
Designer promoted widgets: the constructor only takes a `QWidget*` parent and
|
|
leaves the widget disabled. A `setConfig(Config)` method injects the
|
|
`wfassocpp::Program` pointer and `TargetScope` (and, for the association
|
|
widget, whether the OK/Cancel buttons are visible). Each widget also exposes:
|
|
|
|
* a `refresh()` slot that re-queries the live wfassoc state, intended to be
|
|
called by the host when another component has mutated the registry;
|
|
* a `changed()` signal emitted whenever the widget itself mutates the
|
|
registry (install / uninstall / apply);
|
|
* (`AssociationWidget` only) a `finished(bool accepted)` signal emitted when
|
|
the user clicks OK (after `changed()`) or Cancel, so the host can close the
|
|
dialog.
|
|
|
|
The library also exposes the plain `qwfassoc::Manifest` data struct and a
|
|
`qwfassoc::icon_utils::fromHicon()` helper, but the TOML parsing logic (which
|
|
depends on toml11) lives in the standalone executable.
|
|
|
|
### `qwfassoc-standalone` (executable)
|
|
|
|
Reproduces the original tabbed wfassoc configurator by:
|
|
|
|
1. parsing `-c/--manifest <path>` and `-f/--for <user|system>` from the
|
|
command line;
|
|
2. building a `wfassocpp::Program` via `parseManifestFile` + `buildSchema`;
|
|
3. hosting `ApplicationWidget` and `AssociationWidget` inside a `QTabWidget`
|
|
in a `MainWindow` dialog;
|
|
4. wiring the widgets' `changed()` and `finished()` signals so that any
|
|
registry mutation refreshes both pages and OK/Cancel drive the dialog's
|
|
acceptance.
|
|
|
|
## Requirements
|
|
|
|
* **CMake** 3.20 or newer (3.21+ recommended for `qt6_add_translations`).
|
|
* A C++17 compiler.
|
|
* **Qt 6** with the `Widgets` and `LinguistTools` components.
|
|
* **wfassoc**, with `wfassoc_ROOT` pointing at an installed tree (see
|
|
[`cmake/Findwfassoc.cmake`](cmake/Findwfassoc.cmake) for the expected
|
|
directory layout).
|
|
* **toml11** — only required when building the standalone executable.
|
|
|
|
## Building
|
|
|
|
```bat
|
|
cmake -S . -B build ^
|
|
-DCMAKE_PREFIX_PATH=C:\Qt\6.x.x\msvc2022_64 ^
|
|
-Dwfassoc_ROOT=C:\path\to\wfassoc\install ^
|
|
-Dtoml11_DIR=C:\path\to\toml11\share\toml11\cmake
|
|
cmake --build build --config Release
|
|
```
|
|
|
|
To skip the standalone executable (and the toml11 dependency):
|
|
|
|
```bat
|
|
cmake -S . -B build -DQWFASSOC_BUILD_STANDALONE=OFF ...
|
|
```
|
|
|
|
The standalone executable is `build/qwfassoc-standalone/Release/qwfassoc-standalone.exe`
|
|
(or similar, depending on the generator); the library is
|
|
`build/qwfassoc/Release/qwfassoc.dll`.
|
|
|
|
## Running the standalone executable
|
|
|
|
| Short | Long | Meaning |
|
|
| ----- | ------------ | ------------------------------------------------------------------------ |
|
|
| `-c` | `--manifest` | Path to the application manifest TOML file (see [`example/manifest/ppic.toml`](../manifest/ppic.toml)). |
|
|
| `-f` | `--for` | Target scope: `user` or `system`. |
|
|
|
|
```bat
|
|
qwfassoc-standalone -c C:\path\to\ppic.toml -f user
|
|
```
|
|
|
|
## Internationalization
|
|
|
|
Source strings are English and every user-facing string is wrapped in `tr()`
|
|
(in code) or is a plain `<string>` element in the `.ui` file (which `uic`
|
|
wraps in `QCoreApplication::translate`).
|
|
|
|
Each subproject ships its own empty placeholder `.ts` file under its
|
|
`i18n/` directory and registers it with `qt6_add_translations()`:
|
|
|
|
* `qwfassoc/i18n/qwfassoc_zh_CN.ts` — covers the library widgets.
|
|
* `qwfassoc-standalone/i18n/qwfassoc-standalone_zh_CN.ts` — covers the
|
|
executable-specific messages (CLI errors, tab titles, dialog window
|
|
title, etc.).
|
|
|
|
At runtime, `installTranslators()` in `qwfassoc-standalone/src/main.cpp`
|
|
loads both `.qm` files for the user's preferred UI language from the
|
|
`:/i18n/` resource prefix. Translators are expected to fill in the `.ts`
|
|
files; no actual translation work is performed by the build on its own.
|
|
|
|
## Notes and Limitations
|
|
|
|
* "Self" detection in the file-association table is based on comparing the
|
|
display name returned by wfassoc with the display name this program would
|
|
use. Two programs sharing the exact same display name could therefore be
|
|
confused.
|
|
* The system column in `AssociationWidget` is rendered disabled (using
|
|
`Qt::ItemIsSelectable` without `Qt::ItemIsEnabled`) when `TargetScope` is
|
|
`User`; the cells stay visible but cannot be clicked.
|
|
* All errors originating from wfassoc are surfaced through `QMessageBox`
|
|
dialogs; fatal errors during startup cause the process to exit with a
|
|
non-zero status code.
|