KDDockWidgets API Documentation 2.1
Loading...
Searching...
No Matches
slint/src/main.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5 Author: Sérgio Martins <sergio.martins@kdab.com>
6
7 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
8
9 Contact KDAB at <info@kdab.com> for commercial licensing options.
10*/
11
12#include "appwindow.h"
13#include "../../../Item_p.h"
14#include "../../../LayoutingHost_p.h"
15#include "../../../LayoutingGuest_p.h"
16#include "../../../LayoutingSeparator_p.h"
17
18#include <iostream>
19
20using namespace KDDockWidgets;
21
22class Separator;
23class Host : public KDDockWidgets::Core::LayoutingHost
24{
25public:
26 explicit Host(slint::ComponentHandle<AppWindow> ui);
27
28 Separator *
29 separatorForId(int id) const;
30
31 bool supportsHonouringLayoutMinSize() const override
32 {
33 return true;
34 }
35
36 slint::ComponentHandle<AppWindow> ui;
37};
38
39namespace {
40
41int index_of_row(std::string name, slint::ComponentHandle<AppWindow> ui)
42{
43 auto model = ui->get_dockWidgets();
44 if (!model)
45 return -1;
46
47 for (int i = 0, end = model->row_count(); i < end; ++i) {
48 auto dw = model->row_data(i);
49 if (dw->uniqueName.data() == name) {
50 return i;
51 }
52 }
53
54 return -1;
55}
56
57int index_of_separator_row(int id, slint::ComponentHandle<AppWindow> ui)
58{
59 auto model = ui->get_separators();
60 if (!model)
61 return -1;
62
63 for (int i = 0, end = model->row_count(); i < end; ++i) {
64 auto dw = model->row_data(i);
65 if (dw->id == id) {
66 return i;
67 }
68 }
69
70 return -1;
71}
72
73void dump_model(slint::ComponentHandle<AppWindow> ui)
74{
75 if (auto model = ui->get_dockWidgets()) {
76 for (int i = 0, end = model->row_count(); i < end; ++i) {
77 std::cout << "i=" << i << "name=" << model->row_data(i)->uniqueName.data() << "\n";
78 }
79 } else {
80 std::cerr << "null model\n";
81 }
82}
83
84void update_model_row(DockWidgetDescriptor desc, slint::ComponentHandle<AppWindow> ui)
85{
86 const int index = index_of_row(desc.uniqueName.data(), ui);
87 if (index == -1) {
88 std::cerr << "Failed to find descriptor for: " << desc.uniqueName << "; count is: " << ui->get_dockWidgets()->row_count() << "\n";
89 } else {
90 auto model = ui->get_dockWidgets();
91 assert(model);
92 model->set_row_data(index, desc);
93 }
94}
95
96void add_model_row(DockWidgetDescriptor desc, slint::ComponentHandle<AppWindow> ui)
97{
98 const int index = index_of_row(desc.uniqueName.data(), ui);
99 if (index != -1) {
100 std::cerr << "add_model_row: Row already exists!\n";
101 return;
102 }
103
104 if (auto model = ui->get_dockWidgets()) {
105 auto vecModel = std::static_pointer_cast<slint::VectorModel<DockWidgetDescriptor>>(model);
106 vecModel->push_back(desc);
107 } else {
108 std::vector<DockWidgetDescriptor> dockDescriptors = {
109 desc
110 };
111
112 ui->set_dockWidgets(std::make_shared<slint::VectorModel<DockWidgetDescriptor>>(dockDescriptors));
113 }
114}
115
116void add_separator_model_row(SeparatorDescriptor desc, slint::ComponentHandle<AppWindow> ui)
117{
118 auto separatorModel = ui->get_separators();
119 if (separatorModel) {
120 auto vecModel = std::static_pointer_cast<slint::VectorModel<SeparatorDescriptor>>(separatorModel);
121 vecModel->push_back(desc);
122 } else {
123 std::vector<SeparatorDescriptor> sepDescriptors { desc };
124 ui->set_separators(std::make_shared<slint::VectorModel<SeparatorDescriptor>>(sepDescriptors));
125 }
126}
127
128void update_separator_model_row(SeparatorDescriptor desc, slint::ComponentHandle<AppWindow> ui)
129{
130 const int index = index_of_separator_row(desc.id, ui);
131 if (index == -1) {
132 std::cerr << "Failed to find separator descriptor for: " << desc.id << "; count is: " << ui->get_separators()->row_count() << "\n";
133 } else {
134 auto model = ui->get_separators();
135 assert(model);
136 model->set_row_data(index, desc);
137 }
138}
139
140void remove_separator_model_row(int id, slint::ComponentHandle<AppWindow> ui)
141{
142 const int index = index_of_separator_row(id, ui);
143 if (index == -1) {
144 std::cerr << "remove_separator_model_row: Failed to find separator descriptor for: " << id << "; count is: " << ui->get_separators()->row_count() << "\n";
145 } else {
146 auto vecModel = std::static_pointer_cast<slint::VectorModel<SeparatorDescriptor>>(ui->get_separators());
147 vecModel->erase(index);
148 }
149}
150
151}
152
153class Guest : public KDDockWidgets::Core::LayoutingGuest
154{
155public:
156 explicit Guest(Host *host, const QString &uniqueName, slint::ComponentHandle<AppWindow> ui)
157 : _uniqueName(uniqueName)
158 , ui(ui)
159 {
160 auto item = new Core::Item(host);
161 item->setGuest(this);
162 }
163
164 Size minSize() const override
165 {
166 return { 100, 100 };
167 }
168
169 Size maxSizeHint() const override
170 {
171 return { 1000, 1000 };
172 }
173
174 void setGeometry(Rect r) override
175 {
176 if (r == _geometry)
177 return;
178
179 _geometry = r;
180 update_model_row(descriptor(), ui);
181 }
182
183 DockWidgetDescriptor descriptor() const
184 {
185 return DockWidgetDescriptor { _isVisible, slint::SharedString(_uniqueName), float(_geometry.x()), float(geometry().y()), float(_geometry.width()), float(_geometry.height()) };
186 }
187
188 void setVisible(bool is) override
189 {
190 if (_isVisible == is)
191 return;
192
193 _isVisible = is;
194 update_model_row(descriptor(), ui);
195 }
196
197 Rect geometry() const override
198 {
199 return _geometry;
200 }
201
202 void setHost(Core::LayoutingHost *parent) override
203 {
204 if (_layoutingHost == parent)
205 return;
206
207 add_model_row(descriptor(), ui);
208 _layoutingHost = parent;
209 }
210
211 Core::LayoutingHost *host() const override
212 {
213 return _layoutingHost;
214 }
215
216 QString id() const override
217 {
218 return _uniqueName;
219 }
220
221 Core::LayoutingHost *_layoutingHost = nullptr;
222 QString _uniqueName;
223 slint::ComponentHandle<AppWindow> ui;
224 Rect _geometry;
225 bool _isVisible = false;
226};
227
228class Separator : public Core::LayoutingSeparator
229{
230public:
231 explicit Separator(Core::LayoutingHost *host, Qt::Orientation orientation, Core::ItemBoxContainer *container)
232 : Core::LayoutingSeparator(host, orientation, container)
233 , _host(static_cast<Host *>(host))
234 {
235 static int counter = 0;
236 _id = ++counter;
237
238 add_separator_model_row(descriptor(), this->_host->ui);
239 }
240
241 ~Separator() override
242 {
243 remove_separator_model_row(_id, _host->ui);
244 }
245
246 Rect
247 geometry() const override
248 {
249 return _geo;
250 }
251
252 void setGeometry(Rect g) override
253 {
254 if (g == _geo)
255 return;
256
257 _geo = g;
258 update_separator_model_row(descriptor(), _host->ui);
259 }
260
261 SeparatorDescriptor descriptor() const
262 {
263 return SeparatorDescriptor { float(_geo.x()), float(_geo.y()), float(_geo.width()), float(_geo.height()), _id, isVertical() };
264 }
265
266 Rect _geo;
267 int _id = 0;
268 Host *const _host;
269};
270
271Host::Host(slint::ComponentHandle<AppWindow> ui)
272 : ui(ui)
273
274{
275 m_rootItem = new Core::ItemBoxContainer(this);
276
277 ui->on_window_size_changed_callback([this](float w, float h) -> bool {
278 m_rootItem->setSize_recursive({ int(w), int(h) });
279 return true;
280 });
281
282 ui->on_separator_event([&](int id, slint::private_api::PointerEvent ev) {
283 if (Separator *separator = separatorForId(id)) {
284 if (ev.kind == slint::cbindgen_private::PointerEventKind::Down) {
285 separator->onMousePress();
286 } else if (ev.kind == slint::cbindgen_private::PointerEventKind::Up) {
287 separator->onMouseRelease();
288 }
289 } else {
290 std::cerr << "on_separator_event: Expected separator with id=" << id << "\n";
291 }
292 });
293
294 ui->on_separator_moved([&](int id, float x, float y) {
295 if (Separator *sep = separatorForId(id)) {
296 if (sep->isVertical()) {
297 const int oldPos = sep->position();
298 sep->onMouseMove({ 0, int(oldPos + y) });
299 } else {
300 const int oldPos = sep->position();
301 sep->onMouseMove({ int(oldPos + x), 0 });
302 }
303 } else {
304 std::cerr << "on_separator_moved: Expected separator with id=" << id << "\n";
305 }
306 });
307}
308
309Separator *Host::separatorForId(int id) const
310{
311 auto separators = static_cast<Core::ItemBoxContainer *>(m_rootItem)->separators_recursive();
312 for (auto separator : separators) {
313 auto slintSeparator = static_cast<Separator *>(separator);
314 if (slintSeparator->_id == id)
315 return slintSeparator;
316 }
317
318 return nullptr;
319}
320
321int main(int argc, char **argv)
322{
323 auto ui = AppWindow::create();
324 ui->set_image(slint::Image::load_from_path(SRC_DIR "/slint-logo-full-dark-large.png"));
325
327 Core::Item::setCreateSeparatorFunc([](Core::LayoutingHost *host, Qt::Orientation orientation, Core::ItemBoxContainer *container) -> Core::LayoutingSeparator * {
328 return new Separator(host, orientation, container);
329 });
330
331 Host host(ui);
332 auto guest1 = new Guest(&host, "1", ui);
333 auto guest2 = new Guest(&host, "2", ui);
334 auto guest3 = new Guest(&host, "3", ui);
335 auto guest4 = new Guest(&host, "4", ui);
336
337 host.insertItem(guest1, KDDockWidgets::Location_OnLeft);
338 host.insertItem(guest2, KDDockWidgets::Location_OnRight);
339 host.insertItemRelativeTo(guest3, /*relativeTo=*/guest2, KDDockWidgets::Location_OnBottom);
340 host.insertItem(guest4, KDDockWidgets::Location_OnTop, Size(0, 200));
341
342 ui->run();
343 return 0;
344}
Class to abstract QAction, so code still works with QtQuick and Flutter.
@ Location_OnTop
‍Left docking location
@ Location_OnRight
‍Top docking location
@ Location_OnBottom
‍Right docking location
Orientation
void setGeometry(int x, int y, int w, int h)
int main(int argc, char **argv)

© Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
KDDockWidgets
Advanced Dock Widget Framework for Qt
https://www.kdab.com/development-resources/qt-tools/kddockwidgets/
Generated by doxygen 1.9.8