implement seeking in playback window and add playback line in graphing view

This commit is contained in:
Leopixelo
2026-06-08 15:13:12 +02:00
parent af048e8615
commit 614f2fef54
8 changed files with 137 additions and 0 deletions
+42
View File
@@ -1,4 +1,5 @@
#include "frameplaybackobject.h" #include "frameplaybackobject.h"
#include <algorithm>
FramePlaybackObject::FramePlaybackObject() FramePlaybackObject::FramePlaybackObject()
{ {
@@ -290,6 +291,47 @@ void FramePlaybackObject::pausePlayback()
emit statusUpdate(currentPosition); emit statusUpdate(currentPosition);
} }
void FramePlaybackObject::seekPlayback(double timestamp)
{
if (currentSeqItem == NULL)
return;
/* make sure we execute in mThread context */
if (mThread_p && (mThread_p != QThread::currentThread()))
{
QMetaObject::invokeMethod(this, "seekPlayback", Qt::BlockingQueuedConnection, timestamp);
return;
}
// playbackTimer->stop();
// playbackActive = false;
timestamp *= 1000000; // convert to us
size_t lowIdx = 0;
size_t highIdx = currentSeqItem->data.count() - 1;
while (lowIdx < highIdx)
{
int midIdx = lowIdx + (highIdx - lowIdx) / 2;
CANFrame midFrame = currentSeqItem->data[midIdx];
if (midFrame.timeStamp().seconds() * 1000000 + midFrame.timeStamp().microSeconds() < timestamp)
{
lowIdx = midIdx + 1;
}
else
{
highIdx = midIdx - 1;
}
}
currentPosition = lowIdx;
emit statusUpdate(currentPosition);
startPlaybackForward();
}
void FramePlaybackObject::setSequenceObject(SequenceItem *item) void FramePlaybackObject::setSequenceObject(SequenceItem *item)
{ {
currentSeqItem = item; currentSeqItem = item;
+1
View File
@@ -54,6 +54,7 @@ public slots:
void stepPlaybackBackward(); void stepPlaybackBackward();
void stopPlayback(); void stopPlayback();
void pausePlayback(); void pausePlayback();
void seekPlayback(double timestamp);
void setSequenceObject(SequenceItem *item); void setSequenceObject(SequenceItem *item);
void setUseOriginalTiming(bool state); void setUseOriginalTiming(bool state);
+39
View File
@@ -407,10 +407,24 @@ void FramePlaybackWindow::EndOfFrameCache()
} }
} }
void FramePlaybackWindow::gotCenterTimeID(uint32_t ID, double timestamp)
{
Q_UNUSED(ID);
// isPlaying = false;
// wantPlaying = false;
// haveIncomingTraffic = false;
playbackObject.seekPlayback(timestamp);
}
void FramePlaybackWindow::getStatusUpdate(int frameNum) void FramePlaybackWindow::getStatusUpdate(int frameNum)
{ {
currentPosition = frameNum; currentPosition = frameNum;
updateFrameLabel(); updateFrameLabel();
QCanBusFrame::TimeStamp ts = seqItems[currentSeqNum].data[currentPosition].timeStamp();
emit sendCurrentTimestamp((double)(ts.seconds()) + ts.microSeconds() / 1000000.0f);
} }
void FramePlaybackWindow::updateFrameLabel() void FramePlaybackWindow::updateFrameLabel()
@@ -426,15 +440,40 @@ void FramePlaybackWindow::updateFrameLabel()
{ {
ui->lblCurrPlayback->setText(""); ui->lblCurrPlayback->setText("");
ui->lblPosition->setText(""); ui->lblPosition->setText("");
ui->timePosition->setText("");
return; return;
} }
ui->lblCurrPlayback->setText(currentSeqItem->filename); ui->lblCurrPlayback->setText(currentSeqItem->filename);
// convert current and last timestamp to text according to time format
QVariant currentTimestamp = Utility::formatTimestamp(seqItems[row].data[currentPosition].timeStamp().microSeconds());
QString currentTimestampText;
if (currentTimestamp.typeId() == QMetaType::Double)
currentTimestampText = QString::number(currentTimestamp.toDouble(), 'f', 5);
else if (currentTimestamp.typeId() == QMetaType::LongLong || currentTimestamp.typeId() == QMetaType::ULongLong)
currentTimestampText = QString::number(currentTimestamp.toLongLong());
else if (currentTimestamp.typeId() == QMetaType::QDateTime)
currentTimestampText = currentTimestamp.toDateTime().toString(Utility::timeFormat);
else
currentTimestampText = currentTimestamp.toString();
QVariant lastTimestamp = Utility::formatTimestamp(seqItems[row].data.last().timeStamp().microSeconds());
QString lastTimestampText;
if (lastTimestamp.typeId() == QMetaType::Double)
lastTimestampText = QString::number(lastTimestamp.toDouble(), 'f', 5);
else if (lastTimestamp.typeId() == QMetaType::LongLong || lastTimestamp.typeId() == QMetaType::ULongLong)
lastTimestampText = QString::number(lastTimestamp.toLongLong());
else if (lastTimestamp.typeId() == QMetaType::QDateTime)
lastTimestampText = lastTimestamp.toDateTime().toString(Utility::timeFormat);
else
lastTimestampText = lastTimestamp.toString();
if (wantPlaying && !isPlaying) if (wantPlaying && !isPlaying)
ui->lblPosition->setText(QString::number(currentPosition) + tr(" of ") + QString::number(seqItems[row].data.count()) + " (WAITING)"); ui->lblPosition->setText(QString::number(currentPosition) + tr(" of ") + QString::number(seqItems[row].data.count()) + " (WAITING)");
else else
ui->lblPosition->setText(QString::number(currentPosition) + tr(" of ") + QString::number(seqItems[row].data.count())); ui->lblPosition->setText(QString::number(currentPosition) + tr(" of ") + QString::number(seqItems[row].data.count()));
ui->timePosition->setText(currentTimestampText + tr(" of ") + lastTimestampText);
} }
void FramePlaybackWindow::seqTableCellClicked(int row, int col) void FramePlaybackWindow::seqTableCellClicked(int row, int col)
+4
View File
@@ -42,10 +42,14 @@ private slots:
void saveFilters(); void saveFilters();
void loadFilters(); void loadFilters();
void useOrigTimingClicked(); void useOrigTimingClicked();
void gotCenterTimeID(uint32_t ID, double timestamp);
void getStatusUpdate(int frameNum); void getStatusUpdate(int frameNum);
void EndOfFrameCache(); void EndOfFrameCache();
void updatedFrames(int); void updatedFrames(int);
signals:
void sendCurrentTimestamp(double timestamp);
private: private:
Ui::FramePlaybackWindow *ui; Ui::FramePlaybackWindow *ui;
QList<int> foundID; QList<int> foundID;
+12
View File
@@ -1684,6 +1684,11 @@ void MainWindow::showGraphingWindow()
connect(lastGraphingWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(uint32_t,double))); connect(lastGraphingWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), flowViewWindow, SLOT(gotCenterTimeID(uint32_t,double)));
connect(flowViewWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), lastGraphingWindow, SLOT(gotCenterTimeID(uint32_t,double))); connect(flowViewWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), lastGraphingWindow, SLOT(gotCenterTimeID(uint32_t,double)));
} }
if (playbackWindow)
{
connect(lastGraphingWindow, SIGNAL(sendCenterTimeID(uint32_t,double)), playbackWindow, SLOT(gotCenterTimeID(uint32_t,double)));
connect(playbackWindow, SIGNAL(sendCurrentTimestamp(double)), lastGraphingWindow, SLOT(gotPlaybackTimestamp(double)));
}
lastGraphingWindow->show(); lastGraphingWindow->show();
} }
@@ -1786,6 +1791,13 @@ void MainWindow::showPlaybackWindow()
playbackWindow = new FramePlaybackWindow(model->getListReference()); playbackWindow = new FramePlaybackWindow(model->getListReference());
else else
playbackWindow = new FramePlaybackWindow(model->getFilteredListReference()); playbackWindow = new FramePlaybackWindow(model->getFilteredListReference());
connect(this, SIGNAL(sendCenterTimeID(uint32_t, double)), playbackWindow, SLOT(gotCenterTimeID(uint32_t, double)));
for (auto &&graphWindow : graphWindows)
{
connect(graphWindow, SIGNAL(sendCenterTimeID(uint32_t, double)), playbackWindow, SLOT(gotCenterTimeID(uint32_t, double)));
connect(playbackWindow, SIGNAL(sendCurrentTimestamp(double)), graphWindow, SLOT(gotPlaybackTimestamp(double)));
}
} }
playbackWindow->show(); playbackWindow->show();
} }
+29
View File
@@ -69,6 +69,13 @@ GraphingWindow::GraphingWindow(const QVector<CANFrame> *frames, QWidget *parent)
itemTracer->setStyle(QCPItemTracer::tsCircle); itemTracer->setStyle(QCPItemTracer::tsCircle);
itemTracer->setSize(20); itemTracer->setSize(20);
playbackPen.setWidth(1);
playbackPen.setColor(Qt::red);
playbackLine = new QCPItemStraightLine(ui->graphingView);
playbackLine->setSelectable(false);
playbackLine->setPen(playbackPen);
playbackLine->setVisible(false);
// connect slot that ties some axis selections together (especially opposite axes): // connect slot that ties some axis selections together (especially opposite axes):
connect(ui->graphingView, SIGNAL(selectionChangedByUser()), this, SLOT(selectionChanged())); connect(ui->graphingView, SIGNAL(selectionChangedByUser()), this, SLOT(selectionChanged()));
//connect up the mouse controls //connect up the mouse controls
@@ -329,6 +336,28 @@ void GraphingWindow::gotCenterTimeID(uint32_t ID, double timestamp)
ui->graphingView->replot(); ui->graphingView->replot();
} }
void GraphingWindow::gotPlaybackTimestamp(double timestamp)
{
if (timestamp == INFINITY) {
playbackLine->setVisible(false);
return;
}
playbackLine->setVisible(true);
// timestamp is always givin in seconds
if (Utility::timeStyle == TS_MICROS)
timestamp *= 1000000;
else if (Utility::timeStyle == TS_MILLIS)
timestamp *= 1000;
else if (Utility::timeStyle == TS_CLOCK)
timestamp += 3600; // offset of one hour needed
playbackLine->point1->setCoords(timestamp, 0);
playbackLine->point2->setCoords(timestamp, 1);
ui->graphingView->replot();
}
void GraphingWindow::titleDoubleClick(QMouseEvent* event, QCPTextElement* title) void GraphingWindow::titleDoubleClick(QMouseEvent* event, QCPTextElement* title)
{ {
Q_UNUSED(event) Q_UNUSED(event)
+3
View File
@@ -84,6 +84,7 @@ private slots:
void editSelectedGraph(); void editSelectedGraph();
void updatedFrames(int); void updatedFrames(int);
void gotCenterTimeID(uint32_t ID, double timestamp); void gotCenterTimeID(uint32_t ID, double timestamp);
void gotPlaybackTimestamp(double timestamp);
void resetView(); void resetView();
void zoomIn(); void zoomIn();
void zoomOut(); void zoomOut();
@@ -105,6 +106,8 @@ private:
QCPSelectionDecorator *selDecorator; QCPSelectionDecorator *selDecorator;
QCPItemText *locationText; QCPItemText *locationText;
QCPItemTracer *itemTracer; QCPItemTracer *itemTracer;
QPen playbackPen;
QCPItemStraightLine *playbackLine;
bool needScaleSetup; //do we need to set x,y graphing extents? bool needScaleSetup; //do we need to set x,y graphing extents?
bool useOpenGL; bool useOpenGL;
bool followGraphEnd; bool followGraphEnd;
+7
View File
@@ -227,6 +227,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item alignment="Qt::AlignHCenter">
<widget class="QLabel" name="timePosition">
<property name="text">
<string>x of y</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>