Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/yuja/qmluic
QML -> QtWidgets UI/C++ transpiler
https://github.com/yuja/qmluic
cpp gui qml qt qtwidgets
Last synced: 16 days ago
JSON representation
QML -> QtWidgets UI/C++ transpiler
- Host: GitHub
- URL: https://github.com/yuja/qmluic
- Owner: yuja
- License: mit
- Created: 2022-04-27T13:55:00.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2024-10-21T10:43:54.000Z (23 days ago)
- Last Synced: 2024-10-22T03:45:54.512Z (22 days ago)
- Topics: cpp, gui, qml, qt, qtwidgets
- Language: Rust
- Homepage:
- Size: 1.64 MB
- Stars: 7
- Watchers: 3
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
qmluic - Write QtWidgets UI in QML
==================================*A .qml-to-.ui transpiler.*
Write UI in QML:
```qml
import qmluic.QtWidgetsQDialog {
windowTitle: qsTr("Hello")
QVBoxLayout {
QLabel { text: qsTr("Hello world!") }
}
}
```Run live preview and polish the UI:
```
$ qmluic preview HelloDialog.qml
```Transpile to `*.ui`/`ui_*.h`/`uisupport_*.h`:
```
$ qmluic generate-ui HelloDialog.qml
$ uic hellodialog.ui -o ui_hellodialog.h
```See [examples/](examples/) directory for details.
Usage
-----`qmluic generate-ui` command translates `.qml` file to `.ui` XML file and
`uisupport_*.h` C++ code. `.ui` can then be processed by Qt User Interface
Compiler `uic` command. See [Dynamic Binding](#dynamic-binding) for
`uisupport_*.h`.By default, `qmluic generate-ui` loads type information from the
`QT_INSTALL_LIBS/metatypes` directory. Use `--qmake` or `--foreign-types`
option to load metatype.json files from the other directory or files.### CMake
There's a basic helper to integrate `qmluic generate-ui` in the build step.
By default, the output `.ui` and `.h` files are generated into the
`CMAKE_CURRENT_BINARY_DIR`. This can be changed by the `OUTPUT_DIRECTORY`
option.Please make sure to not enable `CMAKE_AUTOUIC`, which conflicts with the .ui
generation step.```cmake
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# DO NOT ENABLE: set(CMAKE_AUTOUIC ON)find_package(Qt6 REQUIRED COMPONENTS Widgets)
find_package(Qmluic REQUIRED)# Help Qt Creator find qmluic type stub
set(QML_IMPORT_PATH ${QMLUIC_QML_IMPORT_PATH} CACHE STRING "" FORCE)add_executable(myapp
main.cpp
...
)qmluic_target_qml_sources(myapp
MyDialog.qml
...
)
```See [examples/CMakeLists.txt](examples/CMakeLists.txt) for details.
#### Optional CMake
If you want to optionally enable the qmluic integration, copy
[cmake/QmluicShim.cmake](cmake/QmluicShim.cmake) to your project tree and
load it if qmluic not found:```cmake
find_package(Qt6 REQUIRED COMPONENTS Widgets)
find_package(Qmluic QUIET)
if(Qmluic_FOUND)
set(QML_IMPORT_PATH ${QMLUIC_QML_IMPORT_PATH} CACHE STRING "" FORCE)
else()
include("${CMAKE_SOURCE_DIR}/cmake/QmluicShim.cmake")
endif()qmluic_target_qml_sources(myapp
MyDialog.qml
...
# Put the generated .ui in the source directory so they will be committed.
OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
```### Code Completion
You can leverage the excellent Qt Creator's QML editor. You just need to add
`share/qmluic/imports` to the `QML_IMPORT_PATH` so the creator can find our
type stubs.See the following examples:
* [examples/CMakeLists.txt](examples/CMakeLists.txt)
* [examples/examples.qmlproject](examples/examples.qmlproject)### Live Preview
`qmluic preview` command starts filesystem watcher, and updates the preview
window to reflect the source QML file changes. It does not support multi-file
QML sources yet.```
$ qmluic preview HelloDialog.qml
```The previewer might not work on Windows because of the stdio use. Patches are
welcome.### Dynamic Binding
(To turn off this feature, set `--no-dynamic-binding` or `NO_DYNAMIC_BINDING`
option in CMake.)`qmluic generate-ui` generates a `uisupport_*.h` file in addition to `*.ui`,
which sets up signal/slot connections for the dynamic binding expressions.```qml
import qmluic.QtWidgetsQDialog {
id: root
QVBoxLayout {
QCheckBox { id: checkBox; checked: true }
QLabel { id: label; visible: checkBox.checked; text: qsTr("Checked") }
}
}
```In this example, `visible: checkBox.checked` is conceptually translated to the
following code:```c++
void UiSupport::MainWindow::setup() {
connect(checkBox, &QAbstractButton::toggled, root,
[this]() { label->setVisible(checkBox->isChecked()); });
}
```(The generated code would be more verbose since QML/JS expression is first
transformed to basic intermediate representation.)[A subset of QML/JS syntax is supported](docs/language.md).
Building
--------Requirements:
- Rust
- CargoOptional requirements for previewer and type stubs:
- CMake
- Qt 5.15 or 6.2+If you have all requirements installed, use Cargo and CMake to build/install
the binaries and data. There's a GNU Make wrapper to automate the build steps.```
$ make release install
```If you just need to build the `qmluic` frontend, simply run
`cargo build --release --workspace`.See [Makefile](Makefile), [CMakeLists.txt](CMakeLists.txt), and
[build.yml](.github/workflows/build.yml) for more details.Debugging
---------Debug logging can be enabled by `QMLUIC_LOG` environment variable.
```
$ QMLUIC_LOG=trace cargo run -- generate-ui SettingsDialog.qml
```https://docs.rs/env_logger/latest/env_logger/
Major TODOs
------------ [ ] Load type stubs from qmldir/plugins.qmltypes instead of metatypes.json
- [ ] Better type resolution, namespace support
- [ ] Live preview triggered by lsp
- [ ] Live preview for multi-document file
- [ ] Better support for static `QComboBox`/`QListWidget` items
- [ ] Improve support for dynamic property bindings / signal callbacks
- [ ] `.toString()`
- [x] `"".isEmpty()`
- [ ] Export helper functions from C++
- [ ] User type and property (so C++ data model can be bound to UI)Comparison to DeclarativeWidgets
--------------------------------[DeclarativeWidgets](https://github.com/KDAB/DeclarativeWidgets) exports
QtWidgets classes to the QML world. You can write widget application in a way
you would do for QtQuick applications. You can fully leverage property
bindings, etc. The downside is the runtime dependency. And I guess it would
be a bit tedious to "control" a widget from C++ side.`qmluic` is merely a .ui file generator. You can't write expressive property
bindings. You can (and need to) implement C++ counterpart for each QML UI.