Continues migration with DDS, Common
This commit is contained in:
1 parent
9b15cee841
commit
fa48db111e
668 files changed
+111841
-2
No files matched your search
+505
@@ -0,0 +1,505 @@
|
||||
#include "timeline_view_drag_handler.h"
|
||||
#include "item.h"
|
||||
#include "track.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QMouseEvent>
|
||||
#include <QDrag>
|
||||
#include <QMimeData>
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
namespace LtsTimeline
|
||||
{
|
||||
|
||||
TimelineViewDragHandler::TimelineViewDragHandler(TimelineView *view)
|
||||
: m_view(view)
|
||||
{}
|
||||
|
||||
TimelineViewDragHandler::~TimelineViewDragHandler()
|
||||
{
|
||||
m_view = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void TimelineViewDragHandler::dragEnterEvent(QDragEnterEvent *e)
|
||||
{
|
||||
if (!m_view->timelineModel()->isEditable() || e->source() != m_view || m_dragItemIds.isEmpty() || !m_dragStartIndex.isValid())
|
||||
{
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
if (e->mimeData()->hasFormat(Item::mimetype))
|
||||
e->acceptProposedAction();
|
||||
else
|
||||
e->ignore();
|
||||
}
|
||||
|
||||
void TimelineViewDragHandler::dragMoveEvent(QDragMoveEvent *e)
|
||||
{
|
||||
if (!m_view->timelineModel()->isEditable() || e->source() != m_view || m_dragItemIds.isEmpty() || !m_dragStartIndex.isValid())
|
||||
{
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
if (!e->mimeData()->hasFormat(Item::mimetype))
|
||||
return;
|
||||
|
||||
m_dragPos = e->pos();
|
||||
m_view->m_header->setHoverPosition(m_dragPos.x());
|
||||
e->setAccepted(canDragItemsTo(e->pos()));
|
||||
m_view->viewport()->update();
|
||||
}
|
||||
|
||||
void TimelineViewDragHandler::dragLeaveEvent(QDragLeaveEvent *e)
|
||||
{
|
||||
Q_UNUSED(e);
|
||||
m_dragPos = {};
|
||||
}
|
||||
|
||||
void TimelineViewDragHandler::dropEvent(QDropEvent *e)
|
||||
{
|
||||
if (!m_view->timelineModel()->isEditable() || e->source() != m_view || m_dragItemIds.isEmpty())
|
||||
{
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
if (!e->mimeData()->hasFormat(Item::mimetype))
|
||||
return;
|
||||
|
||||
if (!canDragItemsTo(e->pos()))
|
||||
{
|
||||
clear();
|
||||
e->acceptProposedAction();
|
||||
return;
|
||||
}
|
||||
|
||||
qint64 dt = deltaTime();
|
||||
try
|
||||
{
|
||||
for (const int &itemId : qAsConst(m_dragItemIds))
|
||||
{
|
||||
const Item &item = m_view->timelineModel()->item(itemId);
|
||||
m_view->timelineModel()->moveItemToTrack(itemId, dragItemTrackId(item), item.startTime() + dt);
|
||||
}
|
||||
}
|
||||
catch (const QString &str) { ERROR_LOG(m_view->m_logger) << LOGFUNCTION << " " << str; }
|
||||
catch (...) { ERROR_LOG(m_view->m_logger) << LOGFUNCTION << " failed"; }
|
||||
clear();
|
||||
e->acceptProposedAction();
|
||||
}
|
||||
|
||||
void TimelineViewDragHandler::mouseMoveEvent(QMouseEvent *e)
|
||||
{
|
||||
if (!m_view->timelineModel()->isEditable())
|
||||
return;
|
||||
|
||||
if (e->buttons() != Qt::LeftButton)
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_dragItemIds.isEmpty() || !m_dragStartIndex.isValid())
|
||||
return;
|
||||
|
||||
if ((e->pos() - m_dragStartPos).manhattanLength() < QApplication::startDragDistance())
|
||||
return;
|
||||
|
||||
|
||||
const QModelIndex index = m_view->indexAt(e->pos());
|
||||
if (!index.isValid() || index.column() == Section::eActuator)
|
||||
{
|
||||
m_view->setCursor(QCursor(Qt::ForbiddenCursor));
|
||||
return;
|
||||
}
|
||||
|
||||
m_dragPos = e->pos();
|
||||
m_view->setCursor(QCursor(canDragItemsTo(m_dragPos) ? Qt::ClosedHandCursor : Qt::ForbiddenCursor));
|
||||
if (index.data().toInt() == m_dragStartIndex.data().toInt())
|
||||
return;
|
||||
|
||||
QMimeData *mimeData = new QMimeData();
|
||||
mimeData->setData(Item::mimetype, {});
|
||||
QDrag *drag = new QDrag(m_view);
|
||||
drag->setMimeData(mimeData);
|
||||
if (drag->exec(Qt::MoveAction) == Qt::MoveAction)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineViewDragHandler::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
if (!m_view->timelineModel()->isEditable())
|
||||
return;
|
||||
|
||||
if (e->button() != Qt::LeftButton)
|
||||
return;
|
||||
|
||||
|
||||
const QModelIndex index = m_view->indexAt(e->pos());
|
||||
if (!index.isValid() || index.column() == Section::eActuator)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
Track &track = m_view->timelineModel()->track(index.data().toInt());
|
||||
Item &item = track.itemAt(m_view->toTime(e->pos().x()));
|
||||
m_dragItemIds = m_view->m_selectedItemIds;
|
||||
if (!m_dragItemIds.contains(item.id()))
|
||||
m_dragItemIds = { item.id() };
|
||||
|
||||
for (const int &itemId : m_dragItemIds)
|
||||
if (!m_view->timelineModel()->item(itemId).isEditable())
|
||||
return;
|
||||
|
||||
m_dragStartIndex = index;
|
||||
m_dragStartTime = m_view->toTime(e->pos().x());
|
||||
m_dragStartPos = e->pos();
|
||||
m_dragPos = m_dragStartPos;
|
||||
m_view->setCursor(QCursor(Qt::ClosedHandCursor));
|
||||
}
|
||||
catch (const QString &str) { DEBUG_LOG(m_view->m_logger) << LOGFUNCTION << " " << str; }
|
||||
catch (...) {}
|
||||
}
|
||||
|
||||
void TimelineViewDragHandler::mouseReleaseEvent(QMouseEvent *e)
|
||||
{
|
||||
if (!m_view->timelineModel()->isEditable())
|
||||
return;
|
||||
|
||||
if (e->button() != Qt::LeftButton)
|
||||
return;
|
||||
|
||||
if (m_dragItemIds.isEmpty() || !m_dragStartIndex.isValid())
|
||||
return;
|
||||
|
||||
|
||||
const QModelIndex index = m_view->indexAt(e->pos());
|
||||
if (!index.isValid() || index.column() == Section::eActuator)
|
||||
return;
|
||||
|
||||
if (index.data().toInt() != m_dragStartIndex.data().toInt())
|
||||
return;
|
||||
|
||||
m_dragPos = e->pos();
|
||||
if (m_dragPos.x() == m_dragStartPos.x())
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
if (!canMoveItemsTo(m_dragPos))
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
emit m_view->currentItemTimeChanged();
|
||||
qint64 dt = deltaTime();
|
||||
for (const int &itemId : m_dragItemIds)
|
||||
{
|
||||
Item &item = m_view->timelineModel()->item(itemId);
|
||||
m_view->timelineModel()->setItemStartTime(item, item.startTime() + dt);
|
||||
}
|
||||
clear();
|
||||
}
|
||||
|
||||
void TimelineViewDragHandler::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
if (!m_view->timelineModel()->isEditable())
|
||||
return;
|
||||
if (m_view->m_selectedItemIds.isEmpty())
|
||||
return;
|
||||
|
||||
if (e->key() == Qt::Key_Escape)
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (e->key() != Qt::Key_Left && e->key() != Qt::Key_Right)
|
||||
return;
|
||||
|
||||
int dt = m_view->timelineModel()->snapStep();
|
||||
if (e->key() == Qt::Key_Left)
|
||||
moveItemsLeft(m_view->selectedItemIds(), QApplication::keyboardModifiers().testFlag(Qt::ControlModifier) ? -dt : -10 * dt);
|
||||
else
|
||||
moveItemsRight(m_view->selectedItemIds(), QApplication::keyboardModifiers().testFlag(Qt::ControlModifier) ? dt : 10 * dt);
|
||||
}
|
||||
|
||||
|
||||
bool TimelineViewDragHandler::isActive() const
|
||||
{
|
||||
return !m_dragItemIds.isEmpty() && (m_dragPos - m_dragStartPos).manhattanLength() >= QApplication::startDragDistance();
|
||||
}
|
||||
|
||||
|
||||
int TimelineViewDragHandler::deltaX() const
|
||||
{
|
||||
if (!m_view->timelineModel()->isSnapEnabled())
|
||||
return m_dragPos.x() - m_dragStartPos.x();
|
||||
return m_view->toPixel(m_dragStartTime + deltaTime()) - m_view->toPixel(m_dragStartTime);
|
||||
}
|
||||
|
||||
int TimelineViewDragHandler::deltaY() const
|
||||
{
|
||||
|
||||
const QModelIndex dragIndex = m_view->indexAt(m_dragPos);
|
||||
if (!dragIndex.isValid())
|
||||
return m_dragPos.y() - m_dragStartPos.y();
|
||||
return m_view->visualRect(dragIndex).top() - m_view->visualRect(m_dragStartIndex).top();
|
||||
}
|
||||
|
||||
qint64 TimelineViewDragHandler::deltaTime() const
|
||||
{
|
||||
if (!m_view->timelineModel()->isSnapEnabled())
|
||||
return m_view->toTime(m_dragPos.x()) - m_view->toTime(m_dragStartPos.x());
|
||||
|
||||
qint64 dt = ((m_view->toTime(m_dragPos.x()) - m_dragStartTime) / m_view->timelineModel()->snapStep()) * m_view->timelineModel()->snapStep();
|
||||
int dtAbsMin = 2 * m_view->timelineModel()->snapTolerance();
|
||||
int eps = m_view->timelineModel()->snapTolerance();
|
||||
for (const int &dragItemId : m_dragItemIds)
|
||||
{
|
||||
const Item &dragItem = m_view->timelineModel()->item(dragItemId);
|
||||
qint64 start = dragItem.startTime() + dt;
|
||||
qint64 end = start + dragItem.duration();
|
||||
for (int itemId : m_view->timelineModel()->itemIds())
|
||||
{
|
||||
if (m_dragItemIds.contains(itemId))
|
||||
continue;
|
||||
|
||||
const Item &item = m_view->timelineModel()->item(itemId);
|
||||
if (start - eps < item.startTime() + item.duration() && item.startTime() + item.duration() < start + eps)
|
||||
{
|
||||
qint64 dtCurrent = item.startTime() + item.duration() - dragItem.startTime();
|
||||
qint64 dtAbsCurrent = std::abs(dtCurrent);
|
||||
if (dtAbsCurrent < dtAbsMin)
|
||||
{
|
||||
dtAbsMin = dtAbsCurrent;
|
||||
dt = dtCurrent;
|
||||
}
|
||||
}
|
||||
else if (end - eps < item.startTime() && item.startTime() < end + eps)
|
||||
{
|
||||
qint64 dtCurrent = item.startTime() - (dragItem.startTime() + dragItem.duration());
|
||||
qint64 dtAbsCurrent = std::abs(dtCurrent);
|
||||
if (dtAbsCurrent < dtAbsMin)
|
||||
{
|
||||
dtAbsMin = dtAbsCurrent;
|
||||
dt = dtCurrent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool TimelineViewDragHandler::canDragItemsTo(const QPoint &point) const
|
||||
{
|
||||
if (!m_view->timelineModel()->isEditable())
|
||||
return false;
|
||||
|
||||
if (m_dragItemIds.isEmpty() || !m_dragStartIndex.isValid())
|
||||
return false;
|
||||
|
||||
|
||||
const QModelIndex index = m_view->indexAt(point);
|
||||
if (!index.isValid() || index.column() == Section::eActuator)
|
||||
return false;
|
||||
|
||||
if (index.data().toInt() == m_dragStartIndex.data().toInt())
|
||||
return canMoveItemsTo(point);
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
qint64 dt = deltaTime();
|
||||
for (const int &itemId : m_dragItemIds)
|
||||
{
|
||||
const Item &item = m_view->timelineModel()->item(itemId);
|
||||
int trackId = dragItemTrackId(item);
|
||||
if (trackId == 0)
|
||||
return false;
|
||||
|
||||
const Track &track = m_view->timelineModel()->track(trackId);
|
||||
qint64 startNew = item.startTime() + dt;
|
||||
if (!m_view->timelineModel()->canDropItem(item, track.id(), startNew))
|
||||
return false;
|
||||
|
||||
if (track.isItemsBetween(startNew, startNew + item.duration(), m_dragItemIds, true))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TimelineViewDragHandler::canMoveItemsTo(const QPoint &point) const
|
||||
{
|
||||
if (!m_view->timelineModel()->isEditable())
|
||||
return false;
|
||||
if (m_dragItemIds.isEmpty() || !m_dragStartIndex.isValid())
|
||||
return false;
|
||||
|
||||
|
||||
const QModelIndex index = m_view->indexAt(point);
|
||||
if (!index.isValid() || index.column() == Section::eActuator || index.data().toInt() != m_dragStartIndex.data().toInt())
|
||||
return false;
|
||||
|
||||
qint64 dt = deltaTime();
|
||||
for (const int &itemId : m_dragItemIds)
|
||||
{
|
||||
const Item &item = m_view->timelineModel()->item(itemId);
|
||||
qint64 startNew = item.startTime() + dt;
|
||||
if (!m_view->timelineModel()->canMoveItem(item, startNew))
|
||||
return false;
|
||||
|
||||
const Track &track = m_view->timelineModel()->track(item.parentTrackId());
|
||||
if (track.isItemsBetween(startNew, startNew + item.duration(), m_dragItemIds, true))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void TimelineViewDragHandler::moveItemsLeft(const QVector<int> &itemIds, int dt)
|
||||
{
|
||||
Q_ASSERT(dt < 0);
|
||||
try
|
||||
{
|
||||
for (int itemId : itemIds)
|
||||
{
|
||||
const Item &item = m_view->timelineModel()->item(itemId);
|
||||
const Track &track = m_view->timelineModel()->track(item.parentTrackId());
|
||||
if (track.isItemsBetween(item.startTime() + dt, item.startTime() + item.duration() + dt, itemIds, true))
|
||||
{
|
||||
if (dt < - m_view->timelineModel()->snapStep())
|
||||
moveItemsLeft(itemIds, dt + m_view->timelineModel()->snapStep());
|
||||
return;
|
||||
}
|
||||
if (!m_view->timelineModel()->canMoveItem(item, item.startTime() + dt))
|
||||
{
|
||||
if (dt < - m_view->timelineModel()->snapStep())
|
||||
moveItemsLeft(itemIds, dt + m_view->timelineModel()->snapStep());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const QString &errMsg)
|
||||
{
|
||||
ERROR_LOG(m_view->m_logger) << LOGFUNCTION << " failed: " << errMsg;
|
||||
return;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ERROR_LOG(m_view->m_logger) << LOGFUNCTION << " failed";
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
for (int itemId : itemIds)
|
||||
{
|
||||
Item &item = m_view->timelineModel()->item(itemId);
|
||||
m_view->timelineModel()->setItemStartTime(item, item.startTime() + dt);
|
||||
}
|
||||
}
|
||||
catch (const QString &str) { ERROR_LOG(m_view->m_logger) << LOGFUNCTION << " " << str; }
|
||||
catch (...) {}
|
||||
}
|
||||
|
||||
void TimelineViewDragHandler::moveItemsRight(const QVector<int> &itemIds, int dt)
|
||||
{
|
||||
Q_ASSERT(dt > 0);
|
||||
try
|
||||
{
|
||||
for (int itemId : itemIds)
|
||||
{
|
||||
const Item &item = m_view->timelineModel()->item(itemId);
|
||||
const Track &track = m_view->timelineModel()->track(item.parentTrackId());
|
||||
if (track.isItemsBetween(item.startTime() + dt, item.startTime() + item.duration() + dt, itemIds, true))
|
||||
{
|
||||
if (dt > m_view->timelineModel()->snapStep())
|
||||
moveItemsRight(itemIds, dt - m_view->timelineModel()->snapStep());
|
||||
return;
|
||||
}
|
||||
if (!m_view->timelineModel()->canMoveItem(item, item.startTime() + dt))
|
||||
{
|
||||
if (dt > m_view->timelineModel()->snapStep())
|
||||
moveItemsRight(itemIds, dt - m_view->timelineModel()->snapStep());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const QString &errMsg)
|
||||
{
|
||||
ERROR_LOG(m_view->m_logger) << LOGFUNCTION << " failed: " << errMsg;
|
||||
return;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
ERROR_LOG(m_view->m_logger) << LOGFUNCTION << " failed";
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
for (int itemId : itemIds)
|
||||
{
|
||||
Item &item = m_view->timelineModel()->item(itemId);
|
||||
m_view->timelineModel()->setItemStartTime(item, item.startTime() + dt);
|
||||
}
|
||||
}
|
||||
catch (const QString &errMsg) { ERROR_LOG(m_view->m_logger) << LOGFUNCTION << " " << errMsg; }
|
||||
catch (...) {}
|
||||
}
|
||||
|
||||
|
||||
int TimelineViewDragHandler::dragItemTrackId(const Item &item) const
|
||||
{
|
||||
int dy = deltaY();
|
||||
|
||||
const QModelIndex index = m_view->indexAt(m_dragStartPos + QPoint(0, dy));
|
||||
if (index.data().toInt() == m_dragStartIndex.data().toInt())
|
||||
return item.parentTrackId();
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
const QModelIndex originalIndex = m_view->timelineModel()->indexOfTrack(item.parentTrackId());
|
||||
|
||||
const QModelIndex newIndex = m_view->indexAt(m_view->visualRect(originalIndex).center() + QPoint(0, dy));
|
||||
return newIndex.data().toInt();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineViewDragHandler::clear()
|
||||
{
|
||||
m_dragStartIndex = {};
|
||||
m_dragStartTime = -1;
|
||||
m_dragStartPos = {};
|
||||
m_dragPos = {};
|
||||
m_dragItemIds.clear();
|
||||
m_view->setCursor(QCursor(Qt::ArrowCursor));
|
||||
m_view->viewport()->update();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user