#include "timeline_widget.h" #include "ui_timeline_widget.h" #include "timeline_view.h" #include "timeline_header_view.h" #include "timeline_model.h" #include "item_delegate.h" #include #include #include #include #include #include #include namespace LtsTimeline { TimelineWidget::TimelineWidget(QWidget *parent) : QWidget(parent) , m_ui(new Ui::Timeline) , m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("Timeline.Widget")) { m_ui->setupUi(this); m_ui->debugWidget->hide(); m_ui->wPlaceholder->hide(); m_ui->pbZoomIn->setProperty("const", true); m_ui->pbZoomOut->setProperty("const", true); m_ui->cbZoom->setProperty("const", true); connect(m_ui->cbZoom, qOverload(&QComboBox::currentIndexChanged), this, &TimelineWidget::onZoomSelected); m_ui->pbZoomIn->setIcon(QIcon(QStringLiteral("icon:bgv_zoom_in.svg"))); connect(m_ui->pbZoomIn, &QPushButton::clicked, this, &TimelineWidget::onZoomIn); m_ui->pbZoomOut->setIcon(QIcon(QStringLiteral("icon:bgv_zoom_out.svg"))); connect(m_ui->pbZoomOut, &QPushButton::clicked, this, &TimelineWidget::onZoomOut); connect(m_ui->view, &TimelineView::rangeChanged, this, [this](qint64 min, qint64 max) { m_ui->slider->setRange(min / 1000, (max - m_ui->view->zoomFactor()) / 1000); onUpdateZoomButtons(); }); connect(m_ui->view, &TimelineView::currentTimeChanged, this, [this](qint64 time) { m_ui->slider->setValue(time / 1000); }); connect(m_ui->view, &TimelineView::zoomChanged, this, &TimelineWidget::onZoomChanged); connect(m_ui->view->header(), &TimelineHeaderView::sectionResized, this, &TimelineWidget::onSectionResized); connect(m_ui->slider, &QScrollBar::valueChanged, this, &TimelineWidget::onSliderValueChanged); onZoomChanged(m_ui->view->zoomFactor()); } TimelineWidget::~TimelineWidget() { delete m_ui; } TimelineView *TimelineWidget::view() { return m_ui->view; } TimelineHeaderView *TimelineWidget::header() { return m_ui->view->header(); } TimelineModel *TimelineWidget::timelineModel() { return m_ui->view->timelineModel(); } void TimelineWidget::setModel(QAbstractItemModel *model) { m_ui->view->setModel(model); } QScrollBar *TimelineWidget::slider() { return m_ui->slider; } ZoomFactor TimelineWidget::zoomFactor() const { return m_ui->view->zoomFactor(); } void TimelineWidget::setZoomFactor(ZoomFactor factor) { m_ui->view->setZoomFactor(factor); } ZoomFactor TimelineWidget::minimumZoomFactor() const { return m_ui->view->minimumZoomFactor(); } void TimelineWidget::setMinimumZoomFactor(ZoomFactor factor) { m_ui->view->setMinimumZoomFactor(factor); populateZoomFactorComboBox(); } ZoomFactor TimelineWidget::maximumZoomFactor() const { return m_ui->view->maximumZoomFactor(); } void TimelineWidget::setMaximumZoomFactor(ZoomFactor factor) { m_ui->view->setMaximumZoomFactor(factor); populateZoomFactorComboBox(); } qint64 TimelineWidget::startTime() const { return m_ui->view->startTime(); } void TimelineWidget::setStartTime(qint64 time) { m_ui->view->setStartTime(time); } qint64 TimelineWidget::currentTime() const { return m_ui->view->currentTime(); } void TimelineWidget::setCurrentTime(qint64 time) { m_ui->view->setCurrentTime(time); } qint64 TimelineWidget::endTime() const { return m_ui->view->endTime(); } void TimelineWidget::setEndTime(qint64 time) { m_ui->view->setEndTime(time); } int TimelineWidget::duration() const { return m_ui->view->duration(); } void TimelineWidget::setDuration(int duration) { m_ui->view->setDuration(duration); } bool TimelineWidget::isCursorTextVisible() const { return m_ui->view->isCursorTextVisible(); } void TimelineWidget::setCursorTextVisible(bool visible) { m_ui->view->setCursorTextVisible(visible); } void TimelineWidget::setCursorText(const QString &text) { m_ui->view->setCursorText(text); } bool TimelineWidget::isSnapEnabled() const { return m_ui->view->timelineModel()->isSnapEnabled(); } void TimelineWidget::setSnapEnabled(bool enabled) { m_ui->view->timelineModel()->setSnapEnabled(enabled); } void TimelineWidget::enableSnap() { m_ui->view->timelineModel()->setSnapEnabled(true); } void TimelineWidget::disableSnap() { m_ui->view->timelineModel()->setSnapEnabled(false); } void TimelineWidget::triggerSnap() { m_ui->view->timelineModel()->setSnapEnabled(!m_ui->view->timelineModel()->isSnapEnabled()); if (m_ui->debugWidget->isVisible()) m_ui->pbDebugTriggerSnap->setText(m_ui->view->timelineModel()->isSnapEnabled() ? QStringLiteral("Disable Snap") : QStringLiteral("Enable Snap")); } void TimelineWidget::setZoomInIcon(QIcon icon) { m_ui->pbZoomIn->setIcon(icon); } void TimelineWidget::setZoomOutIcon(QIcon icon) { m_ui->pbZoomOut->setIcon(icon); } QWidget *TimelineWidget::placeholder() { if (m_ui->wPlaceholder->layout()->count() == 0) return nullptr; return m_ui->wPlaceholder->layout()->itemAt(0)->widget(); } void TimelineWidget::setPlaceholder(QWidget *widget) { QWidget *ptr = placeholder(); if (ptr) { if (ptr == widget) return; m_ui->wPlaceholder->layout()->removeWidget(ptr); delete ptr; } m_ui->wPlaceholder->layout()->addWidget(widget); } void TimelineWidget::showDebugWidget() { m_ui->debugWidget->show(); m_ui->sbDebugSnapStep->setValue(m_ui->view->timelineModel()->snapStep()); m_ui->sbDebugSnapTol->setValue(m_ui->view->timelineModel()->snapTolerance()); m_ui->pbDebugTriggerSnap->setText(m_ui->view->header()->isIndicatorVisible() ? QStringLiteral("Disable Snap") : QStringLiteral("Enable Snap")); m_ui->pbDebugTriggerIndicator->setText(m_ui->view->header()->isIndicatorVisible() ? QStringLiteral("Disable Indicator") : QStringLiteral("Enable Indicator")); m_ui->pbDebugTriggerHover->setText(m_ui->view->header()->isIndicatorVisible() ? QStringLiteral("Disable Hover") : QStringLiteral("Enable Hover")); connect(m_ui->view, &TimelineView::currentTimeChanged, this, &TimelineWidget::onUpdateDebugInfo); connect(m_ui->view, &TimelineView::rangeChanged, this, &TimelineWidget::onUpdateDebugInfo); connect(m_ui->view, &TimelineView::selectedItemsChanged, this, &TimelineWidget::onUpdateDebugInfo); connect(m_ui->view, &TimelineView::zoomChanged, this, &TimelineWidget::onUpdateDebugInfo); connect(m_ui->pbDebugTriggerSnap, &QPushButton::clicked, this, &TimelineWidget::triggerSnap); connect(m_ui->sbDebugSnapStep, qOverload(&QSpinBox::valueChanged), m_ui->view->timelineModel(), &TimelineModel::setSnapStep); connect(m_ui->sbDebugSnapTol, qOverload(&QSpinBox::valueChanged), m_ui->view->timelineModel(), &TimelineModel::setSnapTolerance); connect(m_ui->pbDebugTriggerIndicator, &QPushButton::clicked, this, [this]() { m_ui->view->header()->setIndicatorVisible(!m_ui->view->header()->isIndicatorVisible()); m_ui->pbDebugTriggerIndicator->setText(m_ui->view->header()->isIndicatorVisible() ? QStringLiteral("Disable Indicator") : QStringLiteral("Enable Indicator")); }); connect(m_ui->pbDebugTriggerHover, &QPushButton::clicked, this, [this]() { m_ui->view->header()->setHoverVisible(!m_ui->view->header()->isHoverVisible()); m_ui->pbDebugTriggerHover->setText(m_ui->view->header()->isHoverVisible() ? QStringLiteral("Disable Hover") : QStringLiteral("Enable Hover")); }); onUpdateDebugInfo(); } void TimelineWidget::hideDebugWidget() { m_ui->debugWidget->hide(); disconnect(m_ui->view, &TimelineView::currentTimeChanged, this, &TimelineWidget::onUpdateDebugInfo); disconnect(m_ui->view, &TimelineView::rangeChanged, this, &TimelineWidget::onUpdateDebugInfo); disconnect(m_ui->view, &TimelineView::selectedItemsChanged, this, &TimelineWidget::onUpdateDebugInfo); disconnect(m_ui->view, &TimelineView::zoomChanged, this, &TimelineWidget::onUpdateDebugInfo); disconnect(m_ui->pbDebugTriggerSnap, &QPushButton::clicked, this, &TimelineWidget::triggerSnap); disconnect(m_ui->sbDebugSnapStep, qOverload(&QSpinBox::valueChanged), m_ui->view->timelineModel(), &TimelineModel::setSnapStep); disconnect(m_ui->sbDebugSnapTol, qOverload(&QSpinBox::valueChanged), m_ui->view->timelineModel(), &TimelineModel::setSnapTolerance); disconnect(m_ui->pbDebugTriggerIndicator); disconnect(m_ui->pbDebugTriggerHover); } void TimelineWidget::populateZoomFactorComboBox() { disconnect(m_ui->cbZoom, qOverload(&QComboBox::currentIndexChanged), this, &TimelineWidget::onZoomSelected); m_ui->cbZoom->clear(); QVector availableZooms = Zoom::availableZoomFactors(m_ui->view->minimumZoomFactor(), m_ui->view->upperZoomFactor()); for (ZoomFactor factor : qAsConst(availableZooms)) { m_ui->cbZoom->addItem(Zoom::toString(factor), QVariant(factor)); if (factor == zoomFactor()) m_ui->cbZoom->setCurrentIndex(m_ui->cbZoom->findData(static_cast(zoomFactor()))); } connect(m_ui->cbZoom, qOverload(&QComboBox::currentIndexChanged), this, &TimelineWidget::onZoomSelected); } void TimelineWidget::onSectionResized(int logicalIndex, int oldSize, int newSize) { Q_UNUSED(oldSize); if (logicalIndex == Section::eItems) { int width = m_ui->view->verticalScrollBar()->width(); m_ui->slider->setMinimumHeight(width); m_ui->slider->setMaximumHeight(width); m_ui->slider->setMaximumWidth(newSize); m_ui->slider->setMinimumWidth(newSize); } } void TimelineWidget::onSliderValueChanged(int value) { setCurrentTime(qint64(value) * 1000); } void TimelineWidget::onUpdateZoomButtons() { m_ui->pbZoomIn->setEnabled(zoomFactor() > minimumZoomFactor()); m_ui->pbZoomOut->setEnabled(zoomFactor() < m_ui->view->upperZoomFactor()); populateZoomFactorComboBox(); } void TimelineWidget::onZoomChanged(ZoomFactor factor) { m_ui->slider->setMaximum((m_ui->view->endTime() - m_ui->view->zoomFactor()) / 1000); m_ui->slider->setPageStep(factor / 1000); m_ui->slider->setSingleStep(Zoom::minorInterval(factor)); onUpdateZoomButtons(); if (static_cast(m_ui->cbZoom->currentData().toInt()) != factor) m_ui->cbZoom->setCurrentIndex(m_ui->cbZoom->findData(QVariant(factor))); } void TimelineWidget::onZoomSelected() { ZoomFactor factor = static_cast(m_ui->cbZoom->currentData().toInt()); if (factor != zoomFactor()) setZoomFactor(factor); } void TimelineWidget::onZoomIn() { setZoomFactor(Zoom::decrement(zoomFactor())); } void TimelineWidget::onZoomOut() { setZoomFactor(Zoom::increment(zoomFactor())); } void TimelineWidget::onUpdateDebugInfo() { m_ui->lblDebugStart->setText(DateTime::toString(startTime(), DateTimeFormat::DTG)); m_ui->lblDebugEnd->setText(DateTime::toString(endTime(), DateTimeFormat::DTG)); m_ui->lblDebugDuration->setText(QString::number(duration() / 1000) + QStringLiteral("s")); m_ui->lblDebugCurrent->setText(DateTime::toString(currentTime(), DateTimeFormat::DTG)); m_ui->lblDebugSlider->setText(DateTime::toString(qint64(m_ui->slider->value()) * 1000, DateTimeFormat::DTG)); m_ui->lblDebugZoom->setText(Zoom::toString(m_ui->view->zoomFactor())); QString selection; for (int itemId : qAsConst(m_ui->view->selectedItemIds())) selection += QString::number(itemId) + QStringLiteral(", "); if (selection.size() > 1) selection.chop(2); m_ui->lblDebugSelection->setText(selection); } }