A .qml-to-.ui transpiler.
Write UI in QML:
import qmluic.QtWidgets
QDialog {
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/ directory for details.
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 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.
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.
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 for details.
If you want to optionally enable the qmluic integration, copy cmake/QmluicShim.cmake to your project tree and load it if qmluic not found:
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}
)
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:
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.
(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.
import qmluic.QtWidgets
QDialog {
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:
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.
Requirements:
- Rust
- Cargo
Optional 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, CMakeLists.txt, and build.yml for more details.
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/
- 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()
-
"".isEmpty()
-
- Export helper functions from C++
- User type and property (so C++ data model can be bound to UI)
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.