feat: 增加窗口多开的功能

增加窗口多开的窗口类,用于绘制应用图标和打开窗口的图标,根据实际情况让其显示到正确的位置

Log: 增加窗口多开的功能
Influence: 控制中心开启多开窗口显示,观察应用打开的窗口是否在对应的位置显示
Task: https://pms.uniontech.com/task-view-170977.html
Change-Id: I96371b1304f5373f17dad95893ee656056e5f457
This commit is contained in:
donghualin 2022-08-18 15:41:46 +00:00
parent 90a076a043
commit 56c3019a5c
14 changed files with 922 additions and 63 deletions

View File

@ -25,6 +25,7 @@
#include "pluginsitem.h"
#include "traypluginitem.h"
#include "utils.h"
#include "appmultiitem.h"
#include <QDebug>
#include <QGSettings>
@ -47,16 +48,23 @@ DockItemManager::DockItemManager(QObject *parent)
// 应用区域
for (auto entry : m_appInter->entries()) {
AppItem *it = new AppItem(m_appSettings, m_activeSettings, m_dockedSettings, entry);
AppItem *it = new AppItem(m_appInter, m_appSettings, m_activeSettings, m_dockedSettings, entry);
manageItem(it);
connect(it, &AppItem::requestActivateWindow, m_appInter, &DockInter::ActivateWindow, Qt::QueuedConnection);
connect(it, &AppItem::requestPreviewWindow, m_appInter, &DockInter::PreviewWindow);
connect(it, &AppItem::requestCancelPreview, m_appInter, &DockInter::CancelPreviewWindow);
#ifdef USE_AM
connect(it, &AppItem::windowCountChanged, this, &DockItemManager::onAppWindowCountChanged);
#endif
connect(this, &DockItemManager::requestUpdateDockItem, it, &AppItem::requestUpdateEntryGeometries);
m_itemList.append(it);
#ifdef USE_AM
updateMultiItems(it);
#endif
}
// 托盘区域和插件区域 由DockPluginsController获取
@ -65,6 +73,9 @@ DockItemManager::DockItemManager(QObject *parent)
connect(m_appInter, &DockInter::EntryAdded, this, &DockItemManager::appItemAdded);
connect(m_appInter, &DockInter::EntryRemoved, this, static_cast<void (DockItemManager::*)(const QString &)>(&DockItemManager::appItemRemoved), Qt::QueuedConnection);
connect(m_appInter, &DockInter::ServiceRestarted, this, &DockItemManager::reloadAppItems);
#ifdef USE_AM
connect(m_appInter, &DockInter::ShowMultiWindowChanged, this, &DockItemManager::onShowMultiWindowChanged);
#endif
// 插件信号
connect(m_pluginsInter, &DockPluginsController::pluginItemInserted, this, &DockItemManager::pluginItemInserted, Qt::QueuedConnection);
@ -194,7 +205,7 @@ void DockItemManager::appItemAdded(const QDBusObjectPath &path, const int index)
++insertIndex;
}
AppItem *item = new AppItem(m_appSettings, m_activeSettings, m_dockedSettings, path);
AppItem *item = new AppItem(m_appInter, m_appSettings, m_activeSettings, m_dockedSettings, path);
if (m_appIDist.contains(item->appId())) {
delete item;
@ -206,17 +217,24 @@ void DockItemManager::appItemAdded(const QDBusObjectPath &path, const int index)
connect(item, &AppItem::requestActivateWindow, m_appInter, &DockInter::ActivateWindow, Qt::QueuedConnection);
connect(item, &AppItem::requestPreviewWindow, m_appInter, &DockInter::PreviewWindow);
connect(item, &AppItem::requestCancelPreview, m_appInter, &DockInter::CancelPreviewWindow);
#ifdef USE_AM
connect(item, &AppItem::windowCountChanged, this, &DockItemManager::onAppWindowCountChanged);
#endif
connect(this, &DockItemManager::requestUpdateDockItem, item, &AppItem::requestUpdateEntryGeometries);
m_itemList.insert(insertIndex, item);
m_appIDist.append(item->appId());
if (index != -1) {
emit itemInserted(insertIndex - 1, item);
return;
}
int itemIndex = insertIndex;
if (index != -1)
itemIndex = insertIndex - 1;
emit itemInserted(insertIndex, item);
// 插入dockItem
emit itemInserted(itemIndex, item);
#ifdef USE_AM
// 向后插入多开窗口
updateMultiItems(item, true);
#endif
}
void DockItemManager::appItemRemoved(const QString &appId)
@ -299,9 +317,7 @@ void DockItemManager::pluginItemInserted(PluginsItem *item)
m_itemList.insert(insertIndex, item);
if(pluginType == DockItem::FixedPlugin)
{
insertIndex ++;
}
if (!Utils::SettingValue(QString("com.deepin.dde.dock.module.") + item->pluginName(), QByteArray(), "enable", true).toBool())
item->setVisible(false);
@ -345,3 +361,115 @@ void DockItemManager::onPluginLoadFinished()
updatePluginsItemOrderKey();
m_loadFinished = true;
}
#ifdef USE_AM
void DockItemManager::onAppWindowCountChanged()
{
AppItem *appItem = static_cast<AppItem *>(sender());
updateMultiItems(appItem, true);
}
void DockItemManager::updateMultiItems(AppItem *appItem, bool emitSignal)
{
// 如果系统设置不开启应用多窗口拆分,则无需之后的操作
if (!m_appInter->showMultiWindow())
return;
// 如果开启了多窗口拆分,则同步窗口和多窗口应用的信息
const WindowInfoMap &windowInfoMap = appItem->windowsMap();
QList<AppMultiItem *> removeItems;
// 同步当前已经存在的多开窗口的列表,删除不存在的多开窗口
for (int i = 0; i < m_itemList.size(); i++) {
QPointer<DockItem> dockItem = m_itemList[i];
AppMultiItem *multiItem = qobject_cast<AppMultiItem *>(dockItem.data());
if (!multiItem || multiItem->appItem() != appItem)
continue;
// 如果查找到的当前的应用的窗口不需要移除,则继续下一个循环
if (!needRemoveMultiWindow(multiItem))
continue;
removeItems << multiItem;
}
// 从itemList中移除多开窗口
for (AppMultiItem *dockItem : removeItems)
m_itemList.removeOne(dockItem);
if (emitSignal) {
// 移除发送每个多开窗口的移除信号
for (AppMultiItem *dockItem : removeItems)
Q_EMIT itemRemoved(dockItem);
}
qDeleteAll(removeItems);
// 遍历当前APP打开的所有窗口的列表如果不存在多开窗口的应用则新增同时发送信号
for (auto it = windowInfoMap.begin(); it != windowInfoMap.end(); it++) {
if (multiWindowExist(it.key()))
continue;
const WindowInfo &windowInfo = it.value();
// 如果不存在这个窗口对应的多开窗口,则新建一个窗口,同时发送窗口新增的信号
AppMultiItem *multiItem = new AppMultiItem(appItem, it.key(), windowInfo);
m_itemList << multiItem;
if (emitSignal)
Q_EMIT itemInserted(-1, multiItem);
}
}
// 检查对应的窗口是否存在多开窗口
bool DockItemManager::multiWindowExist(quint32 winId) const
{
for (QPointer<DockItem> dockItem : m_itemList) {
AppMultiItem *multiItem = qobject_cast<AppMultiItem *>(dockItem.data());
if (!multiItem)
continue;
if (multiItem->winId() == winId)
return true;
}
return false;
}
// 检查当前多开窗口是否需要移除
// 如果当前多开窗口图标对应的窗口在这个窗口所属的APP中所有打开窗口中不存在那么则认为该多窗口已经被关闭
bool DockItemManager::needRemoveMultiWindow(AppMultiItem *multiItem) const
{
// 查找多分窗口对应的窗口在应用所有的打开的窗口中是否存在,只要它对应的窗口存在,就无需删除
// 只要不存在,就需要删除
AppItem *appItem = multiItem->appItem();
const WindowInfoMap &windowInfoMap = appItem->windowsMap();
for (auto it = windowInfoMap.begin(); it != windowInfoMap.end(); it++) {
if (it.key() == multiItem->winId())
return false;
}
return true;
}
void DockItemManager::onShowMultiWindowChanged()
{
if (m_appInter->showMultiWindow()) {
// 如果当前设置支持窗口多开那么就依次对每个APPItem加载多开窗口
for (const QPointer<DockItem> &dockItem : m_itemList) {
if (dockItem->itemType() != DockItem::ItemType::App)
continue;
updateMultiItems(static_cast<AppItem *>(dockItem.data()), true);
}
} else {
// 如果当前设置不支持窗口多开,则删除所有的多开窗口
QList<DockItem *> multiWindows;
for (const QPointer<DockItem> &dockItem : m_itemList) {
if (dockItem->itemType() != DockItem::AppMultiWindow)
continue;
multiWindows << dockItem.data();
}
for (DockItem *multiItem : multiWindows) {
m_itemList.removeOne(multiItem);
Q_EMIT itemRemoved(multiItem);
multiItem->deleteLater();
}
}
}
#endif

