KDDockWidgets API Documentation 2.1
Loading...
Searching...
No Matches
FocusScope.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
19#include "FocusScope.h"
20#include "Platform.h"
21#include "ViewGuard.h"
22#include "core/DockWidget.h"
23#include "core/Group.h"
24#include "DockRegistry.h"
25#include "core/Platform_p.h"
26#include "core/Logging_p.h"
27#include "core/ViewGuard.h"
28#include "View.h"
30
31using namespace KDDockWidgets;
32using namespace KDDockWidgets::Core;
33
34class FocusScope::Private
35{
36public:
37 Private(FocusScope *qq, View *thisView)
38 : q(qq)
39 , m_thisView(thisView)
40 {
41 auto plat = Platform::instance();
42 m_connection = plat->d->focusedViewChanged.connect(&Private::onFocusedViewChanged, this);
43
44 onFocusedViewChanged(plat->focusedView());
45
46 // NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
47 m_inCtor = false;
48 }
49
51 bool lastFocusedIsTabWidget() const
52 {
53 return m_lastFocusedInScope && !m_lastFocusedInScope->isNull()
54 && m_lastFocusedInScope->is(ViewType::Stack);
55 }
56
57 ~Private();
58
59 void setIsFocused(bool);
60 void onFocusedViewChanged(std::shared_ptr<View> view);
61 bool isInFocusScope(std::shared_ptr<View> view) const;
62
63 FocusScope *const q;
64 ViewGuard m_thisView;
65 bool m_isFocused = false;
66 bool m_inCtor = true;
67 std::shared_ptr<View> m_lastFocusedInScope;
69};
70
71FocusScope::Private::~Private()
72{
73 m_connection.disconnect();
74}
75
77 : d(new Private(this, thisView))
78{
79}
80
82{
83 delete d;
84}
85
87{
88 return d->m_isFocused;
89}
90
92{
93 // Note: For QtQuick, qGuiApp->focusObject().isVisible() can be false! Because QtQuick.
94
95 if (d->m_lastFocusedInScope && !d->m_lastFocusedInScope->isNull() && d->m_lastFocusedInScope->isVisible()
96 && !d->lastFocusedIsTabWidget()) {
97 // When we focus the FocusScope, we give focus to the last focused widget, but let's
98 // do better than focusing a tab widget. The tab widget itself being focused isn't
99 // very useful.
100 d->m_lastFocusedInScope->setFocus(reason);
101 } else {
102 if (auto group = d->m_thisView->asGroupController()) {
103 if (auto dw = group->currentDockWidget()) {
104 if (auto dwView = dynamic_cast<Core::DockWidgetViewInterface *>(dw->view())) {
105 if (auto candidate = dwView->focusCandidate()) {
106 if (candidate->focusPolicy() != Qt::NoFocus) {
107 KDDW_DEBUG("FocusScope::focus: Setting focus on candidate!");
108 candidate->setFocus(reason);
109 } else {
110 KDDW_DEBUG("FocusScope::focus: Candidate has no focus policy");
111 }
112 } else {
113 KDDW_DEBUG("FocusScope::focus: Candidate not found");
114 }
115 } else {
116 KDDW_DEBUG("FocusScope::focus: Dw doesn't have view");
117 }
118 } else {
119 KDDW_DEBUG("FocusScope::focus: Group doesn't have current DW");
120 }
121 } else {
122 // Not a use case right now
123 KDDW_DEBUG("FocusScope::focus: No group found");
124 d->m_thisView->setFocus(reason);
125 }
126 }
127}
128
129void FocusScope::Private::setIsFocused(bool is)
130{
131 if (is != m_isFocused) {
132 m_isFocused = is;
133
134 if (!m_inCtor) // Hack so we don't call pure-virtual
135 /* Q_EMIT */ q->isFocusedChangedCallback();
136 }
137}
138
139void FocusScope::Private::onFocusedViewChanged(std::shared_ptr<View> view)
140{
141 if (!view || view->isNull()) {
142 setIsFocused(false);
143 return;
144 }
145
146 const bool is = isInFocusScope(view);
147 const bool focusViewChanged = !m_lastFocusedInScope || m_lastFocusedInScope->isNull()
148 || !m_lastFocusedInScope->equals(view);
149 if (is && focusViewChanged && !view->is(ViewType::TitleBar)) {
150 m_lastFocusedInScope = view;
151 setIsFocused(is);
152 /* Q_EMIT */ q->focusedWidgetChangedCallback();
153 } else {
154 setIsFocused(is);
155 }
156}
157
158bool FocusScope::Private::isInFocusScope(std::shared_ptr<View> view) const
159{
160 if (m_thisView.isNull())
161 return false;
162
163 auto p = (view && !view->isNull()) ? view : std::shared_ptr<View>();
164 while (p) {
165 if (p->handle() == m_thisView->handle())
166 return true;
167
168 p = p->parentView();
169 }
170
171 return false;
172}
FocusScope.
A ConnectionHandle represents the connection of a Signal to a slot (i.e. a function that is called wh...
Definition signal.h:68
The interface that DockWidget views should implement.
Allows to implement a similar functionality to QtQuick's FocusScope item, in QtWidgets.
Definition FocusScope.h:31
bool isFocused() const
Returns true if this FocusScope is focused. This is similar to the QWidget::hasFocus(),...
void focus(Qt::FocusReason=Qt::OtherFocusReason)
Sets focus on this scope.
FocusScope(View *thisView)
constructor
static Platform * instance()
Returns the platform singleton.
This class provides a weak reference to a view i.e., it becomes null automatically once a View is des...
Definition ViewGuard.h:27
virtual std::shared_ptr< View > parentView() const =0
Returns the gui element's parent. Like QWidget::parentWidget()
std::shared_ptr< Core::View > focusedView() const override
Returns the focused view, if any.
The DockWidget controller that's shared between QtWidgets and QtQuick frontends.
Class to abstract QAction, so code still works with QtQuick and Flutter.
QtQuick::Platform * plat()
Definition utils.h:161
FocusReason

© 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