1
0
Files
wfassoc/example/qwfassoc
2026-06-23 21:38:54 +08:00
..
2026-06-23 20:46:56 +08:00
2026-06-23 21:38:54 +08:00
2026-06-23 21:38:54 +08:00
2026-06-23 21:38:54 +08:00
2026-06-23 21:38:54 +08:00

qwfassoc (suite)

A Qt Widgets based GUI for the 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 for the expected directory layout).
  • toml11 — only required when building the standalone executable.

Building

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):

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).
-f --for Target scope: user or system.
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.