View File

@ -31,6 +31,7 @@
#include <QObject>
class AppMultiItem;
/**
* @brief The DockItemManager class
*
@ -64,6 +65,11 @@ public slots:
private Q_SLOTS:
void onPluginLoadFinished();
#ifdef USE_AM
void onAppWindowCountChanged();
void onShowMultiWindowChanged();
#endif
private:
explicit DockItemManager(QObject *parent = nullptr);
void appItemAdded(const QDBusObjectPath &path, const int index);
@ -75,6 +81,12 @@ private:
void reloadAppItems();
void manageItem(DockItem *item);
#ifdef USE_AM
void updateMultiItems(AppItem *appItem, bool emitSignal = false);
bool multiWindowExist(quint32 winId) const;
bool needRemoveMultiWindow(AppMultiItem *multiItem) const;
#endif
private:
DockInter *m_appInter;
DockPluginsController *m_pluginsInter;

View File

@ -0,0 +1,154 @@
/*
* 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 "multiwindowhelper.h"
#include "appmultiitem.h"
#include "appitem.h"
MultiWindowHelper::MultiWindowHelper(QWidget *appWidget, QWidget *multiWindowWidget, QObject *parent)
: QObject(parent)
, m_appWidget(appWidget)
, m_multiWindowWidget(multiWindowWidget)
, m_displayMode(Dock::DisplayMode::Efficient)
{
m_appWidget->installEventFilter(this);
m_multiWindowWidget->installEventFilter(this);
}
void MultiWindowHelper::setDisplayMode(Dock::DisplayMode displayMode)
{
if (m_displayMode == displayMode)
return;
m_displayMode = displayMode;
resetMultiItemPosition();
}
void MultiWindowHelper::addMultiWindow(int, AppMultiItem *item)
{
int index = itemIndex(item);
if (m_displayMode == Dock::DisplayMode::Efficient) {
// 将多开窗口项目插入到对应的APP的后面
insertChildWidget(m_appWidget, index, item);
} else {
// 将多开窗口插入到工具区域的前面
insertChildWidget(m_multiWindowWidget, index, item);
}
}
void MultiWindowHelper::removeMultiWindow(AppMultiItem *item)
{
if (m_appWidget->children().contains(item))
m_appWidget->layout()->removeWidget(item);
else
m_multiWindowWidget->layout()->removeWidget(item);
}
bool MultiWindowHelper::eventFilter(QObject *watched, QEvent *event)
{
if (watched == m_appWidget || watched == m_multiWindowWidget) {
switch(event->type()) {
case QEvent::ChildAdded:
case QEvent::ChildRemoved: {
/* 这里用异步的方式因为收到QEvent::ChildAdded信号的时候
Widget中QEvent::ChildRemoved信号的时候
*/
QMetaObject::invokeMethod(this, &MultiWindowHelper::requestUpdate, Qt::QueuedConnection);
break;
}
default:
break;
}
}
return QObject::eventFilter(watched, event);
}
int MultiWindowHelper::itemIndex(AppMultiItem *item)
{
if (m_displayMode != Dock::DisplayMode::Efficient)
return -1;
// 高效模式,查找对应的应用或者这个应用所有的子窗口所在的位置,然后插入到最大的值的后面
int lastIndex = -1;
for (int i = 0; i < m_appWidget->layout()->count(); i++) {
DockItem *dockItem = qobject_cast<DockItem *>(m_appWidget->layout()->itemAt(i)->widget());
if (!dockItem)
continue;
if (dockItem != item->appItem()) {
AppMultiItem *multiItem = qobject_cast<AppMultiItem *>(dockItem);
if (!multiItem || multiItem->appItem() != item->appItem())
continue;
}
lastIndex = i;
}
if (lastIndex >= 0)
return ++lastIndex;
return -1;
}
void MultiWindowHelper::insertChildWidget(QWidget *parentWidget, int index, AppMultiItem *item)
{
QBoxLayout *layout = static_cast<QBoxLayout *>(parentWidget->layout());
if (index >= 0)
layout->insertWidget(index, item);
else
layout->addWidget(item);
}
void MultiWindowHelper::resetMultiItemPosition()
{
QWidget *fromWidget = nullptr;
QWidget *toWidget = nullptr;
if (m_displayMode == Dock::DisplayMode::Efficient) {
// 从时尚模式变换为高效模式
fromWidget = m_multiWindowWidget;
toWidget = m_appWidget;
} else {
// 从高效模式变换到时尚模式
fromWidget = m_appWidget;
toWidget = m_multiWindowWidget;
}
QList<AppMultiItem *> moveWidgetItem;
for (int i = 0; i < fromWidget->layout()->count(); i++) {
AppMultiItem *multiItem = qobject_cast<AppMultiItem *>(fromWidget->layout()->itemAt(i)->widget());
if (!multiItem)
continue;
moveWidgetItem << multiItem;
}
QBoxLayout *toLayout = static_cast<QBoxLayout *>(toWidget->layout());
for (AppMultiItem *item : moveWidgetItem) {
fromWidget->layout()->removeWidget(item);
int index = itemIndex(item);
if (index >= 0)
toLayout->insertWidget(index, item);
else
toLayout->addWidget(item);
}
}

