KDDockWidgets API Documentation  1.5
FocusScope.cpp
Go to the documentation of this file.
1 /*
2  This file is part of KDDockWidgets.
3 
4  SPDX-FileCopyrightText: 2019-2022 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 "DockWidgetBase.h"
21 
22 #include "private/TitleBar_p.h"
23 #include "private/Frame_p.h"
24 #include "private/DockRegistry_p.h"
25 
26 #include <QObject>
27 #include <QGuiApplication>
28 #include <QPointer>
29 
30 using namespace KDDockWidgets;
31 
32 // Our Private inherits from QObject since FocusScope can't (Since Frame is already QObject)
33 class FocusScope::Private : public QObject //clazy:exclude=missing-qobject-macro (breaks unity build with earlier cmake due to including .moc here.)
34 {
35 public:
36  Private(FocusScope *qq, QWidgetAdapter *thisWidget)
37  : q(qq)
38  , m_thisWidget(thisWidget)
39  {
41  this, &Private::onFocusObjectChanged);
42 
43  onFocusObjectChanged(qApp->focusObject());
44  m_inCtor = false;
45  }
46 
48  bool lastFocusedIsTabWidget() const
49  {
50  if (!m_lastFocusedInScope)
51  return false;
52 
53  if (auto metaObj = m_lastFocusedInScope->metaObject()) {
54  const auto className = QLatin1String(metaObj->className());
55 
56  return className == QLatin1String("KDDockWidgets::TabBarWidget")
57  || className == QLatin1String("KDDockWidgets::TabBarQuick");
58  }
59 
60  return false;
61  }
62 
63  ~Private() override;
64 
65  void setIsFocused(bool);
66  void onFocusObjectChanged(QObject *);
67  bool isInFocusScope(WidgetType *) const;
68 
69  FocusScope *const q;
70  QWidgetAdapter *const m_thisWidget;
71  bool m_isFocused = false;
72  bool m_inCtor = true;
73  QPointer<WidgetType> m_lastFocusedInScope;
74 };
75 
76 FocusScope::Private::~Private()
77 {
78 }
79 
80 FocusScope::FocusScope(QWidgetAdapter *thisWidget)
81  : d(new Private(this, thisWidget))
82 {
83 }
84 
86 {
87  delete d;
88 }
89 
91 {
92  return d->m_isFocused;
93 }
94 
96 {
97  return d->m_lastFocusedInScope;
98 }
99 
101 {
102  if (d->m_lastFocusedInScope && !d->lastFocusedIsTabWidget()) {
103  // When we focus the FocusScope, we give focus to the last focused widget, but let's
104  // do better than focusing a tab widget. The tab widget itself being focused isn't
105  // very useful.
106  d->m_lastFocusedInScope->setFocus(reason);
107  } else {
108  if (auto frame = qobject_cast<Frame *>(d->m_thisWidget)) {
109  if (DockWidgetBase *dw = frame->currentDockWidget()) {
110  if (auto guest = dw->widget()) {
111  if (guest->focusPolicy() != Qt::NoFocus)
112  guest->setFocus(reason);
113  }
114  }
115  } else {
116  // Not a use case right now
117  d->m_thisWidget->setFocus(reason);
118  }
119  }
120 }
121 
122 void FocusScope::Private::setIsFocused(bool is)
123 {
124  if (is != m_isFocused) {
125  m_isFocused = is;
126 
127  if (!m_inCtor) // Hack so we don't call pure-virtual
128  /* Q_EMIT */ q->isFocusedChangedCallback();
129  }
130 }
131 
132 void FocusScope::Private::onFocusObjectChanged(QObject *obj)
133 {
134  auto widget = qobject_cast<WidgetType *>(obj);
135  if (!widget) {
136  setIsFocused(false);
137  return;
138  }
139 
140  const bool is = isInFocusScope(widget);
141  if (is && m_lastFocusedInScope != widget && !qobject_cast<TitleBar *>(obj)) {
142  m_lastFocusedInScope = widget;
143  setIsFocused(is);
144  /* Q_EMIT */ q->focusedWidgetChangedCallback();
145  } else {
146  setIsFocused(is);
147  }
148 }
149 
150 bool FocusScope::Private::isInFocusScope(WidgetType *widget) const
151 {
152  WidgetType *p = widget;
153  while (p) {
154  if (p == m_thisWidget)
155  return true;
156 
157  p = KDDockWidgets::Private::parentWidget(p);
158  }
159 
160  return false;
161 }
QPointer
DockWidgetBase.h
The DockWidget base-class that's shared between QtWidgets and QtQuick stack.
FocusScope.h
FocusScope.
KDDockWidgets::FocusScope::focus
void focus(Qt::FocusReason=Qt::OtherFocusReason)
Sets focus on this scope.
Definition: FocusScope.cpp:100
QWidget
KDDockWidgets::FocusScope::FocusScope
FocusScope(QWidgetAdapter *thisWidget)
constructor
Definition: FocusScope.cpp:80
KDDockWidgets::FocusScope::~FocusScope
virtual ~FocusScope()
Definition: FocusScope.cpp:85
KDDockWidgets::FocusScope
Allows to implement a similar functionality to QtQuick's FocusScope item, in QtWidgets.
Definition: FocusScope.h:28
KDDockWidgets::FocusScope::isFocused
bool isFocused() const
Returns true if this FocusScope is focused. This is similar to the QWidget::hasFocus(),...
Definition: FocusScope.cpp:90
QObject
Qt::FocusReason
FocusReason
QLatin1String
KDDockWidgets::FocusScope::focusedWidget
WidgetType * focusedWidget() const
Returns the widget that's focused in this scope The widget itself might not have focus as in QWidget:...
Definition: FocusScope.cpp:95
QGuiApplication::focusObjectChanged
void focusObjectChanged(QObject *focusObject)
KDDockWidgets::DockWidgetBase
The DockWidget base-class. DockWidget and DockWidgetBase are only split in two so we can share some c...
Definition: DockWidgetBase.h:61
KDDockWidgets
Definition: Config.cpp:36
Qt::NoFocus
NoFocus

© 2019-2022 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 on Mon Mar 7 2022 02:01:20 for KDDockWidgets API Documentation by doxygen 1.8.20