dde-application-manager/src/modules/dock/entries.cpp

344 lines
9.2 KiB
C++
Raw Normal View History

/*
* Copyright (C) 2021 ~ 2022 Deepin Technology Co., Ltd.
*
* Author: weizhixiang <weizhixiang@uniontech.com>
*
* Maintainer: weizhixiang <weizhixiang@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 "entries.h"
#include "dock.h"
Entries::Entries(Dock *_dock)
: m_dock(_dock)
{
}
QVector<Entry *> Entries::filterDockedEntries()
{
QVector<Entry *> ret;
for (auto &entry : m_items) {
if (entry->isValid() && entry->getIsDocked())
ret.push_back(entry);
}
return ret;
}
Entry *Entries::getByInnerId(QString innerId)
{
Entry *ret = nullptr;
for (auto &entry : m_items) {
if (entry->getInnerId() == innerId)
ret = entry;
}
return ret;
}
void Entries::append(Entry *entry)
{
insert(entry, -1);
}
void Entries::insert(Entry *entry, int index)
{
if (index < 0 || index >= m_items.size()) {
// append
index = m_items.size();
m_items.push_back(entry);
} else {
// insert
m_items.insert(index, entry);
}
insertCb(entry, index);
}
void Entries::remove(Entry *entry)
{
for (auto iter = m_items.begin(); iter != m_items.end();) {
if ((*iter)->getId() == entry->getId()) {
iter = m_items.erase(iter);
removeCb(entry);
delete entry;
} else {
iter++;
}
}
}
void Entries::move(int oldIndex, int newIndex)
{
if (oldIndex == newIndex || oldIndex < 0 || newIndex < 0 || oldIndex >= m_items.size() || newIndex >= m_items.size())
return;
m_items.swap(oldIndex, newIndex);
}
Entry *Entries::getByWindowPid(int pid)
{
Entry *ret = nullptr;
for (auto &entry : m_items) {
if (entry->getWindowInfoByPid(pid)) {
ret = entry;
break;
}
}
return ret;
}
Entry *Entries::getByWindowId(XWindow windowId)
{
Entry *ret = nullptr;
for (auto &entry : m_items) {
if (entry->getWindowInfoByWinId(windowId)) {
ret = entry;
break;
}
}
return ret;
}
Entry *Entries::getByDesktopFilePath(QString filePath)
{
Entry *ret = nullptr;
for (auto &entry : m_items) {
if (entry->getFileName() == filePath) {
ret = entry;
break;
}
}
return ret;
}
QStringList Entries::getEntryIDs()
{
QStringList list;
if (static_cast<DisplayMode>(m_dock->getDisplayMode()) == DisplayMode::Fashion
&& m_dock->showRecent()) {
for (Entry *item : m_items)
list.push_back(item->getId());
} else {
// 如果是高效模式或者没有开启显示最近应用的功能,那么未驻留并且没有子窗口的就不显示
// 换句话说,只显示已经驻留或者有子窗口的应用
for (Entry *item : m_items) {
if (!item->getIsDocked() && !item->hasWindow())
continue;
list << item->getId();
}
}
return list;
}
Entry *Entries::getDockedEntryByDesktopFile(const QString &desktopFile)
{
Entry *ret = nullptr;
for (auto entry : filterDockedEntries()) {
if (!entry->isValid())
continue;
if (desktopFile == entry->getFileName()) {
ret = entry;
break;
}
}
return ret;
}
QString Entries::queryWindowIdentifyMethod(XWindow windowId)
{
QString ret;
for (auto entry : m_items) {
auto window = entry->getWindowInfoByWinId(windowId);
if (window) {
auto app = window->getAppInfo();
if (app) {
ret = app->getIdentifyMethod();
} else {
ret = "Failed";
}
break;
}
}
return ret;
}
void Entries::handleActiveWindowChanged(XWindow activeWindId)
{
for (auto entry : m_items) {
auto windowInfo = entry->getWindowInfoByWinId(activeWindId);
if (windowInfo) {
entry->setPropIsActive(true);
entry->setCurrentWindowInfo(windowInfo);
entry->updateName();
entry->updateIcon();
} else {
entry->setPropIsActive(false);
}
}
}
void Entries::updateEntriesMenu()
{
for (auto entry : m_items) {
entry->updateMenu();
}
}
const QList<Entry *> Entries::unDockedEntries() const
{
QList<Entry *> entrys;
for (Entry *entry : m_items) {
if (!entry->isValid() || entry->getIsDocked())
continue;
entrys << entry;
}
return entrys;
}
void Entries::moveEntryToLast(Entry *entry)
{
if (m_items.contains(entry)) {
m_items.removeOne(entry);
m_items << entry;
}
}
void Entries::insertCb(Entry *entry, int index)
{
if (entry->getIsDocked() || entry->hasWindow() ||
(static_cast<DisplayMode>(m_dock->getDisplayMode()) == DisplayMode::Fashion) && m_dock->showRecent())
Q_EMIT m_dock->entryAdded(QDBusObjectPath(entry->path()), index);
}
void Entries::removeCb(Entry *entry)
{
Q_EMIT m_dock->entryRemoved(entry->getId());
entry->stopExport();
}
bool Entries::shouldInRecent()
{
// 如果当前移除的应用是未驻留应用则判断未驻留应用的数量是否小于等于3则让其始终显示
QList<Entry *> unDocktrys;
for (Entry *entry : m_items) {
if (entry->isValid() && !entry->getIsDocked())
unDocktrys << entry;
}
// 如果当前未驻留应用的数量小于3个则认为后续的应用应该显示到最近打开应用
return (unDocktrys.size() <= MAX_UNOPEN_RECENT_COUNT);
}
void Entries::removeLastRecent()
{
// 先查找最近使用的应用,删除没有使用的
int unDockCount = 0;
QList<Entry *> unDockEntrys;
QList<Entry *> removeEntrys;
for (Entry *entry : m_items) {
if (entry->getIsDocked())
continue;
// 此处只移除没有子窗口的图标
if (!entry->hasWindow()) {
if (!entry->isValid())
removeEntrys << entry; // 如果应用已经被卸载,那么需要删除
else
unDockEntrys << entry;
}
unDockCount++;
}
if (unDockCount >= MAX_UNOPEN_RECENT_COUNT && unDockEntrys.size() > 0) {
// 只有当最近使用区域的图标大于等于某个数值3的时候并且存在没有子窗口的Entry那么就移除该Entry
Entry *entry = unDockEntrys[0];
m_items.removeOne(entry);
removeEntrys << entry;
}
for (Entry *entry : removeEntrys) {
removeCb(entry);
delete entry;
}
}
void Entries::setDisplayMode(DisplayMode displayMode)
{
if (!m_dock->showRecent())
return;
// 如果从时尚模式变成高效模式,对列表中所有的没有打开窗口的应用发送移除信号
if (displayMode == DisplayMode::Efficient) {
for (Entry *entry : m_items) {
entry->updateMode();
if (!entry->getIsDocked() && !entry->hasWindow())
Q_EMIT m_dock->entryRemoved(entry->getId());
}
} else {
// 如果从高效模式变成时尚模式,列表中所有的未驻留且不存在打开窗口的应用认为是最近打开应用,发送新增信号
for (Entry *entry : m_items) {
entry->updateMode();
if (!entry->getIsDocked() && !entry->hasWindow()) {
QString objPath = entry->path();
int index = m_items.indexOf(entry);
Q_EMIT m_dock->entryAdded(QDBusObjectPath(objPath), index);
}
}
}
}
void Entries::updateShowRecent()
{
// 高效模式无需做任何操作
if (static_cast<DisplayMode>(m_dock->getDisplayMode()) != DisplayMode::Fashion)
return;
bool showRecent = m_dock->showRecent();
if (showRecent) {
// 如果显示最近打开应用,则发送新增信号
for (Entry *entry : m_items) {
// 已经驻留的或者有子窗口的本来就在任务栏上面,无需发送信号
entry->updateMode();
if (entry->getIsDocked() || entry->hasWindow())
continue;
QString objPath = entry->path();
int index = m_items.indexOf(entry);
Q_EMIT m_dock->entryAdded(QDBusObjectPath(objPath), index);
}
} else {
// 如果是隐藏最近打开的应用,则发送移除的信号
for (Entry *entry : m_items) {
// 已经驻留的或者有子窗口的本来就在任务栏上面,无需发送信号
entry->updateMode();
if (entry->getIsDocked() || entry->hasWindow())
continue;
Q_EMIT m_dock->entryRemoved(entry->getId());
}
}
}