dde-dock/plugins/tray/fashiontray/containers/abstractcontainer.cpp
chenjun cc9af0844c fix: 声音、网络、键盘布局等图标排序时不再区分是否系统图标,同时将排序字段统一成pos_%1_%2格式
在图标排序时,对于系统图标,会自动全部排在其他图标后面,而声音图标正好是属于系统图标,在切换Dock显示模式时,会将声音图标显示在网络图标后面

Log: 修复调整声音插件顺序,切换任务栏模式之后,声音插件顺序改变问题(bug:38862)
Bug: https://pms.uniontech.com/zentao/bug-view-38862.html
Change-Id: Ib080d6eed3a361974142911ff81e9fa0003ae01f
Reviewed-on: http://gerrit.uniontech.com/c/dde-dock/+/343
Reviewed-by: lizhongming <lizhongming@uniontech.com>
Tested-by: lizhongming <lizhongming@uniontech.com>
2020-07-23 08:43:03 +00:00

434 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author:
*
* Maintainer: zhaolong <zhaolong@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 "abstractcontainer.h"
#include "../fashiontrayconstants.h"
AbstractContainer::AbstractContainer(TrayPlugin *trayPlugin, QWidget *parent)
: QWidget(parent)
, m_trayPlugin(trayPlugin)
, m_wrapperLayout(new QBoxLayout(QBoxLayout::LeftToRight, this))
, m_currentDraggingWrapper(nullptr)
, m_expand(true)
, m_dockPosition(Dock::Position::Bottom)
// , m_wrapperSize(QSize(PLUGIN_BACKGROUND_MAX_SIZE, PLUGIN_BACKGROUND_MAX_SIZE))
{
setAcceptDrops(true);
m_wrapperLayout->setMargin(0);
m_wrapperLayout->setContentsMargins(0, 0, 0, 0);
m_wrapperLayout->setSpacing(TraySpace);
setLayout(m_wrapperLayout);
setMinimumWidth(TraySpace);
setMinimumHeight(TraySpace);
}
void AbstractContainer::refreshVisible()
{
if (!m_wrapperList.isEmpty()) {
//非空保留两边边距
if (m_dockPosition == Dock::Position::Top || m_dockPosition == Dock::Position::Bottom) {
m_wrapperLayout->setContentsMargins(TraySpace, 0, TraySpace, 0);
} else {
m_wrapperLayout->setContentsMargins(0, TraySpace, 0, TraySpace);
}
} else {
// 空保留最小size可以拖入
m_wrapperLayout->setContentsMargins(0, 0, 0, 0);
}
}
void AbstractContainer::addWrapper(FashionTrayWidgetWrapper *wrapper)
{
if (containsWrapper(wrapper)) {
return;
}
const int index = whereToInsert(wrapper);
m_wrapperLayout->insertWidget(index, wrapper);
m_wrapperList.insert(index, wrapper);
wrapper->setAttention(false);
connect(wrapper, &FashionTrayWidgetWrapper::attentionChanged, this, &AbstractContainer::onWrapperAttentionhChanged, static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection));
connect(wrapper, &FashionTrayWidgetWrapper::dragStart, this, &AbstractContainer::onWrapperDragStart, Qt::UniqueConnection);
connect(wrapper, &FashionTrayWidgetWrapper::dragStop, this, &AbstractContainer::onWrapperDragStop, Qt::UniqueConnection);
connect(wrapper, &FashionTrayWidgetWrapper::requestSwapWithDragging, this, &AbstractContainer::onWrapperRequestSwapWithDragging, Qt::UniqueConnection);
refreshVisible();
}
bool AbstractContainer::removeWrapper(FashionTrayWidgetWrapper *wrapper)
{
FashionTrayWidgetWrapper *w = takeWrapper(wrapper);
if (!w) {
return false;
}
// do not delete real tray object, just delete it's wrapper object
// the real tray object should be deleted in TrayPlugin class
if (!w->absTrayWidget().isNull())
w->absTrayWidget()->setParent(nullptr);
if (w->isDragging()) {
w->cancelDragging();
}
w->deleteLater();
refreshVisible();
return true;
}
bool AbstractContainer::removeWrapperByTrayWidget(AbstractTrayWidget *trayWidget)
{
FashionTrayWidgetWrapper *w = wrapperByTrayWidget(trayWidget);
if (!w) {
return false;
}
return removeWrapper(w);
}
FashionTrayWidgetWrapper *AbstractContainer::takeWrapper(FashionTrayWidgetWrapper *wrapper)
{
if (!containsWrapper(wrapper)) {
return nullptr;
}
if (m_currentDraggingWrapper == wrapper) {
m_currentDraggingWrapper = nullptr;
}
wrapper->disconnect();
m_wrapperLayout->removeWidget(wrapper);
m_wrapperList.removeAll(wrapper);
refreshVisible();
return wrapper;
}
void AbstractContainer::setDockPosition(const Dock::Position pos)
{
m_dockPosition = pos;
if (pos == Dock::Position::Top || pos == Dock::Position::Bottom) {
m_wrapperLayout->setDirection(QBoxLayout::Direction::LeftToRight);
} else {
m_wrapperLayout->setDirection(QBoxLayout::Direction::TopToBottom);
}
refreshVisible();
}
void AbstractContainer::setExpand(const bool expand)
{
m_expand = expand;
refreshVisible();
}
//QSize AbstractContainer::sizeHint() const
//{
// return totalSize();
//}
void AbstractContainer::setItemSize(int itemSize)
{
m_itemSize = itemSize;
for (auto w : wrapperList()) {
if (dockPosition() == Dock::Top || dockPosition() == Dock::Bottom)
w->setFixedSize(m_itemSize, QWIDGETSIZE_MAX);
else
w->setFixedSize(QWIDGETSIZE_MAX, m_itemSize);
}
}
QSize AbstractContainer::totalSize() const
{
QSize size;
if (m_dockPosition == Dock::Position::Top || m_dockPosition == Dock::Position::Bottom) {
int itemSize = qBound(PLUGIN_BACKGROUND_MIN_SIZE, parentWidget()->height(), PLUGIN_BACKGROUND_MAX_SIZE);
if (itemSize > m_itemSize)
itemSize = m_itemSize;
size.setWidth(
(expand() ? (m_wrapperList.size() * itemSize // 所有托盘图标
+ m_wrapperList.size() * TraySpace) : 0 // 所有托盘图标之间 + 一个尾部的 space
) + TraySpace
);
size.setHeight(height());
} else {
int itemSize = qBound(PLUGIN_BACKGROUND_MIN_SIZE, parentWidget()->width(), PLUGIN_BACKGROUND_MAX_SIZE);
if (itemSize > m_itemSize)
itemSize = m_itemSize;
size.setWidth(width());
size.setHeight(
(expand() ? (m_wrapperList.size() * itemSize // 所有托盘图标
+ m_wrapperList.size() * TraySpace) : 0 // 所有托盘图标之间 + 一个尾部的 space
) + TraySpace
);
}
return size;
}
void AbstractContainer::clearWrapper()
{
QList<QPointer<FashionTrayWidgetWrapper>> mList = m_wrapperList;
for (auto wrapper : mList) {
removeWrapper(wrapper);
}
m_wrapperList.clear();
refreshVisible();
}
void AbstractContainer::saveCurrentOrderToConfig()
{
for (int i = 0; i < m_wrapperList.size(); ++i) {
m_trayPlugin->setSortKey(m_wrapperList.at(i)->itemKey(), i + 1);
}
}
bool AbstractContainer::isEmpty()
{
return m_wrapperList.isEmpty();
}
int AbstractContainer::itemCount()
{
return m_wrapperList.count();
}
bool AbstractContainer::containsWrapper(FashionTrayWidgetWrapper *wrapper)
{
for (auto w : m_wrapperList) {
if (w == wrapper) {
return true;
}
}
return false;
}
bool AbstractContainer::containsWrapperByTrayWidget(AbstractTrayWidget *trayWidget)
{
if (wrapperByTrayWidget(trayWidget)) {
return true;
}
return false;
}
FashionTrayWidgetWrapper *AbstractContainer::wrapperByTrayWidget(AbstractTrayWidget *trayWidget)
{
for (auto w : m_wrapperList) {
if (w->absTrayWidget() == trayWidget) {
return w;
}
}
return nullptr;
}
void AbstractContainer::addDraggingWrapper(FashionTrayWidgetWrapper *wrapper)
{
addWrapper(wrapper);
if (containsWrapper(wrapper)) {
m_currentDraggingWrapper = wrapper;
}
}
FashionTrayWidgetWrapper *AbstractContainer::takeDraggingWrapper()
{
if (!m_currentDraggingWrapper) {
return nullptr;
}
return takeWrapper(m_currentDraggingWrapper);
}
int AbstractContainer::whereToInsert(FashionTrayWidgetWrapper *wrapper)
{
if (m_wrapperList.isEmpty()) {
return 0;
}
//根据配置文件记录的顺序排序
int destSortKey = m_trayPlugin->itemSortKey(wrapper->itemKey());
if (destSortKey < -1) {
return 0;
}
if (destSortKey == -1) {
return m_wrapperList.size();
}
// 当目标插入位置为列表的大小时将从最后面追加到列表中
int destIndex = m_wrapperList.size();
for (int i = 0; i < m_wrapperList.size(); ++i) {
if (destSortKey > m_trayPlugin->itemSortKey(m_wrapperList.at(i)->itemKey())) {
continue;
}
destIndex = i;
break;
}
return destIndex;
}
TrayPlugin *AbstractContainer::trayPlugin() const
{
return m_trayPlugin;
}
QList<QPointer<FashionTrayWidgetWrapper> > AbstractContainer::wrapperList() const
{
return m_wrapperList;
}
QBoxLayout *AbstractContainer::wrapperLayout() const
{
return m_wrapperLayout;
}
// replace current WrapperLayout by "layout"
// but will not setLayout here, so the caller should handle the new WrapperLayout
void AbstractContainer::setWrapperLayout(QBoxLayout *layout)
{
delete m_wrapperLayout;
m_wrapperLayout = layout;
}
bool AbstractContainer::expand() const
{
return m_expand;
}
Dock::Position AbstractContainer::dockPosition() const
{
return m_dockPosition;
}
//QSize AbstractContainer::wrapperSize() const
//{
// return m_wrapperSize;
//}
void AbstractContainer::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat(TRAY_ITEM_DRAG_MIMEDATA) && !m_currentDraggingWrapper) {
event->accept();
Q_EMIT requestDraggingWrapper();
return;
}
QWidget::dragEnterEvent(event);
}
void AbstractContainer::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent(event);
QPainter p(this);
}
void AbstractContainer::onWrapperAttentionhChanged(const bool attention)
{
FashionTrayWidgetWrapper *wrapper = dynamic_cast<FashionTrayWidgetWrapper *>(sender());
if (!wrapper) {
return;
}
Q_EMIT attentionChanged(wrapper, attention);
}
void AbstractContainer::onWrapperDragStart()
{
FashionTrayWidgetWrapper *wrapper = static_cast<FashionTrayWidgetWrapper *>(sender());
if (!wrapper) {
return;
}
m_currentDraggingWrapper = wrapper;
Q_EMIT draggingStateChanged(wrapper, true);
}
void AbstractContainer::onWrapperDragStop()
{
FashionTrayWidgetWrapper *wrapper = static_cast<FashionTrayWidgetWrapper *>(sender());
if (!wrapper) {
return;
}
if (m_currentDraggingWrapper == wrapper) {
m_currentDraggingWrapper = nullptr;
} else {
Q_UNREACHABLE();
}
saveCurrentOrderToConfig();
Q_EMIT draggingStateChanged(wrapper, false);
}
void AbstractContainer::onWrapperRequestSwapWithDragging()
{
FashionTrayWidgetWrapper *wrapper = static_cast<FashionTrayWidgetWrapper *>(sender());
if (!wrapper || wrapper == m_currentDraggingWrapper) {
return;
}
// the current dragging wrapper is null means that the dragging wrapper is contains by
// another container, so this container need to emit requireDraggingWrapper() signal
// to notify FashionTrayItem, the FashionTrayItem will move the dragging wrapper to this container
if (!m_currentDraggingWrapper) {
Q_EMIT requestDraggingWrapper();
// here have to give up if dragging wrapper is still null
if (!m_currentDraggingWrapper) {
return;
}
}
const int indexOfDest = m_wrapperLayout->indexOf(wrapper);
const int indexOfDragging = m_wrapperLayout->indexOf(m_currentDraggingWrapper);
m_wrapperLayout->removeWidget(m_currentDraggingWrapper);
m_wrapperLayout->insertWidget(indexOfDest, m_currentDraggingWrapper);
m_wrapperList.insert(indexOfDest, m_wrapperList.takeAt(indexOfDragging));
}