Files
DRAMSys/extensions/apps/traceAnalyzer/presentation/tracescroller.cpp
2023-08-29 09:26:25 +02:00

350 lines
12 KiB
C++

/*
* Copyright (c) 2015, RPTU Kaiserslautern-Landau
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Janik Schlemminger
* Robert Gernhardt
* Matthias Jung
* Derek Christ
*/
#include "tracescroller.h"
#include "traceplotitem.h"
#include "util/engineeringScaleDraw.h"
#include <QItemSelectionModel>
#include <QMouseEvent>
#include <QWheelEvent>
#include <qwt_plot_zoneitem.h>
TraceScroller::TraceScroller(QWidget* parent) :
QwtPlot(parent),
isInitialized(false),
drawingProperties(false,
false,
{DependencyOption::Disabled, DependencyTextOption::Disabled},
ColorGrouping::PhaseType)
{
setAxisScaleDraw(xBottom, new EngineeringScaleDraw);
canvas()->setCursor(Qt::ArrowCursor);
canvasClip = new QwtPlotZoneItem();
canvasClip->setZ(2);
canvasClip->attach(this);
}
void TraceScroller::init(TraceNavigator* navigator,
TracePlot* tracePlot,
TracePlotLineDataSource* tracePlotLineDataSource)
{
Q_ASSERT(isInitialized == false);
isInitialized = true;
this->tracePlotLineDataSource = tracePlotLineDataSource;
this->navigator = navigator;
connectNavigatorQ_SIGNALS();
const CommentModel* commentModel = navigator->getCommentModel();
QObject::connect(
commentModel, &CommentModel::dataChanged, this, &TraceScroller::commentsChanged);
QObject::connect(
commentModel, &CommentModel::rowsRemoved, this, &TraceScroller::commentsChanged);
QObject::connect(commentModel->selectionModel(),
&QItemSelectionModel::selectionChanged,
this,
&TraceScroller::commentsChanged);
QObject::connect(tracePlotLineDataSource,
&TracePlotLineDataSource::modelChanged,
this,
&TraceScroller::updateAxis);
setUpDrawingProperties();
setUpAxis();
setUpTracePlotItem();
updateAxis();
getAndDrawComments();
this->tracePlot = tracePlot;
QObject::connect(tracePlot, SIGNAL(tracePlotZoomChanged()), this, SLOT(tracePlotZoomChanged()));
tracePlotZoomChanged();
QObject::connect(tracePlot,
SIGNAL(colorGroupingChanged(ColorGrouping)),
this,
SLOT(colorGroupingChanged(ColorGrouping)));
QObject::connect(tracePlot, SIGNAL(tracePlotLinesChanged()), this, SLOT(updateAxis()));
}
void TraceScroller::setUpTracePlotItem()
{
TracePlotItem* tracePlotItem = new TracePlotItem(transactions, *navigator, drawingProperties);
tracePlotItem->setZ(1);
tracePlotItem->attach(this);
}
void TraceScroller::setUpDrawingProperties()
{
drawingProperties.init(tracePlotLineDataSource);
drawingProperties.textColor = palette().text().color();
drawingProperties.numberOfRanks = navigator->GeneralTraceInfo().numberOfRanks;
drawingProperties.numberOfBankGroups = navigator->GeneralTraceInfo().numberOfBankGroups;
drawingProperties.numberOfBanks = navigator->GeneralTraceInfo().numberOfBanks;
drawingProperties.banksPerRank =
drawingProperties.numberOfBanks / drawingProperties.numberOfRanks;
drawingProperties.groupsPerRank =
drawingProperties.numberOfBankGroups / drawingProperties.numberOfRanks;
drawingProperties.banksPerGroup =
drawingProperties.numberOfBanks / drawingProperties.numberOfBankGroups;
drawingProperties.per2BankOffset = navigator->GeneralTraceInfo().per2BankOffset;
}
void TraceScroller::setUpAxis()
{
axisScaleDraw(yLeft)->enableComponent(QwtAbstractScaleDraw::Labels, false);
axisScaleDraw(yLeft)->enableComponent(QwtAbstractScaleDraw::Ticks, false);
}
void TraceScroller::updateAxis()
{
setAxisScale(yLeft, -1, drawingProperties.getNumberOfDisplayedLines(), 1.0);
replot();
}
void TraceScroller::connectNavigatorQ_SIGNALS()
{
QObject::connect(
navigator, SIGNAL(currentTraceTimeChanged()), this, SLOT(currentTraceTimeChanged()));
QObject::connect(navigator,
SIGNAL(selectedTransactionsChanged()),
this,
SLOT(selectedTransactionsChanged()));
}
Timespan TraceScroller::GetCurrentTimespan()
{
traceTime deltaOnTracePlot = navigator->GeneralTraceInfo().span.End() - tracePlot->ZoomLevel();
traceTime deltaOnTraceScroller = navigator->GeneralTraceInfo().span.End() - zoomLevel;
traceTime newBegin = static_cast<traceTime>(tracePlot->GetCurrentTimespan().Begin() *
(1.0 * deltaOnTraceScroller) / deltaOnTracePlot);
Timespan span(newBegin, newBegin + zoomLevel);
if (span.Begin() < 0)
span.shift(-span.Begin());
else if (span.End() > navigator->GeneralTraceInfo().span.End())
span.shift(navigator->GeneralTraceInfo().span.End() - span.End());
return span;
}
void TraceScroller::getAndDrawComments()
{
const CommentModel* commentModel = navigator->getCommentModel();
QList<QModelIndex> selectedRows = commentModel->selectionModel()->selectedRows();
for (int row = 0; row < commentModel->rowCount(); row++)
{
QModelIndex timeIndex =
commentModel->index(row, static_cast<int>(CommentModel::Column::Time));
bool selected =
std::find(selectedRows.begin(), selectedRows.end(), commentModel->index(row, 0)) !=
selectedRows.end();
QwtPlotMarker* maker = new QwtPlotMarker();
maker->setXValue(static_cast<double>(timeIndex.data(Qt::UserRole).toLongLong()));
maker->setLineStyle(QwtPlotMarker::LineStyle::VLine);
maker->setLinePen(QColor(selected ? Qt::red : Qt::blue), 2);
maker->attach(this);
}
}
/* Q_SLOTS
*
*
*/
void TraceScroller::selectedTransactionsChanged()
{
replot();
}
void TraceScroller::colorGroupingChanged(ColorGrouping colorGrouping)
{
drawingProperties.colorGrouping = colorGrouping;
replot();
}
void TraceScroller::currentTraceTimeChanged()
{
bool drawDependencies =
drawingProperties.drawDependenciesOption.draw != DependencyOption::Disabled;
Timespan spanOnTracePlot = tracePlot->GetCurrentTimespan();
canvasClip->setInterval(spanOnTracePlot.Begin(), spanOnTracePlot.End());
Timespan span = GetCurrentTimespan();
transactions = navigator->TraceFile().getTransactionsInTimespan(span, drawDependencies);
if (drawDependencies)
{
navigator->TraceFile().updateDependenciesInTimespan(span);
}
setAxisScale(xBottom, span.Begin(), span.End());
replot();
}
void TraceScroller::commentsChanged()
{
detachItems(QwtPlotItem::Rtti_PlotMarker);
getAndDrawComments();
replot();
}
void TraceScroller::tracePlotZoomChanged()
{
zoomLevel = tracePlot->ZoomLevel() * tracePlotEnlargementFactor;
if (zoomLevel > navigator->GeneralTraceInfo().span.timeCovered())
zoomLevel = navigator->GeneralTraceInfo().span.timeCovered();
}
bool TraceScroller::eventFilter(QObject* object, QEvent* event)
{
if (object == canvas())
{
static bool clipDragged = false;
static bool leftMousePressed = false;
static int mouseDownX = 0;
static traceTime mouseDownTracePlotTime = 0;
switch (event->type())
{
case QEvent::Wheel:
{
QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
traceTime offset;
int speed = 4;
(wheelEvent->angleDelta().y() > 0) ? offset = -zoomLevel* speed
: offset = zoomLevel * speed;
navigator->navigateToTime(navigator->CurrentTraceTime() + offset);
return true;
}
case QEvent::MouseButtonDblClick:
{
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
traceTime time = invTransform(xBottom, mouseEvent->x());
navigator->navigateToTime(time);
return true;
}
case QEvent::MouseButtonPress:
{
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::LeftButton)
{
canvas()->setCursor(Qt::ClosedHandCursor);
leftMousePressed = true;
mouseDownTracePlotTime = tracePlot->GetCurrentTimespan().Middle();
mouseDownX = mouseEvent->x();
if (tracePlot->GetCurrentTimespan().contains(
invTransform(xBottom, mouseEvent->x())))
clipDragged = true;
else
clipDragged = false;
return true;
}
else if (mouseEvent->button() == Qt::RightButton)
{
navigator->navigateToTime(
static_cast<traceTime>(invTransform(xBottom, mouseEvent->x())));
return true;
}
}
case QEvent::MouseButtonRelease:
{
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() == Qt::LeftButton)
{
clipDragged = false;
leftMousePressed = false;
canvas()->setCursor(Qt::ArrowCursor);
return true;
}
}
case QEvent::MouseMove:
{
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
if (leftMousePressed)
{
if (clipDragged)
{
double clipWidth =
transform(xBottom, tracePlot->ZoomLevel()) - transform(xBottom, 0);
if (mouseEvent->x() < clipWidth / 2)
{
navigator->navigateToTime(0);
}
else if (mouseEvent->x() > canvas()->width() - clipWidth / 2)
{
navigator->navigateToTime(navigator->GeneralTraceInfo().span.End());
}
else
{
traceTime time = static_cast<traceTime>(
(mouseEvent->x() - clipWidth / 2) / (canvas()->width() - clipWidth) *
(navigator->GeneralTraceInfo().span.End() - tracePlot->ZoomLevel()));
navigator->navigateToTime(time);
}
}
else
{
traceTime deltaTime =
invTransform(xBottom, mouseDownX) - invTransform(xBottom, mouseEvent->x());
navigator->navigateToTime(mouseDownTracePlotTime + deltaTime);
}
return true;
}
}
default:
break;
}
}
return false;
}