Kirigami2

toolbarlayoutdelegate.cpp
1 /*
2  * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <[email protected]>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5  */
6 
7 #include "toolbarlayoutdelegate.h"
8 
9 #include "loggingcategory.h"
10 #include "toolbarlayout.h"
11 
12 ToolBarDelegateIncubator::ToolBarDelegateIncubator(QQmlComponent *component, QQmlContext *context)
14  , m_component(component)
15  , m_context(context)
16 {
17 }
18 
19 void ToolBarDelegateIncubator::setStateCallback(std::function<void(QQuickItem *)> callback)
20 {
21  m_stateCallback = callback;
22 }
23 
24 void ToolBarDelegateIncubator::setCompletedCallback(std::function<void(ToolBarDelegateIncubator *)> callback)
25 {
26  m_completedCallback = callback;
27 }
28 
29 void ToolBarDelegateIncubator::create()
30 {
31  m_component->create(*this, m_context);
32 }
33 
34 bool ToolBarDelegateIncubator::isFinished()
35 {
36  return m_finished;
37 }
38 
39 void ToolBarDelegateIncubator::setInitialState(QObject *object)
40 {
41  auto item = qobject_cast<QQuickItem *>(object);
42  if (item) {
43  m_stateCallback(item);
44  }
45 }
46 
47 void ToolBarDelegateIncubator::statusChanged(QQmlIncubator::Status status)
48 {
50  qCWarning(KirigamiLog) << "Could not create delegate for ToolBarLayout";
51  const auto e = errors();
52  for (const auto &error : e) {
53  qCWarning(KirigamiLog) << error;
54  }
55  m_finished = true;
56  }
57 
59  m_completedCallback(this);
60  m_finished = true;
61  }
62 }
63 
64 ToolBarLayoutDelegate::ToolBarLayoutDelegate(ToolBarLayout *parent)
65  : QObject() // Note: delegates are managed by unique_ptr, so don't parent
66  , m_parent(parent)
67 {
68 }
69 
70 ToolBarLayoutDelegate::~ToolBarLayoutDelegate()
71 {
72  if (m_fullIncubator) {
73  m_fullIncubator->clear();
74  delete m_fullIncubator;
75  }
76  if (m_iconIncubator) {
77  m_iconIncubator->clear();
78  delete m_iconIncubator;
79  }
80  if (m_full) {
81  m_full->disconnect(this);
82  delete m_full;
83  }
84  if (m_icon) {
85  m_icon->disconnect(this);
86  delete m_icon;
87  }
88 }
89 
90 QObject *ToolBarLayoutDelegate::action() const
91 {
92  return m_action;
93 }
94 
95 void ToolBarLayoutDelegate::setAction(QObject *action)
96 {
97  if (action == m_action) {
98  return;
99  }
100 
101  if (m_action) {
102  QObject::disconnect(m_action, SIGNAL(visibleChanged()), this, SLOT(actionVisibleChanged()));
103  QObject::disconnect(m_action, SIGNAL(displayHintChanged()), this, SLOT(displayHintChanged()));
104  }
105 
106  m_action = action;
107  if (m_action) {
108  if (m_action->property("visible").isValid()) {
109  QObject::connect(m_action, SIGNAL(visibleChanged()), this, SLOT(actionVisibleChanged()));
110  m_actionVisible = m_action->property("visible").toBool();
111  }
112 
113  if (m_action->property("displayHint").isValid()) {
114  QObject::connect(m_action, SIGNAL(displayHintChanged()), this, SLOT(displayHintChanged()));
115  m_displayHint = DisplayHint::DisplayHints{m_action->property("displayHint").toInt()};
116  }
117  }
118 }
119 
120 void ToolBarLayoutDelegate::createItems(QQmlComponent *fullComponent, QQmlComponent *iconComponent, std::function<void(QQuickItem *)> callback)
121 {
122  m_fullIncubator = new ToolBarDelegateIncubator(fullComponent, qmlContext(fullComponent));
123  m_fullIncubator->setStateCallback(callback);
124  m_fullIncubator->setCompletedCallback([this](ToolBarDelegateIncubator *incubator) {
125  if (incubator->isError()) {
126  qCWarning(KirigamiLog) << "Could not create delegate for ToolBarLayout";
127  const auto errors = incubator->errors();
128  for (const auto &error : errors) {
129  qCWarning(KirigamiLog) << error;
130  }
131  return;
132  }
133 
134  m_full = qobject_cast<QQuickItem *>(incubator->object());
135  m_full->setVisible(false);
136  connect(m_full, &QQuickItem::widthChanged, this, [this]() {
137  m_parent->relayout();
138  });
139  connect(m_full, &QQuickItem::heightChanged, this, [this]() {
140  m_parent->relayout();
141  });
142  connect(m_full, &QQuickItem::visibleChanged, this, &ToolBarLayoutDelegate::ensureItemVisibility);
143 
144  if (m_icon) {
145  m_ready = true;
146  }
147 
148  m_parent->relayout();
149 
150  QMetaObject::invokeMethod(this, &ToolBarLayoutDelegate::cleanupIncubators, Qt::QueuedConnection);
151  });
152  m_iconIncubator = new ToolBarDelegateIncubator(iconComponent, qmlContext(iconComponent));
153  m_iconIncubator->setStateCallback(callback);
154  m_iconIncubator->setCompletedCallback([this](ToolBarDelegateIncubator *incubator) {
155  if (incubator->isError()) {
156  qCWarning(KirigamiLog) << "Could not create delegate for ToolBarLayout";
157  const auto errors = incubator->errors();
158  for (const auto &error : errors) {
159  qCWarning(KirigamiLog) << error;
160  }
161  return;
162  }
163 
164  m_icon = qobject_cast<QQuickItem *>(incubator->object());
165  m_icon->setVisible(false);
166  connect(m_icon, &QQuickItem::widthChanged, this, [this]() {
167  m_parent->relayout();
168  });
169  connect(m_icon, &QQuickItem::heightChanged, this, [this]() {
170  m_parent->relayout();
171  });
172  connect(m_icon, &QQuickItem::visibleChanged, this, &ToolBarLayoutDelegate::ensureItemVisibility);
173 
174  if (m_full) {
175  m_ready = true;
176  }
177 
178  m_parent->relayout();
179 
180  QMetaObject::invokeMethod(this, &ToolBarLayoutDelegate::cleanupIncubators, Qt::QueuedConnection);
181  });
182 
183  m_fullIncubator->create();
184  m_iconIncubator->create();
185 }
186 
187 bool ToolBarLayoutDelegate::isReady() const
188 {
189  return m_ready;
190 }
191 
192 bool ToolBarLayoutDelegate::isActionVisible() const
193 {
194  return m_actionVisible;
195 }
196 
197 bool ToolBarLayoutDelegate::isHidden() const
198 {
199  return DisplayHint::isDisplayHintSet(m_displayHint, DisplayHint::AlwaysHide);
200 }
201 
202 bool ToolBarLayoutDelegate::isIconOnly() const
203 {
204  return DisplayHint::isDisplayHintSet(m_displayHint, DisplayHint::IconOnly);
205 }
206 
207 bool ToolBarLayoutDelegate::isKeepVisible() const
208 {
209  return DisplayHint::isDisplayHintSet(m_displayHint, DisplayHint::KeepVisible);
210 }
211 
212 bool ToolBarLayoutDelegate::isVisible() const
213 {
214  return m_iconVisible || m_fullVisible;
215 }
216 
217 void ToolBarLayoutDelegate::hide()
218 {
219  m_iconVisible = false;
220  m_fullVisible = false;
221  ensureItemVisibility();
222 }
223 
224 void ToolBarLayoutDelegate::showFull()
225 {
226  m_iconVisible = false;
227  m_fullVisible = true;
228 }
229 
230 void ToolBarLayoutDelegate::showIcon()
231 {
232  m_iconVisible = true;
233  m_fullVisible = false;
234 }
235 
236 void ToolBarLayoutDelegate::show()
237 {
238  ensureItemVisibility();
239 }
240 
241 void ToolBarLayoutDelegate::setPosition(qreal x, qreal y)
242 {
243  m_full->setX(x);
244  m_icon->setX(x);
245  m_full->setY(y);
246  m_icon->setY(y);
247 }
248 
249 void ToolBarLayoutDelegate::setHeight(qreal height)
250 {
251  m_full->setHeight(height);
252  m_icon->setHeight(height);
253 }
254 
255 qreal ToolBarLayoutDelegate::width() const
256 {
257  if (m_iconVisible) {
258  return m_icon->width();
259  }
260  return m_full->width();
261 }
262 
263 qreal ToolBarLayoutDelegate::height() const
264 {
265  if (m_iconVisible) {
266  return m_icon->height();
267  }
268  return m_full->height();
269 }
270 
271 qreal ToolBarLayoutDelegate::implicitWidth() const
272 {
273  if (m_iconVisible) {
274  return m_icon->implicitWidth();
275  }
276  return m_full->implicitWidth();
277 }
278 
279 qreal ToolBarLayoutDelegate::implicitHeight() const
280 {
281  if (m_iconVisible) {
282  return m_icon->implicitHeight();
283  }
284  return m_full->implicitHeight();
285 }
286 
287 qreal ToolBarLayoutDelegate::maxHeight() const
288 {
289  return std::max(m_full->height(), m_icon->height());
290 }
291 
292 qreal ToolBarLayoutDelegate::iconWidth() const
293 {
294  return m_icon->width();
295 }
296 
297 qreal ToolBarLayoutDelegate::fullWidth() const
298 {
299  return m_full->width();
300 }
301 
302 void ToolBarLayoutDelegate::actionVisibleChanged()
303 {
304  m_actionVisible = m_action->property("visible").toBool();
305  m_parent->relayout();
306 }
307 
308 void ToolBarLayoutDelegate::displayHintChanged()
309 {
310  m_displayHint = DisplayHint::DisplayHints{m_action->property("displayHint").toInt()};
311  m_parent->relayout();
312 }
313 
314 void ToolBarLayoutDelegate::cleanupIncubators()
315 {
316  if (m_fullIncubator && m_fullIncubator->isFinished()) {
317  delete m_fullIncubator;
318  m_fullIncubator = nullptr;
319  }
320 
321  if (m_iconIncubator && m_iconIncubator->isFinished()) {
322  delete m_iconIncubator;
323  m_iconIncubator = nullptr;
324  }
325 }
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Q_SCRIPTABLE CaptureState status()
QueuedConnection
void heightChanged()
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
An item that creates delegates for actions and lays them out in a row.
Definition: toolbarlayout.h:46
bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9)
void visibleChanged()
void widthChanged()
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Feb 7 2023 04:14:24 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.