/* * Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd. * * Author: donghualin * * Maintainer: donghualin * * 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 . */ #include "systempluginwindow.h" #include "systemplugincontroller.h" #include "systempluginitem.h" #include "fixedplugincontroller.h" #include #include #include #include #include #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(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(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(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(ICONSIZE * (qApp->devicePixelRatio())); painter.drawPixmap(rctPixmap, icon.pixmap(iconSize, iconSize)); } QSize StretchPluginsItem::suitableSize(const Position &position) const { int iconSize = static_cast(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 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); }