File indexing completed on 2024-04-28 07:44:50
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "toolbarlayoutdelegate.h" 0008 0009 #include "loggingcategory.h" 0010 #include "toolbarlayout.h" 0011 0012 ToolBarDelegateIncubator::ToolBarDelegateIncubator(QQmlComponent *component, QQmlContext *context) 0013 : QQmlIncubator(QQmlIncubator::Asynchronous) 0014 , m_component(component) 0015 , m_context(context) 0016 { 0017 } 0018 0019 void ToolBarDelegateIncubator::setStateCallback(std::function<void(QQuickItem *)> callback) 0020 { 0021 m_stateCallback = callback; 0022 } 0023 0024 void ToolBarDelegateIncubator::setCompletedCallback(std::function<void(ToolBarDelegateIncubator *)> callback) 0025 { 0026 m_completedCallback = callback; 0027 } 0028 0029 void ToolBarDelegateIncubator::create() 0030 { 0031 m_component->create(*this, m_context); 0032 } 0033 0034 bool ToolBarDelegateIncubator::isFinished() 0035 { 0036 return m_finished; 0037 } 0038 0039 void ToolBarDelegateIncubator::setInitialState(QObject *object) 0040 { 0041 auto item = qobject_cast<QQuickItem *>(object); 0042 if (item) { 0043 m_stateCallback(item); 0044 } 0045 } 0046 0047 void ToolBarDelegateIncubator::statusChanged(QQmlIncubator::Status status) 0048 { 0049 if (status == QQmlIncubator::Error) { 0050 qCWarning(KirigamiLog) << "Could not create delegate for ToolBarLayout"; 0051 const auto e = errors(); 0052 for (const auto &error : e) { 0053 qCWarning(KirigamiLog) << error; 0054 } 0055 m_finished = true; 0056 } 0057 0058 if (status == QQmlIncubator::Ready) { 0059 m_completedCallback(this); 0060 m_finished = true; 0061 } 0062 } 0063 0064 ToolBarLayoutDelegate::ToolBarLayoutDelegate(ToolBarLayout *parent) 0065 : QObject() // Note: delegates are managed by unique_ptr, so don't parent 0066 , m_parent(parent) 0067 { 0068 } 0069 0070 ToolBarLayoutDelegate::~ToolBarLayoutDelegate() 0071 { 0072 if (m_fullIncubator) { 0073 m_fullIncubator->clear(); 0074 delete m_fullIncubator; 0075 } 0076 if (m_iconIncubator) { 0077 m_iconIncubator->clear(); 0078 delete m_iconIncubator; 0079 } 0080 if (m_full) { 0081 m_full->disconnect(this); 0082 delete m_full; 0083 } 0084 if (m_icon) { 0085 m_icon->disconnect(this); 0086 delete m_icon; 0087 } 0088 } 0089 0090 QObject *ToolBarLayoutDelegate::action() const 0091 { 0092 return m_action; 0093 } 0094 0095 void ToolBarLayoutDelegate::setAction(QObject *action) 0096 { 0097 if (action == m_action) { 0098 return; 0099 } 0100 0101 if (m_action) { 0102 QObject::disconnect(m_action, SIGNAL(visibleChanged()), this, SLOT(actionVisibleChanged())); 0103 QObject::disconnect(m_action, SIGNAL(displayHintChanged()), this, SLOT(displayHintChanged())); 0104 } 0105 0106 m_action = action; 0107 if (m_action) { 0108 if (m_action->property("visible").isValid()) { 0109 QObject::connect(m_action, SIGNAL(visibleChanged()), this, SLOT(actionVisibleChanged())); 0110 m_actionVisible = m_action->property("visible").toBool(); 0111 } 0112 0113 if (m_action->property("displayHint").isValid()) { 0114 QObject::connect(m_action, SIGNAL(displayHintChanged()), this, SLOT(displayHintChanged())); 0115 m_displayHint = DisplayHint::DisplayHints{m_action->property("displayHint").toInt()}; 0116 } 0117 } 0118 } 0119 0120 void ToolBarLayoutDelegate::createItems(QQmlComponent *fullComponent, QQmlComponent *iconComponent, std::function<void(QQuickItem *)> callback) 0121 { 0122 m_fullIncubator = new ToolBarDelegateIncubator(fullComponent, qmlContext(fullComponent)); 0123 m_fullIncubator->setStateCallback(callback); 0124 m_fullIncubator->setCompletedCallback([this](ToolBarDelegateIncubator *incubator) { 0125 if (incubator->isError()) { 0126 qCWarning(KirigamiLog) << "Could not create delegate for ToolBarLayout"; 0127 const auto errors = incubator->errors(); 0128 for (const auto &error : errors) { 0129 qCWarning(KirigamiLog) << error; 0130 } 0131 return; 0132 } 0133 0134 m_full = qobject_cast<QQuickItem *>(incubator->object()); 0135 m_full->setVisible(false); 0136 connect(m_full, &QQuickItem::implicitWidthChanged, this, &ToolBarLayoutDelegate::triggerRelayout); 0137 connect(m_full, &QQuickItem::implicitHeightChanged, this, &ToolBarLayoutDelegate::triggerRelayout); 0138 connect(m_full, &QQuickItem::visibleChanged, this, &ToolBarLayoutDelegate::ensureItemVisibility); 0139 0140 if (m_icon) { 0141 m_ready = true; 0142 } 0143 0144 m_parent->relayout(); 0145 0146 QMetaObject::invokeMethod(this, &ToolBarLayoutDelegate::cleanupIncubators, Qt::QueuedConnection); 0147 }); 0148 m_iconIncubator = new ToolBarDelegateIncubator(iconComponent, qmlContext(iconComponent)); 0149 m_iconIncubator->setStateCallback(callback); 0150 m_iconIncubator->setCompletedCallback([this](ToolBarDelegateIncubator *incubator) { 0151 if (incubator->isError()) { 0152 qCWarning(KirigamiLog) << "Could not create delegate for ToolBarLayout"; 0153 const auto errors = incubator->errors(); 0154 for (const auto &error : errors) { 0155 qCWarning(KirigamiLog) << error; 0156 } 0157 return; 0158 } 0159 0160 m_icon = qobject_cast<QQuickItem *>(incubator->object()); 0161 m_icon->setVisible(false); 0162 connect(m_icon, &QQuickItem::implicitWidthChanged, this, &ToolBarLayoutDelegate::triggerRelayout); 0163 connect(m_icon, &QQuickItem::implicitHeightChanged, this, &ToolBarLayoutDelegate::triggerRelayout); 0164 connect(m_icon, &QQuickItem::visibleChanged, this, &ToolBarLayoutDelegate::ensureItemVisibility); 0165 0166 if (m_full) { 0167 m_ready = true; 0168 } 0169 0170 m_parent->relayout(); 0171 0172 QMetaObject::invokeMethod(this, &ToolBarLayoutDelegate::cleanupIncubators, Qt::QueuedConnection); 0173 }); 0174 0175 m_fullIncubator->create(); 0176 m_iconIncubator->create(); 0177 } 0178 0179 bool ToolBarLayoutDelegate::isReady() const 0180 { 0181 return m_ready; 0182 } 0183 0184 bool ToolBarLayoutDelegate::isActionVisible() const 0185 { 0186 return m_actionVisible; 0187 } 0188 0189 bool ToolBarLayoutDelegate::isHidden() const 0190 { 0191 return DisplayHint::isDisplayHintSet(m_displayHint, DisplayHint::AlwaysHide); 0192 } 0193 0194 bool ToolBarLayoutDelegate::isIconOnly() const 0195 { 0196 return DisplayHint::isDisplayHintSet(m_displayHint, DisplayHint::IconOnly); 0197 } 0198 0199 bool ToolBarLayoutDelegate::isKeepVisible() const 0200 { 0201 return DisplayHint::isDisplayHintSet(m_displayHint, DisplayHint::KeepVisible); 0202 } 0203 0204 bool ToolBarLayoutDelegate::isVisible() const 0205 { 0206 return m_iconVisible || m_fullVisible; 0207 } 0208 0209 void ToolBarLayoutDelegate::hide() 0210 { 0211 m_iconVisible = false; 0212 m_fullVisible = false; 0213 ensureItemVisibility(); 0214 } 0215 0216 void ToolBarLayoutDelegate::showFull() 0217 { 0218 m_iconVisible = false; 0219 m_fullVisible = true; 0220 } 0221 0222 void ToolBarLayoutDelegate::showIcon() 0223 { 0224 m_iconVisible = true; 0225 m_fullVisible = false; 0226 } 0227 0228 void ToolBarLayoutDelegate::show() 0229 { 0230 ensureItemVisibility(); 0231 } 0232 0233 void ToolBarLayoutDelegate::setPosition(qreal x, qreal y) 0234 { 0235 m_full->setX(x); 0236 m_icon->setX(x); 0237 m_full->setY(y); 0238 m_icon->setY(y); 0239 } 0240 0241 void ToolBarLayoutDelegate::setHeight(qreal height) 0242 { 0243 m_full->setHeight(height); 0244 m_icon->setHeight(height); 0245 } 0246 0247 void ToolBarLayoutDelegate::resetHeight() 0248 { 0249 m_full->resetHeight(); 0250 m_icon->resetHeight(); 0251 } 0252 0253 qreal ToolBarLayoutDelegate::width() const 0254 { 0255 if (m_iconVisible) { 0256 return m_icon->width(); 0257 } 0258 return m_full->width(); 0259 } 0260 0261 qreal ToolBarLayoutDelegate::height() const 0262 { 0263 if (m_iconVisible) { 0264 return m_icon->height(); 0265 } 0266 return m_full->height(); 0267 } 0268 0269 qreal ToolBarLayoutDelegate::implicitWidth() const 0270 { 0271 if (m_iconVisible) { 0272 return m_icon->implicitWidth(); 0273 } 0274 return m_full->implicitWidth(); 0275 } 0276 0277 qreal ToolBarLayoutDelegate::implicitHeight() const 0278 { 0279 if (m_iconVisible) { 0280 return m_icon->implicitHeight(); 0281 } 0282 return m_full->implicitHeight(); 0283 } 0284 0285 qreal ToolBarLayoutDelegate::maxHeight() const 0286 { 0287 return std::max(m_full->implicitHeight(), m_icon->implicitHeight()); 0288 } 0289 0290 qreal ToolBarLayoutDelegate::iconWidth() const 0291 { 0292 return m_icon->width(); 0293 } 0294 0295 qreal ToolBarLayoutDelegate::fullWidth() const 0296 { 0297 return m_full->width(); 0298 } 0299 0300 void ToolBarLayoutDelegate::actionVisibleChanged() 0301 { 0302 m_actionVisible = m_action->property("visible").toBool(); 0303 m_parent->relayout(); 0304 } 0305 0306 void ToolBarLayoutDelegate::displayHintChanged() 0307 { 0308 m_displayHint = DisplayHint::DisplayHints{m_action->property("displayHint").toInt()}; 0309 m_parent->relayout(); 0310 } 0311 0312 void ToolBarLayoutDelegate::cleanupIncubators() 0313 { 0314 if (m_fullIncubator && m_fullIncubator->isFinished()) { 0315 delete m_fullIncubator; 0316 m_fullIncubator = nullptr; 0317 } 0318 0319 if (m_iconIncubator && m_iconIncubator->isFinished()) { 0320 delete m_iconIncubator; 0321 m_iconIncubator = nullptr; 0322 } 0323 } 0324 0325 void ToolBarLayoutDelegate::triggerRelayout() 0326 { 0327 m_parent->relayout(); 0328 } 0329 0330 #include "moc_toolbarlayoutdelegate.cpp"