#include "script_timeline.h" #include "ui_script_timeline.h" #include "track_widget.h" #include "tools.h" #include "track_entry.h" #include "track_content_widget.h" #include "filter_track_widget.h" #include "filter_background_widget.h" #include "temporary_pointer_vector.h" #include #include #include #include #include #include #include #include namespace LtsScriptTimeline { ScriptTimeline::ScriptTimeline(QWidget *parent) : QWidget(parent) , ui(new Ui::ScriptTimeline) , m_uniqueId(0) , m_scriptId(-1) , m_baseTrackWidgetWidth(150) , m_readonly(false) , m_time(0) , m_tools(new Tools(this)) , m_mlmsMaster(nullptr) , m_ignoreChanges(false) { ui->setupUi(this); this->setFocusPolicy(Qt::StrongFocus); ui->indicator->setTools(m_tools); ui->trackScrollBar->setMinimum(0); ui->trackScrollBar->setMaximum(5 * 60); connect(ui->zoomSlider, &QSlider::valueChanged, this, &ScriptTimeline::slotZoomValueChanged); connect(ui->trackScrollBar, &QScrollBar::sliderReleased, this, &ScriptTimeline::slotScrollbarValueChanged); connect(ui->trackScrollBar, &QScrollBar::actionTriggered, this, &ScriptTimeline::slotScrollbarValueChanged); connect(ui->indicator, &Indicator::signalHandleResized, this, &ScriptTimeline::slotHeaderHandleResized); connect(ui->indicator, &Indicator::signalHeaderIndicatorTimeChanged, this, &ScriptTimeline::slotHeaderIndicatorTimeChanged); connect(ui->indicator, &Indicator::signalHeaderIndicatorTimeUserChanged, this, &ScriptTimeline::signalHeaderIndicatorTimeUserChanged); QTimer *t = new QTimer(this); t->setInterval(1500); connect(t, &QTimer::timeout, this, &ScriptTimeline::slotSetNewScrollBarMaximum); t->start(); slotZoomValueChanged(ui->zoomSlider->value()); } ScriptTimeline::~ScriptTimeline() { m_copyTopics.clear(); m_ignoreChanges = true; qDeleteAll(m_clipboard); delete ui; } void ScriptTimeline::selectAll() { const QList vecTrackWidgets = getTrackWidgets(); for (TrackWidget *tw : vecTrackWidgets) { TrackContentWidget *tcw = tw->getTrackContentWidget(); tcw->selectAll(); } } bool ScriptTimeline::checkNewLength(TrackEntry *te, int newLength) { const QList tws = getTrackWidgets(); TrackContentWidget *tesTcw = nullptr; for (TrackWidget *tw : tws) { const QVector &tes = tw->getTrackContentWidget()->getTrackEntries(); auto it = std::find_if(tes.begin(), tes.end(), [te](const TrackEntry * a) { return (a->m_topicId == te->m_topicId); }); if (it == tes.end()) continue; tesTcw = tw->getTrackContentWidget(); break; } if (tesTcw == nullptr) return false; TrackEntry newTe(te); newTe.m_length = newLength; return tesTcw->checkForCollisionsSimple(newTe); } void ScriptTimeline::lockIndicator(bool lock) { ui->indicator->lockIndicator(lock); } void ScriptTimeline::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Delete) { slotDeleteSelectedTopics(); } else if (QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier) && event->key() == Qt::Key_C) { slotCopyTopics(); } else if (QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier) && event->key() == Qt::Key_V) { slotPasteTopics(); } else if (QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier) && event->key() == Qt::Key_X) { slotCutTopics(); } else if (QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier) && event->key() == Qt::Key_A) { selectAll(); } else if (QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier) && event->key() == Qt::Key_S) { emit signalSave(); } else { const QList vecTrackWidgets = getTrackWidgets(); for (auto w : vecTrackWidgets) w->keyPressEvent(event); } } void ScriptTimeline::mousePressEvent(QMouseEvent *event) { if (event->buttons() != Qt::LeftButton) return; slotStartRubberband(event->pos()); } void ScriptTimeline::mouseMoveEvent(QMouseEvent *) { slotModifyRubberband(); } void ScriptTimeline::mouseReleaseEvent(QMouseEvent *) { const QList vecTrackWidgets = getTrackWidgets(); for (auto w : vecTrackWidgets) w->unselectAll(); slotStopRubberband(); } void ScriptTimeline::slotScroll(int incr) { int oldValue = ui->trackScrollBar->value(); ui->trackScrollBar->setValue(oldValue + incr); slotScrollbarValueChanged(); } void ScriptTimeline::setReadonly(bool readonly) { m_readonly = readonly; const QList vecTrackWidgets = getTrackWidgets(); for (TrackWidget *tw : vecTrackWidgets) tw->setReadonly(readonly); } void ScriptTimeline::clear() { m_copyTopics.clear(); const QList trackWidgetList = getTrackWidgets(); for (TrackWidget *tw : trackWidgetList) delete tw; qDeleteAll(m_clipboard); m_clipboard.clear(); m_uniqueId = 0; updateEverything(); } void ScriptTimeline::slotSetNewScrollBarMaximum() { int max = 5 * 60; const QList trackWidgetList = getTrackWidgets(); for (const TrackWidget *tw : trackWidgetList) { const QVector &trackEntries = tw->getTrackContentWidget()->getTrackEntries(); for (const TrackEntry *te : trackEntries) { int maxTeTime = te->m_startTime + te->m_length; if (maxTeTime > max) { max = maxTeTime + 5 * 60; } } } ui->trackScrollBar->setMaximum(max); ui->trackScrollBar->setPageStep(60); m_tools->m_timelineLength = max; updateEverything(); } void ScriptTimeline::setIndicatorTime(int time) { ui->indicator->setIndicatorTime(time); } int ScriptTimeline::getCurrentScriptEndTime() { int currEndTime = 0; const QList listTrackWidgets = getTrackWidgets(); for (const auto ltw : listTrackWidgets) { const auto cont = ltw->getTrackEntries(); for (const auto pTE : cont) { int endTime = pTE->m_startTime + pTE->m_length; currEndTime = qMax(currEndTime, endTime); } } return currEndTime; } void ScriptTimeline::slotHeaderIndicatorTimeChanged(int time) { m_time = time; const QList trackWidgetList = getTrackWidgets(); for (TrackWidget *tw : trackWidgetList) tw->setIndicatorTime(time); emit signalHeaderIndicatorTimeChanged(time); } void ScriptTimeline::slotHeaderHandleResized(int newSize) { m_baseTrackWidgetWidth = newSize; updateEverything(); const QList trackWidgetList = getTrackWidgets(); for (TrackWidget *tw : trackWidgetList) tw->setBaseWidth(newSize); } void ScriptTimeline::slotDeleteTracks() { int count = 0; const QList trackWidgetList = getTrackWidgets(); for (const TrackWidget *tw : trackWidgetList) { if (tw->isSelected()) count++; } if (count < 1) { QApplication::beep(); return; } if (QMessageBox::question(this, tr("Delete selected tracks"), tr("Are you sure you want to delete all %1 tracks?").arg(count), QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return; for (TrackWidget *tw : trackWidgetList) { if (tw->isSelected()) tw->deleteLater(); } } void ScriptTimeline::slotZoomValueChanged(int value) { if (value < 1) value = 1; m_tools->m_zoomFactor = value; updateEverything(); } void ScriptTimeline::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); { QPixmap p(QStringLiteral(":/style/portrait-mode.svg")); int h = ui->trackScrollBar->height(); QSize s(h, h); ui->lbPortrait->setPixmap(p.scaled(s, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); ui->lbPortrait->setFixedSize(s); } { QPixmap p(QStringLiteral(":/style/landscape-mode.svg")); int h = ui->trackScrollBar->height(); QSize s(h, h); ui->lbLandscape->setPixmap(p.scaled(s, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); ui->lbLandscape->setFixedSize(s); } updateEverything(); } void ScriptTimeline::slotUnselectAll() { const QList trackWidgetList = getTrackWidgets(); for (TrackWidget *tw : trackWidgetList) tw->unselectAll(); } int ScriptTimeline::getFilterTrackEntryRealTime(TrackEntry *te) { const QList trackWidgetList = getTrackWidgets(); for (TrackWidget *tw : trackWidgetList) { for (FilterTrackWidget *ftw : tw->filterLines()) { const QMap &filterContentWidgets = ftw->fbw()->filterContentWidgets(); int foundMainTrackEntryId = -1; for (auto itFcw = filterContentWidgets.begin(); itFcw != filterContentWidgets.end(); ++itFcw) { const TrackContentWidget *tcw = itFcw.value(); const QVector &trackEntries = tcw->getTrackEntries(); for (const TrackEntry *tempFilterTe : trackEntries) { if (tempFilterTe->m_topicId == te->m_topicId) { foundMainTrackEntryId = itFcw.key(); break; } } if (foundMainTrackEntryId != -1) break; } if (foundMainTrackEntryId != -1) { const QVector &trackEntries = tw->getTrackContentWidget()->getTrackEntries(); for (const TrackEntry *mainTe : trackEntries) { if (mainTe->m_topicId == foundMainTrackEntryId) return mainTe->m_startTime + te->m_startTime; } } } } return -1; } QList ScriptTimeline::getTrackWidgets() const { return ui->trackScrollArea->findChildren(); } TrackEntry *ScriptTimeline::getTrackEntryWithFiltersAsEntries(int topicId) { const QList trackWidgetList = getTrackWidgets(); for (const TrackWidget *tw : trackWidgetList) { const QVector trackEntries = tw->getTrackEntriesFiltersAsEntries(); for (TrackEntry *te : qAsConst(trackEntries)) { if (te->m_topicId == topicId) return te; } } return nullptr; } TrackEntry *ScriptTimeline::getTrackEntry(int topicId) { const QList trackWidgetList = getTrackWidgets(); for (const TrackWidget *tw : trackWidgetList) { const QVector trackEntries = tw->getTrackEntries(); for (TrackEntry *te : trackEntries) { if (te->m_topicId == topicId) return te; } } return nullptr; } QVector ScriptTimeline::getTrackEntriesWithFiltersAsEntries(bool selectedEntriesOnly) const { QVector tes; const QList trackWidgetList = getTrackWidgets(); for (TrackWidget *tw : trackWidgetList) tes += tw->getTrackEntriesFiltersAsEntries(selectedEntriesOnly); return tes; } QMap > ScriptTimeline::getTrackEntriesWithFilters(bool selectedEntriesOnly) const { QMap > trackList; const QList trackWidgetList = getTrackWidgets(); for (const TrackWidget *tw : trackWidgetList) { QString trackName(tw->trackName()); const QVector trackEntries = tw->getTrackEntriesWithFilters(selectedEntriesOnly); trackList.insert(trackName, trackEntries); } return trackList; } QVector ScriptTimeline::getTrackEntries(bool selectedEntriesOnly) const { QVector tes; const QList trackWidgetList = getTrackWidgets(); for (const TrackWidget *tw : trackWidgetList) tes += tw->getTrackEntries(selectedEntriesOnly); return tes; } bool ScriptTimeline::importTrackEntries(const QVector &importTes) { int importLength = 0; for (TrackEntry *te : qAsConst(importTes)) { int teLen = te->m_startTime + te->m_length; if (teLen > importLength) importLength = teLen; } const QVector tes = getTrackEntries(); int pasteTime = m_time; for (TrackEntry *te : qAsConst(tes)) { int start = te->m_startTime; int sum = start + te->m_length; if (start < m_time && sum > m_time && pasteTime < sum) { pasteTime = sum; } } int diff = pasteTime - m_time; for (TrackEntry *te : qAsConst(tes)) { if (te->m_startTime >= m_time) te->m_startTime += importLength + diff; } QVector finalImportTes(importTes); for (TrackEntry *te : finalImportTes) { te->m_startTime += pasteTime; if (!addTopic(te)) { qCritical() << "could not add te #" << te->m_topicId; delete te; } } m_time = pasteTime; setIndicatorTime(m_time); return true; } bool ScriptTimeline::addTopic(TrackEntry *te) { if (te->m_topicId == 0) te->m_topicId = nextUniqueId(); if (te->m_channelName.isEmpty()) te->m_channelName = tr("Unnamed Track"); te->isSet = true; const QList trackWidgetList = getTrackWidgets(); for (TrackWidget *tw : trackWidgetList) { if (tw->trackName() == te->m_channelName) { m_ignoreChanges = true; bool result = tw->addTrackEntry(te, false); m_ignoreChanges = false; if (!result) return false; tw->updateMe(); return true; } } return false; } QVector ScriptTimeline::getSelectedEntriesWithFilterEntries() const { QVector tes; const QList tws = getTrackWidgets(); for (const TrackWidget *tw : qAsConst(tws)) tes += tw->getTrackEntriesFiltersAsEntries(true); return tes; } QString ScriptTimeline::newTrackName() const { QString newTrackName; int add = 1; const QList trackWidgetList = getTrackWidgets(); bool newTrackNameFound = false; while (!newTrackNameFound) { newTrackNameFound = true; newTrackName = tr("New Track %1").arg(add); for (const TrackWidget *tw : trackWidgetList) { if (tw->trackName() == newTrackName) { add++; newTrackNameFound = false; break; } } } return newTrackName; } void ScriptTimeline::updateAllTracks() { const QList tws = getTrackWidgets(); for (TrackWidget *tw : tws) tw->updateMe(); } QVector ScriptTimeline::getSelectedFilterEntries() const { QVector result; const QList tws = getTrackWidgets(); for (const TrackWidget *tw : qAsConst(tws)) { result += tw->getSelectedFilterEntries(); } return result; } void ScriptTimeline::slotDeleteSelectedTopics() { int topicCount = 0; const QList tws = getTrackWidgets(); for (const TrackWidget *tw : qAsConst(tws)) { topicCount += tw->getSelectedFilterEntries().count(); TrackContentWidget *tcw = tw->getTrackContentWidget(); topicCount += tcw->getSelectedEntries().count(); } if (!topicCount) { QApplication::beep(); return; } connect(new LtsWidgets::LtsMessageDialogNew(this, tr("Are you sure that you want to delete %1 topics?").arg(topicCount), QString(), LtsWidgets::Behaviour::Modal, LtsWidgets::Button::Yes | LtsWidgets::Button::No), &LtsWidgets::LtsMessageDialogNew::yes, this, [this]() { const QList tws = getTrackWidgets(); for (const TrackWidget *tw : qAsConst(tws)) { const QVector &ftws = tw->filterLines(); for (const FilterTrackWidget *ftw : qAsConst(ftws)) { const FilterBackgroundWidget *fbw = ftw->fbw(); const QMap &fcws = fbw->filterContentWidgets(); for (TrackContentWidget *tcw: fcws) tcw->deleteSelectedTopics(); } TrackContentWidget *tcw = tw->getTrackContentWidget(); tcw->deleteSelectedTopics(); } }); } void ScriptTimeline::slotCutTopics() { slotCopyTopics(); const QList tws = getTrackWidgets(); for (const TrackWidget *tw : qAsConst(tws)) { TrackContentWidget *tcw = tw->getTrackContentWidget(); tcw->deleteSelectedTopics(); } } void ScriptTimeline::slotCopyTopics() { const QList tws = getTrackWidgets(); int firstTeTime = -1; for (const TrackWidget *tw : qAsConst(tws)) { TrackContentWidget *tcw = tw->getTrackContentWidget(); const QVector &selected = tcw->getSelectedEntries(); if (tcw->getSelectedEntries().isEmpty()) continue; for (const TrackEntry *te : qAsConst(selected)) { if (firstTeTime > te->m_startTime || firstTeTime == -1) firstTeTime = te->m_startTime; } } if (firstTeTime == -1) { QApplication::beep(); return; } m_copyTopics.clear(); for (TrackWidget *tw : tws) { TrackContentWidget *tcw = tw->getTrackContentWidget(); if (tcw->getSelectedEntries().isEmpty()) continue; connect(tw, &QObject::destroyed, this, [this](QObject *obj) { m_copyTopics.remove(static_cast(obj)); }); m_copyTopics.insert(tw, TrackContentWidget::itemsToData(tw->getTrackEntriesWithFilters(true), firstTeTime, false)); } } void ScriptTimeline::slotPasteTopics() { if (m_copyTopics.isEmpty() || m_time < 0) { QApplication::beep(); return; } for (auto i = m_copyTopics.constBegin(); i != m_copyTopics.constEnd(); ++i) { const TrackWidget *tw = i.key(); const QByteArray &data = i.value(); TrackContentWidget *tcw = tw->getTrackContentWidget(); int dummy = 0; const TemporaryPointerVector tempTes(TrackContentWidget::dataToItems(data, dummy)); if (!tcw->canPasteTopics(tempTes, 0, m_time)) { new LtsWidgets::LtsMessageDialogNew(this, tr("Topics can't be pasted here as one or more topics intersects with another existing topic.")); return; } } for (auto i = m_copyTopics.constBegin(); i != m_copyTopics.constEnd(); ++i) { TrackWidget *tw = i.key(); TrackContentWidget *tcw = tw->getTrackContentWidget(); const QByteArray &data = i.value(); int dummy = 0; const TemporaryPointerVector tempTes(TrackContentWidget::dataToItems(data, dummy)); tcw->forcePasteTopics(tempTes, 0, m_time); } } void ScriptTimeline::slotMoveAll(int direction) { int factor = 1; if (!QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier)) factor = 10; QList tws = getTrackWidgets(); for (TrackWidget *tw : qAsConst(tws)) { TrackContentWidget *tcw = tw->getTrackContentWidget(); if (!tcw->canMoveAll(direction * factor)) { QApplication::beep(); qWarning() << "cols and/or parls @" << tcw; return; } } for (TrackWidget *tw : qAsConst(tws)) { TrackContentWidget *tcw = tw->getTrackContentWidget(); tcw->forceMoveAll(direction * factor); } } static inline bool containsFailedTrackContentWidget(const QHash &mlmsTCWStates) { auto end = mlmsTCWStates.end(); for (auto it = mlmsTCWStates.begin(); it != end; ++it) { if (it.value() == false) return true; } return false; } TrackWidget *ScriptTimeline::addTrack(const QString &name, bool filtersAllowed) { TrackWidget *tw = new TrackWidget(m_baseTrackWidgetWidth, m_readonly, m_tools, filtersAllowed); tw->setScriptTimeline(this); tw->setTrackName(name); ui->trackLayout->insertWidget(1, tw); connect(tw, &TrackWidget::signalTrackEntrySelectionChanged, this, &ScriptTimeline::slotTrackEntrySelectionChanged); connect(tw, &TrackWidget::signalTrackEntryDeleted, this, &ScriptTimeline::signalTrackEntryDeleted); connect(tw, &TrackWidget::signalUnselectAll, this, &ScriptTimeline::slotUnselectAll); connect(tw, &TrackWidget::signalSelectTrack, this, &ScriptTimeline::slotSelectTrack); connect(tw, &TrackWidget::signalChangesMade, this, &ScriptTimeline::signalChangesMade); connect(tw, &TrackWidget::signalEditEntry, this, &ScriptTimeline::signalEditEntry); TrackContentWidget *tcw = tw->getTrackContentWidget(); connect(tcw, &TrackContentWidget::signalStartRubberband, this, &ScriptTimeline::slotStartRubberband); connect(tcw, &TrackContentWidget::signalStopRubberband, this, &ScriptTimeline::slotStopRubberband); connect(tcw, &TrackContentWidget::signalEscapeRubberband, this, &ScriptTimeline::slotEscapeRubberband); connect(tcw, &TrackContentWidget::signalModifyRubberband, this, &ScriptTimeline::slotModifyRubberband); connect(tcw, &TrackContentWidget::signalSelectAllGlobal, this, &ScriptTimeline::selectAll); connect(tcw, &TrackContentWidget::signalCopyTopics, this, &ScriptTimeline::slotCopyTopics); connect(tcw, &TrackContentWidget::signalPasteTopics, this, &ScriptTimeline::slotPasteTopics); connect(tcw, &TrackContentWidget::signalCutTopics, this, &ScriptTimeline::slotCutTopics); connect(tcw, &TrackContentWidget::signalDeleteSelectedTopics, this, &ScriptTimeline::slotDeleteSelectedTopics); connect(tcw, &TrackContentWidget::signalSave, this, &ScriptTimeline::signalSave); connect(tcw, &TrackContentWidget::signalMoveAll, this, &ScriptTimeline::slotMoveAll); connect(tcw, &TrackContentWidget::signalScroll, this, &ScriptTimeline::slotScroll); connect(tcw, &TrackContentWidget::signalMultiLineMultiSelectionFailed, this, [this]() { TrackContentWidget *senderTcw = qobject_cast(sender()); if (senderTcw == nullptr) return; m_mlmsTCWStates.insert(senderTcw, false); const QList tws = getTrackWidgets(); for (TrackWidget *tw : tws) { TrackContentWidget *tcw = tw->getTrackContentWidget(); tcw->setDragPossible(false); } }); connect(tcw, &TrackContentWidget::signalMultiLineMultiSelectionOkay, this, [this]() { TrackContentWidget *senderTcw = qobject_cast(sender()); if (senderTcw == nullptr) return; m_mlmsTCWStates.insert(senderTcw, true); if (containsFailedTrackContentWidget(m_mlmsTCWStates)) return; const QList tws = getTrackWidgets(); for (TrackWidget *tw : tws) { TrackContentWidget *tcw = tw->getTrackContentWidget(); if (tcw == senderTcw) continue; tcw->setDragPossible(true); } }); connect(tcw, &TrackContentWidget::signalMultiLineMultiSelectionDone, this, [this](int dropPos) { TrackContentWidget *senderTcw = qobject_cast(sender()); if (senderTcw == nullptr) return; const QList tws = getTrackWidgets(); for (TrackWidget *tw : tws) { TrackContentWidget *tcw = tw->getTrackContentWidget(); if (tcw == senderTcw) continue; if (containsFailedTrackContentWidget(m_mlmsTCWStates) || dropPos == -1) { QApplication::beep(); tcw->dragEnd(); } else tcw->dragDrop(dropPos); } m_mlmsMaster = nullptr; m_mlmsTCWStates.clear(); m_ignoreChanges = false; updateAllTracks(); }); connect(tcw, &TrackContentWidget::signalMultiLineMultiSelectionMove, this, [this](int x) { TrackContentWidget *senderTcw = qobject_cast(sender()); if (senderTcw == nullptr) return; if (senderTcw != m_mlmsMaster) return; const QList tws = getTrackWidgets(); for (TrackWidget *tw : tws) { TrackContentWidget *tcw = tw->getTrackContentWidget(); if (tcw == senderTcw) continue; tcw->dragMove(x); } }); connect(tcw, &TrackContentWidget::signalMultiLineMultiSelectionStart, this, [this](int dragPosTime) { if (m_mlmsMaster != nullptr) return; TrackContentWidget *senderTcw = qobject_cast(sender()); if (senderTcw == nullptr) return; m_mlmsMaster = senderTcw; m_ignoreChanges = true; const QList tws = getTrackWidgets(); for (TrackWidget *tw : tws) { TrackContentWidget *tcw = tw->getTrackContentWidget(); if (tcw == senderTcw) continue; tcw->dragEnter(tcw->selectedItemsToData(dragPosTime)); } }); return tw; } void ScriptTimeline::slotEscapeRubberband() { if (m_rubberbandAction.rubberBand == nullptr) return; m_rubberbandAction.rubberBand->deleteLater(); } void ScriptTimeline::slotStopRubberband() { if (m_rubberbandAction.rubberBand == nullptr) return; QRect geo(m_rubberbandAction.rubberBand->geometry()); m_rubberbandAction.rubberBand->deleteLater(); if (m_readonly) return; QPoint rubberbandLength = geo.topLeft() - geo.bottomRight(); if (rubberbandLength.manhattanLength() <= 6) return; const QList tws = getTrackWidgets(); for (TrackWidget *tw : tws) { TrackContentWidget *tcw = tw->getTrackContentWidget(); QRect tcwGeo(tcw->geometry()); QPoint topLeft(tcw->mapTo(this, tcwGeo.topLeft())); QPoint bottomRight(tcw->mapTo(this, tcwGeo.bottomRight())); if (QRect(topLeft, bottomRight).intersects(geo)) { QPoint tcwTL(tcw->mapFrom(this, geo.topLeft())); QPoint tcwBR(tcw->mapFrom(this, geo.bottomRight())); int fromPos = tcwTL.x(); int toPos = tcwBR.x(); tcw->selectEntriesAtPositions(fromPos, toPos); } } } void ScriptTimeline::slotStartRubberband(const QPoint &) { if (m_readonly) return; if (m_rubberbandAction.rubberBand == nullptr) { QPoint cursorPos(mapFromGlobal(QCursor::pos())); m_rubberbandAction.origin = cursorPos; m_rubberbandAction.rubberBand = new QRubberBand(QRubberBand::Rectangle, this); m_rubberbandAction.rubberBand->setGeometry(QRect(cursorPos, QSize())); m_rubberbandAction.rubberBand->show(); } } void ScriptTimeline::slotModifyRubberband() { if (!m_rubberbandAction.rubberBand) return; m_rubberbandAction.rubberBand->setGeometry(QRect(m_rubberbandAction.origin, mapFromGlobal(QCursor::pos())).normalized()); } void ScriptTimeline::slotTrackEntrySelectionChanged(TrackEntry *) { if (m_ignoreChanges) return; const QList tws = getTrackWidgets(); bool hasSelections = false; bool activateMultiLineMultiSelectionMode = false; for (const TrackWidget *tw : tws) { if (!hasSelections) { if (!tw->getSelectedEntries().isEmpty() || !tw->getSelectedFilterEntries().isEmpty()) hasSelections = true; } else if (!tw->getSelectedEntries().isEmpty()) { activateMultiLineMultiSelectionMode = true; break; } } for (TrackWidget *tw : qAsConst(tws)) tw->getTrackContentWidget()->setMultiLineMultiSelectionMode(activateMultiLineMultiSelectionMode); emit signalTrackEntrySelectionChanged(nullptr); } void ScriptTimeline::slotSelectTrack() { const QList trackWidgetList = getTrackWidgets(); for (const TrackWidget *tw : trackWidgetList) { if (tw->isSelected()) { return; } } } void ScriptTimeline::updateEverything() { TrackWidget *tw = ui->trackScrollArea->findChild(); if (tw != nullptr) m_tools->m_paintWidth = tw->width(); ui->indicator->updateMe(); updateAllTracks(); update(); } void ScriptTimeline::slotScrollbarValueChanged() { m_tools->m_scrollPos = ui->trackScrollBar->value(); updateEverything(); } }