nim-seaqt
is a set of Nim bindings for Qt generated by seaqt-gen
. See seaqt-gen
for more information.
The bindings are still going through significant changes, including in naming and structure - this repository is a preview intended for feedback.
The code may occasionally be rebased before the dust settles on a generally useful initial release.
The repository contains both Nim
and C
code - see seeqt
for a C
version that can be used stand-alone or as a base for other languages.
Bindings are available from nimble
with each supported Qt version in its own branch:
requires "https://github.com/seaqt/nim-seaqt.git@#qt-6.4"
With that and a copy of Qt itself in place, you're good to go for your first Qt application:
import std/strformat, seaqt/[qapplication, qpushbutton]
let
_ = QApplication.create() # Initialize the Qt library
btn = QPushButton.create("Hello seaqt!")
btn.setFixedWidth(320)
var counter = 0
btn.onPressed(
proc() =
counter += 1
btn.setText(&"You have clicked the button {counter} time(s)")
)
btn.show()
quit QApplication.exec().int
Bindings are generated for each Qt release into a separate branch named after the Qt major.minor
version.
Bindings for a specific minor version can generally be used with all minor Qt versions following it - ie the 6.4
bindings are compatible with 6.5
etc but not with 6.2
and 7.0
. Use the lowest minor
version that provides the functionality you need, for maximum compatibility!
Qt Version | Branch |
---|---|
5.15+ | https://github.com/seaqt/nim-seaqt/tree/qt-5.15 |
6.4+ | https://github.com/seaqt/nim-seaqt/tree/qt-6.4 |
Qt gets located using pkg-config
- use PKG_CONFIG_PATH
to point to a specific Qt installation:
export PKG_CONFIG_PATH="/opt/Qt5.2.1/5.2.1/gcc_64/lib/pkgconfig/:$PKG_CONFIG_PATH"
Similar to Qt, imports are directly derived from the type name, in lowercase:
# To use [`QListView`](https://doc.qt.io/qt-6/qlistview.html):
import seaqt/qlistview
In case of ambiguity, imports are further divided by their Qt module name and derived from their .h
-based include file, where you'll also find imports for symbols that are not covered by the top-level modules:
# This time with a `gen_` prefix - this may change in the future:
import seaqt/QtWidgets/gen_qlistview
Each bound Qt type is made of two parts - a C++-based implementation and a Nim-based "handle" type, similar to the pimpl
idiom in C++.
The lifetime of the C++ instance generally follows that of the Nim instance - to gain better control over lifetimes, put the handle type in a ref
wrapper.
Some Qt functions take ownership of the instance passed to them - these are typically functions that make widgets part of the QObject
/ QWidget
ownership trees. When calling such functions, you must reset the owned
flag of the Nim instance or the instance will be deleted twice:
var
btn = QPushButton.create("button")
toolbar = QToolBar.create()
# `adddWidget` "takes ownership" according to https://doc.qt.io/qt-6/qtoolbar.html#addWidget
discard toolbar.addWidget(btn)
btn.owned = false # Update `owned` flag of Nim instance
Some types such as QAbstractListModel
use inheritance to customise their behavior. To override virtual functions, inherit from the type as you would in C++, albeit with a Virtual
prefix. Overrides of virtual functions are then provided using Nim methods:
type MyList = ref object of VirtualQAbstractListModel
myField: int # Nim fields to accompany the underlying C++ list
method rowCount(self: Model, idx: QModelIndex): cint =
1000
# Instances must be "attached" to C++ using `create`:
let model = Model()
QAbstractListModel.create(model)
# Dereference the model to access the underlying `QAbstractListModel` wrapper
let v = QListView.create()
v.setModel(model[])
Signal connections are done using the on<SignalName>
helpers:
let btn = QPushButton.create("Hello world!")
btn.onPressed(
proc() =
echo "Button pressed"
)
- nimqt - Bindings that generate C++ code on the fly and use verdigris for meta-object integration - require
nim cpp
- nimqml - QML-focused bindings with
nim c
support based on DOtherSide - seaqt-nimqml - drop-in replacement of
nimqml
usingseaqt
backend (for full Qt access)
Broadly, the aim is to support the majority of functionality Qt offers, albeit with adaptations for Nim.
General work in progress includes:
- Multiple inheritance - needs emulation in Nim to be developed
- Macros for deriving custom QObject-based types, including signals, slots and properties
- QML integration