/* * SPDX-FileCopyrightText: 2020 Arjen Hiemstra * * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "toolbarlayoutdelegate.h" #include "loggingcategory.h" #include "toolbarlayout.h" ToolBarDelegateIncubator::ToolBarDelegateIncubator(QQmlComponent *component, QQmlContext *context) : QQmlIncubator(QQmlIncubator::Asynchronous) , m_component(component) , m_context(context) { } void ToolBarDelegateIncubator::setStateCallback(std::function callback) { m_stateCallback = callback; } void ToolBarDelegateIncubator::setCompletedCallback(std::function callback) { m_completedCallback = callback; } void ToolBarDelegateIncubator::create() { m_component->create(*this, m_context); } bool ToolBarDelegateIncubator::isFinished() { return m_finished; } void ToolBarDelegateIncubator::setInitialState(QObject *object) { auto item = qobject_cast(object); if (item) { m_stateCallback(item); } } void ToolBarDelegateIncubator::statusChanged(QQmlIncubator::Status status) { if (status == QQmlIncubator::Error) { qCWarning(KirigamiLayoutsLog) << "Could not create delegate for ToolBarLayout"; const auto e = errors(); for (const auto &error : e) { qCWarning(KirigamiLayoutsLog) << error; } m_finished = true; } if (status == QQmlIncubator::Ready) { m_completedCallback(this); m_finished = true; } } ToolBarLayoutDelegate::ToolBarLayoutDelegate(ToolBarLayout *parent) : QObject() // Note: delegates are managed by unique_ptr, so don't parent , m_parent(parent) { } ToolBarLayoutDelegate::~ToolBarLayoutDelegate() { if (m_fullIncubator) { m_fullIncubator->clear(); delete m_fullIncubator; } if (m_iconIncubator) { m_iconIncubator->clear(); delete m_iconIncubator; } if (m_full) { m_full->disconnect(this); delete m_full; } if (m_icon) { m_icon->disconnect(this); delete m_icon; } } QObject *ToolBarLayoutDelegate::action() const { return m_action; } void ToolBarLayoutDelegate::setAction(QObject *action) { if (action == m_action) { return; } if (m_action) { QObject::disconnect(m_action, SIGNAL(visibleChanged()), this, SLOT(actionVisibleChanged())); QObject::disconnect(m_action, SIGNAL(displayHintChanged()), this, SLOT(displayHintChanged())); } m_action = action; if (m_action) { if (m_action->property("visible").isValid()) { QObject::connect(m_action, SIGNAL(visibleChanged()), this, SLOT(actionVisibleChanged())); m_actionVisible = m_action->property("visible").toBool(); } if (m_action->property("displayHint").isValid()) { QObject::connect(m_action, SIGNAL(displayHintChanged()), this, SLOT(displayHintChanged())); m_displayHint = DisplayHint::DisplayHints{m_action->property("displayHint").toInt()}; } } } void ToolBarLayoutDelegate::createItems(QQmlComponent *fullComponent, QQmlComponent *iconComponent, std::function callback) { m_fullIncubator = new ToolBarDelegateIncubator(fullComponent, qmlContext(fullComponent)); m_fullIncubator->setStateCallback(callback); m_fullIncubator->setCompletedCallback([this](ToolBarDelegateIncubator *incubator) { if (incubator->isError()) { qCWarning(KirigamiLayoutsLog) << "Could not create delegate for ToolBarLayout"; const auto errors = incubator->errors(); for (const auto &error : errors) { qCWarning(KirigamiLayoutsLog) << error; } return; } m_full = qobject_cast(incubator->object()); m_full->setVisible(false); connect(m_full, &QQuickItem::implicitWidthChanged, this, &ToolBarLayoutDelegate::triggerRelayout); connect(m_full, &QQuickItem::implicitHeightChanged, this, &ToolBarLayoutDelegate::triggerRelayout); connect(m_full, &QQuickItem::visibleChanged, this, &ToolBarLayoutDelegate::ensureItemVisibility); if (m_icon) { m_ready = true; } m_parent->relayout(); QMetaObject::invokeMethod(this, &ToolBarLayoutDelegate::cleanupIncubators, Qt::QueuedConnection); }); m_iconIncubator = new ToolBarDelegateIncubator(iconComponent, qmlContext(iconComponent)); m_iconIncubator->setStateCallback(callback); m_iconIncubator->setCompletedCallback([this](ToolBarDelegateIncubator *incubator) { if (incubator->isError()) { qCWarning(KirigamiLayoutsLog) << "Could not create delegate for ToolBarLayout"; const auto errors = incubator->errors(); for (const auto &error : errors) { qCWarning(KirigamiLayoutsLog) << error; } return; } m_icon = qobject_cast(incubator->object()); m_icon->setVisible(false); connect(m_icon, &QQuickItem::implicitWidthChanged, this, &ToolBarLayoutDelegate::triggerRelayout); connect(m_icon, &QQuickItem::implicitHeightChanged, this, &ToolBarLayoutDelegate::triggerRelayout); connect(m_icon, &QQuickItem::visibleChanged, this, &ToolBarLayoutDelegate::ensureItemVisibility); if (m_full) { m_ready = true; } m_parent->relayout(); QMetaObject::invokeMethod(this, &ToolBarLayoutDelegate::cleanupIncubators, Qt::QueuedConnection); }); m_fullIncubator->create(); m_iconIncubator->create(); } bool ToolBarLayoutDelegate::isReady() const { return m_ready; } bool ToolBarLayoutDelegate::isActionVisible() const { return m_actionVisible; } bool ToolBarLayoutDelegate::isHidden() const { return DisplayHint::isDisplayHintSet(m_displayHint, DisplayHint::AlwaysHide); } bool ToolBarLayoutDelegate::isIconOnly() const { return DisplayHint::isDisplayHintSet(m_displayHint, DisplayHint::IconOnly); } bool ToolBarLayoutDelegate::isKeepVisible() const { return DisplayHint::isDisplayHintSet(m_displayHint, DisplayHint::KeepVisible); } bool ToolBarLayoutDelegate::isVisible() const { return m_iconVisible || m_fullVisible; } void ToolBarLayoutDelegate::hide() { m_iconVisible = false; m_fullVisible = false; ensureItemVisibility(); } void ToolBarLayoutDelegate::showFull() { m_iconVisible = false; m_fullVisible = true; } void ToolBarLayoutDelegate::showIcon() { m_iconVisible = true; m_fullVisible = false; } void ToolBarLayoutDelegate::show() { ensureItemVisibility(); } void ToolBarLayoutDelegate::setPosition(qreal x, qreal y) { m_full->setX(x); m_icon->setX(x); m_full->setY(y); m_icon->setY(y); } void ToolBarLayoutDelegate::setHeight(qreal height) { m_full->setHeight(height); m_icon->setHeight(height); } void ToolBarLayoutDelegate::resetHeight() { m_full->resetHeight(); m_icon->resetHeight(); } qreal ToolBarLayoutDelegate::width() const { if (m_iconVisible) { return m_icon->width(); } return m_full->width(); } qreal ToolBarLayoutDelegate::height() const { if (m_iconVisible) { return m_icon->height(); } return m_full->height(); } qreal ToolBarLayoutDelegate::implicitWidth() const { if (m_iconVisible) { return m_icon->implicitWidth(); } return m_full->implicitWidth(); } qreal ToolBarLayoutDelegate::implicitHeight() const { if (m_iconVisible) { return m_icon->implicitHeight(); } return m_full->implicitHeight(); } qreal ToolBarLayoutDelegate::maxHeight() const { return std::max(m_full->implicitHeight(), m_icon->implicitHeight()); } qreal ToolBarLayoutDelegate::iconWidth() const { return m_icon->width(); } qreal ToolBarLayoutDelegate::fullWidth() const { return m_full->width(); } void ToolBarLayoutDelegate::actionVisibleChanged() { m_actionVisible = m_action->property("visible").toBool(); m_parent->relayout(); } void ToolBarLayoutDelegate::displayHintChanged() { m_displayHint = DisplayHint::DisplayHints{m_action->property("displayHint").toInt()}; m_parent->relayout(); } void ToolBarLayoutDelegate::cleanupIncubators() { if (m_fullIncubator && m_fullIncubator->isFinished()) { delete m_fullIncubator; m_fullIncubator = nullptr; } if (m_iconIncubator && m_iconIncubator->isFinished()) { delete m_iconIncubator; m_iconIncubator = nullptr; } } void ToolBarLayoutDelegate::triggerRelayout() { m_parent->relayout(); } #include "moc_toolbarlayoutdelegate.cpp"