/* * Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd. * * Author: sbw * * Maintainer: sbw * * 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 "dockitemcontroller.h" #include "dbus/dbusdockentry.h" #include "item/appitem.h" #include "item/stretchitem.h" #include "item/launcheritem.h" #include "item/pluginsitem.h" #include DockItemController *DockItemController::INSTANCE = nullptr; DockItemController *DockItemController::instance(QObject *parent) { if (!INSTANCE) INSTANCE = new DockItemController(parent); return INSTANCE; } const QList DockItemController::itemList() const { return m_itemList; } const QList DockItemController::pluginList() const { return m_pluginsInter->m_pluginList.keys(); } bool DockItemController::appIsOnDock(const QString &appDesktop) const { return m_appInter->IsOnDock(appDesktop); } bool DockItemController::itemIsInContainer(DockItem * const item) const { return m_containerItem->contains(item); } void DockItemController::setDropping(const bool dropping) { m_containerItem->setDropping(dropping); } void DockItemController::refershItemsIcon() { for (auto item : m_itemList) { item->refershIcon(); item->update(); } } void DockItemController::updatePluginsItemOrderKey() { Q_ASSERT(sender() == m_updatePluginsOrderTimer); int index = 0; for (auto item : m_itemList) { if (item->itemType() != DockItem::Plugins) continue; static_cast(item)->setItemSortKey(++index); } } void DockItemController::itemMove(DockItem * const moveItem, DockItem * const replaceItem) { Q_ASSERT(moveItem != replaceItem); const DockItem::ItemType moveType = moveItem->itemType(); const DockItem::ItemType replaceType = replaceItem->itemType(); // app move if (moveType == DockItem::App) if (replaceType != DockItem::App && replaceType != DockItem::Stretch) return; // plugins move if (moveType == DockItem::Plugins) if (replaceType != DockItem::Plugins) return; const int moveIndex = m_itemList.indexOf(moveItem); const int replaceIndex = replaceType == DockItem::Stretch ? // disable insert after placeholder item m_itemList.indexOf(replaceItem) - 1 : m_itemList.indexOf(replaceItem); m_itemList.removeAt(moveIndex); m_itemList.insert(replaceIndex, moveItem); emit itemMoved(moveItem, replaceIndex); // update plugins sort key if order changed if (moveType == DockItem::Plugins || replaceType == DockItem::Plugins) m_updatePluginsOrderTimer->start(); // for app move, index 0 is launcher item, need to pass it. if (moveType == DockItem::App && replaceType == DockItem::App) m_appInter->MoveEntry(moveIndex - 1, replaceIndex - 1); } void DockItemController::itemDroppedIntoContainer(DockItem * const item) { Q_ASSERT(item->itemType() == DockItem::Plugins); PluginsItem *pi = static_cast(item); if (!pi->allowContainer()) return; if (m_containerItem->contains(item)) return; // qDebug() << "drag into container" << item; // remove from main panel emit itemRemoved(item); m_itemList.removeOne(item); // add to container pi->setInContainer(true); m_containerItem->addItem(item); } void DockItemController::itemDragOutFromContainer(DockItem * const item) { // qDebug() << "drag out from container" << item; // remove from container m_containerItem->removeItem(item); // insert to panel switch (item->itemType()) { case DockItem::Plugins: static_cast(item)->setInContainer(false); pluginItemInserted(static_cast(item)); break; default: Q_UNREACHABLE(); } } void DockItemController::placeholderItemAdded(PlaceholderItem *item, DockItem *position) { const int pos = m_itemList.indexOf(position); m_itemList.insert(pos, item); emit itemInserted(pos, item); } void DockItemController::placeholderItemDocked(const QString &appDesktop, DockItem *position) { m_appInter->RequestDock(appDesktop, m_itemList.indexOf(position) - 1).waitForFinished(); } void DockItemController::placeholderItemRemoved(PlaceholderItem *item) { emit itemRemoved(item); m_itemList.removeOne(item); } DockItemController::DockItemController(QObject *parent) : QObject(parent), m_updatePluginsOrderTimer(new QTimer(this)), m_appInter(new DBusDock(this)), m_pluginsInter(new DockPluginsController(this)), m_placeholderItem(new StretchItem), m_containerItem(new ContainerItem) { // m_placeholderItem->hide(); m_updatePluginsOrderTimer->setSingleShot(true); m_updatePluginsOrderTimer->setInterval(1000); m_itemList.append(new LauncherItem); for (auto entry : m_appInter->entries()) { AppItem *it = new AppItem(entry); connect(it, &AppItem::requestActivateWindow, m_appInter, &DBusDock::ActivateWindow, Qt::QueuedConnection); connect(it, &AppItem::requestPreviewWindow, m_appInter, &DBusDock::PreviewWindow); connect(it, &AppItem::requestCancelPreview, m_appInter, &DBusDock::CancelPreviewWindow); m_itemList.append(it); } m_itemList.append(m_placeholderItem); m_itemList.append(m_containerItem); connect(m_updatePluginsOrderTimer, &QTimer::timeout, this, &DockItemController::updatePluginsItemOrderKey); connect(m_appInter, &DBusDock::EntryAdded, this, &DockItemController::appItemAdded); connect(m_appInter, &DBusDock::EntryRemoved, this, static_cast(&DockItemController::appItemRemoved), Qt::QueuedConnection); connect(m_appInter, &DBusDock::ServiceRestarted, this, &DockItemController::reloadAppItems); connect(m_pluginsInter, &DockPluginsController::pluginItemInserted, this, &DockItemController::pluginItemInserted, Qt::QueuedConnection); connect(m_pluginsInter, &DockPluginsController::pluginItemRemoved, this, &DockItemController::pluginItemRemoved, Qt::QueuedConnection); connect(m_pluginsInter, &DockPluginsController::pluginItemUpdated, this, &DockItemController::itemUpdated, Qt::QueuedConnection); QMetaObject::invokeMethod(this, "refershItemsIcon", Qt::QueuedConnection); } void DockItemController::appItemAdded(const QDBusObjectPath &path, const int index) { // the first index is launcher item int insertIndex = 1; // -1 for append to app list end if (index != -1) { insertIndex += index; } else { for (auto item : m_itemList) if (item->itemType() == DockItem::App) ++insertIndex; } AppItem *item = new AppItem(path); connect(item, &AppItem::requestActivateWindow, m_appInter, &DBusDock::ActivateWindow, Qt::QueuedConnection); connect(item, &AppItem::requestPreviewWindow, m_appInter, &DBusDock::PreviewWindow); connect(item, &AppItem::requestCancelPreview, m_appInter, &DBusDock::CancelPreviewWindow); m_itemList.insert(insertIndex, item); emit itemInserted(insertIndex, item); } void DockItemController::appItemRemoved(const QString &appId) { for (int i(0); i != m_itemList.size(); ++i) { if (m_itemList[i]->itemType() != DockItem::App) continue; AppItem *app = static_cast(m_itemList[i]); if (app->appId() != appId) continue; appItemRemoved(app); break; } } void DockItemController::appItemRemoved(AppItem *appItem) { emit itemRemoved(appItem); m_itemList.removeOne(appItem); appItem->deleteLater(); } void DockItemController::pluginItemInserted(PluginsItem *item) { // check item is in container if (item->allowContainer() && item->isInContainer()) { emit itemManaged(item); return itemDroppedIntoContainer(item); } // find first plugins item position int firstPluginPosition = -1; for (int i(0); i != m_itemList.size(); ++i) { if (m_itemList[i]->itemType() != DockItem::Plugins) continue; firstPluginPosition = i; break; } if (firstPluginPosition == -1) firstPluginPosition = m_itemList.size(); // find insert position int insertIndex = 0; const int itemSortKey = item->itemSortKey(); if (itemSortKey == -1 || firstPluginPosition == -1) { insertIndex = m_itemList.size(); } else if (itemSortKey == 0) { insertIndex = firstPluginPosition; } else { insertIndex = m_itemList.size(); for (int i(firstPluginPosition); i != m_itemList.size(); ++i) { PluginsItem *pItem = static_cast(m_itemList[i]); Q_ASSERT(pItem); if (itemSortKey <= pItem->itemSortKey()) continue; insertIndex = i; break; } } // qDebug() << insertIndex << item; m_itemList.insert(insertIndex, item); emit itemInserted(insertIndex, item); } void DockItemController::pluginItemRemoved(PluginsItem *item) { if (m_containerItem->contains(item)) m_containerItem->removeItem(item); else emit itemRemoved(item); m_itemList.removeOne(item); } void DockItemController::reloadAppItems() { // remove old item for (auto item : m_itemList) if (item->itemType() == DockItem::App) appItemRemoved(static_cast(item)); // append new item for (auto path : m_appInter->entries()) appItemAdded(path, -1); }