dde-dock/plugins/tray/fashiontray/fashiontrayitem.cpp
2023-02-16 15:08:28 +08:00

357 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 <QDebug>
#include <QResizeEvent>
#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<QString, AbstractTrayWidget *> &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<AbstractContainer *>(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<QDynamicPropertyChangeEvent *>(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();
}