280 lines
7.4 KiB
C++
Executable File
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 ¤tItem = 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 ¤tItem = 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;
|
|
}
|
|
|
|
}
|