implement seeking in playback window and add playback line in graphing view
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "frameplaybackobject.h"
|
||||
#include <algorithm>
|
||||
|
||||
FramePlaybackObject::FramePlaybackObject()
|
||||
{
|
||||
@@ -290,6 +291,47 @@ void FramePlaybackObject::pausePlayback()
|
||||
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)
|
||||
{
|
||||
currentSeqItem = item;
|
||||
|
||||
@@ -54,6 +54,7 @@ public slots:
|
||||
void stepPlaybackBackward();
|
||||
void stopPlayback();
|
||||
void pausePlayback();
|
||||
void seekPlayback(double timestamp);
|
||||
|
||||
void setSequenceObject(SequenceItem *item);
|
||||
void setUseOriginalTiming(bool state);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
currentPosition = frameNum;
|
||||
updateFrameLabel();
|
||||
QCanBusFrame::TimeStamp ts = seqItems[currentSeqNum].data[currentPosition].timeStamp();
|
||||
|
||||
emit sendCurrentTimestamp((double)(ts.seconds()) + ts.microSeconds() / 1000000.0f);
|
||||
}
|
||||
|
||||
void FramePlaybackWindow::updateFrameLabel()
|
||||
@@ -426,15 +440,40 @@ void FramePlaybackWindow::updateFrameLabel()
|
||||
{
|
||||
ui->lblCurrPlayback->setText("");
|
||||
ui->lblPosition->setText("");
|
||||
ui->timePosition->setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
ui->lblPosition->setText(QString::number(currentPosition) + tr(" of ") + QString::number(seqItems[row].data.count()) + " (WAITING)");
|
||||
else
|
||||
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)
|
||||
|
||||
@@ -42,10 +42,14 @@ private slots:
|
||||
void saveFilters();
|
||||
void loadFilters();
|
||||
void useOrigTimingClicked();
|
||||
void gotCenterTimeID(uint32_t ID, double timestamp);
|
||||
void getStatusUpdate(int frameNum);
|
||||
void EndOfFrameCache();
|
||||
void updatedFrames(int);
|
||||
|
||||
signals:
|
||||
void sendCurrentTimestamp(double timestamp);
|
||||
|
||||
private:
|
||||
Ui::FramePlaybackWindow *ui;
|
||||
QList<int> foundID;
|
||||
|
||||
@@ -1684,6 +1684,11 @@ void MainWindow::showGraphingWindow()
|
||||
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)));
|
||||
}
|
||||
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();
|
||||
}
|
||||
@@ -1786,6 +1791,13 @@ void MainWindow::showPlaybackWindow()
|
||||
playbackWindow = new FramePlaybackWindow(model->getListReference());
|
||||
else
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -69,6 +69,13 @@ GraphingWindow::GraphingWindow(const QVector<CANFrame> *frames, QWidget *parent)
|
||||
itemTracer->setStyle(QCPItemTracer::tsCircle);
|
||||
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(ui->graphingView, SIGNAL(selectionChangedByUser()), this, SLOT(selectionChanged()));
|
||||
//connect up the mouse controls
|
||||
@@ -329,6 +336,28 @@ void GraphingWindow::gotCenterTimeID(uint32_t ID, double timestamp)
|
||||
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)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
|
||||
@@ -84,6 +84,7 @@ private slots:
|
||||
void editSelectedGraph();
|
||||
void updatedFrames(int);
|
||||
void gotCenterTimeID(uint32_t ID, double timestamp);
|
||||
void gotPlaybackTimestamp(double timestamp);
|
||||
void resetView();
|
||||
void zoomIn();
|
||||
void zoomOut();
|
||||
@@ -105,6 +106,8 @@ private:
|
||||
QCPSelectionDecorator *selDecorator;
|
||||
QCPItemText *locationText;
|
||||
QCPItemTracer *itemTracer;
|
||||
QPen playbackPen;
|
||||
QCPItemStraightLine *playbackLine;
|
||||
bool needScaleSetup; //do we need to set x,y graphing extents?
|
||||
bool useOpenGL;
|
||||
bool followGraphEnd;
|
||||
|
||||
@@ -227,6 +227,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignHCenter">
|
||||
<widget class="QLabel" name="timePosition">
|
||||
<property name="text">
|
||||
<string>x of y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
Reference in New Issue
Block a user