mirror of
https://github.com/linuxdeepin/dde-dock.git
synced 2025-06-04 09:23:03 +00:00

The tray in fashion mode is not the same object as the tray in efficient mode, and only one xembedtray is vaild, so there will be a contention between the two. The latter xembedtray who call reparent() will be the vaild one. So drag from expandiconwidget, the xembed tray click in the efficient mode get no response while the tray click get response when switching from the fashion mode. log: make tray(both fashion and efficient mode) to be one object
447 lines
16 KiB
C++
447 lines
16 KiB
C++
// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
|
||
//
|
||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||
|
||
#include "docktraywindow.h"
|
||
#include "datetimedisplayer.h"
|
||
#include "systempluginwindow.h"
|
||
#include "quickpluginwindow.h"
|
||
#include "tray_gridview.h"
|
||
#include "tray_model.h"
|
||
#include "tray_delegate.h"
|
||
#include "quicksettingcontroller.h"
|
||
#include "pluginsitem.h"
|
||
#include "expandiconwidget.h"
|
||
#include "quickdragcore.h"
|
||
#include "desktop_widget.h"
|
||
|
||
#include <DGuiApplicationHelper>
|
||
|
||
#include <QBoxLayout>
|
||
#include <QLabel>
|
||
#include <QPainter>
|
||
|
||
#define FRONTSPACING 18
|
||
#define SPLITERSIZE 2
|
||
#define SPLITESPACE 5
|
||
|
||
DockTrayWindow::DockTrayWindow(QWidget *parent)
|
||
: QWidget(parent)
|
||
, m_position(Dock::Position::Bottom)
|
||
, m_displayMode(Dock::DisplayMode::Efficient)
|
||
, m_mainBoxLayout(new QBoxLayout(QBoxLayout::Direction::RightToLeft, this))
|
||
, m_showDesktopWidget(new DesktopWidget(this))
|
||
, m_toolWidget(new QWidget(this))
|
||
, m_toolLayout(new QBoxLayout(QBoxLayout::RightToLeft, m_toolWidget))
|
||
, m_toolLineLabel(new QLabel(this))
|
||
, m_dateTimeWidget(new DateTimeDisplayer(true, this))
|
||
, m_systemPuginWidget(new SystemPluginWindow(this))
|
||
, m_quickIconWidget(new QuickPluginWindow(Dock::DisplayMode::Efficient, this))
|
||
, m_trayView(TrayGridView::getDockTrayGridView(this))
|
||
, m_model(TrayModel::getDockModel())
|
||
, m_delegate(TrayDelegate::getDockTrayDelegate(m_trayView, this))
|
||
, m_toolFrontSpaceWidget(new QWidget(this))
|
||
, m_toolBackSpaceWidget(new QWidget(this))
|
||
, m_dateTimeSpaceWidget(new QWidget(this))
|
||
{
|
||
initUi();
|
||
initConnection();
|
||
initAttribute();
|
||
}
|
||
|
||
void DockTrayWindow::setPositon(const Dock::Position &position)
|
||
{
|
||
m_position = position;
|
||
m_dateTimeWidget->setPositon(position);
|
||
m_systemPuginWidget->setPositon(position);
|
||
m_quickIconWidget->setPositon(position);
|
||
m_trayView->setPosition(position);
|
||
m_delegate->setPositon(position);
|
||
// 改变位置的时候,需要切换编辑器,以适应正确的位置
|
||
m_trayView->onUpdateEditorView();
|
||
updateLayout(position);
|
||
onUpdateComponentSize();
|
||
}
|
||
|
||
void DockTrayWindow::setDisplayMode(const Dock::DisplayMode &displayMode)
|
||
{
|
||
m_displayMode = displayMode;
|
||
moveToolPlugin();
|
||
updateToolWidget();
|
||
// 如果当前模式为高效模式,则设置当前的trayView为其计算位置的参照
|
||
if (displayMode == Dock::DisplayMode::Efficient) {
|
||
ExpandIconWidget::popupTrayView()->setReferGridView(m_trayView);
|
||
// TODO: reuse QuickPluginWindow, SystemPluginWindow
|
||
m_mainBoxLayout->addWidget(TrayGridView::getDockTrayGridView());
|
||
} else {
|
||
m_mainBoxLayout->removeWidget(TrayGridView::getDockTrayGridView());
|
||
}
|
||
|
||
}
|
||
|
||
QSize DockTrayWindow::suitableSize(const Dock::Position &position, const int &, const double &) const
|
||
{
|
||
if (position == Dock::Position::Left || position == Dock::Position::Right) {
|
||
// 左右的尺寸
|
||
int height = m_showDesktopWidget->height()
|
||
+ m_toolFrontSpaceWidget->height()
|
||
+ m_toolWidget->height()
|
||
+ m_toolBackSpaceWidget->height()
|
||
+ m_toolLineLabel->height()
|
||
+ m_dateTimeSpaceWidget->height()
|
||
+ m_dateTimeWidget->suitableSize(position).height()
|
||
+ m_systemPuginWidget->suitableSize(position).height()
|
||
+ m_quickIconWidget->suitableSize(position).height()
|
||
+ m_trayView->suitableSize(position).height();
|
||
|
||
return QSize(-1, height);
|
||
}
|
||
// 上下的尺寸
|
||
int width = m_showDesktopWidget->width()
|
||
+ m_toolFrontSpaceWidget->width()
|
||
+ m_toolWidget->width()
|
||
+ m_toolBackSpaceWidget->width()
|
||
+ m_toolLineLabel->width()
|
||
+ m_dateTimeSpaceWidget->width()
|
||
+ m_dateTimeWidget->width()
|
||
+ m_systemPuginWidget->width()
|
||
+ m_quickIconWidget->width()
|
||
+ m_trayView->width();
|
||
return QSize(width, -1);
|
||
}
|
||
|
||
QSize DockTrayWindow::suitableSize() const
|
||
{
|
||
return suitableSize(m_position, 0, 0);
|
||
}
|
||
|
||
void DockTrayWindow::layoutWidget()
|
||
{
|
||
resizeTool();
|
||
}
|
||
|
||
void DockTrayWindow::resizeEvent(QResizeEvent *event)
|
||
{
|
||
// 当尺寸发生变化的时候,通知托盘区域刷新尺寸,让托盘图标始终保持居中显示
|
||
Q_EMIT m_delegate->sizeHintChanged(m_model->index(0, 0));
|
||
QWidget::resizeEvent(event);
|
||
onUpdateComponentSize();
|
||
}
|
||
|
||
void DockTrayWindow::paintEvent(QPaintEvent *event)
|
||
{
|
||
QWidget::paintEvent(event);
|
||
if (!m_toolLineLabel->isVisible())
|
||
return;
|
||
|
||
QPainter painter(this);
|
||
QColor color;
|
||
if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType) {
|
||
color = Qt::black;
|
||
painter.setOpacity(0.5);
|
||
} else {
|
||
color = Qt::white;
|
||
painter.setOpacity(0.1);
|
||
}
|
||
|
||
painter.fillRect(m_toolLineLabel->geometry(), color);
|
||
}
|
||
|
||
bool DockTrayWindow::eventFilter(QObject *watched, QEvent *event)
|
||
{
|
||
if (watched == this || watched == m_toolWidget || watched == m_dateTimeWidget
|
||
|| watched == m_trayView) {
|
||
switch (event->type()) {
|
||
case QEvent::Drop: {
|
||
QDropEvent *dropEvent = static_cast<QDropEvent *>(event);
|
||
onDropIcon(dropEvent);
|
||
break;
|
||
}
|
||
case QEvent::DragEnter: {
|
||
QDragEnterEvent *dragEnterEvent = static_cast<QDragEnterEvent *>(event);
|
||
dragEnterEvent->setDropAction(Qt::CopyAction);
|
||
dragEnterEvent->accept();
|
||
return true;
|
||
}
|
||
case QEvent::DragMove: {
|
||
QDragMoveEvent *dragMoveEvent = static_cast<QDragMoveEvent *>(event);
|
||
dragMoveEvent->setDropAction(Qt::CopyAction);
|
||
dragMoveEvent->accept();
|
||
return true;
|
||
}
|
||
case QEvent::DragLeave: {
|
||
QDragLeaveEvent *dragLeaveEvent = static_cast<QDragLeaveEvent *>(event);
|
||
dragLeaveEvent->accept();
|
||
break;
|
||
}
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
return QWidget::eventFilter(watched, event);
|
||
}
|
||
|
||
/** 根据任务栏的位置来更新布局的方向
|
||
* @brief DockTrayWindow::updateLayout
|
||
* @param position
|
||
*/
|
||
void DockTrayWindow::updateLayout(const Dock::Position &position)
|
||
{
|
||
switch (position) {
|
||
case Dock::Position::Left:
|
||
case Dock::Position::Right: {
|
||
m_mainBoxLayout->setDirection(QBoxLayout::BottomToTop);
|
||
m_toolLayout->setDirection(QBoxLayout::BottomToTop);
|
||
break;
|
||
}
|
||
case Dock::Position::Top:
|
||
case Dock::Position::Bottom: {
|
||
m_mainBoxLayout->setDirection(QBoxLayout::RightToLeft);
|
||
m_toolLayout->setDirection(QBoxLayout::RightToLeft);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void DockTrayWindow::resizeTool() const
|
||
{
|
||
int toolSize = 0;
|
||
int size = 0;
|
||
if (m_position == Dock::Position::Left || m_position == Dock::Position::Right)
|
||
size = width();
|
||
else
|
||
size = height();
|
||
|
||
for (int i = 0; i < m_toolLayout->count(); i++) {
|
||
QLayoutItem *layoutItem = m_toolLayout->itemAt(i);
|
||
if (!layoutItem)
|
||
continue;
|
||
|
||
PluginsItem *toolWidget = qobject_cast<PluginsItem *>(layoutItem->widget());
|
||
if (!toolWidget)
|
||
continue;
|
||
|
||
toolWidget->setFixedSize(size, size);
|
||
toolSize += size;
|
||
}
|
||
|
||
if (m_position == Dock::Position::Left || m_position == Dock::Position::Right)
|
||
m_toolWidget->setFixedSize(QWIDGETSIZE_MAX, toolSize);
|
||
else
|
||
m_toolWidget->setFixedSize(toolSize, QWIDGETSIZE_MAX);
|
||
}
|
||
|
||
bool DockTrayWindow::pluginExists(PluginsItemInterface *itemInter) const
|
||
{
|
||
for (int i = 0; i < m_toolLayout->count(); i++) {
|
||
QLayoutItem *layoutItem = m_toolLayout->itemAt(i);
|
||
if (!layoutItem)
|
||
continue;
|
||
|
||
PluginsItem *pluginItem = qobject_cast<PluginsItem *>(layoutItem->widget());
|
||
if (!pluginItem)
|
||
continue;
|
||
|
||
if (pluginItem->pluginItem() == itemInter)
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
void DockTrayWindow::moveToolPlugin()
|
||
{
|
||
for (int i = m_toolLayout->count() - 1; i >= 0; i--) {
|
||
QLayoutItem *layoutItem = m_toolLayout->itemAt(i);
|
||
if (!layoutItem)
|
||
continue;
|
||
|
||
PluginsItem *pluginWidget = qobject_cast<PluginsItem *>(layoutItem->widget());
|
||
if (!pluginWidget)
|
||
continue;
|
||
|
||
m_toolLayout->removeWidget(pluginWidget);
|
||
}
|
||
if (m_displayMode == Dock::DisplayMode::Efficient) {
|
||
// 如果当前是高效模式,则将所有的工具插件移动到当前的工具区域
|
||
QuickSettingController *quickController = QuickSettingController::instance();
|
||
QList<PluginsItemInterface *> plugins = quickController->pluginItems(QuickSettingController::PluginAttribute::Tool);
|
||
for (PluginsItemInterface *pluginInter : plugins) {
|
||
PluginsItem *pluginWidget = quickController->pluginItemWidget(pluginInter);
|
||
m_toolLayout->addWidget(pluginWidget);
|
||
}
|
||
}
|
||
}
|
||
|
||
void DockTrayWindow::updateToolWidget()
|
||
{
|
||
m_toolWidget->setVisible(m_toolLayout->count() > 0);
|
||
m_toolLineLabel->setVisible(m_toolLayout->count() > 0);
|
||
m_toolFrontSpaceWidget->setVisible(m_toolLayout->count() > 0);
|
||
m_toolBackSpaceWidget->setVisible(m_toolLayout->count() > 0);
|
||
m_dateTimeSpaceWidget->setVisible(m_toolLayout->count() > 0);
|
||
}
|
||
|
||
void DockTrayWindow::initUi()
|
||
{
|
||
m_toolLayout->setContentsMargins(0, 0, 0, 0);
|
||
m_toolLayout->setSpacing(0);
|
||
|
||
m_systemPuginWidget->setDisplayMode(Dock::DisplayMode::Efficient);
|
||
m_mainBoxLayout->setContentsMargins(0, 0, 0, 0);
|
||
m_mainBoxLayout->setSpacing(0);
|
||
m_mainBoxLayout->addWidget(m_showDesktopWidget);
|
||
m_mainBoxLayout->addWidget(m_toolFrontSpaceWidget);
|
||
m_mainBoxLayout->addWidget(m_toolWidget);
|
||
m_mainBoxLayout->addWidget(m_toolBackSpaceWidget);
|
||
m_mainBoxLayout->addWidget(m_toolLineLabel);
|
||
m_mainBoxLayout->addWidget(m_dateTimeSpaceWidget);
|
||
m_mainBoxLayout->addWidget(m_dateTimeWidget);
|
||
m_mainBoxLayout->addWidget(m_systemPuginWidget);
|
||
m_mainBoxLayout->addWidget(m_quickIconWidget);
|
||
m_mainBoxLayout->addWidget(m_trayView);
|
||
m_mainBoxLayout->setAlignment(m_toolLineLabel, Qt::AlignCenter);
|
||
|
||
m_toolLineLabel->setFixedSize(0, 0);
|
||
|
||
m_mainBoxLayout->addStretch();
|
||
updateToolWidget();
|
||
}
|
||
|
||
void DockTrayWindow::initConnection()
|
||
{
|
||
connect(m_systemPuginWidget, &SystemPluginWindow::itemChanged, this, &DockTrayWindow::onUpdateComponentSize);
|
||
connect(m_dateTimeWidget, &DateTimeDisplayer::requestUpdate, this, &DockTrayWindow::onUpdateComponentSize);
|
||
connect(m_quickIconWidget, &QuickPluginWindow::itemCountChanged, this, &DockTrayWindow::onUpdateComponentSize);
|
||
connect(m_systemPuginWidget, &SystemPluginWindow::requestDrop, this, &DockTrayWindow::onDropIcon);
|
||
connect(m_model, &TrayModel::rowCountChanged, this, &DockTrayWindow::onUpdateComponentSize);
|
||
connect(m_model, &TrayModel::rowCountChanged, m_trayView, &TrayGridView::onUpdateEditorView);
|
||
connect(m_model, &TrayModel::requestRefreshEditor, m_trayView, &TrayGridView::onUpdateEditorView);
|
||
connect(m_trayView, &TrayGridView::dragFinished, this, [ this ] {
|
||
// 如果拖拽结束,则隐藏托盘
|
||
Q_EMIT m_delegate->requestDrag(false);
|
||
});
|
||
|
||
connect(m_trayView, &TrayGridView::dragLeaved, m_delegate, [ this ] {
|
||
Q_EMIT m_delegate->requestDrag(true);
|
||
});
|
||
connect(QuickSettingController::instance(), &QuickSettingController::pluginInserted, this, [ this ] (PluginsItemInterface *itemInter, const QuickSettingController::PluginAttribute pluginAttr) {
|
||
switch (pluginAttr) {
|
||
case QuickSettingController::PluginAttribute::Tool:
|
||
// 下方只处理回收站等插件
|
||
onItemAdded(itemInter);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
});
|
||
|
||
connect(QuickSettingController::instance(), &QuickSettingController::pluginRemoved, this, &DockTrayWindow::onItemRemove);
|
||
}
|
||
|
||
void DockTrayWindow::initAttribute()
|
||
{
|
||
setAcceptDrops(true);
|
||
setMouseTracking(true);
|
||
|
||
m_trayView->setModel(m_model);
|
||
m_trayView->setItemDelegate(m_delegate);
|
||
m_trayView->setDragDistance(2);
|
||
m_trayView->setDragEnabled(true);
|
||
|
||
installEventFilter(this);
|
||
m_toolWidget->installEventFilter(this);
|
||
m_dateTimeWidget->installEventFilter(this);
|
||
m_systemPuginWidget->installEventFilter(this);
|
||
m_quickIconWidget->installEventFilter(this);
|
||
m_trayView->installEventFilter(this);
|
||
}
|
||
|
||
void DockTrayWindow::onUpdateComponentSize()
|
||
{
|
||
switch (m_position) {
|
||
case Dock::Position::Left:
|
||
case Dock::Position::Right:
|
||
m_toolLineLabel->setFixedSize(width() * 0.6, SPLITERSIZE);
|
||
m_showDesktopWidget->setFixedSize(QWIDGETSIZE_MAX, FRONTSPACING);
|
||
m_dateTimeWidget->setFixedSize(QWIDGETSIZE_MAX, m_dateTimeWidget->suitableSize().height());
|
||
m_systemPuginWidget->setFixedSize(QWIDGETSIZE_MAX, m_systemPuginWidget->suitableSize().height());
|
||
m_quickIconWidget->setFixedSize(QWIDGETSIZE_MAX, m_quickIconWidget->suitableSize().height());
|
||
m_trayView->setFixedSize(QWIDGETSIZE_MAX, m_trayView->suitableSize().height());
|
||
m_toolFrontSpaceWidget->setFixedSize(QWIDGETSIZE_MAX, SPLITESPACE);
|
||
m_toolBackSpaceWidget->setFixedSize(QWIDGETSIZE_MAX, SPLITESPACE);
|
||
m_dateTimeSpaceWidget->setFixedSize(QWIDGETSIZE_MAX, SPLITESPACE);
|
||
break;
|
||
case Dock::Position::Top:
|
||
case Dock::Position::Bottom:
|
||
m_toolLineLabel->setFixedSize(SPLITERSIZE, height() * 0.6);
|
||
m_showDesktopWidget->setFixedSize(FRONTSPACING, QWIDGETSIZE_MAX);
|
||
// FIXME: in some cases, m_dateTimeWidget QWIDGETSIZE_MAX get a huge height.
|
||
m_dateTimeWidget->setFixedSize(m_dateTimeWidget->suitableSize().width(), qMin(QWIDGETSIZE_MAX, this->height()));
|
||
m_systemPuginWidget->setFixedSize(m_systemPuginWidget->suitableSize().width(), QWIDGETSIZE_MAX);
|
||
m_quickIconWidget->setFixedSize(m_quickIconWidget->suitableSize().width(), QWIDGETSIZE_MAX);
|
||
m_trayView->setFixedSize(m_trayView->suitableSize().width(), QWIDGETSIZE_MAX);
|
||
m_toolFrontSpaceWidget->setFixedSize(SPLITESPACE, QWIDGETSIZE_MAX);
|
||
m_toolBackSpaceWidget->setFixedSize(SPLITESPACE, QWIDGETSIZE_MAX);
|
||
m_dateTimeSpaceWidget->setFixedSize(SPLITESPACE, QWIDGETSIZE_MAX);
|
||
break;
|
||
}
|
||
Q_EMIT requestUpdate();
|
||
}
|
||
|
||
void DockTrayWindow::onItemAdded(PluginsItemInterface *itemInter)
|
||
{
|
||
if (m_displayMode != Dock::DisplayMode::Efficient || pluginExists(itemInter))
|
||
return;
|
||
|
||
QuickSettingController *quickController = QuickSettingController::instance();
|
||
PluginsItem *pluginItem = quickController->pluginItemWidget(itemInter);
|
||
pluginItem->setVisible(true);
|
||
|
||
m_toolLayout->addWidget(pluginItem);
|
||
updateToolWidget();
|
||
|
||
Q_EMIT requestUpdate();
|
||
}
|
||
|
||
void DockTrayWindow::onItemRemove(PluginsItemInterface *itemInter)
|
||
{
|
||
for (int i = 0; i < m_toolLayout->count(); i++) {
|
||
QLayoutItem *layoutItem = m_toolLayout->itemAt(i);
|
||
if (!layoutItem)
|
||
continue;
|
||
|
||
PluginsItem *pluginItem = qobject_cast<PluginsItem *>(layoutItem->widget());
|
||
if (!pluginItem || pluginItem->pluginItem() != itemInter)
|
||
continue;
|
||
|
||
m_toolLayout->removeWidget(pluginItem);
|
||
updateToolWidget();
|
||
|
||
Q_EMIT requestUpdate();
|
||
break;
|
||
}
|
||
}
|
||
|
||
void DockTrayWindow::onDropIcon(QDropEvent *dropEvent)
|
||
{
|
||
if (!dropEvent || !dropEvent->mimeData() || dropEvent->source() == this)
|
||
return;
|
||
|
||
if (m_quickIconWidget->isQuickWindow(dropEvent->source())) {
|
||
const QuickPluginMimeData *mimeData = qobject_cast<const QuickPluginMimeData *>(dropEvent->mimeData());
|
||
if (!mimeData)
|
||
return;
|
||
|
||
PluginsItemInterface *pluginItem = static_cast<PluginsItemInterface *>(mimeData->pluginItemInterface());
|
||
if (pluginItem)
|
||
m_quickIconWidget->dragPlugin(pluginItem);
|
||
} else if (qobject_cast<TrayGridView *>(dropEvent->source())) {
|
||
// 将trayView中的dropEvent扩大到整个区域(this),这样便于随意拖动到这个区域都可以捕获。
|
||
// m_trayView中有e->accept不会导致事件重复处理。
|
||
m_trayView->handleDropEvent(dropEvent);
|
||
}
|
||
}
|