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

原来的TrayManagerWindow的类是放到MainPanelWindow类里面作为它的一部分,导致窗管在显示的时候有很多问题 修改方案: 1、将左右侧区域拆分成两个窗体,让它们继承自相同的基类MainWindowBase。 2、左右区域公共的部分,例如圆角、展示区域、动画获取等,都在基类中实现或者通过接口返回 3、增加WindowManager类,管理所有的界面,WindowManager类无需知道具体子类的指针,只需要根据相应的接口来获取即可 4、所有的界面类在main.cpp中创建,调用WindowManager对象设置 5、拆分MultiScreenWorker类,使MultiScreenWorker类只关心任务栏相关的逻辑,无需关心窗体或界面 Log: 优化任务栏的显示问题 Influence: 打开任务栏,观察时尚模式下圆角,左右侧区域中间是否连接在一起等 Bug: https://pms.uniontech.com/bug-view-137267.html Bug: https://pms.uniontech.com/bug-view-140029.html Bug: https://pms.uniontech.com/bug-view-134527.html Bug: https://pms.uniontech.com/bug-view-146743.html Bug: https://pms.uniontech.com/bug-view-150293.html Change-Id: I4266f6f8c983f61258b92834d93cdacd0221d7de
328 lines
9.8 KiB
C++
328 lines
9.8 KiB
C++
/*
|
||
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||
*
|
||
* Author: donghualin <donghualin@uniontech.com>
|
||
*
|
||
* Maintainer: donghualin <donghualin@uniontech.com>
|
||
*
|
||
* This program is free software: you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation, either version 3 of the License, or
|
||
* any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
#include "systempluginwindow.h"
|
||
#include "systemplugincontroller.h"
|
||
#include "systempluginitem.h"
|
||
#include "fixedplugincontroller.h"
|
||
|
||
#include <DListView>
|
||
#include <QBoxLayout>
|
||
#include <QDir>
|
||
#include <QMetaObject>
|
||
#include <QGuiApplication>
|
||
|
||
#define MAXICONSIZE 48
|
||
#define MINICONSIZE 24
|
||
#define ICONMARGIN 8
|
||
|
||
SystemPluginWindow::SystemPluginWindow(QWidget *parent)
|
||
: QWidget(parent)
|
||
, m_pluginController(new FixedPluginController(this))
|
||
, m_listView(new DListView(this))
|
||
, m_position(Dock::Position::Bottom)
|
||
, m_mainLayout(new QBoxLayout(QBoxLayout::Direction::LeftToRight, this))
|
||
{
|
||
initUi();
|
||
connect(m_pluginController, &FixedPluginController::pluginItemInserted, this, &SystemPluginWindow::onPluginItemAdded);
|
||
connect(m_pluginController, &FixedPluginController::pluginItemRemoved, this, &SystemPluginWindow::onPluginItemRemoved);
|
||
connect(m_pluginController, &FixedPluginController::pluginItemUpdated, this, &SystemPluginWindow::onPluginItemUpdated);
|
||
}
|
||
|
||
SystemPluginWindow::~SystemPluginWindow()
|
||
{
|
||
}
|
||
|
||
void SystemPluginWindow::setPositon(Position position)
|
||
{
|
||
if (m_position == position)
|
||
return;
|
||
|
||
m_position = position;
|
||
|
||
if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom)
|
||
m_mainLayout->setDirection(QBoxLayout::Direction::LeftToRight);
|
||
else
|
||
m_mainLayout->setDirection(QBoxLayout::Direction::TopToBottom);
|
||
|
||
QObjectList childObjects = children();
|
||
for (QObject *childObject : childObjects) {
|
||
StretchPluginsItem *item = qobject_cast<StretchPluginsItem *>(childObject);
|
||
if (!item)
|
||
continue;
|
||
|
||
item->setPosition(m_position);
|
||
}
|
||
}
|
||
|
||
QSize SystemPluginWindow::suitableSize() const
|
||
{
|
||
return suitableSize(m_position);
|
||
}
|
||
|
||
QSize SystemPluginWindow::suitableSize(const Position &position) const
|
||
{
|
||
QObjectList childs = children();
|
||
if (position == Dock::Position::Top || position == Dock::Position::Bottom) {
|
||
int itemWidth = 0;
|
||
for (QObject *childObject : childs) {
|
||
StretchPluginsItem *childItem = qobject_cast<StretchPluginsItem *>(childObject);
|
||
if (!childItem)
|
||
continue;
|
||
|
||
itemWidth += childItem->suitableSize(position).width();
|
||
}
|
||
|
||
return QSize(itemWidth, QWIDGETSIZE_MAX);
|
||
}
|
||
|
||
int itemHeight = 0;
|
||
for (QObject *childObject : childs) {
|
||
StretchPluginsItem *item = qobject_cast<StretchPluginsItem *>(childObject);
|
||
if (!item)
|
||
continue;
|
||
|
||
itemHeight += item->suitableSize(position).height();
|
||
}
|
||
|
||
return QSize(QWIDGETSIZE_MAX, itemHeight);
|
||
}
|
||
|
||
void SystemPluginWindow::initUi()
|
||
{
|
||
m_mainLayout->setContentsMargins(0, 0, 0, 0);
|
||
m_mainLayout->setSpacing(0);
|
||
}
|
||
|
||
bool SystemPluginWindow::pluginExist(StretchPluginsItem *pluginItem)
|
||
{
|
||
for (int i = 0; i < m_mainLayout->count(); i++) {
|
||
QLayoutItem *layoutItem = m_mainLayout->itemAt(i);
|
||
if (!layoutItem)
|
||
continue;
|
||
|
||
if (layoutItem->widget() == pluginItem)
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
void SystemPluginWindow::onPluginItemAdded(StretchPluginsItem *pluginItem)
|
||
{
|
||
if (pluginExist(pluginItem))
|
||
return;
|
||
|
||
pluginItem->setPosition(m_position);
|
||
pluginItem->setParent(this);
|
||
pluginItem->show();
|
||
m_mainLayout->addWidget(pluginItem);
|
||
Q_EMIT itemChanged();
|
||
}
|
||
|
||
void SystemPluginWindow::onPluginItemRemoved(StretchPluginsItem *pluginItem)
|
||
{
|
||
if (!pluginExist(pluginItem))
|
||
return;
|
||
|
||
pluginItem->setParent(nullptr);
|
||
pluginItem->hide();
|
||
m_mainLayout->removeWidget(pluginItem);
|
||
Q_EMIT itemChanged();
|
||
}
|
||
|
||
void SystemPluginWindow::onPluginItemUpdated(StretchPluginsItem *pluginItem)
|
||
{
|
||
pluginItem->update();
|
||
}
|
||
|
||
#define ICONSIZE 20
|
||
#define ICONTEXTSPACE 6
|
||
#define PLUGIN_ITEM_DRAG_THRESHOLD 20
|
||
|
||
StretchPluginsItem::StretchPluginsItem(PluginsItemInterface * const pluginInter, const QString &itemKey, QWidget *parent)
|
||
: DockItem(parent)
|
||
, m_pluginInter(pluginInter)
|
||
, m_itemKey(itemKey)
|
||
, m_position(Dock::Position::Bottom)
|
||
{
|
||
}
|
||
|
||
StretchPluginsItem::~StretchPluginsItem()
|
||
{
|
||
}
|
||
|
||
void StretchPluginsItem::setPosition(Position position)
|
||
{
|
||
m_position = position;
|
||
update();
|
||
}
|
||
|
||
QString StretchPluginsItem::itemKey() const
|
||
{
|
||
return m_itemKey;
|
||
}
|
||
|
||
QSize StretchPluginsItem::suitableSize() const
|
||
{
|
||
return suitableSize(m_position);
|
||
}
|
||
|
||
PluginsItemInterface *StretchPluginsItem::pluginInter() const
|
||
{
|
||
return m_pluginInter;
|
||
}
|
||
|
||
void StretchPluginsItem::paintEvent(QPaintEvent *event)
|
||
{
|
||
Q_UNUSED(event);
|
||
QPainter painter(this);
|
||
QIcon icon = m_pluginInter->icon(DockPart::SystemPanel);
|
||
|
||
QRect rctPixmap(rect());
|
||
if (needShowText()) {
|
||
int textHeight = QFontMetrics(textFont()).height();
|
||
// 文本与图标的间距为6
|
||
int iconTop = (height() - textHeight - ICONSIZE - ICONTEXTSPACE) / 2;
|
||
rctPixmap.setX((width() - ICONSIZE) / 2);
|
||
rctPixmap.setY(iconTop);
|
||
rctPixmap.setWidth(ICONSIZE);
|
||
rctPixmap.setHeight(ICONSIZE);
|
||
// 先绘制下面的文本
|
||
painter.setFont(textFont());
|
||
painter.drawText(QRect(0, iconTop + ICONSIZE + ICONTEXTSPACE, width(), textHeight), Qt::AlignCenter, m_pluginInter->pluginDisplayName());
|
||
} else {
|
||
rctPixmap.setX((width() - ICONSIZE) / 2);
|
||
rctPixmap.setY((height() - ICONSIZE) / 2);
|
||
rctPixmap.setWidth(ICONSIZE);
|
||
rctPixmap.setHeight(ICONSIZE);
|
||
}
|
||
|
||
// 绘制图标
|
||
int iconSize = static_cast<int>(ICONSIZE * (qApp->devicePixelRatio()));
|
||
painter.drawPixmap(rctPixmap, icon.pixmap(iconSize, iconSize));
|
||
}
|
||
|
||
QSize StretchPluginsItem::suitableSize(const Position &position) const
|
||
{
|
||
int iconSize = static_cast<int>(ICONSIZE * (qApp->devicePixelRatio()));
|
||
if (position == Dock::Position::Top || position == Dock::Position::Bottom) {
|
||
int textWidth = QFontMetrics(textFont(position)).boundingRect(m_pluginInter->pluginDisplayName()).width();
|
||
return QSize(qMax(textWidth, iconSize) + 10 * 2, -1);
|
||
}
|
||
|
||
int height = 6; // 图标上边距6
|
||
height += iconSize; // 图标尺寸20
|
||
height += ICONTEXTSPACE; // 图标与文字间距6
|
||
height += QFontMetrics(textFont(position)).height(); // 文本高度
|
||
height += 4; // 下间距4
|
||
return QSize(-1, height);
|
||
}
|
||
|
||
QFont StretchPluginsItem::textFont() const
|
||
{
|
||
return textFont(m_position);
|
||
}
|
||
|
||
QFont StretchPluginsItem::textFont(const Position &position) const
|
||
{
|
||
if (position == Dock::Position::Top || position == Dock::Position::Bottom) {
|
||
static QList<QFont> fonts{ DFontSizeManager::instance()->t9(),
|
||
DFontSizeManager::instance()->t8(),
|
||
DFontSizeManager::instance()->t7(),
|
||
DFontSizeManager::instance()->t6() };
|
||
#define MINHEIGHT 50
|
||
// 如果当前的实际位置和请求的位置不一致,说明当前正在切换位置,此时将它的宽度作为它的高度(左到下切换的时候,左侧的宽度和下面的高度一致)
|
||
int size = (m_position == position ? height() : width());
|
||
int index = qMin(qMax((size - MINHEIGHT) / 2, 0), fonts.size() - 1);
|
||
return fonts[index];
|
||
}
|
||
|
||
return DFontSizeManager::instance()->t10();
|
||
}
|
||
|
||
bool StretchPluginsItem::needShowText() const
|
||
{
|
||
// 任务栏在上方或者下方显示的时候,根据设计图,只有在当前区域高度大于50的时候才同时显示文本和图标
|
||
if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom)
|
||
return height() >= 50;
|
||
|
||
return true;
|
||
}
|
||
|
||
const QString StretchPluginsItem::contextMenu() const
|
||
{
|
||
return m_pluginInter->itemContextMenu(m_itemKey);
|
||
}
|
||
|
||
void StretchPluginsItem::invokedMenuItem(const QString &itemId, const bool checked)
|
||
{
|
||
m_pluginInter->invokedMenuItem(m_itemKey, itemId, checked);
|
||
}
|
||
|
||
void StretchPluginsItem::mousePressEvent(QMouseEvent *e)
|
||
{
|
||
m_hover = false;
|
||
update();
|
||
|
||
if (PopupWindow->isVisible())
|
||
hideNonModel();
|
||
|
||
if (e->button() == Qt::LeftButton)
|
||
m_mousePressPoint = e->pos();
|
||
|
||
m_popupTipsDelayTimer->stop();
|
||
hideNonModel();
|
||
|
||
if (e->button() == Qt::RightButton
|
||
&& perfectIconRect().contains(e->pos()))
|
||
return showContextMenu();
|
||
|
||
DockItem::mousePressEvent(e);
|
||
}
|
||
|
||
void StretchPluginsItem::mouseReleaseEvent(QMouseEvent *e)
|
||
{
|
||
DockItem::mouseReleaseEvent(e);
|
||
|
||
if (e->button() != Qt::LeftButton)
|
||
return;
|
||
|
||
if (checkAndResetTapHoldGestureState() && e->source() == Qt::MouseEventSynthesizedByQt)
|
||
return;
|
||
|
||
const QPoint distance = e->pos() - m_mousePressPoint;
|
||
if (distance.manhattanLength() < PLUGIN_ITEM_DRAG_THRESHOLD)
|
||
mouseClick();
|
||
}
|
||
|
||
void StretchPluginsItem::mouseClick()
|
||
{
|
||
const QString command = m_pluginInter->itemCommand(m_itemKey);
|
||
if (!command.isEmpty()) {
|
||
QProcess::startDetached(command);
|
||
return;
|
||
}
|
||
|
||
// request popup applet
|
||
if (QWidget *w = m_pluginInter->itemPopupApplet(m_itemKey))
|
||
showPopupApplet(w);
|
||
}
|