// Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. // SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later #include "fashiontrayitem.h" #include "fashiontray/fashiontrayconstants.h" #include "system-trays/systemtrayitem.h" #include "containers/abstractcontainer.h" #include #include #define ExpandedKey "fashion-tray-expanded" int FashionTrayItem::TrayWidgetWidth = PLUGIN_BACKGROUND_MAX_SIZE; int FashionTrayItem::TrayWidgetHeight = PLUGIN_BACKGROUND_MAX_SIZE; FashionTrayItem::FashionTrayItem(TrayPlugin *trayPlugin, QWidget *parent) : QWidget(parent), m_mainBoxLayout(new QBoxLayout(QBoxLayout::Direction::LeftToRight, this)) , m_attentionDelayTimer(new QTimer(this)) , m_trayPlugin(trayPlugin) , m_controlWidget(new FashionTrayControlWidget(trayPlugin->dockPosition(), this)) , m_normalContainer(new NormalContainer(m_trayPlugin, this)) , m_attentionContainer(new AttentionContainer(m_trayPlugin, this)) , m_holdContainer(new HoldContainer(m_trayPlugin, this)) , m_leftSpace(new QWidget(this)) { setAcceptDrops(true); m_normalContainer->setVisible(false); m_attentionContainer->setVisible(false); m_holdContainer->setVisible(false); m_mainBoxLayout->setMargin(0); m_mainBoxLayout->setContentsMargins(0, 0, 0, 0); m_mainBoxLayout->setSpacing(0); m_leftSpace->setFixedSize(TraySpace, TraySpace); m_leftSpace->setAccessibleName("leftspace"); m_mainBoxLayout->addWidget(m_leftSpace); m_mainBoxLayout->addWidget(m_normalContainer); m_mainBoxLayout->addWidget(m_controlWidget); m_mainBoxLayout->addWidget(m_holdContainer); m_mainBoxLayout->addWidget(m_attentionContainer); setLayout(m_mainBoxLayout); m_attentionDelayTimer->setInterval(3000); m_attentionDelayTimer->setSingleShot(true); connect(m_controlWidget, &FashionTrayControlWidget::expandChanged, this, &FashionTrayItem::onExpandChanged); connect(m_normalContainer, &NormalContainer::attentionChanged, this, &FashionTrayItem::onWrapperAttentionChanged); connect(m_attentionContainer, &AttentionContainer::attentionChanged, this, &FashionTrayItem::onWrapperAttentionChanged); connect(m_normalContainer, &NormalContainer::requestDraggingWrapper, this, &FashionTrayItem::onRequireDraggingWrapper); connect(m_holdContainer, &HoldContainer::requestDraggingWrapper, this, &FashionTrayItem::onRequireDraggingWrapper); // do not call init immediately the TrayPlugin has not be constructed for now QTimer::singleShot(0, this, &FashionTrayItem::init); } void FashionTrayItem::setTrayWidgets(const QMap &itemTrayMap) { clearTrayWidgets(); for (auto it = itemTrayMap.constBegin(); it != itemTrayMap.constEnd(); ++it) { trayWidgetAdded(it.key(), it.value()); } } void FashionTrayItem::trayWidgetAdded(const QString &itemKey, AbstractTrayWidget *trayWidget) { if (m_normalContainer->containsWrapperByTrayWidget(trayWidget)) { qDebug() << "Reject! want to insert duplicate trayWidget:" << itemKey << trayWidget; return; } FashionTrayWidgetWrapper *wrapper = new FashionTrayWidgetWrapper(itemKey, trayWidget); do { if (m_holdContainer->acceptWrapper(wrapper)) { m_holdContainer->addWrapper(wrapper); break; } if (m_normalContainer->acceptWrapper(wrapper)) { m_normalContainer->addWrapper(wrapper); break; } } while (false); onExpandChanged(m_controlWidget->expanded()); requestResize(); } void FashionTrayItem::trayWidgetRemoved(AbstractTrayWidget *trayWidget) { bool deleted = false; do { if (m_normalContainer->removeWrapperByTrayWidget(trayWidget)) { deleted = true; break; } if (m_attentionContainer->removeWrapperByTrayWidget(trayWidget)) { deleted = true; break; } if (m_holdContainer->removeWrapperByTrayWidget(trayWidget)) { deleted = true; break; } } while (false); if (!deleted) { qDebug() << "Error! can not find the tray widget in fashion tray list" << trayWidget; } requestResize(); } void FashionTrayItem::clearTrayWidgets() { m_normalContainer->clearWrapper(); m_attentionContainer->clearWrapper(); m_holdContainer->clearWrapper(); requestResize(); } void FashionTrayItem::setDockPosition(Dock::Position pos) { m_dockpos = pos; m_controlWidget->setDockPostion(pos); SystemTrayItem::setDockPostion(pos); SNITrayWidget::setDockPostion(pos); m_normalContainer->setDockPosition(pos); m_attentionContainer->setDockPosition(pos); m_holdContainer->setDockPosition(pos); if (pos == Dock::Position::Top || pos == Dock::Position::Bottom) { m_mainBoxLayout->setDirection(QBoxLayout::Direction::LeftToRight); } else { m_mainBoxLayout->setDirection(QBoxLayout::Direction::TopToBottom); } requestResize(); } void FashionTrayItem::onExpandChanged(const bool expand) { m_trayPlugin->saveValue(FASHION_MODE_ITEM_KEY, ExpandedKey, expand); m_normalContainer->setExpand(expand); m_attentionContainer->setExpand(expand); m_holdContainer->setExpand(expand); m_attentionDelayTimer->start(); attentionWrapperToNormalWrapper(); requestResize(); } void FashionTrayItem::setRightSplitVisible(const bool visible) { Q_UNUSED(visible); } void FashionTrayItem::onPluginSettingsChanged() { m_controlWidget->setExpanded(m_trayPlugin->getValue(FASHION_MODE_ITEM_KEY, ExpandedKey, true).toBool()); } void FashionTrayItem::showEvent(QShowEvent *event) { requestResize(); QWidget::showEvent(event); } void FashionTrayItem::hideEvent(QHideEvent *event) { requestResize(); QWidget::hideEvent(event); } void FashionTrayItem::resizeEvent(QResizeEvent *event) { resizeTray(); QWidget::resizeEvent(event); } void FashionTrayItem::dragEnterEvent(QDragEnterEvent *event) { // accept but do not handle the trays drag event // in order to avoid the for forbidden label displayed on the mouse if (event->mimeData()->hasFormat(TRAY_ITEM_DRAG_MIMEDATA)) { event->accept(); return; } QWidget::dragEnterEvent(event); } void FashionTrayItem::init() { qDebug() << "init Fashion mode tray plugin item"; m_controlWidget->setExpanded(m_trayPlugin->getValue(FASHION_MODE_ITEM_KEY, ExpandedKey, true).toBool()); setDockPosition(m_trayPlugin->dockPosition()); onExpandChanged(m_controlWidget->expanded()); } void FashionTrayItem::onWrapperAttentionChanged(FashionTrayWidgetWrapper *wrapper, const bool attention) { if (m_controlWidget->expanded()) { return; } // 在timer处于Active状态期间不设置新的活动图标 if (attention && m_attentionDelayTimer->isActive()) { return; } if (attention) { // ignore the attention which is come from AttentionContainer if (m_attentionContainer->containsWrapper(wrapper)) { return; } // move previous attention wrapper from AttentionContainer to NormalContainer attentionWrapperToNormalWrapper(); // move current attention wrapper from NormalContainer to AttentionContainer normalWrapperToAttentionWrapper(wrapper); } else { // only focus the disattention from AttentionContainer if (m_attentionContainer->containsWrapper(wrapper)) { attentionWrapperToNormalWrapper(); } } m_attentionDelayTimer->start(); requestResize(); } void FashionTrayItem::attentionWrapperToNormalWrapper() { FashionTrayWidgetWrapper *preAttentionWrapper = m_attentionContainer->takeAttentionWrapper(); if (preAttentionWrapper) { m_normalContainer->addWrapper(preAttentionWrapper); } } void FashionTrayItem::normalWrapperToAttentionWrapper(FashionTrayWidgetWrapper *wrapper) { FashionTrayWidgetWrapper *attentionWrapper = m_normalContainer->takeWrapper(wrapper); if (attentionWrapper) { m_attentionContainer->addWrapper(attentionWrapper); } else { qDebug() << "Warnning: not find the attention wrapper in NormalContainer"; } } void FashionTrayItem::requestResize() { // 通知dock,当前托盘有几个图标显示,用来计算图标大小 m_leftSpace->setVisible(!m_controlWidget->expanded()); int count = m_normalContainer->itemCount() + m_holdContainer->itemCount() + m_attentionContainer->itemCount(); setProperty("TrayVisableItemCount", count + 1); // +1 : m_controlWidget resizeTray(); } void FashionTrayItem::onRequireDraggingWrapper() { AbstractContainer *container = dynamic_cast(sender()); if (!container) { return; } FashionTrayWidgetWrapper *draggingWrapper = nullptr; do { draggingWrapper = m_normalContainer->takeDraggingWrapper(); if (draggingWrapper) { break; } draggingWrapper = m_holdContainer->takeDraggingWrapper(); if (draggingWrapper) { break; } } while (false); if (!draggingWrapper) { return; } container->addDraggingWrapper(draggingWrapper); } bool FashionTrayItem::event(QEvent *event) { if (event->type() == QEvent::DynamicPropertyChange) { const QString &propertyName = static_cast(event)->propertyName(); if (propertyName == "iconSize") { m_iconSize = property("iconSize").toInt(); m_normalContainer->setItemSize(m_iconSize); m_holdContainer->setItemSize(m_iconSize); m_attentionContainer->setItemSize(m_iconSize); resizeTray(); } } return QWidget::event(event); } void FashionTrayItem::resizeTray() { if (!m_iconSize) return; if (m_dockpos == Dock::Position::Top || m_dockpos == Dock::Position::Bottom) { if (m_attentionContainer->itemCount() != 0){ m_mainBoxLayout->setContentsMargins(0, 0, TraySpace, 0); } else { m_mainBoxLayout->setContentsMargins(0, 0, 0, 0); } m_holdContainer->setFixedWidth((m_iconSize + TraySpace) * m_holdContainer->itemCount() + TraySpace); m_holdContainer->setFixedHeight(QWIDGETSIZE_MAX); m_attentionContainer->setFixedWidth(m_iconSize * m_attentionContainer->itemCount()); m_attentionContainer->setFixedHeight(QWIDGETSIZE_MAX); m_controlWidget->setFixedSize(m_iconSize, QWIDGETSIZE_MAX); } else { m_holdContainer->setFixedWidth(QWIDGETSIZE_MAX); if (m_attentionContainer->itemCount() != 0){ m_mainBoxLayout->setContentsMargins(0, 0, 0, TraySpace); } else { m_mainBoxLayout->setContentsMargins(0, 0, 0, 0); } m_holdContainer->setFixedHeight((m_iconSize + TraySpace) * m_holdContainer->itemCount() + TraySpace); m_attentionContainer->setFixedWidth(QWIDGETSIZE_MAX); m_attentionContainer->setFixedHeight(m_iconSize * m_attentionContainer->itemCount()); m_controlWidget->setFixedSize(QWIDGETSIZE_MAX, m_iconSize); } m_normalContainer->updateSize(); }