Skip to content

Commit 0a7dd9d

Browse files
authored
Add qapplication in add cxx qt lib extras (#869)
* Add QApplication
1 parent 85d04fd commit 0a7dd9d

File tree

5 files changed

+280
-1
lines changed

5 files changed

+280
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// clang-format off
2+
// SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
3+
// clang-format on
4+
// SPDX-FileContributor: Laurent Montel <[email protected]>
5+
//
6+
// SPDX-License-Identifier: MIT OR Apache-2.0
7+
#pragma once
8+
9+
#include <memory>
10+
11+
#include <QtGui/QFont>
12+
#include <QtWidgets/QApplication>
13+
14+
#include "rust/cxx.h"
15+
16+
namespace rust {
17+
namespace cxxqtlib1 {
18+
19+
::std::unique_ptr<QApplication>
20+
qapplicationNew(const QVector<QByteArray>& args);
21+
22+
void
23+
qapplicationSetFont(QApplication& app, const QFont& font);
24+
25+
QFont
26+
qapplicationFont(const QApplication& app);
27+
28+
}
29+
}

crates/cxx-qt-lib-extras-headers/src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ pub fn build_opts() -> cxx_qt_build::CxxQtBuildersOpts {
1414
include_str!("../include/core/qelapsedtimer.h"),
1515
"qelapsedtimer.h",
1616
),
17+
(
18+
include_str!("../include/gui/qapplication.h"),
19+
"qapplication.h",
20+
),
1721
(
1822
include_str!("../include/core/qcommandlineparser.h"),
1923
"qcommandlineparser.h",
@@ -26,5 +30,5 @@ pub fn build_opts() -> cxx_qt_build::CxxQtBuildersOpts {
2630
opts = opts.header(file_contents, "cxx-qt-lib-extras", file_name);
2731
}
2832

29-
opts
33+
opts.qt_module("Gui").qt_module("Widgets")
3034
}

crates/cxx-qt-lib-extras/build.rs

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ fn main() {
1212
"core/qelapsedtimer",
1313
"core/qcommandlineoption",
1414
"core/qcommandlineparser",
15+
"gui/qapplication",
1516
];
1617

1718
for rust_source in &rust_bridges {
@@ -22,6 +23,7 @@ fn main() {
2223
"core/qelapsedtimer",
2324
"core/qcommandlineoption",
2425
"core/qcommandlineparser",
26+
"gui/qapplication",
2527
];
2628

2729
builder = builder.cc_builder(move |cc| {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// clang-format off
2+
// SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
3+
// clang-format on
4+
// SPDX-FileContributor: Laurent Montel <[email protected]>
5+
//
6+
// SPDX-License-Identifier: MIT OR Apache-2.0
7+
8+
#include "cxx-qt-lib-extras/qapplication.h"
9+
10+
#include "cxx-qt-lib/qcoreapplication.h"
11+
12+
namespace rust {
13+
namespace cxxqtlib1 {
14+
15+
::std::unique_ptr<QApplication>
16+
qapplicationNew(const QVector<QByteArray>& args)
17+
{
18+
// Ensure that our QVector has the same lifetime as the QApplication
19+
// by storing it inside a QObject that has QApplication as it's parent
20+
auto argsData = new ApplicationArgsData(args);
21+
// Note that QApplication uses a reference to an int for the size here
22+
// so we need to ensure that reference remains valid
23+
auto ptr =
24+
::std::make_unique<QApplication>(argsData->size(), argsData->data());
25+
Q_ASSERT(ptr != nullptr);
26+
argsData->setParent(ptr.get());
27+
28+
return ptr;
29+
}
30+
31+
void
32+
qapplicationSetFont(QApplication& app, const QFont& font)
33+
{
34+
app.setFont(font);
35+
}
36+
37+
QFont
38+
qapplicationFont(const QApplication& app)
39+
{
40+
return app.font();
41+
}
42+
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
// SPDX-FileCopyrightText: 2024 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
2+
// SPDX-FileContributor: Laurent Montel <[email protected]>
3+
//
4+
// SPDX-License-Identifier: MIT OR Apache-2.0
5+
6+
use crate::{QByteArray, QFont, QString, QStringList, QVector};
7+
use core::pin::Pin;
8+
9+
#[cxx::bridge]
10+
mod ffi {
11+
unsafe extern "C++" {
12+
include!("cxx-qt-lib/qbytearray.h");
13+
type QByteArray = crate::QByteArray;
14+
include!("cxx-qt-lib/qstring.h");
15+
type QString = crate::QString;
16+
include!("cxx-qt-lib/qstringlist.h");
17+
type QStringList = crate::QStringList;
18+
include!("cxx-qt-lib/qvector.h");
19+
type QVector_QByteArray = crate::QVector<QByteArray>;
20+
include!("cxx-qt-lib/qfont.h");
21+
type QFont = crate::QFont;
22+
23+
include!("cxx-qt-lib-extras/qapplication.h");
24+
type QApplication;
25+
}
26+
27+
#[namespace = "rust::cxxqtlib1"]
28+
unsafe extern "C++" {
29+
#[doc(hidden)]
30+
#[rust_name = "qpplication_new"]
31+
fn qapplicationNew(args: &QVector_QByteArray) -> UniquePtr<QApplication>;
32+
}
33+
34+
// These are all static, so we need to create bindings until CXX supports statics
35+
#[namespace = "rust::cxxqtlib1"]
36+
unsafe extern "C++" {
37+
// Reuse the templated versions from QCoreApplication
38+
include!("cxx-qt-lib/qcoreapplication.h");
39+
40+
#[doc(hidden)]
41+
#[rust_name = "qapplication_add_library_path"]
42+
fn qapplicationAddLibraryPath(app: Pin<&mut QApplication>, path: &QString);
43+
#[doc(hidden)]
44+
#[rust_name = "qapplication_application_name"]
45+
fn qapplicationApplicationName(app: &QApplication) -> QString;
46+
#[doc(hidden)]
47+
#[rust_name = "qapplication_remove_library_path"]
48+
fn qapplicationRemoveLibraryPath(app: &QApplication, path: &QString);
49+
#[doc(hidden)]
50+
#[rust_name = "qapplication_application_version"]
51+
fn qapplicationApplicationVersion(app: &QApplication) -> QString;
52+
#[doc(hidden)]
53+
#[rust_name = "qapplication_exec"]
54+
fn qapplicationExec(app: Pin<&mut QApplication>) -> i32;
55+
#[doc(hidden)]
56+
#[rust_name = "qapplication_library_paths"]
57+
fn qapplicationLibraryPaths(app: &QApplication) -> QStringList;
58+
#[doc(hidden)]
59+
#[rust_name = "qapplication_organization_domain"]
60+
fn qapplicationOrganizationDomain(app: &QApplication) -> QString;
61+
#[doc(hidden)]
62+
#[rust_name = "qapplication_organization_name"]
63+
fn qapplicationOrganizationName(app: &QApplication) -> QString;
64+
#[doc(hidden)]
65+
#[rust_name = "qapplication_set_application_name"]
66+
fn qapplicationSetApplicationName(app: Pin<&mut QApplication>, name: &QString);
67+
#[doc(hidden)]
68+
#[rust_name = "qapplication_set_application_version"]
69+
fn qapplicationSetApplicationVersion(app: Pin<&mut QApplication>, version: &QString);
70+
#[doc(hidden)]
71+
#[rust_name = "qapplication_set_font"]
72+
fn qapplicationSetFont(app: Pin<&mut QApplication>, font: &QFont);
73+
#[doc(hidden)]
74+
#[rust_name = "qapplication_font"]
75+
fn qapplicationFont(app: &QApplication) -> QFont;
76+
#[doc(hidden)]
77+
#[rust_name = "qapplication_set_library_paths"]
78+
fn qapplicationSetLibraryPaths(app: Pin<&mut QApplication>, paths: &QStringList);
79+
#[doc(hidden)]
80+
#[rust_name = "qapplication_set_organization_domain"]
81+
fn qapplicationSetOrganizationDomain(app: Pin<&mut QApplication>, domain: &QString);
82+
#[doc(hidden)]
83+
#[rust_name = "qapplication_set_organization_name"]
84+
fn qapplicationSetOrganizationName(app: Pin<&mut QApplication>, name: &QString);
85+
}
86+
87+
// QApplication is not a trivial to CXX and is not relocatable in Qt
88+
// as the following fails in C++. So we cannot mark it as a trivial type
89+
// and need to use references or pointers.
90+
// static_assert(QTypeInfo<QApplication>::isRelocatable);
91+
impl UniquePtr<QApplication> {}
92+
}
93+
94+
pub use ffi::QApplication;
95+
96+
impl QApplication {
97+
/// Prepends path to the beginning of the library path list,
98+
/// ensuring that it is searched for libraries first.
99+
/// If path is empty or already in the path list, the path list is not changed.
100+
pub fn add_library_path(self: Pin<&mut Self>, path: &QString) {
101+
ffi::qapplication_add_library_path(self, path);
102+
}
103+
104+
/// The name of this application
105+
pub fn application_name(&self) -> QString {
106+
ffi::qapplication_application_name(self)
107+
}
108+
109+
/// The version of this application
110+
pub fn application_version(&self) -> QString {
111+
ffi::qapplication_application_version(self)
112+
}
113+
114+
/// Enters the main event loop and waits until exit() is called,
115+
/// and then returns the value that was set to exit() (which is 0 if exit() is called via quit()).
116+
pub fn exec(self: Pin<&mut Self>) -> i32 {
117+
ffi::qapplication_exec(self)
118+
}
119+
120+
/// Returns the default application font.
121+
pub fn font(&self) -> QFont {
122+
ffi::qapplication_font(self)
123+
}
124+
125+
/// Returns a list of paths that the application will search when dynamically loading libraries.
126+
pub fn library_paths(&self) -> QStringList {
127+
ffi::qapplication_library_paths(self)
128+
}
129+
130+
/// Initializes the window system and constructs an application object.
131+
/// Standard [Qt command line arguments](https://doc.qt.io/qt-6/qapplication.html#supported-command-line-options) are handled automatically.
132+
pub fn new() -> cxx::UniquePtr<Self> {
133+
let mut vector = QVector::<QByteArray>::default();
134+
135+
// Construct an owned QVector of the args
136+
// as we need the args_os data to outlive this method
137+
// so we pass a QVector to C++ which is then stored
138+
for arg in std::env::args_os() {
139+
// Unix OsStrings can be directly converted to bytes.
140+
#[cfg(unix)]
141+
use std::os::unix::ffi::OsStrExt;
142+
143+
// Windows OsStrings are WTF-8 encoded, so they need to be
144+
// converted to UTF-8 Strings before being converted to bytes.
145+
// https://simonsapin.github.io/wtf-8/
146+
#[cfg(windows)]
147+
let arg = arg.to_string_lossy();
148+
149+
vector.append(QByteArray::from(arg.as_bytes()));
150+
}
151+
152+
ffi::qapplication_new(&vector)
153+
}
154+
155+
/// The Internet domain of the organization that wrote this application
156+
pub fn organization_domain(&self) -> QString {
157+
ffi::qapplication_organization_domain(self)
158+
}
159+
160+
/// The name of the organization that wrote this application
161+
pub fn organization_name(&self) -> QString {
162+
ffi::qapplication_organization_name(self)
163+
}
164+
165+
/// Set the name of this application
166+
pub fn set_application_name(self: Pin<&mut Self>, name: &QString) {
167+
ffi::qapplication_set_application_name(self, name);
168+
}
169+
170+
/// Removes path from the library path list. If path is empty or not in the path list, the list is not changed.
171+
pub fn remove_library_path(&self, path: &QString) {
172+
ffi::qapplication_remove_library_path(self, path)
173+
}
174+
175+
/// Set the version of this application
176+
pub fn set_application_version(self: Pin<&mut Self>, version: &QString) {
177+
ffi::qapplication_set_application_version(self, version);
178+
}
179+
180+
/// Changes the default application font to font.
181+
pub fn set_application_font(self: Pin<&mut Self>, font: &QFont) {
182+
ffi::qapplication_set_font(self, font);
183+
}
184+
185+
/// Sets the list of directories to search when loading plugins with QLibrary to paths.
186+
/// All existing paths will be deleted and the path list will consist of the paths given in paths and the path to the application.
187+
pub fn set_library_paths(self: Pin<&mut Self>, paths: &QStringList) {
188+
ffi::qapplication_set_library_paths(self, paths);
189+
}
190+
191+
/// Sets the Internet domain of the organization that wrote this application
192+
pub fn set_organization_domain(self: Pin<&mut Self>, domain: &QString) {
193+
ffi::qapplication_set_organization_domain(self, domain);
194+
}
195+
196+
/// Sets the name of the organization that wrote this application
197+
pub fn set_organization_name(self: Pin<&mut Self>, name: &QString) {
198+
ffi::qapplication_set_organization_name(self, name);
199+
}
200+
}

0 commit comments

Comments
 (0)