dde-dock/frame/item/components/appdragwidget.cpp

221 lines
6.0 KiB
C++
Raw Normal View History

/*
* Copyright (C) 2011 ~ 2018 Deepin Technology Co., Ltd.
*
* Author: listenerri <listenerri@gmail.com>
*
* Maintainer: listenerri <listenerri@gmail.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 "appdragwidget.h"
#include "../appitem.h"
class AppGraphicsObject : public QGraphicsObject
{
public:
AppGraphicsObject(QGraphicsItem *parent = Q_NULLPTR) : QGraphicsObject(parent) {};
~AppGraphicsObject() { }
void setAppPixmap(QPixmap pix)
{
m_appPixmap = pix;
resetProperty();
update();
}
void resetProperty()
{
setScale(1.0);
setRotation(0);
setOpacity(1.0);
update();
}
QRectF boundingRect() const Q_DECL_OVERRIDE
{
return m_appPixmap.rect();
};
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = Q_NULLPTR) Q_DECL_OVERRIDE
{
Q_ASSERT(!m_appPixmap.isNull());
painter->drawPixmap(QPoint(0, 0), m_appPixmap);
};
private:
QPixmap m_appPixmap;
};
AppDragWidget::AppDragWidget(QWidget *parent) :
QGraphicsView(parent),
m_object(new AppGraphicsObject),
m_scene(new QGraphicsScene(this)),
m_followMouseTimer(new QTimer(this)),
m_animScale(new QPropertyAnimation(m_object, "scale", this)),
m_animRotation(new QPropertyAnimation(m_object, "rotation", this)),
m_animOpacity(new QPropertyAnimation(m_object, "opacity", this)),
m_animGroup(new QParallelAnimationGroup(this))
{
m_scene->addItem(m_object);
setScene(m_scene);
setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
setAttribute(Qt::WA_TranslucentBackground);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setMouseTracking(true);
setAcceptDrops(true);
initAnimations();
m_followMouseTimer->setSingleShot(false);
m_followMouseTimer->setInterval(1);
connect(m_followMouseTimer, &QTimer::timeout, [this] {
QPoint destPos = QCursor::pos();
move(destPos.x() - width() / 2, destPos.y() - height() / 2);
});
m_followMouseTimer->start();
}
AppDragWidget::~AppDragWidget() { }
void AppDragWidget::mouseMoveEvent(QMouseEvent *event)
{
QGraphicsView::mouseMoveEvent(event);
// hide widget when receiving mouseMoveEvent because this means drag-and-drop has been finished
hide();
}
void AppDragWidget::dragEnterEvent(QDragEnterEvent *event)
{
event->accept();
m_dragStartPoint = event->pos();
}
void AppDragWidget::dragMoveEvent(QDragMoveEvent *event)
{
if (isRemoveAble()) {
m_object->setOpacity(0.5);
m_animOpacity->setStartValue(0.5);
} else {
m_object->setOpacity(1.0);
m_animOpacity->setStartValue(1.0);
}
}
void AppDragWidget::dropEvent(QDropEvent *event)
{
m_followMouseTimer->stop();
if (isRemoveAble()) {
showRemoveAnimation();
AppItem *appItem = static_cast<AppItem *>(event->source());
appItem->undock();
} else {
hide();
}
}
void AppDragWidget::hideEvent(QHideEvent *event)
{
deleteLater();
}
void AppDragWidget::setAppPixmap(const QPixmap &pix)
{
setFixedSize(pix.size() + QSize(10,10));
m_object->setAppPixmap(pix);
m_object->setTransformOriginPoint(pix.rect().center());
}
void AppDragWidget::setDockInfo(Dock::Position dockPosition, const QRect &dockGeometry)
{
m_dockPosition = dockPosition;
m_dockGeometry = dockGeometry;
}
void AppDragWidget::initAnimations()
{
m_animScale->setDuration(300);
m_animScale->setStartValue(1.0);
m_animScale->setEndValue(0.0);
m_animRotation->setDuration(300);
m_animRotation->setStartValue(0);
m_animRotation->setEndValue(90);
m_animOpacity->setDuration(300);
m_animOpacity->setStartValue(1.0);
m_animOpacity->setEndValue(0.0);
m_animGroup->addAnimation(m_animScale);
m_animGroup->addAnimation(m_animRotation);
m_animGroup->addAnimation(m_animOpacity);
connect(m_animGroup, &QParallelAnimationGroup::stateChanged,
this, &AppDragWidget::onRemoveAnimationStateChanged);
}
void AppDragWidget::showRemoveAnimation()
{
if (m_animGroup->state() == QParallelAnimationGroup::Running) {
m_animGroup->stop();
}
m_object->resetProperty();
m_animGroup->start();
}
void AppDragWidget::onRemoveAnimationStateChanged(QAbstractAnimation::State newState,
QAbstractAnimation::State oldState)
{
if (newState == QAbstractAnimation::Stopped) {
hide();
}
}
bool AppDragWidget::isRemoveAble()
{
const QPoint &p = QCursor::pos();
switch (m_dockPosition) {
case Dock::Position::Left:
if ((p.x() - m_dockGeometry.topRight().x()) > (m_dockGeometry.width() * 3)) {
return true;
}
break;
case Dock::Position::Top:
if ((p.y() - m_dockGeometry.bottomLeft().y()) > (m_dockGeometry.height() * 3)) {
return true;
}
break;
case Dock::Position::Right:
if ((m_dockGeometry.topLeft().x() - p.x()) > (m_dockGeometry.width() * 3)) {
return true;
}
break;
case Dock::Position::Bottom:
if ((m_dockGeometry.topLeft().y() - p.y()) > (m_dockGeometry.height() * 3)) {
return true;
}
break;
default:
break;
}
return false;
}