dde-dock/plugins/tray/fashiontray/containers/abstractcontainer.cpp
chenjun 88d52e28d1 fix: 为了将maintain/5.1分支合入uos,重新对任务栏图标点击、移动、拖动范围处理
由原来的提交的用鼠标当前坐标是否在图标范围内的判断方式修改为设置图标布局的边距的方式。以便于将maintain/5.1分支合入uos而不影响其他
功能

Log: 重新对任务栏图标可点击、移动或拖动范围进行处理
Change-Id: Icf6df593f468c247c6d4fc5c2ba0936d5135626b
Reviewed-on: http://gerrit.uniontech.com/c/dde-dock/+/4271
Reviewed-by: <mailman@uniontech.com>
Reviewed-by: fanpengcheng <fanpengcheng@uniontech.com>
Tested-by: <mailman@uniontech.com>
2020-09-11 15:29:02 +08:00

429 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();
}
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));
}