View File

@ -0,0 +1,58 @@
/*
* 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/>.
*/
#ifndef MULTIWINDOWHELPER_H
#define MULTIWINDOWHELPER_H
#include "constants.h"
#include <QObject>
class AppMultiItem;
class MultiWindowHelper : public QObject
{
Q_OBJECT
public:
explicit MultiWindowHelper(QWidget *appWidget, QWidget *multiWindowWidget, QObject *parent = nullptr);
void setDisplayMode(Dock::DisplayMode displayMode);
void addMultiWindow(int, AppMultiItem *item);
void removeMultiWindow(AppMultiItem *item);
Q_SIGNALS:
void requestUpdate();
protected:
bool eventFilter(QObject *watched, QEvent *event) override;
private:
int itemIndex(AppMultiItem *item);
void insertChildWidget(QWidget *parentWidget, int index, AppMultiItem *item);
void resetMultiItemPosition();
private:
QWidget *m_appWidget;
QWidget *m_multiWindowWidget;
Dock::DisplayMode m_displayMode;
};
#endif // MULTIWINDOWHELPER_H

View File

@ -328,6 +328,11 @@ bool Dde_Dock::showRecent() const
return qvariant_cast<bool>(property("ShowRecent"));
}
bool Dde_Dock::showMultiWindow() const
{
return qvariant_cast<bool>(property("ShowMultiWindow"));
}
QDBusPendingReply<> Dde_Dock::ActivateWindow(uint in0)
{
return m_wm->ActivateWindow(in0);

View File

@ -128,6 +128,9 @@ public:
Q_PROPERTY(bool ShowRecent READ showRecent NOTIFY showRecentChanged)
bool showRecent() const;
Q_PROPERTY(bool ShowMultiWindow READ showMultiWindow NOTIFY ShowMultiWindowChanged)
bool showMultiWindow() const;
public Q_SLOTS: // METHODS
QDBusPendingReply<> ActivateWindow(uint in0);
@ -326,6 +329,7 @@ Q_SIGNALS: // SIGNALS
void WindowSizeEfficientChanged(uint value) const;
void WindowSizeFashionChanged(uint value) const;
void showRecentChanged(bool) const;
void ShowMultiWindowChanged(bool) const;
public Q_SLOTS:
void CallQueued(const QString &callName, const QList<QVariant> &args);

View File

@ -145,6 +145,13 @@ public Q_SLOTS: // METHODS
return asyncCallWithArgumentList(QStringLiteral("ForceQuit"), argumentList);
}
inline QDBusPendingReply<> ActiveWindow(quint32 in0)
{
QList<QVariant> argumentList;
argumentList << in0;
return asyncCallWithArgumentList(QStringLiteral("ActiveWindow"), argumentList);
}
inline void ForceQuitQueued()
{
QList<QVariant> argumentList;

View File

@ -50,7 +50,7 @@ DCORE_USE_NAMESPACE
QPoint AppItem::MousePressPos;
AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const QDBusObjectPath &entry, QWidget *parent)
AppItem::AppItem(DockInter *dockInter, const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const QDBusObjectPath &entry, QWidget *parent)
: DockItem(parent)
, m_appSettings(appSettings)
, m_activeAppSettings(activeAppSettings)
@ -72,6 +72,7 @@ AppItem::AppItem(const QGSettings *appSettings, const QGSettings *activeAppSetti
, m_themeType(DGuiApplicationHelper::instance()->themeType())
, m_createMSecs(QDateTime::currentMSecsSinceEpoch())
, m_screenSpliter(ScreenSpliterFactory::createScreenSpliter(this, m_itemEntryInter))
, m_dockInter(dockInter)
{
QHBoxLayout *centralLayout = new QHBoxLayout;
centralLayout->setMargin(0);
@ -135,6 +136,11 @@ const QString AppItem::appId() const
return m_id;
}
QString AppItem::name() const
{
return m_itemEntryInter->name();
}
bool AppItem::isValid() const
{
return m_itemEntryInter->isValid() && !m_itemEntryInter->id().isEmpty();
@ -216,8 +222,14 @@ int AppItem::mode() const
{
return m_itemEntryInter->mode();
}
#endif
DockEntryInter *AppItem::itemEntryInter() const
{
return m_itemEntryInter;
}
QString AppItem::accessibleName()
{
return m_itemEntryInter->name();
@ -243,6 +255,11 @@ void AppItem::updateMSecs()
m_createMSecs = QDateTime::currentMSecsSinceEpoch();
}
const WindowInfoMap &AppItem::windowsMap() const
{
return m_windowInfos;
}
void AppItem::moveEvent(QMoveEvent *e)
{
DockItem::moveEvent(e);
@ -281,14 +298,26 @@ void AppItem::paintEvent(QPaintEvent *e)
QPainterPath path;
path.addRoundedRect(backgroundRect, 8, 8);
if (m_active) {
painter.fillPath(path, QColor(0, 0, 0, 255 * 0.8));
} else if (!m_windowInfos.isEmpty()) {
if (hasAttention())
painter.fillPath(path, QColor(241, 138, 46, 255 * .8));
else
painter.fillPath(path, QColor(0, 0, 0, 255 * 0.3));
// 在没有开启窗口多开的情况下,显示背景色
#ifdef USE_AM
if (!m_dockInter->showMultiWindow()) {
#endif
if (m_active) {
QColor color = Qt::black;
color.setAlpha(255 * 0.8);
painter.fillPath(path, color);
} else if (!m_windowInfos.isEmpty()) {
if (hasAttention()) {
painter.fillPath(path, QColor(241, 138, 46, 255 * .8));
} else {
QColor color = Qt::black;
color.setAlpha(255 * 0.3);
painter.fillPath(path, color);
}
}
#ifdef USE_AM
}
#endif
} else {
if (!m_windowInfos.isEmpty()) {
QPoint p;
@ -381,12 +410,21 @@ void AppItem::mouseReleaseEvent(QMouseEvent *e)
qDebug() << "app item clicked, name:" << m_itemEntryInter->name()
<< "id:" << m_itemEntryInter->id() << "my-id:" << m_id << "icon:" << m_itemEntryInter->icon();
m_itemEntryInter->Activate(QX11Info::getTimestamp());
// play launch effect
if (m_windowInfos.isEmpty() && DGuiApplicationHelper::isSpecialEffectsEnvironment())
playSwingEffect();
#ifdef USE_AM
if (m_dockInter->showMultiWindow()) {
// 如果开启了多窗口显示,则直接新建一个窗口
m_itemEntryInter->NewInstance(QX11Info::getTimestamp());
} else {
#endif
// 如果没有开启新窗口显示,则
m_itemEntryInter->Activate(QX11Info::getTimestamp());
// play launch effect
if (m_windowInfos.isEmpty() && DGuiApplicationHelper::isSpecialEffectsEnvironment())
playSwingEffect();
}
#ifdef USE_AM
}
#endif
}
void AppItem::mousePressEvent(QMouseEvent *e)
@ -640,6 +678,9 @@ void AppItem::updateWindowInfos(const WindowInfoMap &info)
}
update();
// 通知外面窗体数量发生变化,需要更新多开窗口的信息
Q_EMIT windowCountChanged();
}
void AppItem::refreshIcon()

View File

@ -43,11 +43,12 @@ class AppItem : public DockItem
Q_OBJECT
public:
explicit AppItem(const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const QDBusObjectPath &entry, QWidget *parent = nullptr);
explicit AppItem(DockInter *dockInter, const QGSettings *appSettings, const QGSettings *activeAppSettings, const QGSettings *dockedAppSettings, const QDBusObjectPath &entry, QWidget *parent = nullptr);
~AppItem() override;
void checkEntry() override;
const QString appId() const;
QString name() const;
bool isValid() const;
void updateWindowIconGeometries();
void undock();
@ -61,6 +62,7 @@ public:
#ifdef USE_AM
int mode() const;
#endif
DockEntryInter *itemEntryInter() const;
inline ItemType itemType() const override { return App; }
QPixmap appIcon(){ return m_appIcon; }
virtual QString accessibleName() override;
@ -68,6 +70,7 @@ public:
bool isDocked() const;
qint64 appOpenMSecs() const;
void updateMSecs();
const WindowInfoMap &windowsMap() const;
signals:
void requestActivateWindow(const WId wid) const;
@ -76,6 +79,7 @@ signals:
void dragReady(QWidget *dragWidget);
void requestUpdateEntryGeometries() const;
void windowCountChanged() const;
#ifdef USE_AM
void modeChanged(int) const;
#else
@ -161,6 +165,7 @@ private:
static QPoint MousePressPos;
ScreenSpliter *m_screenSpliter;
DockInter *m_dockInter;
};
#endif // APPITEM_H

