Files
qt6-migration-pipeline/Lts/Common/LtsTimeline/timeline_view_resize_handler.cpp
T

280 lines
7.4 KiB
C++
Executable File

#include "timeline_view_resize_handler.h"
#include "timeline_view.h"
#include "timeline_header_view.h"
#include "item.h"
#include "track.h"
#include <QApplication>
#include <QMouseEvent>
#include <QDebug>
namespace LtsTimeline
{
TimelineViewResizeHandler::TimelineViewResizeHandler(TimelineView *view)
: m_view(view)
{}
TimelineViewResizeHandler::~TimelineViewResizeHandler()
{
m_view = nullptr;
}
void TimelineViewResizeHandler::mouseMoveEvent(QMouseEvent *e)
{
if (!m_view->timelineModel()->isEditable())
return;
if (m_currentTrackId == -1 || m_currentItemId == -1 || m_resizePos == ResizePosition::eNone)
return;
if (!m_view->timelineModel()->item(m_currentItemId).isEditable())
return;
const QModelIndex index(m_view->indexAt(e->pos()));
if (index.column() == Section::eActuator || !index.isValid())
return;
Track &track = m_view->timelineModel()->track(index.data().toInt());
if (track.id() != m_currentTrackId)
return;
qint64 time = m_view->timelineModel()->isSnapEnabled() ? globalSnapTime(e->pos().x()) : localSnapTime(e->pos().x());
try
{
Item &item = m_view->timelineModel()->item(m_currentItemId);
if (m_resizePos == ResizePosition::eStart)
{
if (item.startTime() == time)
return;
if (!m_view->timelineModel()->canResizeItem(item, time, item.startTime() + item.duration() - time))
return;
m_view->timelineModel()->setItemDuration(track, item, item.startTime() + item.duration() - time);
m_view->timelineModel()->setItemStartTime(track, item, time);
}
else
{
if (item.duration() == time - item.startTime())
return;
if (!m_view->timelineModel()->canResizeItem(item, item.startTime(), time - item.startTime()))
return;
m_view->timelineModel()->setItemDuration(track, item, time - item.startTime());
}
}
catch (...)
{
mouseReleaseEvent(e);
}
}
void TimelineViewResizeHandler::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
{
const Track &track = m_view->timelineModel()->track(index.data().toInt());
const Item &item = track.itemAt(m_view->toTime(e->pos().x()));
if (!item.isEditable())
return;
const int startPos = m_view->toPixel(item.startTime());
const int endPos = m_view->toPixel(item.startTime() + item.duration());
if (endPos - startPos < 15 || (startPos + 5 < e->pos().x() && e->pos().x() < endPos - 5))
{
m_resizePos = ResizePosition::eNone;
return;
}
else if (startPos + 5 >= e->pos().x())
m_resizePos = ResizePosition::eStart;
else
m_resizePos = ResizePosition::eEnd;
m_currentTrackId = track.id();
m_currentItemId = item.id();
}
catch (const QString &str)
{
ERROR_LOG(m_view->m_logger) << str;
}
catch (...) {}
}
void TimelineViewResizeHandler::mouseReleaseEvent(QMouseEvent *e)
{
if (!m_view->timelineModel()->isEditable())
return;
if (e->button() != Qt::LeftButton)
return;
emit m_view->currentItemTimeChanged();
m_view->setCursor(QCursor(Qt::ArrowCursor));
m_currentTrackId = -1;
m_currentItemId = -1;
m_resizePos = ResizePosition::eNone;
}
qint64 TimelineViewResizeHandler::localSnapTime(int pos) const
{
qint64 time = m_view->toTime(pos);
if (m_currentItemId == -1 || m_resizePos == ResizePosition::eNone)
return time;
try
{
Track &track = m_view->timelineModel()->track(m_currentTrackId);
const Item &currentItem = m_view->timelineModel()->item(m_currentItemId);
if (m_resizePos == ResizePosition::eStart)
{
if (time >= currentItem.startTime() + currentItem.duration())
time = currentItem.startTime() + currentItem.duration() - m_view->timelineModel()->minimumDuration();
else
{
try
{
const Item &previous = track.previous(m_currentItemId);
const qint64 endTime = previous.startTime() + previous.duration();
if (time <= endTime)
time = endTime;
}
catch (const QString &str)
{
ERROR_LOG(m_view->m_logger) << str;
}
catch (...) {}
}
}
else
{
if (time <= currentItem.startTime())
time = currentItem.startTime() + m_view->timelineModel()->minimumDuration();
else
{
try
{
Item &next = track.next(m_currentItemId);
if (time >= next.startTime())
time = next.startTime();
}
catch (const QString &str)
{
ERROR_LOG(m_view->m_logger) << str;
}
catch (...) {}
}
}
}
catch (const QString &str)
{
ERROR_LOG(m_view->m_logger) << str;
}
catch (...) {}
return time;
}
qint64 TimelineViewResizeHandler::globalSnapTime(int pos) const
{
qint64 tPos = (m_view->toTime(pos) / m_view->timelineModel()->snapStep()) * m_view->timelineModel()->snapStep();
if (m_currentItemId == -1 || m_resizePos == ResizePosition::eNone)
return tPos;
qint64 tMin = m_view->m_startTime;
qint64 tMax = m_view->endTime();
try
{
const Item &previous = m_view->timelineModel()->track(m_currentTrackId).previous(m_currentItemId);
tMin = previous.startTime() + previous.duration();
}
catch (const QString &str)
{
DEBUG_LOG(m_view->m_logger) << str;
}
catch (...) {}
try
{
const Item &next = m_view->timelineModel()->track(m_currentTrackId).next(m_currentItemId);
tMax = next.startTime();
}
catch (const QString &str)
{
DEBUG_LOG(m_view->m_logger) << str;
}
catch (...) {}
qint64 time = tPos;
try
{
const Item &currentItem = m_view->timelineModel()->item(m_currentItemId);
int minDist = 2 * m_view->timelineModel()->snapTolerance();
int eps = m_view->timelineModel()->snapTolerance();
for (int itemId : m_view->timelineModel()->itemIds())
{
if (itemId == m_currentItemId)
continue;
try
{
const Item &item = m_view->timelineModel()->item(itemId);
qint64 t;
if (time - eps < item.startTime() && item.startTime() < time + eps)
t = item.startTime();
else if (time - eps < item.startTime() + item.duration() && item.startTime() + item.duration() < time + eps)
t = item.startTime() + item.duration();
else
continue;
if (std::abs(t - tPos) < minDist)
{
if ((m_resizePos == ResizePosition::eStart && t >= currentItem.startTime() + currentItem.duration()) ||
(m_resizePos == ResizePosition::eEnd && t <= currentItem.startTime()))
continue;
time = t;
minDist = time - tPos;
}
}
catch (const QString &str)
{
ERROR_LOG(m_view->m_logger) << str;
}
catch (...) {}
}
if (m_resizePos == ResizePosition::eStart && time >= currentItem.startTime() + currentItem.duration())
return currentItem.startTime() + currentItem.duration() - m_view->timelineModel()->minimumDuration();
else if (m_resizePos == ResizePosition::eEnd && time <= currentItem.startTime())
return currentItem.startTime() + m_view->timelineModel()->minimumDuration();
}
catch (const QString &str)
{
ERROR_LOG(m_view->m_logger) << str;
}
catch (...) {}
time = std::max(tMin, time);
time = std::min(tMax, time);
return time;
}
}