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

321 lines
8.0 KiB
C++
Executable File

#include "timeline_view_selection_handler.h"
#include "item_delegate.h"
#include <QApplication>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QSize>
#include <QModelIndex>
#include <QDebug>
namespace LtsTimeline
{
TimelineViewSelectHandler::TimelineViewSelectHandler(TimelineView *view)
: m_view(view)
{
}
TimelineViewSelectHandler::~TimelineViewSelectHandler()
{
m_view = nullptr;
}
void TimelineViewSelectHandler::mouseDoubleClickEvent(QMouseEvent *e)
{
if (e->button() != Qt::LeftButton)
return;
m_view->clearSelectedItems();
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()));
emit m_view->itemActivated(item.id());
}
catch (const QString &str) { DEBUG_LOG(m_view->m_logger) << LOGFUNCTION << " " << str; }
catch (...) { ERROR_LOG(m_view->m_logger) << LOGFUNCTION << " failed"; }
}
void TimelineViewSelectHandler::mouseMoveEvent(QMouseEvent *e)
{
if (m_isRubberBandActive)
{
m_view->setCursor(QCursor(Qt::CrossCursor));
if (!m_view->isCursorWithinRangeX(e->pos().x()))
m_rubberBand.setHeight(e->pos().y() - m_rubberBand.top());
else
m_rubberBand.setRect(
m_rubberBand.left(), m_rubberBand.top(), e->pos().x() - m_rubberBand.left(), e->pos().y() - m_rubberBand.top()
);
}
else
m_selectedItemId = -1;
}
void TimelineViewSelectHandler::mousePressEvent(QMouseEvent *e)
{
if (e->button() != Qt::LeftButton && e->button() != Qt::RightButton)
return;
const QModelIndex index = m_view->indexAt(e->pos());
if (index.isValid())
{
if (index.column() == Section::eActuator)
{
qWarning() << "clicked on row with actuator" << index.data().toString();
return;
}
try
{
Track &track = m_view->timelineModel()->track(index.data().toInt());
Item &item = track.itemAt(m_view->toTime(e->pos().x()));
if (e->button() == Qt::LeftButton)
m_selectedItemId = item.id();
return;
}
catch (...)
{
if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
return;
if (e->button() == Qt::RightButton)
{
emit m_view->customContextMenuRequested(e->pos());
return;
}
m_view->clearSelectedItems();
m_rubberBand.setLeft(e->pos().x());
m_rubberBand.setTop(e->pos().y());
m_rubberBand.setSize(QSize(0, 0));
m_isRubberBandActive = true;
return;
}
return;
}
else
{
qWarning() << "TimelineViewSelectHandler::mousePressEvent: index invalid";
}
if (e->button() == Qt::RightButton)
return;
if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
return;
m_view->clearSelectedItems();
if (!m_view->isCursorWithinRangeX(e->pos().x()))
return;
m_rubberBand.setLeft(e->pos().x());
m_rubberBand.setTop(e->pos().y());
m_rubberBand.setSize(QSize(0, 0));
m_isRubberBandActive = true;
}
void TimelineViewSelectHandler::mouseReleaseEvent(QMouseEvent *e)
{
if (e->button() == Qt::RightButton)
{
return;
}
if (e->button() != Qt::LeftButton)
return;
if (m_isRubberBandActive)
{
m_view->selectItems(getItemsWithinRubberBand());
m_isRubberBandActive = false;
m_rubberBand.setSize(QSize(0, 0));
m_view->setCursor(QCursor(Qt::ArrowCursor));
return;
}
else
{
const QModelIndex index = m_view->indexAt(e->pos());
if (!index.isValid() || index.column() == Section::eActuator)
{
m_selectedItemId = -1;
return;
}
try
{
Track &track = m_view->timelineModel()->track(index.data().toInt());
Item &item = track.itemAt(m_view->toTime(e->pos().x()));
if (item.id() == m_selectedItemId)
{
if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
{
if (m_view->selectedItemIds().contains(m_selectedItemId))
m_view->unselectItem(m_selectedItemId);
else
m_view->selectItem(m_selectedItemId, false);
}
else
{
if (m_view->m_selectedItemIds.size() > 1 || !m_view->m_selectedItemIds.contains(m_selectedItemId))
m_view->selectItem(m_selectedItemId);
else
m_view->unselectItem(m_selectedItemId);
}
}
} catch (...) {}
m_selectedItemId = -1;
}
}
void TimelineViewSelectHandler::keyPressEvent(QKeyEvent *e)
{
if (e->key() == Qt::Key_Escape)
{
m_selectedItemId = -1;
m_view->clearSelectedItems();
}
else if (e->key() == Qt::Key_Delete)
{
if (!m_view->m_selectedItemIds.isEmpty())
{
for (const int &itemId : qAsConst(m_view->m_selectedItemIds))
{
try
{
m_view->timelineModel()->removeItem(itemId);
}
catch (const QString &str) { ERROR_LOG(m_view->m_logger) << LOGFUNCTION << " " << str; }
catch (...) { ERROR_LOG(m_view->m_logger) << LOGFUNCTION << " failed"; }
}
m_view->clearSelectedItems();
m_selectedItemId = -1;
}
}
else if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
{
try
{
switch (e->key())
{
case Qt::Key_A:
m_view->selectAllItems();
m_selectedItemId = -1;
break;
case Qt::Key_C:
if (m_view->hasSelectedItems())
m_view->timelineModel()->copyToClipboard(m_view->selectedItemIds());
break;
case Qt::Key_X:
if (m_view->hasSelectedItems())
{
m_view->timelineModel()->cutToClipboard(m_view->selectedItemIds());
m_view->clearSelectedItems();
}
break;
case Qt::Key_V:
if (!m_view->timelineModel()->m_clipboard.empty())
{
qint64 time = m_view->currentTime();
if (m_view->m_header->isIndicatorVisible() && m_view->m_header->indicatorTime() != -1)
time = m_view->m_header->indicatorTime();
m_view->timelineModel()->pasteFromClipboard(time);
}
break;
default:
break;
}
}
catch (const QString &str) { ERROR_LOG(m_view->m_logger) << LOGFUNCTION << " " << str; }
catch (...) { ERROR_LOG(m_view->m_logger) << LOGFUNCTION << " failed"; }
}
}
bool TimelineViewSelectHandler::isActive() const
{
if (QApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
return true;
if (m_isRubberBandActive)
return true;
return m_selectedItemId != -1;
}
QVector<int> TimelineViewSelectHandler::getItemsWithinRubberBand() const
{
const QPoint topLeft = { std::min(m_rubberBand.left(), m_rubberBand.right()), std::min(m_rubberBand.top(), m_rubberBand.bottom()) };
const QPoint bottomRight = { std::max(m_rubberBand.left(), m_rubberBand.right()), std::max(m_rubberBand.top(), m_rubberBand.bottom()) };
const qint64 start = m_view->toTime(topLeft.x());
const qint64 end = m_view->toTime(bottomRight.x());
if (start == end)
return {};
QVector<int> itemsWithinRubberBand;
const int h = m_view->itemDelegate()->sizeHint({}, {}).height();
for (int y = topLeft.y(); y <= bottomRight.y(); y += h)
{
const QPoint point = { topLeft.x(), y };
const QModelIndex index = m_view->indexAt(point);
if (!index.isValid())
continue;
try
{
const Track &track = m_view->timelineModel()->track(index.data().toInt());
itemsWithinRubberBand += track.itemIdsBetween(start, end);
}
catch (const QString &str)
{
ERROR_LOG(m_view->m_logger) << str;
}
catch (...) {}
}
if (topLeft.y() + h > bottomRight.y())
{
const QModelIndex index = m_view->indexAt(bottomRight);
if (!index.isValid())
return itemsWithinRubberBand;
try
{
const Track &track = m_view->timelineModel()->track(index.data().toInt());
itemsWithinRubberBand += track.itemIdsBetween(start, end);
}
catch (const QString &str)
{
ERROR_LOG(m_view->m_logger) << str;
}
catch (...) {}
}
return itemsWithinRubberBand;
}
}