286
frame/item/appmultiitem.cpp Normal file
View File

@ -0,0 +1,286 @@
/*
* 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 "appitem.h"
#include "appmultiitem.h"
#include "imageutil.h"
#include "themeappicon.h"
#include <QBitmap>
#include <QMenu>
#include <QPixmap>
#include <QX11Info>
#include <X11/Xlib.h>
#include <X11/X.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <sys/shm.h>
struct SHMInfo {
long shmid;
long width;
long height;
long bytesPerLine;
long format;
struct Rect {
long x;
long y;
long width;
long height;
} rect;
};
AppMultiItem::AppMultiItem(AppItem *appItem, WId winId, const WindowInfo &windowInfo, QWidget *parent)
: DockItem(parent)
, m_appItem(appItem)
, m_windowInfo(windowInfo)
, m_entryInter(appItem->itemEntryInter())
, m_winId(winId)
, m_menu(new QMenu(this))
{
initMenu();
initConnection();
}
AppMultiItem::~AppMultiItem()
{
}
QSize AppMultiItem::suitableSize(int size) const
{
return QSize(size, size);
}
AppItem *AppMultiItem::appItem() const
{
return m_appItem;
}
quint32 AppMultiItem::winId() const
{
return m_winId;
}
const WindowInfo &AppMultiItem::windowInfo() const
{
return m_windowInfo;
}
DockItem::ItemType AppMultiItem::itemType() const
{
return DockItem::AppMultiWindow;
}
bool AppMultiItem::isKWinAvailable() const
{
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.KWin"))) {
QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Effects"), QStringLiteral("org.kde.kwin.Effects"));
QDBusReply<bool> reply = interface.call(QStringLiteral("isEffectLoaded"), "screenshot");
return reply.value();
}
return false;
}
QImage AppMultiItem::snapImage() const
{
// 优先使用窗管进行窗口截图
if (isKWinAvailable()) {
QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot"));
QList<QVariant> args;
args << QVariant::fromValue(m_winId);
args << QVariant::fromValue(quint32(width() - 20));
args << QVariant::fromValue(quint32(height() - 20));
QImage image;
QDBusReply<QString> reply = interface.callWithArgumentList(QDBus::Block, QStringLiteral("screenshotForWindowExtend"), args);
if(reply.isValid()){
const QString tmpFile = reply.value();
if (QFile::exists(tmpFile)) {
image.load(tmpFile);
qDebug() << "reply: " << tmpFile;
QFile::remove(tmpFile);
} else {
qDebug() << "get current workspace bckground error, file does not exist : " << tmpFile;
}
} else {
qDebug() << "get current workspace bckground error: "<< reply.error().message();
}
return image;
}
// get window image from shm(only for deepin app)
SHMInfo *info = getImageDSHM();
QImage image;
uchar *image_data = 0;
if (info) {
qDebug() << "get Image from dxcbplugin SHM...";
image_data = (uchar *)shmat(info->shmid, 0, 0);
if ((qint64)image_data != -1)
return QImage(image_data, info->width, info->height, info->bytesPerLine, (QImage::Format)info->format);
qDebug() << "invalid pointer of shm!";
image_data = nullptr;
}
QImage qimage;
XImage *ximage;
if (!image_data || qimage.isNull()) {
ximage = getImageXlib();
if (!ximage)
return QImage();
qimage = QImage((const uchar *)(ximage->data), ximage->width, ximage->height, ximage->bytes_per_line, QImage::Format_RGB32);
}
return image;
}
SHMInfo *AppMultiItem::getImageDSHM() const
{
const auto display = Utils::IS_WAYLAND_DISPLAY ? XOpenDisplay(nullptr) : QX11Info::display();
if (!display) {
qWarning() << "Error: get display failed!";
return nullptr;
}
Atom atom_prop = XInternAtom(display, "_DEEPIN_DXCB_SHM_INFO", true);
if (!atom_prop) {
return nullptr;
}
Atom actual_type_return_deepin_shm;
int actual_format_return_deepin_shm;
unsigned long nitems_return_deepin_shm;
unsigned long bytes_after_return_deepin_shm;
unsigned char *prop_return_deepin_shm;
XGetWindowProperty(display, m_winId, atom_prop, 0, 32 * 9, false, AnyPropertyType,
&actual_type_return_deepin_shm, &actual_format_return_deepin_shm, &nitems_return_deepin_shm,
&bytes_after_return_deepin_shm, &prop_return_deepin_shm);
return reinterpret_cast<SHMInfo *>(prop_return_deepin_shm);
}
XImage *AppMultiItem::getImageXlib() const
{
const auto display = Utils::IS_WAYLAND_DISPLAY ? XOpenDisplay(nullptr) : QX11Info::display();
if (!display) {
qWarning() << "Error: get display failed!";
return nullptr;
}
Window unused_window;
int unused_int;
unsigned unused_uint, w, h;
XGetGeometry(display, m_winId, &unused_window, &unused_int, &unused_int, &w, &h, &unused_uint, &unused_uint);
return XGetImage(display, m_winId, 0, 0, w, h, AllPlanes, ZPixmap);
}
void AppMultiItem::initMenu()
{
QAction *actionOpen = new QAction(m_menu);
actionOpen->setText(tr("Open"));
connect(actionOpen, &QAction::triggered, this, &AppMultiItem::onOpen);
m_menu->addAction(actionOpen);
}
void AppMultiItem::initConnection()
{
connect(m_entryInter, &DockEntryInter::CurrentWindowChanged, this, &AppMultiItem::onCurrentWindowChanged);
}
void AppMultiItem::onOpen()
{
#ifdef USE_AM
m_entryInter->ActiveWindow(m_winId);
#endif
}
void AppMultiItem::onCurrentWindowChanged(uint32_t value)
{
if (value != m_winId)
return;
update();
}
void AppMultiItem::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
if (m_snapImage.isNull()) {
m_snapImage = snapImage();
}
DStyleHelper dstyle(style());
const int radius = dstyle.pixelMetric(DStyle::PM_FrameRadius);
QRect itemRect = rect();
itemRect.marginsRemoved(QMargins(6, 6, 6, 6));
QPixmap pixmapWindowIcon = QPixmap::fromImage(m_snapImage);
QPainterPath path;
path.addRoundedRect(rect(), radius, radius);
painter.fillPath(path, Qt::transparent);
if (m_entryInter->currentWindow() == m_winId) {
QColor backColor = Qt::black;
backColor.setAlpha(255 * 0.8);
painter.fillPath(path, backColor);
}
itemRect = m_snapImage.rect();
int itemWidth = itemRect.width();
int itemHeight = itemRect.height();
int x = (rect().width() - itemWidth) / 2;
int y = (rect().height() - itemHeight) / 2;
painter.drawPixmap(QRect(x, y, itemWidth, itemHeight), pixmapWindowIcon);
QPixmap pixmapAppIcon;
ThemeAppIcon::getIcon(pixmapAppIcon, m_entryInter->icon(), qMin(width(), height()) * 0.8);
if (!pixmapAppIcon.isNull()) {
// 绘制下方的图标,下方的小图标大约为应用图标的三分之一的大小
//pixmap = pixmap.scaled(pixmap.width() * 0.3, pixmap.height() * 0.3);
QRect rectIcon = rect();
int iconWidth = rectIcon.width() * 0.3;
int iconHeight = rectIcon.height() * 0.3;
rectIcon.setX((rect().width() - iconWidth) * 0.5);
rectIcon.setY(rect().height() - iconHeight);
rectIcon.setWidth(iconWidth);
rectIcon.setHeight(iconHeight);
painter.drawPixmap(rectIcon, pixmapAppIcon);
}
}
void AppMultiItem::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
#ifdef USE_AM
m_entryInter->ActiveWindow(m_winId);
#endif
} else {
QPoint currentPoint = QCursor::pos();
m_menu->exec(currentPoint);
}
}

74
frame/item/appmultiitem.h Normal file
View File

@ -0,0 +1,74 @@
/*
* 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/>.
*/
#ifndef APPMULTIITEM_H
#define APPMULTIITEM_H
#include "dockitem.h"
#include "dbusutil.h"
struct SHMInfo;
struct _XImage;
typedef _XImage XImage;
class AppItem;
class AppMultiItem : public DockItem
{
Q_OBJECT
friend class AppItem;
public:
AppMultiItem(AppItem *appItem, WId winId, const WindowInfo &windowInfo, QWidget *parent = Q_NULLPTR);
~AppMultiItem() override;
QSize suitableSize(int size) const;
AppItem *appItem() const;
quint32 winId() const;
const WindowInfo &windowInfo() const;
ItemType itemType() const override;
protected:
void paintEvent(QPaintEvent *) override;
void mouseReleaseEvent(QMouseEvent *event) override;
private:
bool isKWinAvailable() const;
QImage snapImage() const;
SHMInfo *getImageDSHM() const;
XImage *getImageXlib() const;
void initMenu();
void initConnection();
private Q_SLOTS:
void onOpen();
void onCurrentWindowChanged(uint32_t value);
private:
AppItem *m_appItem;
WindowInfo m_windowInfo;
DockEntryInter *m_entryInter;
QImage m_snapImage;
WId m_winId;
QMenu *m_menu;
};
#endif // APPMULTIITEM_H

