You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
latte-dock/app/view/eventssink.cpp

257 lines
8.3 KiB
C++

/*
* Copyright 2020 Michail Vourlakos <mvourlakos@gmail.com>
*
* This file is part of Latte-Dock
*
* Latte-Dock 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 2 of
* the License, or (at your option) any later version.
*
* Latte-Dock 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 "eventssink.h"
// local
#include "view.h"
#include "positioner.h"
// Qt
#include <QDragEnterEvent>
#include <QDragMoveEvent>
#include <QDropEvent>
#include <QMouseEvent>
#include <QPointF>
#include <QRectF>
namespace Latte {
namespace ViewPart {
EventsSink::EventsSink(Latte::View *parent)
: QObject(parent),
m_view(parent)
{
}
EventsSink::~EventsSink()
{
}
QQuickItem *EventsSink::originParentItem() const
{
return m_originParentItem;
}
QQuickItem *EventsSink::destinationItem() const
{
return m_destinationItem;
}
void EventsSink::setSink(QQuickItem *originParent, QQuickItem *destination)
{
if ((m_originParentItem == originParent) && (m_destinationItem == destination)) {
return;
}
m_originParentItem = originParent;
m_destinationItem = destination;
emit itemsChanged();
}
bool EventsSink::isActive()
{
return ((m_originParentItem != nullptr) && (m_destinationItem != nullptr));
}
void EventsSink::release()
{
setSink(nullptr, nullptr);
}
QEvent *EventsSink::onEvent(QEvent *e)
{
if (!e) {
return nullptr;
}
if (!isActive()) {
return e;
}
QEvent *sunkevent = e;
switch (e->type()) {
case QEvent::Leave:
release();
break;
case QEvent::DragEnter:
if (auto de = static_cast<QDragEnterEvent *>(e)) {
QPointF point = de->posF();
if (originSinksContain(point)) {
auto de2 = new QDragEnterEvent(positionAdjustedForDestination(point).toPoint(),
de->possibleActions(),
de->mimeData(),
de->mouseButtons(),
de->keyboardModifiers());
sunkevent = de2;
} else if (!destinationContains(point)) {
release();
}
}
break;
case QEvent::DragMove:
if (auto de = static_cast<QDragMoveEvent *>(e)) {
QPointF point = de->posF();
if (originSinksContain(point)) {
auto de2 = new QDragMoveEvent(positionAdjustedForDestination(point).toPoint(),
de->possibleActions(),
de->mimeData(),
de->mouseButtons(),
de->keyboardModifiers());
sunkevent = de2;
} else if (!destinationContains(point)) {
release();
}
}
break;
case QEvent::Drop:
if (auto de = static_cast<QDropEvent *>(e)) {
QPointF point = de->posF();
if (originSinksContain(point)) {
auto de2 = new QDropEvent(positionAdjustedForDestination(point).toPoint(),
de->possibleActions(),
de->mimeData(),
de->mouseButtons(),
de->keyboardModifiers());
sunkevent = de2;
} else if (!destinationContains(point)) {
release();
}
}
break;
case QEvent::MouseMove:
if (auto me = dynamic_cast<QMouseEvent *>(e)) {
if (m_view->positioner() && m_view->positioner()->isCursorInsideView() && originSinksContain(me->windowPos())) {
auto positionadjusted = positionAdjustedForDestination(me->windowPos());
auto me2 = new QMouseEvent(me->type(),
positionadjusted,
positionadjusted,
positionadjusted + m_view->position(),
me->button(), me->buttons(), me->modifiers());
sunkevent = me2;
} else if (!destinationContains(me->windowPos())) {
release();
}
}
break;
case QEvent::MouseButtonPress:
if (auto me = dynamic_cast<QMouseEvent *>(e)) {
if (originSinksContain(me->windowPos())) {
auto positionadjusted = positionAdjustedForDestination(me->windowPos());
auto me2 = new QMouseEvent(me->type(),
positionadjusted,
positionadjusted,
positionadjusted + m_view->position(),
me->button(), me->buttons(), me->modifiers());
qDebug() << "Sunk Event:: sunk event pressed...";
sunkevent = me2;
} else if (!destinationContains(me->windowPos())) {
release();
}
}
break;
case QEvent::MouseButtonRelease:
if (auto me = dynamic_cast<QMouseEvent *>(e)) {
if (originSinksContain(me->windowPos())) {
auto positionadjusted = positionAdjustedForDestination(me->windowPos());
auto me2 = new QMouseEvent(me->type(),
positionadjusted,
positionadjusted,
positionadjusted + m_view->position(),
me->button(), me->buttons(), me->modifiers());
sunkevent = me2;
} else if (!destinationContains(me->windowPos())) {
release();
}
}
break;
case QEvent::Wheel:
if (auto we = dynamic_cast<QWheelEvent *>(e)) {
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QPoint pos = QPoint(we->x(), we->y());
#else
QPoint pos = we->position().toPoint();
#endif
if (originSinksContain(pos)) {
auto positionadjusted = positionAdjustedForDestination(pos);
auto we2 = new QWheelEvent(positionadjusted,
positionadjusted + m_view->position(),
we->pixelDelta(), we->angleDelta(), we->angleDelta().y(),
we->orientation(), we->buttons(), we->modifiers(), we->phase());
sunkevent = we2;
} else if (!destinationContains(pos)) {
release();
}
}
break;
default:
break;
}
return sunkevent;
}
QPointF EventsSink::positionAdjustedForDestination(const QPointF &point) const
{
QRectF destinationRectToScene = m_destinationItem->mapRectToScene(QRectF(0, 0, m_destinationItem->width() - 1, m_destinationItem->height() - 1));
return QPointF(qBound(destinationRectToScene.left(), point.x(), destinationRectToScene.right()),
qBound(destinationRectToScene.top(), point.y(), destinationRectToScene.bottom()));
}
bool EventsSink::destinationContains(const QPointF &point) const
{
QRectF destinationRectToScene = m_destinationItem->mapRectToScene(QRectF(0, 0, m_destinationItem->width() - 1, m_destinationItem->height() - 1));
return destinationRectToScene.contains(point);
}
bool EventsSink::originSinksContain(const QPointF &point) const
{
QRegion originsRegion;
for(const auto currentOrigin: m_originParentItem->childItems()) {
QRectF currentOriginGeometry = currentOrigin->mapRectToScene(QRectF(0, 0, currentOrigin->width(), currentOrigin->height()));
originsRegion = originsRegion.united(currentOriginGeometry.toRect());
}
return originsRegion.contains(point.toPoint());
}
}
}