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 owner
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.owner = false # Update `owner` 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"
)
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