View File

@ -48,7 +48,8 @@ public:
Placeholder,
TrayPlugin, // 托盘插件
QuickSettingPlugin, // 快捷设置区域插件
StretchPlugin // 时尚模式下的固定在最右侧的插件,例如开关机插件
StretchPlugin, // 时尚模式下的固定在最右侧的插件,例如开关机插件
AppMultiWindow // APP的多开应用的窗口
};
public:

View File

@ -36,6 +36,10 @@
#include "displaymanager.h"
#include "recentapphelper.h"
#include "toolapphelper.h"
#include "multiwindowhelper.h"
#include "mainwindow.h"
#include "appmultiitem.h"
#include "multiwindowhelper.h"
#include <QDrag>
#include <QTimer>
@ -89,7 +93,11 @@ MainPanelControl::MainPanelControl(QWidget *parent)
, m_recentLayout(new QBoxLayout(QBoxLayout::LeftToRight, this))
, m_recentSpliter(new QLabel(this))
, m_toolAreaWidget(new QWidget(this))
, m_toolLayout(new QBoxLayout(QBoxLayout::LeftToRight, m_toolAreaWidget))
, m_toolAreaLayout(new QBoxLayout(QBoxLayout::LeftToRight, m_toolAreaWidget))
, m_multiWindowWidget(new QWidget(m_toolAreaWidget))
, m_multiWindowLayout(new QBoxLayout(QBoxLayout::LeftToRight, m_multiWindowWidget))
, m_toolSonAreaWidget(new QWidget(m_toolAreaWidget))
, m_toolSonLayout(new QBoxLayout(QBoxLayout::LeftToRight, m_toolSonAreaWidget))
, m_trayManagerWidget(new TrayManagerWindow(this))
, m_pluginLayout(new QBoxLayout(QBoxLayout::LeftToRight, this))
, m_desktopWidget(new DesktopWidget(this))
@ -102,6 +110,7 @@ MainPanelControl::MainPanelControl(QWidget *parent)
, m_dockInter(new DockInter(dockServiceName(), dockServicePath(), QDBusConnection::sessionBus(), this))
, m_recentHelper(new RecentAppHelper(m_appAreaSonWidget, m_recentAreaWidget, m_dockInter, this))
, m_toolHelper(new ToolAppHelper(m_pluginAreaWidget, m_toolAreaWidget, this))
, m_multiHelper(new MultiWindowHelper(m_appAreaSonWidget, m_multiWindowWidget, this))
{
initUI();
initConnection();
@ -158,12 +167,27 @@ void MainPanelControl::initUI()
m_mainPanelLayout->addWidget(m_recentSpliter);
/* 工具应用 */
m_toolAreaWidget->setObjectName("toolarea");
m_toolAreaWidget->setAccessibleName("toolarea");
m_toolAreaWidget->setLayout(m_toolLayout);
m_toolLayout->setSpacing(0);
m_toolLayout->setContentsMargins(0, 0, 0, 0);
// 包含窗口多开和工具组合
m_toolAreaWidget->setObjectName("toolArea");
m_toolAreaWidget->setAccessibleName("toolArea");
m_toolAreaWidget->setLayout(m_toolAreaLayout);
m_toolAreaLayout->setContentsMargins(0, 0, 0, 0);
m_toolAreaLayout->setSpacing(0);
m_mainPanelLayout->addWidget(m_toolAreaWidget);
// 多开窗口区域
m_multiWindowWidget->setObjectName("multiWindow");
m_multiWindowWidget->setAccessibleName("multiWindow");
m_multiWindowWidget->setLayout(m_multiWindowLayout);
m_multiWindowLayout->setContentsMargins(0, 2, 0, 2);
m_multiWindowLayout->setSpacing(0);
m_toolAreaLayout->addWidget(m_multiWindowWidget);
// 工具应用区域-包含打开窗口区域和回收站区域
m_toolSonAreaWidget->setObjectName("toolsonarea");
m_toolSonAreaWidget->setAccessibleName("toolsonarea");
m_toolSonAreaWidget->setLayout(m_toolSonLayout);
m_toolSonLayout->setSpacing(0);
m_toolSonLayout->setContentsMargins(0, 0, 0, 0);
m_toolAreaLayout->addWidget(m_toolSonAreaWidget);
/* 托盘区域 */
m_trayAreaWidget->setObjectName("trayarea");
@ -206,6 +230,7 @@ void MainPanelControl::initConnection()
connect(m_recentHelper, &RecentAppHelper::dockAppVisibleChanged, this, &MainPanelControl::onDockAppVisibleChanged);
connect(m_toolHelper, &ToolAppHelper::requestUpdate, this, &MainPanelControl::requestUpdate);
connect(m_toolHelper, &ToolAppHelper::toolVisibleChanged, this, &MainPanelControl::onToolVisibleChanged);
connect(m_multiHelper, &MultiWindowHelper::requestUpdate, this, &MainPanelControl::requestUpdate);
}
/**
@ -220,6 +245,7 @@ void MainPanelControl::setDisplayMode(DisplayMode dislayMode)
m_displayMode = dislayMode;
m_recentHelper->setDisplayMode(dislayMode);
m_toolHelper->setDisplayMode(dislayMode);
m_multiHelper->setDisplayMode(dislayMode);
updateDisplayMode();
}
@ -244,6 +270,7 @@ void MainPanelControl::updateMainPanelLayout()
m_recentLayout->setDirection(QBoxLayout::LeftToRight);
m_trayAreaLayout->setContentsMargins(0, 10, 0, 10);
m_pluginLayout->setContentsMargins(10, 0, 10, 0);
m_multiWindowLayout->setContentsMargins(0, 2, 0, 2);
break;
case Position::Right:
case Position::Left:
@ -260,6 +287,7 @@ void MainPanelControl::updateMainPanelLayout()
m_recentLayout->setDirection(QBoxLayout::TopToBottom);
m_trayAreaLayout->setContentsMargins(10, 0, 10, 0);
m_pluginLayout->setContentsMargins(0, 10, 0, 10);
m_multiWindowLayout->setContentsMargins(2, 0, 2, 0);
break;
}
@ -379,12 +407,12 @@ void MainPanelControl::updateAppAreaSonWidgetSize()
m_appAreaSonWidget->setMaximumHeight(height());
m_appAreaSonWidget->setMaximumWidth(m_appAreaWidget->width());
m_recentAreaWidget->setFixedHeight(height());
m_toolAreaWidget->setFixedHeight(height());
//m_toolAreaWidget->setFixedHeight(height());
} else {
m_appAreaSonWidget->setMaximumWidth(width());
m_appAreaSonWidget->setMaximumHeight(m_appAreaWidget->height());
m_recentAreaWidget->setFixedWidth(width());
m_toolAreaWidget->setFixedWidth(width());
//m_toolAreaWidget->setFixedWidth(width());
}
m_appAreaSonWidget->adjustSize();
@ -434,10 +462,13 @@ void MainPanelControl::insertItem(int index, DockItem *item)
addTrayAreaItem(index, item);
break;
case DockItem::Plugins:
//addPluginAreaItem(index, item);
m_toolHelper->addPluginItem(index, item);
break;
default: break;
case DockItem::AppMultiWindow:
m_multiHelper->addMultiWindow(index, static_cast<AppMultiItem *>(item));
break;
default:
break;
}
// 同removeItem处 注意:不能屏蔽此接口,否则会造成插件插入时无法显示
@ -469,7 +500,11 @@ void MainPanelControl::removeItem(DockItem *item)
case DockItem::Plugins:
m_toolHelper->removePluginItem(item);
break;
default: break;
case DockItem::AppMultiWindow:
m_multiHelper->removeMultiWindow(static_cast<AppMultiItem *>(item));
break;
default:
break;
}
item->removeEventFilter(this);
@ -954,7 +989,7 @@ void MainPanelControl::updateModeChange()
m_trayAreaWidget->setVisible(m_displayMode == DisplayMode::Efficient);
m_traySpliter->setVisible(m_displayMode == DisplayMode::Efficient);
m_pluginAreaWidget->setVisible(m_displayMode == DisplayMode::Efficient);
m_trayManagerWidget->setVisible(m_displayMode != DisplayMode::Efficient);
m_toolAreaWidget->setVisible(m_displayMode == DisplayMode::Fashion);
onRecentVisibleChanged(m_recentHelper->recentIsVisible());
onDockAppVisibleChanged(m_recentHelper->dockAppIsVisible());
onToolVisibleChanged(m_toolHelper->toolIsVisible());
@ -969,20 +1004,11 @@ void MainPanelControl::moveAppSonWidget()
{
QRect rect(QPoint(0, 0), m_appAreaSonWidget->size());
if (DisplayMode::Efficient == m_displayMode) {
switch (m_position) {
case Top:
case Bottom :
rect.moveTo(m_appAreaWidget->pos());
break;
case Right:
case Left:
rect.moveTo(m_appAreaWidget->pos());
break;
}
rect.moveTo(m_appAreaWidget->pos());
} else {
switch (m_position) {
case Top:
case Bottom :
case Bottom:
rect.moveCenter(this->rect().center());
if (rect.right() > m_appAreaWidget->geometry().right()) {
rect.moveRight(m_appAreaWidget->geometry().right());
@ -1041,7 +1067,7 @@ QPainterPath MainPanelControl::areaPath()
if (m_recentLayout->count() > 0)
leftWidth += m_recentAreaWidget->width();
if (m_toolLayout->count() > 0)
if (m_toolAreaLayout->count() > 0)
leftWidth += m_toolAreaWidget->width();
int roundHeight = height();
@ -1053,7 +1079,7 @@ QPainterPath MainPanelControl::areaPath()
if (m_recentLayout->count() > 0)
topHeight += m_recentAreaWidget->height();
if (m_toolLayout->count() > 0)
if (m_toolAreaLayout->count() > 0)
topHeight += m_toolAreaWidget->height();
path.addRoundedRect(QRect(0, 0, roundWidth, topHeight), radius, radius);
@ -1086,7 +1112,7 @@ QSize MainPanelControl::suitableSize(int screenSize, double deviceRatio) const
// 减去右侧托盘和快捷设置还有插件区域的尺寸
totalLength -= (((m_position == Position::Top || m_position == Position::Bottom) ? traySuitableSize.width() : traySuitableSize.height()) / ratio);
// 需要参与计算的图标的总数
int iconCount = m_fixedAreaLayout->count() + m_appAreaSonLayout->count() + m_recentLayout->count() + m_toolLayout->count();
int iconCount = m_fixedAreaLayout->count() + m_appAreaSonLayout->count() + m_recentLayout->count() + m_toolAreaLayout->count();
if (iconCount <= 0) {
if (m_position == Position::Top || m_position == Position::Bottom)
return QSize((static_cast<int>((traySuitableSize.width() + 20) / ratio)), height());
@ -1195,7 +1221,12 @@ void MainPanelControl::resizeDockIcon()
// 减去右侧托盘和插件区域的宽度
totalLength -= ((m_position == Position::Top) || (m_position == Position::Bottom)) ? trayManagerSize.width() : trayManagerSize.height();
iconCount = m_fixedAreaLayout->count() + m_appAreaSonLayout->count() + m_recentLayout->count();
iconCount = m_fixedAreaLayout->count() + m_appAreaSonLayout->count();
if (m_recentAreaWidget->isVisible())
iconCount += m_recentLayout->count();
if (m_toolAreaWidget->isVisible())
iconCount += m_toolSonLayout->count();
if (iconCount <= 0)
return;
@ -1333,11 +1364,11 @@ void MainPanelControl::calcuDockIconSize(int w, int h, int traySize)
m_recentSpliter->setFixedSize(int(h * 0.6), SPLITER_SIZE);
}
for (int i = 0; i < m_appAreaSonLayout->count(); ++i)
m_appAreaSonLayout->itemAt(i)->widget()->setFixedSize(appItemSize, appItemSize);
// 时尚模式下判断是否需要显示最近打开的应用区域
if (m_displayMode == Dock::DisplayMode::Fashion) {
for (int i = 0; i < m_appAreaSonLayout->count(); ++i)
m_appAreaSonLayout->itemAt(i)->widget()->setFixedSize(appItemSize, appItemSize);
if (m_recentLayout->count() > 0) {
for (int i = 0; i < m_recentLayout->count(); ++i)
m_recentLayout->itemAt(i)->widget()->setFixedSize(appItemSize, appItemSize);
@ -1349,14 +1380,61 @@ void MainPanelControl::calcuDockIconSize(int w, int h, int traySize)
m_recentAreaWidget->setFixedHeight(appItemSize * m_recentLayout->count());
}
if (m_toolLayout->count() > 0) {
for (int i = 0; i < m_toolLayout->count(); i++)
m_toolLayout->itemAt(i)->widget()->setFixedSize(appItemSize, appItemSize);
if (m_multiWindowLayout->count() > 0) {
QList<QSize> multiSizes;
for (int i = 0; i < m_multiWindowLayout->count(); i++) {
// 因为多开窗口的长宽会不一样,因此,需要将当前的尺寸传入
// 由它自己来计算自己的长宽尺寸
AppMultiItem *appMultiItem = qobject_cast<AppMultiItem *>(m_multiWindowLayout->itemAt(i)->widget());
if (!appMultiItem)
continue;
if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom)
m_toolAreaWidget->setFixedWidth(appItemSize * m_toolLayout->count());
else
m_toolAreaWidget->setFixedHeight(appItemSize * m_toolLayout->count());
QSize size = appMultiItem->suitableSize(appItemSize);
appMultiItem->setFixedSize(size);
multiSizes << size;
}
// 计算多开窗口的尺寸
int totalSize = 0;
if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) {
for (QSize size : multiSizes)
totalSize += size.width();
m_multiWindowWidget->setFixedSize(totalSize, appItemSize);
} else {
for (QSize size : multiSizes)
totalSize += size.height();
m_multiWindowWidget->setFixedSize(appItemSize, totalSize);
}
} else {
m_multiWindowWidget->setFixedSize(0, 0);
}
if (m_toolSonLayout->count() > 0) {
for (int i = 0; i < m_toolSonLayout->count(); i++)
m_toolSonLayout->itemAt(i)->widget()->setFixedSize(appItemSize, appItemSize);
if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom) {
m_toolSonAreaWidget->setFixedWidth(appItemSize * m_toolSonLayout->count());
} else {
m_toolSonAreaWidget->setFixedHeight(appItemSize * m_toolSonLayout->count());
}
}
if (m_position == Dock::Position::Top || m_position == Dock::Position::Bottom)
m_toolAreaWidget->setFixedWidth(m_multiWindowWidget->width() + m_toolSonAreaWidget->width());
else
m_toolAreaWidget->setFixedHeight(m_multiWindowWidget->height() + m_toolSonAreaWidget->height());
} else {
for (int i = 0; i < m_appAreaSonLayout->count(); ++i) {
DockItem *dockItem = qobject_cast<DockItem *>(m_appAreaSonLayout->itemAt(i)->widget());
if (!dockItem)
continue;
if (dockItem->itemType() == DockItem::ItemType::AppMultiWindow) {
AppMultiItem *appMultiItem = qobject_cast<AppMultiItem *>(dockItem);
dockItem->setFixedSize(appMultiItem->suitableSize(appItemSize));
} else {
dockItem->setFixedSize(appItemSize, appItemSize);
}
}
}

View File

@ -43,6 +43,7 @@ class TrayManagerWindow;
class DockScreen;
class RecentAppHelper;
class ToolAppHelper;
class MultiWindowHelper;
class MainPanelControl : public QWidget
{
@ -132,8 +133,12 @@ private:
QWidget *m_recentAreaWidget; // 最近打开应用
QBoxLayout *m_recentLayout;
QLabel *m_recentSpliter; // 最近打开应用区域分割线
QWidget *m_toolAreaWidget; // 工具区域
QBoxLayout *m_toolLayout; // 工具区域布局
QWidget *m_toolAreaWidget; // 工具区域,用来存放多开窗口和回收站等
QBoxLayout *m_toolAreaLayout; // 工具区域的布局
QWidget *m_multiWindowWidget; // 多开窗口区域,用来存放多开窗口
QBoxLayout *m_multiWindowLayout;// 用来存放多开窗口的布局
QWidget *m_toolSonAreaWidget; // 工具区域,用来存放回收站等工具
QBoxLayout *m_toolSonLayout; // 工具区域布局
TrayManagerWindow *m_trayManagerWidget;
QBoxLayout *m_pluginLayout; // 插件区域布局
@ -152,6 +157,7 @@ private:
DockInter *m_dockInter;
RecentAppHelper *m_recentHelper;
ToolAppHelper *m_toolHelper;
MultiWindowHelper *m_multiHelper;
};
#endif // MAINPANELCONTROL_H