KDDockWidgets API Documentation 2.1
Loading...
Searching...
No Matches
qtquick/views/ClassicIndicatorsWindow.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2019 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
13#include "core/DropIndicatorOverlay_p.h"
14#include "kddockwidgets/core/indicators/ClassicDropIndicatorOverlay.h"
15#include "core/Utils_p.h"
16#include "qtquick/Platform.h"
17#include "View.h"
18
19#include <QQmlContext>
20#include <QQmlEngine>
21#include <QQuickItem>
22
23using namespace KDDockWidgets;
24using namespace KDDockWidgets::QtQuick;
25
26namespace KDDockWidgets {
27
28static QString iconName(DropLocation loc, bool active)
29{
30 QString suffix = active ? QStringLiteral("_active") : QString();
31
32 QString name;
33 switch (loc) {
35 name = QStringLiteral("center");
36 break;
38 name = QStringLiteral("inner_left");
39 break;
41 name = QStringLiteral("inner_right");
42 break;
44 name = QStringLiteral("inner_bottom");
45 break;
47 name = QStringLiteral("inner_top");
48 break;
50 name = QStringLiteral("outter_left");
51 break;
53 name = QStringLiteral("outter_bottom");
54 break;
56 name = QStringLiteral("outter_right");
57 break;
59 name = QStringLiteral("outter_top");
60 break;
66 return QString();
67 }
68
69 return name + suffix;
70}
71}
72
75 , m_classicIndicators(classicIndicators)
76 , m_window(isWayland() ? nullptr : new IndicatorWindow())
77{
78 Q_ASSERT(parent);
79 classicIndicators->dptr()->hoveredGroupRectChanged.connect([this] { hoveredGroupRectChanged(); });
80 classicIndicators->dptr()->currentDropLocationChanged.connect([this] { currentDropLocationChanged(); });
81
82 if (isWayland()) {
83 auto subContext = new QQmlContext(plat()->qmlEngine()->rootContext(), this);
84 subContext->setContextProperty(QStringLiteral("_kddw_overlayWindow"), this);
85 m_overlayItem = QtQuick::View::createItem(qmlSouceUrl().toString(), QtQuick::asView_qtquick(parent), subContext);
86 Q_ASSERT(m_overlayItem);
87 View::makeItemFillParent(m_overlayItem);
88 m_overlayItem->setZ(2);
89 } else {
90 m_window->rootContext()->setContextProperty(QStringLiteral("_kddw_overlayWindow"), this);
91 m_window->init(qmlSouceUrl());
92 }
93}
94
96{
97 delete m_window;
98 delete m_overlayItem;
99}
100
102{
103 return KDDockWidgets::iconName(DropLocation(loc), active);
104}
105
110
115
120
125
130
135
140
145
150
152{
153 return m_classicIndicators->hoveredGroupRect();
154}
155
157{
158 return m_classicIndicators->currentDropLocation();
159}
160
162{
163 QQuickItem *item = indicatorForPos(pt);
164 return item ? locationForIndicator(item) : DropLocation_None;
165}
166
171
172QQuickItem *ClassicDropIndicatorOverlay::indicatorForPos(QPoint pt) const
173{
174 const QVector<QQuickItem *> indicators = indicatorItems();
175 Q_ASSERT(indicators.size() == 9);
176
177 for (QQuickItem *item : indicators) {
178 if (item->isVisible()) {
179 QRect rect(0, 0, int(item->width()), int(item->height()));
180 rect.moveTopLeft(item->mapToGlobal(QPointF(0, 0)).toPoint());
181 if (rect.contains(pt)) {
182 return item;
183 }
184 }
185 }
186
187 return nullptr;
188}
189
191{
192 // Not needed to implement, the Indicators use QML anchors
193}
194
196{
197 QQuickItem *indicator = ClassicDropIndicatorOverlay::indicatorForLocation(loc);
198 return indicator->mapToGlobal(indicator->boundingRect().center()).toPoint();
199}
200
206
208
209void IndicatorWindow::init(const QUrl &rootQml)
210{
211 setSource(rootQml);
212
213 // Two workarounds for two unrelated bugs:
214 if (KDDockWidgets::isOffscreen()) {
215 // 1. We need to create the window asap, otherwise, if a drag triggers the indicator window
216 // to show, that creates a QOffscreenWindow, which flushes events in the ctor, triggering
217 // more hover events which will trigger another QOffscreenWindow.
218 // We then end up with a QWindow with two QPlatformWindow, and only one is deleted in
219 // at shutdown, meaning some timers aren't unregistered, meaning we get a crash when
220 // the timer event is sent to the destroyed QWindow.
221 create();
222 } else {
223 // 2.
224 // Small hack to avoid flickering when we drag over a window the first time
225 // Not sure why a simply create() doesn't work instead
226 // Not if offscreen though, as that QPA is flaky with window activation/focus
227 resize(QSize(1, 1));
228 show();
229 hide();
230 }
231}
232
233QUrl ClassicDropIndicatorOverlay::qmlSouceUrl() const
234{
235 return QUrl(QStringLiteral("qrc:/kddockwidgets/qtquick/views/qml/ClassicIndicatorsOverlay.qml"));
236}
237
239{
240 const QVector<QQuickItem *> indicators = indicatorItems();
241 Q_ASSERT(indicators.size() == 9);
242
243 for (QQuickItem *item : indicators) {
244 if (locationForIndicator(item) == loc)
245 return item;
246 }
247
248 qWarning() << Q_FUNC_INFO << "Couldn't find indicator for location" << loc;
249 return nullptr;
250}
251
252DropLocation ClassicDropIndicatorOverlay::locationForIndicator(const QQuickItem *item) const
253{
254 return DropLocation(item->property("indicatorType").toInt());
255}
256
257QVector<QQuickItem *> ClassicDropIndicatorOverlay::indicatorItems() const
258{
259 QVector<QQuickItem *> indicators;
260 indicators.reserve(9);
261
262 QQuickItem *root = m_window ? m_window->rootObject() : m_overlayItem;
263 const QList<QQuickItem *> items = root->childItems();
264 for (QQuickItem *item : items) {
265 if (QString::fromLatin1(item->metaObject()->className())
266 .startsWith(QLatin1String("ClassicIndicator_QMLTYPE"))) {
267 indicators.push_back(item);
268 } else if (item->objectName() == QLatin1String("innerIndicators")) {
269 const QList<QQuickItem *> innerIndicators = item->childItems();
270 for (QQuickItem *innerItem : innerIndicators) {
271 if (QString::fromLatin1(innerItem->metaObject()->className())
272 .startsWith(QLatin1String("ClassicIndicator_QMLTYPE"))) {
273 indicators.push_back(innerItem);
274 }
275 }
276 }
277 }
278
279 return indicators;
280}
282{
283 if (m_window) {
284 m_window->raise();
285 } else {
286 // The wayland item has an higher Z, no need to raise
287 }
288}
289
291{
292 if (m_window) {
293 m_window->setGeometry(geo);
294 } else {
295 // The wayland item has "anchors.fill: parent", no need to resize
296 }
297}
298
303
305{
306 if (m_window) {
307 m_window->setVisible(is);
308 } else {
309 // Wayland case
310 m_overlayItem->setVisible(is);
311 }
312}
313
315{
316 if (m_window) {
317 m_window->resize(sz);
318 } else {
319 // The wayland item has "anchors.fill: parent", no need to resize
320 }
321}
322
324{
325 return m_window != nullptr;
326}
virtual bool dropIndicatorVisible(DropLocation) const
Returns whether the specified drop indicator should be visible.
ClassicDropIndicatorOverlay(Core::ClassicDropIndicatorOverlay *, Core::View *parent)
static QQuickItem * createItem(QQmlEngine *engine, const QString &filename, QQmlContext *context=nullptr)
Convenience to create a QQuickItem.
static void makeItemFillParent(QQuickItem *item)
This is equivalent to "anchors.fill: parent but in C++.
View * asView_qtquick(Core::View *view)
Class to abstract QAction, so code still works with QtQuick and Flutter.
QtQuick::Platform * plat()
DropLocation
Enum describing the different drop indicator types.
static QString iconName(DropLocation loc, bool active)
Q_EMITQ_EMIT
void setObjectName(const QString &name)
QObject * parent() const const
QString fromLatin1(const char *str, int size)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
transparent
FramelessWindowHint
void push_back(const T &value)
void reserve(int size)
int size() const const

© 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