All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Yordan Karadzhov (VMware)" <y.karadz@gmail.com>
To: rostedt@goodmis.org
Cc: linux-trace-devel@vger.kernel.org,
	"Yordan Karadzhov (VMware)" <y.karadz@gmail.com>
Subject: [PATCH v2 17/27] kernel-shark: Update KsTraceGraph and KsQuickContextMenu
Date: Thu, 11 Feb 2021 12:31:55 +0200	[thread overview]
Message-ID: <20210211103205.418588-18-y.karadz@gmail.com> (raw)
In-Reply-To: <20210211103205.418588-1-y.karadz@gmail.com>

The compilation of KsTraceGraph.cpp and KsQuickContextMenu.cpp is
re-enabled and all functionalities are made compatible with the new
version of the C API of libkshark (KernelShark 2.0). The two source
files are updated in a single patch because of their interdependence.

Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com>
---
 src/CMakeLists.txt         |  12 +-
 src/KsQuickContextMenu.cpp | 151 +++++++++----
 src/KsQuickContextMenu.hpp |  26 ++-
 src/KsTraceGraph.cpp       | 426 ++++++++++++++++++-------------------
 src/KsTraceGraph.hpp       |  43 ++--
 5 files changed, 351 insertions(+), 307 deletions(-)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3dc7213..ab74d5a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -71,12 +71,12 @@ if (Qt5Widgets_FOUND AND Qt5Network_FOUND AND TT_FONT_FILE)
                         KsGLWidget.hpp
                         KsSearchFSM.hpp
                         KsDualMarker.hpp
-                        KsWidgetsLib.hpp)
-#                         KsTraceGraph.hpp
+                        KsWidgetsLib.hpp
+                        KsTraceGraph.hpp
 #                         KsTraceViewer.hpp
 #                         KsMainWindow.hpp
 #                         KsCaptureDialog.hpp
-#                         KsQuickContextMenu.hpp
+                        KsQuickContextMenu.hpp)
 #                         KsAdvFilteringDialog.hpp)
 
     QT5_WRAP_CPP(ks-guiLib_hdr_moc ${ks-guiLib_hdr})
@@ -87,12 +87,12 @@ if (Qt5Widgets_FOUND AND Qt5Network_FOUND AND TT_FONT_FILE)
                                                             KsGLWidget.cpp
                                                             KsSearchFSM.cpp
                                                             KsDualMarker.cpp
-                                                            KsWidgetsLib.cpp)
-#                                                             KsTraceGraph.cpp
+                                                            KsWidgetsLib.cpp
+                                                            KsTraceGraph.cpp
 #                                                             KsTraceViewer.cpp
 #                                                             KsMainWindow.cpp
 #                                                             KsCaptureDialog.cpp
-#                                                             KsQuickContextMenu.cpp
+                                                            KsQuickContextMenu.cpp)
 #                                                             KsAdvFilteringDialog.cpp)
 
     target_link_libraries(kshark-gui kshark-plot
diff --git a/src/KsQuickContextMenu.cpp b/src/KsQuickContextMenu.cpp
index a84444e..6fa242d 100644
--- a/src/KsQuickContextMenu.cpp
+++ b/src/KsQuickContextMenu.cpp
@@ -39,17 +39,19 @@ KsQuickMarkerMenu::KsQuickMarkerMenu(KsDualMarkerSM *dm, QWidget *parent)
 /**
  * @brief Create KsQuickContextMenu.
  *
+ * @param dm: The State machine of the Dual marker.
  * @param data: Input location for the KsDataStore object.
  * @param row: The index of the entry used to initialize the menu.
- * @param dm: The State machine of the Dual marker.
  * @param parent: The parent of this widget.
  */
-KsQuickContextMenu::KsQuickContextMenu(KsDataStore *data, size_t row,
-				       KsDualMarkerSM *dm,
+KsQuickContextMenu::KsQuickContextMenu(KsDualMarkerSM *dm,
+				       KsDataStore *data, size_t row,
 				       QWidget *parent)
 : KsQuickMarkerMenu(dm, parent),
   _data(data),
   _row(row),
+  _rawTime(this),
+  _rawEvent(this),
   _graphSyncCBox(nullptr),
   _listSyncCBox(nullptr),
   _hideTaskAction(this),
@@ -65,16 +67,50 @@ KsQuickContextMenu::KsQuickContextMenu(KsDataStore *data, size_t row,
   _clearAllFilters(this)
 {
 	typedef void (KsQuickContextMenu::*mfp)();
-	QString taskName, parentName, descr;
+	QString time, taskName, parentName, descr;
+	kshark_entry *entry = _data->rows()[_row];
+	kshark_context *kshark_ctx(nullptr);
+	kshark_data_stream *stream;
+	QStringList eventFields;
+	int pid, cpu, sd, ret;
 	KsTraceGraph *graphs;
-	int pid, cpu;
+	int64_t fieldVal;
 
 	if (!parent || !_data)
 		return;
 
-	taskName = kshark_get_task_easy(_data->rows()[_row]);
-	pid = kshark_get_pid_easy(_data->rows()[_row]);
-	cpu = _data->rows()[_row]->cpu;
+	if (!kshark_instance(&kshark_ctx))
+		return;
+
+	taskName = kshark_get_task(entry);
+	pid = kshark_get_pid(entry);
+	cpu = entry->cpu;
+	sd = entry->stream_id;
+
+	stream = kshark_get_data_stream(kshark_ctx, sd);
+	if (!stream)
+		return;
+
+	QString evtData("\t"), val;
+	eventFields =  KsUtils::getEventFieldsList(entry->stream_id,
+						   entry->event_id);
+
+	for (auto const &field: eventFields) {
+		std::string buff = field.toStdString();
+		ret = kshark_read_event_field_int(entry, buff.c_str(), &fieldVal);
+		if (ret < 0)
+			continue;
+
+		evtData += field + ":  " + val.setNum(fieldVal) + "\n\t";
+	}
+
+	addSection("Raw event");
+	time = QString("\ttime:  %1 [ns]").arg(entry->ts);
+
+	_rawTime.setDefaultWidget(new QLabel(time));
+	addAction(&_rawTime);
+	_rawEvent.setDefaultWidget(new QLabel(evtData));
+	addAction(&_rawEvent);
 
 	auto lamAddAction = [this, &descr] (QAction *action, mfp mf) {
 		action->setText(descr);
@@ -104,12 +140,12 @@ KsQuickContextMenu::KsQuickContextMenu(KsDataStore *data, size_t row,
 	lamAddAction(&_hideTaskAction, &KsQuickContextMenu::_hideTask);
 
 	descr = "Show event [";
-	descr += kshark_get_event_name_easy(_data->rows()[_row]);
+	descr += kshark_get_event_name(entry);
 	descr += "] only";
 	lamAddAction(&_showEventAction, &KsQuickContextMenu::_showEvent);
 
 	descr = "Hide event [";
-	descr += kshark_get_event_name_easy(_data->rows()[_row]);
+	descr += kshark_get_event_name(entry);
 	descr += "]";
 	lamAddAction(&_hideEventAction, &KsQuickContextMenu::_hideEvent);
 
@@ -118,7 +154,7 @@ KsQuickContextMenu::KsQuickContextMenu(KsDataStore *data, size_t row,
 		lamAddAction(&_showCPUAction, &KsQuickContextMenu::_showCPU);
 	}
 
-	descr = QString("Hide CPU [%1]").arg(_data->rows()[_row]->cpu);
+	descr = QString("Hide CPU [%1]").arg(entry->cpu);
 	lamAddAction(&_hideCPUAction, &KsQuickContextMenu::_hideCPU);
 
 	descr = "Clear all filters";
@@ -138,7 +174,7 @@ KsQuickContextMenu::KsQuickContextMenu(KsDataStore *data, size_t row,
 
 	if (parentName == "KsTraceGraph" &&
 	    (graphs = dynamic_cast<KsTraceGraph *>(parent))) {
-		if (graphs->glPtr()->_taskList.contains(pid)) {
+		if (graphs->glPtr()->_streamPlots[sd]._taskList.contains(pid)) {
 			descr = "Remove [";
 			descr += taskName;
 			descr += "-";
@@ -156,7 +192,7 @@ KsQuickContextMenu::KsQuickContextMenu(KsDataStore *data, size_t row,
 				     &KsQuickContextMenu::_addTaskPlot);
 		}
 
-		if (graphs->glPtr()->_cpuList.contains(cpu)) {
+		if (graphs->glPtr()->_streamPlots[sd]._cpuList.contains(cpu)) {
 			descr = "Remove [CPU ";
 			descr += QString("%1").arg(cpu);
 			descr += "] plot";
@@ -174,66 +210,86 @@ KsQuickContextMenu::KsQuickContextMenu(KsDataStore *data, size_t row,
 
 void KsQuickContextMenu::_hideTask()
 {
-	int pid = kshark_get_pid_easy(_data->rows()[_row]);
+	int pid = kshark_get_pid(_data->rows()[_row]);
+	int sd = _data->rows()[_row]->stream_id;
 	kshark_context *kshark_ctx(nullptr);
+	kshark_data_stream *stream;
 	QVector<int> vec;
 
 	if (!kshark_instance(&kshark_ctx))
 		return;
 
-	vec =_getFilterVector(kshark_ctx->hide_task_filter, pid);
-	_data->applyNegTaskFilter(vec);
+	stream = kshark_get_data_stream(kshark_ctx, sd);
+	if (!stream)
+		return;
+
+	vec =_getFilterVector(stream->hide_task_filter, pid);
+	_data->applyNegTaskFilter(sd, vec);
 }
 
 void KsQuickContextMenu::_showTask()
 {
-	int pid = kshark_get_pid_easy(_data->rows()[_row]);
-
-	_data->applyPosTaskFilter(QVector<int>(1, pid));
+	int pid = kshark_get_pid(_data->rows()[_row]);
+	int sd = _data->rows()[_row]->stream_id;
+	_data->applyPosTaskFilter(sd, QVector<int>(1, pid));
 }
 
 void KsQuickContextMenu::_hideEvent()
 {
-	int eventId = kshark_get_event_id_easy(_data->rows()[_row]);
+	int eventId = kshark_get_event_id(_data->rows()[_row]);
+	int sd = _data->rows()[_row]->stream_id;
 	kshark_context *kshark_ctx(nullptr);
+	kshark_data_stream *stream;
 	QVector<int> vec;
 
 	if (!kshark_instance(&kshark_ctx))
 		return;
 
-	vec =_getFilterVector(kshark_ctx->hide_event_filter, eventId);
-	_data->applyNegEventFilter(vec);
+	stream = kshark_get_data_stream(kshark_ctx, sd);
+	if (!stream)
+		return;
+
+	vec =_getFilterVector(stream->hide_event_filter, eventId);
+	_data->applyNegEventFilter(sd, vec);
 }
 
 void KsQuickContextMenu::_showEvent()
 {
-	int eventId = kshark_get_event_id_easy(_data->rows()[_row]);
+	int eventId = kshark_get_event_id(_data->rows()[_row]);
+	int sd = _data->rows()[_row]->stream_id;
 
-	_data->applyPosEventFilter(QVector<int>(1, eventId));
+	_data->applyPosEventFilter(sd, QVector<int>(1, eventId));
 }
 
 void KsQuickContextMenu::_showCPU()
 {
 	int cpu = _data->rows()[_row]->cpu;
+	int sd = _data->rows()[_row]->stream_id;
 
-	_data->applyPosCPUFilter(QVector<int>(1, cpu));
+	_data->applyPosCPUFilter(sd, QVector<int>(1, cpu));
 }
 
 void KsQuickContextMenu::_hideCPU()
 {
+	int sd = _data->rows()[_row]->stream_id;
 	kshark_context *kshark_ctx(nullptr);
+	kshark_data_stream *stream;
 	QVector<int> vec;
 
 	if (!kshark_instance(&kshark_ctx))
 		return;
 
-	vec =_getFilterVector(kshark_ctx->hide_cpu_filter,
+	stream = kshark_get_data_stream(kshark_ctx, sd);
+	if (!stream)
+		return;
+
+	vec =_getFilterVector(stream->hide_cpu_filter,
 			      _data->rows()[_row]->cpu);
 
-	_data->applyNegCPUFilter(vec);
+	_data->applyNegCPUFilter(sd, vec);
 }
 
-QVector<int> KsQuickContextMenu::_getFilterVector(tracecmd_filter_id *filter, int newId)
+QVector<int> KsQuickContextMenu::_getFilterVector(kshark_hash_id *filter, int newId)
 {
 	QVector<int> vec = KsUtils::getFilterIds(filter);
 	if (!vec.contains(newId))
@@ -244,38 +300,42 @@ QVector<int> KsQuickContextMenu::_getFilterVector(tracecmd_filter_id *filter, in
 
 void KsQuickContextMenu::_addTaskPlot()
 {
-	int pid = kshark_get_pid_easy(_data->rows()[_row]);
+	int pid = kshark_get_pid(_data->rows()[_row]);
+	int sd = _data->rows()[_row]->stream_id;
 
-	emit addTaskPlot(pid);
+	emit addTaskPlot(sd, pid);
 }
 
 void KsQuickContextMenu::_addCPUPlot()
 {
-	emit addCPUPlot(_data->rows()[_row]->cpu);
+	emit addCPUPlot(_data->rows()[_row]->stream_id, _data->rows()[_row]->cpu);
 }
 
 void KsQuickContextMenu::_removeTaskPlot()
 {
-	int pid = kshark_get_pid_easy(_data->rows()[_row]);
+	int pid = kshark_get_pid(_data->rows()[_row]);
+	int sd = _data->rows()[_row]->stream_id;
 
-	emit removeTaskPlot(pid);
+	emit removeTaskPlot(sd, pid);
 }
 
 void KsQuickContextMenu::_removeCPUPlot()
 {
-	emit removeCPUPlot(_data->rows()[_row]->cpu);
+	emit removeCPUPlot(_data->rows()[_row]->stream_id, _data->rows()[_row]->cpu);
 }
 
 /**
  * @brief Create KsRmPlotContextMenu.
  *
  * @param dm: The State machine of the Dual marker.
+ * @param sd: Data stream identifier.
  * @param parent: The parent of this widget.
  */
-KsRmPlotContextMenu::KsRmPlotContextMenu(KsDualMarkerSM *dm,
+KsRmPlotContextMenu::KsRmPlotContextMenu(KsDualMarkerSM *dm, int sd,
 					 QWidget *parent)
 : KsQuickMarkerMenu(dm, parent),
-  _removePlotAction(this)
+  _removePlotAction(this),
+  _sd(sd)
 {
 	addSection("Plots");
 
@@ -289,12 +349,13 @@ KsRmPlotContextMenu::KsRmPlotContextMenu(KsDualMarkerSM *dm,
  * @brief Create KsRmCPUPlotMenu.
  *
  * @param dm: The State machine of the Dual marker.
+ * @param sd: Data stream identifier.
  * @param cpu : CPU Id.
  * @param parent: The parent of this widget.
  */
-KsRmCPUPlotMenu::KsRmCPUPlotMenu(KsDualMarkerSM *dm, int cpu,
+KsRmCPUPlotMenu::KsRmCPUPlotMenu(KsDualMarkerSM *dm, int sd, int cpu,
 				 QWidget *parent)
-: KsRmPlotContextMenu(dm, parent)
+: KsRmPlotContextMenu(dm, sd, parent)
 {
 	_removePlotAction.setText(QString("Remove [CPU %1]").arg(cpu));
 }
@@ -303,20 +364,18 @@ KsRmCPUPlotMenu::KsRmCPUPlotMenu(KsDualMarkerSM *dm, int cpu,
  * @brief Create KsRmTaskPlotMenu.
  *
  * @param dm: The State machine of the Dual marker.
+ * @param sd: Data stream identifier.
  * @param pid: Process Id.
  * @param parent: The parent of this widget.
  */
-KsRmTaskPlotMenu::KsRmTaskPlotMenu(KsDualMarkerSM *dm, int pid,
+KsRmTaskPlotMenu::KsRmTaskPlotMenu(KsDualMarkerSM *dm, int sd, int pid,
 				   QWidget *parent)
-: KsRmPlotContextMenu(dm, parent)
+: KsRmPlotContextMenu(dm, sd, parent)
 {
-	kshark_context *kshark_ctx(nullptr);
-	QString descr("Remove [ ");
-
-	if (!kshark_instance(&kshark_ctx))
-		return;
+	QString descr;
 
-	descr += tep_data_comm_from_pid(kshark_ctx->pevent, pid);
+	descr = "Remove [ ";
+	descr += kshark_comm_from_pid(sd, pid);
 	descr += "-";
 	descr += QString("%1").arg(pid);
 	descr += "] plot";
diff --git a/src/KsQuickContextMenu.hpp b/src/KsQuickContextMenu.hpp
index df8a65b..ca0b341 100644
--- a/src/KsQuickContextMenu.hpp
+++ b/src/KsQuickContextMenu.hpp
@@ -45,22 +45,22 @@ class KsQuickContextMenu : public KsQuickMarkerMenu {
 public:
 	KsQuickContextMenu() = delete;
 
-	KsQuickContextMenu(KsDataStore *data, size_t row,
-			   KsDualMarkerSM *dm,
+	KsQuickContextMenu(KsDualMarkerSM *dm,
+			   KsDataStore *data, size_t row,
 			   QWidget *parent = nullptr);
 
 signals:
 	/** Signal to add a task plot. */
-	void addTaskPlot(int);
+	void addTaskPlot(int sd, int pid);
 
 	/** Signal to add a CPU plot. */
-	void addCPUPlot(int);
+	void addCPUPlot(int sd, int cpu);
 
 	/** Signal to remove a task plot. */
-	void removeTaskPlot(int);
+	void removeTaskPlot(int sd, int pid);
 
 	/** Signal to remove a CPU plot. */
-	void removeCPUPlot(int);
+	void removeCPUPlot(int sd, int cpu);
 
 private:
 	void _hideTask();
@@ -83,7 +83,7 @@ private:
 
 	void _removeTaskPlot();
 
-	QVector<int> _getFilterVector(tracecmd_filter_id *filter, int newId);
+	QVector<int> _getFilterVector(kshark_hash_id *filter, int newId);
 
 	void _clearFilters() {_data->clearAllFilters();}
 
@@ -91,6 +91,8 @@ private:
 
 	size_t		_row;
 
+	QWidgetAction	_rawTime, _rawEvent;
+
 	QCheckBox	*_graphSyncCBox, *_listSyncCBox;
 
 	QAction _hideTaskAction, _showTaskAction;
@@ -118,7 +120,8 @@ class KsRmPlotContextMenu : public KsQuickMarkerMenu {
 public:
 	KsRmPlotContextMenu() = delete;
 
-	KsRmPlotContextMenu(KsDualMarkerSM *dm, QWidget *parent = nullptr);
+	KsRmPlotContextMenu(KsDualMarkerSM *dm, int sd,
+			    QWidget *parent = nullptr);
 
 signals:
 	/** Signal to remove a plot. */
@@ -127,13 +130,16 @@ signals:
 protected:
 	/** Menu action. */
 	QAction _removePlotAction;
+
+	/** Data stream identifier. */
+	int _sd;
 };
 
 /**
  * The KsQuickMarkerMenu class provides CPU Plot remove menus.
  */
 struct KsRmCPUPlotMenu : public KsRmPlotContextMenu {
-	KsRmCPUPlotMenu(KsDualMarkerSM *dm, int cpu,
+	KsRmCPUPlotMenu(KsDualMarkerSM *dm, int sd, int cpu,
 			QWidget *parent = nullptr);
 };
 
@@ -141,7 +147,7 @@ struct KsRmCPUPlotMenu : public KsRmPlotContextMenu {
  * The KsQuickMarkerMenu class provides Task Plot remove menus.
  */
 struct KsRmTaskPlotMenu : public KsRmPlotContextMenu {
-	KsRmTaskPlotMenu(KsDualMarkerSM *dm, int pid,
+	KsRmTaskPlotMenu(KsDualMarkerSM *dm, int sd, int pid,
 			 QWidget *parent = nullptr);
 };
 
diff --git a/src/KsTraceGraph.cpp b/src/KsTraceGraph.cpp
index 7b656c0..fd9cfac 100644
--- a/src/KsTraceGraph.cpp
+++ b/src/KsTraceGraph.cpp
@@ -17,7 +17,7 @@
 
 /** Create a default (empty) Trace graph widget. */
 KsTraceGraph::KsTraceGraph(QWidget *parent)
-: QWidget(parent),
+: KsWidgetsLib::KsDataWidget(parent),
   _pointerBar(this),
   _navigationBar(this),
   _zoomInButton("+", this),
@@ -34,13 +34,7 @@ KsTraceGraph::KsTraceGraph(QWidget *parent)
   _labelI4("", this),
   _labelI5("", this),
   _scrollArea(this),
-  _drawWindow(&_scrollArea),
-  _legendWindow(&_drawWindow),
-  _legendAxisX(&_drawWindow),
-  _labelXMin("", &_legendAxisX),
-  _labelXMid("", &_legendAxisX),
-  _labelXMax("", &_legendAxisX),
-  _glWindow(&_drawWindow),
+  _glWindow(&_scrollArea),
   _mState(nullptr),
   _data(nullptr),
   _keyPressed(false)
@@ -62,7 +56,7 @@ KsTraceGraph::KsTraceGraph(QWidget *parent)
 
 	_pointerBar.addWidget(&_labelP1);
 	_labelP2.setFrameStyle(QFrame::Panel | QFrame::Sunken);
-	_labelP2.setStyleSheet("QLabel { background-color : white; color: black}");
+	_labelP2.setStyleSheet("QLabel {background-color : white; color: black}");
 	_labelP2.setTextInteractionFlags(Qt::TextSelectableByMouse);
 	_labelP2.setFixedWidth(FONT_WIDTH * 16);
 	_pointerBar.addWidget(&_labelP2);
@@ -84,31 +78,7 @@ KsTraceGraph::KsTraceGraph(QWidget *parent)
 	_pointerBar.addSeparator();
 	_pointerBar.addWidget(&_labelI5);
 
-	_legendAxisX.setFixedHeight(FONT_HEIGHT * 1.5);
-	_legendAxisX.setLayout(new QHBoxLayout);
-	_legendAxisX.layout()->setSpacing(0);
-	_legendAxisX.layout()->setContentsMargins(0, 0, FONT_WIDTH, 0);
-
-	_labelXMin.setAlignment(Qt::AlignLeft);
-	_labelXMid.setAlignment(Qt::AlignHCenter);
-	_labelXMax.setAlignment(Qt::AlignRight);
-
-	_legendAxisX.layout()->addWidget(&_labelXMin);
-	_legendAxisX.layout()->addWidget(&_labelXMid);
-	_legendAxisX.layout()->addWidget(&_labelXMax);
-	_legendAxisX.setStyleSheet("QLabel { background-color : white; color: black}");
-
-	_drawWindow.setMinimumSize(100, 100);
-	_drawWindow.setStyleSheet("QWidget {background-color : white;}");
-
-	_drawLayout.setContentsMargins(0, 0, 0, 0);
-	_drawLayout.setSpacing(0);
-	_drawLayout.addWidget(&_legendAxisX, 0, 1);
-	_drawLayout.addWidget(&_legendWindow, 1, 0);
-	_drawLayout.addWidget(&_glWindow, 1, 1);
-	_drawWindow.setLayout(&_drawLayout);
-
-	_drawWindow.installEventFilter(this);
+	_glWindow.installEventFilter(this);
 
 	connect(&_glWindow,	&KsGLWidget::select,
 		this,		&KsTraceGraph::markEntry);
@@ -134,15 +104,12 @@ KsTraceGraph::KsTraceGraph(QWidget *parent)
 	connect(&_glWindow,	&KsGLWidget::stopUpdating,
 		this,		&KsTraceGraph::_stopUpdating);
 
-	connect(_glWindow.model(),	&KsGraphModel::modelReset,
-		this,			&KsTraceGraph::_updateTimeLegends);
-
 	_glWindow.setContextMenuPolicy(Qt::CustomContextMenu);
 	connect(&_glWindow,	&QWidget::customContextMenuRequested,
 		this,		&KsTraceGraph::_onCustomContextMenu);
 
 	_scrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-	_scrollArea.setWidget(&_drawWindow);
+	_scrollArea.setWidget(&_glWindow);
 
 	lamMakeNavButton(&_scrollLeftButton);
 	connect(&_scrollLeftButton,	&QPushButton::pressed,
@@ -187,7 +154,6 @@ void KsTraceGraph::loadData(KsDataStore *data)
 {
 	_data = data;
 	_glWindow.loadData(data);
-	_updateGraphLegends();
 	updateGeom();
 }
 
@@ -211,14 +177,10 @@ void KsTraceGraph::reset()
 		l1->setText("");
 
 	_selfUpdate();
-	for (auto l2: {&_labelXMin, &_labelXMid, &_labelXMax})
-		l2->setText("");
 }
 
 void KsTraceGraph::_selfUpdate()
 {
-	_updateGraphLegends();
-	_updateTimeLegends();
 	_markerReDraw();
 	_glWindow.model()->update();
 	updateGeom();
@@ -226,12 +188,20 @@ void KsTraceGraph::_selfUpdate()
 
 void KsTraceGraph::_zoomIn()
 {
-	_updateGraphs(GraphActions::ZoomIn);
+	KsWidgetsLib::KsDataWork action = KsWidgetsLib::KsDataWork::ZoomIn;
+
+	startOfWork(action);
+	_updateGraphs(action);
+	endOfWork(action);
 }
 
 void KsTraceGraph::_zoomOut()
 {
-	_updateGraphs(GraphActions::ZoomOut);
+	KsWidgetsLib::KsDataWork action = KsWidgetsLib::KsDataWork::ZoomOut;
+
+	startOfWork(action);
+	_updateGraphs(action);
+	endOfWork(action);
 }
 
 void KsTraceGraph::_quickZoomIn()
@@ -239,6 +209,8 @@ void KsTraceGraph::_quickZoomIn()
 	if (_glWindow.isEmpty())
 		return;
 
+	startOfWork(KsWidgetsLib::KsDataWork::QuickZoomIn);
+
 	/* Bin size will be 100 ns. */
 	_glWindow.model()->quickZoomIn(100);
 	if (_mState->activeMarker()._isSet &&
@@ -249,7 +221,10 @@ void KsTraceGraph::_quickZoomIn()
 		 */
 		uint64_t ts = _mState->activeMarker()._ts;
 		_glWindow.model()->jumpTo(ts);
+		_glWindow.render();
 	}
+
+	endOfWork(KsWidgetsLib::KsDataWork::QuickZoomIn);
 }
 
 void KsTraceGraph::_quickZoomOut()
@@ -257,17 +232,28 @@ void KsTraceGraph::_quickZoomOut()
 	if (_glWindow.isEmpty())
 		return;
 
+	startOfWork(KsWidgetsLib::KsDataWork::QuickZoomOut);
 	_glWindow.model()->quickZoomOut();
+	_glWindow.render();
+	endOfWork(KsWidgetsLib::KsDataWork::QuickZoomOut);
 }
 
 void KsTraceGraph::_scrollLeft()
 {
-	_updateGraphs(GraphActions::ScrollLeft);
+	KsWidgetsLib::KsDataWork action = KsWidgetsLib::KsDataWork::ScrollLeft;
+
+	startOfWork(action);
+	_updateGraphs(action);
+	endOfWork(action);
 }
 
 void KsTraceGraph::_scrollRight()
 {
-	_updateGraphs(GraphActions::ScrollRight);
+	KsWidgetsLib::KsDataWork action = KsWidgetsLib::KsDataWork::ScrollRight;
+
+	startOfWork(action);
+	_updateGraphs(action);
+	endOfWork(action);
 }
 
 void KsTraceGraph::_stopUpdating()
@@ -292,10 +278,18 @@ QString KsTraceGraph::_t2str(uint64_t sec, uint64_t usec) {
 	return QString::number(sec) + "." + usecStr;
 }
 
-void KsTraceGraph::_resetPointer(uint64_t ts, int cpu, int pid)
+void KsTraceGraph::_resetPointer(int64_t ts, int sd, int cpu, int pid)
 {
+	kshark_entry entry;
 	uint64_t sec, usec;
 
+	entry.cpu = cpu;
+	entry.pid = pid;
+	entry.stream_id = sd;
+
+	if (ts < 0)
+		ts = 0;
+
 	kshark_convert_nano(ts, &sec, &usec);
 	_labelP2.setText(_t2str(sec, usec));
 
@@ -305,7 +299,7 @@ void KsTraceGraph::_resetPointer(uint64_t ts, int cpu, int pid)
 		if (!kshark_instance(&kshark_ctx))
 			return;
 
-		QString comm(tep_data_comm_from_pid(kshark_ctx->pevent, pid));
+		QString comm(kshark_get_task(&entry));
 		comm.append("-");
 		comm.append(QString("%1").arg(pid));
 		_labelI1.setText(comm);
@@ -323,23 +317,30 @@ void KsTraceGraph::_resetPointer(uint64_t ts, int cpu, int pid)
 void KsTraceGraph::_setPointerInfo(size_t i)
 {
 	kshark_entry *e = _data->rows()[i];
-	QString event(kshark_get_event_name_easy(e));
-	QString lat(kshark_get_latency_easy(e));
-	QString info(kshark_get_info_easy(e));
-	QString comm(kshark_get_task_easy(e));
-	int labelWidth, width;
-	QString elidedText;
+	auto lanMakeString = [] (char *buffer) {
+		QString str(buffer);
+		free(buffer);
+		return str;
+	};
+
+	QString event(lanMakeString(kshark_get_event_name(e)));
+	QString aux(lanMakeString(kshark_get_aux_info(e)));
+	QString info(lanMakeString(kshark_get_info(e)));
+	QString comm(lanMakeString(kshark_get_task(e)));
+	QString pointer, elidedText;
+	int labelWidth;
 	uint64_t sec, usec;
 
 	kshark_convert_nano(e->ts, &sec, &usec);
-	_labelP2.setText(_t2str(sec, usec));
+	pointer.sprintf("%" PRIu64 ".%06" PRIu64 "", sec, usec);
+	_labelP2.setText(pointer);
 
 	comm.append("-");
-	comm.append(QString("%1").arg(kshark_get_pid_easy(e)));
+	comm.append(QString("%1").arg(kshark_get_pid(e)));
 
 	_labelI1.setText(comm);
 	_labelI2.setText(QString("CPU %1").arg(e->cpu));
-	_labelI3.setText(lat);
+	_labelI3.setText(aux);
 	_labelI4.setText(event);
 	_labelI5.setText(info);
 	QCoreApplication::processEvents();
@@ -353,16 +354,7 @@ void KsTraceGraph::_setPointerInfo(size_t i)
 	 * The Info string is too long and cannot be displayed on the toolbar.
 	 * Try to fit the text in the available space.
 	 */
-	QFontMetrics metrix(_labelI5.font());
-	width = labelWidth - FONT_WIDTH * 3;
-	elidedText = metrix.elidedText(info, Qt::ElideRight, width);
-
-	while(labelWidth < STRING_WIDTH(elidedText) + FONT_WIDTH * 5) {
-		width -= FONT_WIDTH * 3;
-		elidedText = metrix.elidedText(info, Qt::ElideRight, width);
-	}
-
-	_labelI5.setText(elidedText);
+	KsUtils::setElidedText(&_labelI5, info, Qt::ElideRight, labelWidth);
 	_labelI5.setVisible(true);
 	QCoreApplication::processEvents();
 }
@@ -374,127 +366,188 @@ void KsTraceGraph::_setPointerInfo(size_t i)
  */
 void KsTraceGraph::markEntry(size_t row)
 {
-	int graph, cpuGrId, taskGrId;
-
-	_glWindow.findGraphIds(*_data->rows()[row], &cpuGrId, &taskGrId);
-
-	/*
-	 * If a Task graph has been found, this Task graph will be
-	 * visible. If no Task graph has been found, make visible
-	 * the corresponding CPU graph.
-	 */
-	if (taskGrId >= 0)
-		graph = taskGrId;
-	else
-		graph = cpuGrId;
-
-	_scrollArea.ensureVisible(0,
-				  _legendAxisX.height() +
-				  _glWindow.vMargin() +
-				  KS_GRAPH_HEIGHT / 2 +
-				  graph*(KS_GRAPH_HEIGHT + _glWindow.vSpacing()),
-				  50,
-				  KS_GRAPH_HEIGHT / 2 + _glWindow.vSpacing() / 2);
+	int yPosVis(-1);
 
 	_glWindow.model()->jumpTo(_data->rows()[row]->ts);
-	_mState->activeMarker().set(*_data,
-				    _glWindow.model()->histo(),
-				    row, cpuGrId, taskGrId);
+	_mState->activeMarker().set(*_data, _glWindow.model()->histo(),
+				    row, _data->rows()[row]->stream_id);
 
 	_mState->updateMarkers(*_data, &_glWindow);
+
+	/*
+	 * If a Combo graph has been found, this Combo graph will be visible.
+	 * Else the Task graph will be shown. If no Combo and no Task graph
+	 * has been found, make visible the corresponding CPU graph.
+	 */
+	if (_mState->activeMarker()._mark.comboIsVisible())
+		yPosVis = _mState->activeMarker()._mark.comboY();
+	else if (_mState->activeMarker()._mark.taskIsVisible())
+		yPosVis = _mState->activeMarker()._mark.taskY();
+	else if (_mState->activeMarker()._mark.cpuIsVisible())
+		yPosVis = _mState->activeMarker()._mark.cpuY();
+
+	if (yPosVis > 0)
+		_scrollArea.ensureVisible(0, yPosVis);
 }
 
 void KsTraceGraph::_markerReDraw()
 {
-	int cpuGrId, taskGrId;
 	size_t row;
 
 	if (_mState->markerA()._isSet) {
 		row = _mState->markerA()._pos;
-		_glWindow.findGraphIds(*_data->rows()[row], &cpuGrId, &taskGrId);
-		_mState->markerA().set(*_data,
-				       _glWindow.model()->histo(),
-				       row, cpuGrId, taskGrId);
+		_mState->markerA().set(*_data, _glWindow.model()->histo(),
+				       row, _data->rows()[row]->stream_id);
 	}
 
 	if (_mState->markerB()._isSet) {
 		row = _mState->markerB()._pos;
-		_glWindow.findGraphIds(*_data->rows()[row], &cpuGrId, &taskGrId);
-		_mState->markerB().set(*_data,
-				       _glWindow.model()->histo(),
-				       row, cpuGrId, taskGrId);
+		_mState->markerB().set(*_data, _glWindow.model()->histo(),
+				       row, _data->rows()[row]->stream_id);
 	}
 }
 
 /**
  * @brief Redreaw all CPU graphs.
  *
+ * @param sd: Data stream identifier.
  * @param v: CPU ids to be plotted.
  */
-void KsTraceGraph::cpuReDraw(QVector<int> v)
+void KsTraceGraph::cpuReDraw(int sd, QVector<int> v)
 {
-	_glWindow._cpuList = v;
+	startOfWork(KsWidgetsLib::KsDataWork::EditPlotList);
+	if (_glWindow._streamPlots.contains(sd))
+		_glWindow._streamPlots[sd]._cpuList = v;
+
 	_selfUpdate();
+	endOfWork(KsWidgetsLib::KsDataWork::EditPlotList);
 }
 
 /**
  * @brief Redreaw all Task graphs.
  *
+ * @param sd: Data stream identifier.
  * @param v: Process ids of the tasks to be plotted.
  */
-void KsTraceGraph::taskReDraw(QVector<int> v)
+void KsTraceGraph::taskReDraw(int sd, QVector<int> v)
+{
+	startOfWork(KsWidgetsLib::KsDataWork::EditPlotList);
+	if (_glWindow._streamPlots.contains(sd))
+		_glWindow._streamPlots[sd]._taskList = v;
+
+	_selfUpdate();
+	endOfWork(KsWidgetsLib::KsDataWork::EditPlotList);
+}
+
+/**
+ * @brief Redreaw all virtCombo graphs.
+ *
+ * @param nCombos: Numver of Combo plots.
+ * @param v: Descriptor of the Combo to be plotted.
+ */
+void KsTraceGraph::comboReDraw(int nCombos, QVector<int> v)
 {
-	_glWindow._taskList = v;
+	KsComboPlot combo;
+
+	startOfWork(KsWidgetsLib::KsDataWork::EditPlotList);
+
+	_glWindow._comboPlots.clear();
+
+	for (int i = 0; i < nCombos; ++i) {
+		combo.resize(v.takeFirst());
+		for (auto &p: combo)
+			p << v;
+
+		_glWindow._comboPlots.append(combo);
+	}
+
 	_selfUpdate();
+	endOfWork(KsWidgetsLib::KsDataWork::EditPlotList);
 }
 
 /** Add (and plot) a CPU graph to the existing list of CPU graphs. */
-void KsTraceGraph::addCPUPlot(int cpu)
+void KsTraceGraph::addCPUPlot(int sd, int cpu)
 {
-	if (_glWindow._cpuList.contains(cpu))
+	startOfWork(KsWidgetsLib::KsDataWork::EditPlotList);
+	QVector<int> &list = _glWindow._streamPlots[sd]._cpuList;
+	if (list.contains(cpu))
 		return;
 
-	_glWindow._cpuList.append(cpu);
-	std::sort(_glWindow._cpuList.begin(), _glWindow._cpuList.end());
+	list.append(cpu);
+	std::sort(list.begin(), list.end());
+
 	_selfUpdate();
+	endOfWork(KsWidgetsLib::KsDataWork::EditPlotList);
 }
 
 /** Add (and plot) a Task graph to the existing list of Task graphs. */
-void KsTraceGraph::addTaskPlot(int pid)
+void KsTraceGraph::addTaskPlot(int sd, int pid)
 {
-	if (_glWindow._taskList.contains(pid))
+	startOfWork(KsWidgetsLib::KsDataWork::EditPlotList);
+	QVector<int> &list = _glWindow._streamPlots[sd]._taskList;
+	if (list.contains(pid))
 		return;
 
-	_glWindow._taskList.append(pid);
-	std::sort(_glWindow._taskList.begin(), _glWindow._taskList.end());
+	list.append(pid);
+	std::sort(list.begin(), list.end());
+
 	_selfUpdate();
+	endOfWork(KsWidgetsLib::KsDataWork::EditPlotList);
 }
 
 /** Remove a CPU graph from the existing list of CPU graphs. */
-void KsTraceGraph::removeCPUPlot(int cpu)
+void KsTraceGraph::removeCPUPlot(int sd, int cpu)
 {
-	if (!_glWindow._cpuList.contains(cpu))
+	startOfWork(KsWidgetsLib::KsDataWork::EditPlotList);
+	if (!_glWindow._streamPlots[sd]._cpuList.contains(cpu))
 		return;
 
-	_glWindow._cpuList.removeAll(cpu);
+	_glWindow._streamPlots[sd]._cpuList.removeAll(cpu);
 	_selfUpdate();
+	endOfWork(KsWidgetsLib::KsDataWork::EditPlotList);
 }
 
 /** Remove a Task graph from the existing list of Task graphs. */
-void KsTraceGraph::removeTaskPlot(int pid)
+void KsTraceGraph::removeTaskPlot(int sd, int pid)
 {
-	if (!_glWindow._taskList.contains(pid))
+	startOfWork(KsWidgetsLib::KsDataWork::EditPlotList);
+	if (!_glWindow._streamPlots[sd]._taskList.contains(pid))
 		return;
 
-	_glWindow._taskList.removeAll(pid);
+	_glWindow._streamPlots[sd]._taskList.removeAll(pid);
 	_selfUpdate();
+	endOfWork(KsWidgetsLib::KsDataWork::EditPlotList);
 }
 
 /** Update the content of all graphs. */
 void KsTraceGraph::update(KsDataStore *data)
 {
-	_glWindow.model()->update(data);
+	kshark_context *kshark_ctx(nullptr);
+	QVector<int> streamIds;
+
+	if (!kshark_instance(&kshark_ctx))
+		return;
+
+	streamIds = KsUtils::getStreamIdList(kshark_ctx);
+	for (auto const &sd: streamIds)
+		for (auto &pid: _glWindow._streamPlots[sd]._taskList) {
+			kshark_unregister_data_collection(&kshark_ctx->collections,
+							  kshark_match_pid,
+							  sd, &pid, 1);
+		}
+
 	_selfUpdate();
+
+	streamIds = KsUtils::getStreamIdList(kshark_ctx);
+	for (auto const &sd: streamIds)
+		for (auto &pid: _glWindow._streamPlots[sd]._taskList) {
+			kshark_register_data_collection(kshark_ctx,
+							data->rows(),
+							data->size(),
+							kshark_match_pid,
+							sd, &pid, 1,
+							25);
+		}
 }
 
 /** Update the geometry of the widget. */
@@ -519,19 +572,14 @@ void KsTraceGraph::updateGeom()
 	 * of the scroll bar.
 	 */
 	dwWidth = _scrollArea.width();
-	if (_glWindow.height() + _legendAxisX.height() > _scrollArea.height())
+	if (_glWindow.height() > _scrollArea.height())
 		dwWidth -=
 			qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
 
-	/*
-	 * Set the height of the Draw window according to the number of
-	 * plotted graphs.
-	 */
-	_drawWindow.resize(dwWidth,
-			   _glWindow.height() + _legendAxisX.height());
+	_glWindow.resize(dwWidth, _glWindow.height());
 
 	/* Set the minimum height of the Graph widget. */
-	hMin = _drawWindow.height() +
+	hMin = _glWindow.height() +
 	       _pointerBar.height() +
 	       _navigationBar.height() +
 	       _layout.contentsMargins().top() +
@@ -546,7 +594,7 @@ void KsTraceGraph::updateGeom()
 	 * Now use the height of the Draw Window to fix the maximum height
 	 * of the Graph widget.
 	 */
-	setMaximumHeight(_drawWindow.height() +
+	setMaximumHeight(_glWindow.height() +
 			 _pointerBar.height() +
 			 _navigationBar.height() +
 			 _layout.spacing() * 2 +
@@ -560,75 +608,6 @@ void KsTraceGraph::updateGeom()
 	_glWindow.update();
 }
 
-void KsTraceGraph::_updateGraphLegends()
-{
-	QString graphLegends, graphName;
-	QVBoxLayout *layout;
-	int width = 0;
-
-	if (_legendWindow.layout()) {
-		/*
-		 * Remove and delete the existing layout of the legend window.
-		 */
-		QLayoutItem *child;
-		while ((child = _legendWindow.layout()->takeAt(0)) != 0) {
-			delete child->widget();
-			delete child;
-		}
-
-		delete _legendWindow.layout();
-	}
-
-	layout = new QVBoxLayout;
-	layout->setContentsMargins(FONT_WIDTH, 0, 0, 0);
-	layout->setSpacing(_glWindow.vSpacing());
-	layout->setAlignment(Qt::AlignTop);
-	layout->addSpacing(_glWindow.vMargin());
-
-	auto lamMakeName = [&]() {
-		QLabel *name = new QLabel(graphName);
-
-		if (width < STRING_WIDTH(graphName))
-			width = STRING_WIDTH(graphName);
-
-		name->setAlignment(Qt::AlignBottom);
-		name->setStyleSheet("QLabel {background-color : white; color : black}");
-		name->setFixedHeight(KS_GRAPH_HEIGHT);
-		layout->addWidget(name);
-	};
-
-	for (auto const &cpu: _glWindow._cpuList) {
-		graphName = QString("CPU %1").arg(cpu);
-		lamMakeName();
-	}
-
-	for (auto const &pid: _glWindow._taskList) {
-		graphName = QString(tep_data_comm_from_pid(_data->tep(),
-							   pid));
-		graphName.append(QString("-%1").arg(pid));
-		lamMakeName();
-	}
-
-	_legendWindow.setLayout(layout);
-	_legendWindow.setMaximumWidth(width + FONT_WIDTH);
-}
-
-void KsTraceGraph::_updateTimeLegends()
-{
-	uint64_t sec, usec, tsMid;
-
-	kshark_convert_nano(_glWindow.model()->histo()->min, &sec, &usec);
-	_labelXMin.setText(_t2str(sec, usec));
-
-	tsMid = (_glWindow.model()->histo()->min +
-		 _glWindow.model()->histo()->max) / 2;
-	kshark_convert_nano(tsMid, &sec, &usec);
-	_labelXMid.setText(_t2str(sec, usec));
-
-	kshark_convert_nano(_glWindow.model()->histo()->max, &sec, &usec);
-	_labelXMax.setText(_t2str(sec, usec));
-}
-
 /**
  * Reimplemented event handler used to update the geometry of the widget on
  * resize events.
@@ -646,16 +625,25 @@ void KsTraceGraph::resizeEvent(QResizeEvent* event)
  */
 bool KsTraceGraph::eventFilter(QObject* obj, QEvent* evt)
 {
-	if (obj == &_drawWindow && evt->type() == QEvent::Enter)
+	/* Desable all mouse events for the OpenGL wiget when busy. */
+	if (obj == &_glWindow && this->isBusy() &&
+	    (evt->type() == QEvent::MouseButtonDblClick ||
+	     evt->type() == QEvent::MouseButtonPress ||
+	     evt->type() == QEvent::MouseButtonRelease ||
+	     evt->type() == QEvent::MouseMove)
+	)
+		return true;
+
+	if (obj == &_glWindow && evt->type() == QEvent::Enter)
 		_glWindow.setFocus();
 
-	if (obj == &_drawWindow && evt->type() == QEvent::Leave)
+	if (obj == &_glWindow && evt->type() == QEvent::Leave)
 		_glWindow.clearFocus();
 
 	return QWidget::eventFilter(obj, evt);
 }
 
-void KsTraceGraph::_updateGraphs(GraphActions action)
+void KsTraceGraph::_updateGraphs(KsWidgetsLib::KsDataWork action)
 {
 	double k;
 	int bin;
@@ -673,7 +661,7 @@ void KsTraceGraph::_updateGraphs(GraphActions action)
 	k = .01;
 	while (_keyPressed) {
 		switch (action) {
-		case GraphActions::ZoomIn:
+		case KsWidgetsLib::KsDataWork::ZoomIn:
 			if (_mState->activeMarker()._isSet &&
 			    _mState->activeMarker().isVisible()) {
 				/*
@@ -692,7 +680,7 @@ void KsTraceGraph::_updateGraphs(GraphActions action)
 
 			break;
 
-		case GraphActions::ZoomOut:
+		case KsWidgetsLib::KsDataWork::ZoomOut:
 			if (_mState->activeMarker()._isSet &&
 			    _mState->activeMarker().isVisible()) {
 				/*
@@ -711,13 +699,16 @@ void KsTraceGraph::_updateGraphs(GraphActions action)
 
 			break;
 
-		case GraphActions::ScrollLeft:
+		case KsWidgetsLib::KsDataWork::ScrollLeft:
 			_glWindow.model()->shiftBackward(10);
 			break;
 
-		case GraphActions::ScrollRight:
+		case KsWidgetsLib::KsDataWork::ScrollRight:
 			_glWindow.model()->shiftForward(10);
 			break;
+
+		default:
+			return;
 		}
 
 		/*
@@ -729,7 +720,7 @@ void KsTraceGraph::_updateGraphs(GraphActions action)
 			k  *= 1.02;
 
 		_mState->updateMarkers(*_data, &_glWindow);
-		_updateTimeLegends();
+		_glWindow.render();
 		QCoreApplication::processEvents();
 	}
 }
@@ -737,7 +728,7 @@ void KsTraceGraph::_updateGraphs(GraphActions action)
 void KsTraceGraph::_onCustomContextMenu(const QPoint &point)
 {
 	KsQuickMarkerMenu *menu(nullptr);
-	int cpu, pid;
+	int sd, cpu, pid;
 	size_t row;
 	bool found;
 
@@ -745,8 +736,8 @@ void KsTraceGraph::_onCustomContextMenu(const QPoint &point)
 	if (found) {
 		/* KernelShark entry has been found under the cursor. */
 		KsQuickContextMenu *entryMenu;
-		menu = entryMenu = new KsQuickContextMenu(_data, row,
-							  _mState, this);
+		menu = entryMenu = new KsQuickContextMenu(_mState, _data, row,
+							  this);
 
 		connect(entryMenu,	&KsQuickContextMenu::addTaskPlot,
 			this,		&KsTraceGraph::addTaskPlot);
@@ -760,34 +751,35 @@ void KsTraceGraph::_onCustomContextMenu(const QPoint &point)
 		connect(entryMenu,	&KsQuickContextMenu::removeCPUPlot,
 			this,		&KsTraceGraph::removeCPUPlot);
 	} else {
-		cpu = _glWindow.getPlotCPU(point);
+		if (!_glWindow.getPlotInfo(point, &sd, &cpu, &pid))
+			return;
+
 		if (cpu >= 0) {
 			/*
 			 * This is a CPU plot, but we do not have an entry
 			 * under the cursor.
 			 */
 			KsRmCPUPlotMenu *rmMenu;
-			menu = rmMenu = new KsRmCPUPlotMenu(_mState, cpu, this);
+			menu = rmMenu = new KsRmCPUPlotMenu(_mState, sd, cpu, this);
 
-			auto lamRmPlot = [&cpu, this] () {
-				removeCPUPlot(cpu);
+			auto lamRmPlot = [&sd, &cpu, this] () {
+				removeCPUPlot(sd, cpu);
 			};
 
 			connect(rmMenu, &KsRmPlotContextMenu::removePlot,
 				lamRmPlot);
 		}
 
-		pid = _glWindow.getPlotPid(point);
 		if (pid >= 0) {
 			/*
 			 * This is a Task plot, but we do not have an entry
 			 * under the cursor.
 			 */
 			KsRmTaskPlotMenu *rmMenu;
-			menu = rmMenu = new KsRmTaskPlotMenu(_mState, pid, this);
+			menu = rmMenu = new KsRmTaskPlotMenu(_mState, sd, pid, this);
 
-			auto lamRmPlot = [&pid, this] () {
-				removeTaskPlot(pid);
+			auto lamRmPlot = [&sd, &pid, this] () {
+				removeTaskPlot(sd, pid);
 			};
 
 			connect(rmMenu, &KsRmPlotContextMenu::removePlot,
diff --git a/src/KsTraceGraph.hpp b/src/KsTraceGraph.hpp
index 0eeef14..0e31b88 100644
--- a/src/KsTraceGraph.hpp
+++ b/src/KsTraceGraph.hpp
@@ -12,6 +12,7 @@
 #define _KS_TRACEGRAPH_H
 
 // KernelShark
+#include "KsWidgetsLib.hpp"
 #include "KsGLWidget.hpp"
 
 /**
@@ -35,7 +36,7 @@ public:
  * The KsTraceViewer class provides a widget for interactive visualization of
  * trace data shown as time-series.
  */
-class KsTraceGraph : public QWidget
+class KsTraceGraph : public KsWidgetsLib::KsDataWidget
 {
 	Q_OBJECT
 public:
@@ -52,17 +53,19 @@ public:
 
 	void markEntry(size_t);
 
-	void cpuReDraw(QVector<int>);
+	void cpuReDraw(int sd, QVector<int> cpus);
 
-	void taskReDraw(QVector<int>);
+	void taskReDraw(int sd, QVector<int> pids);
 
-	void addCPUPlot(int);
+	void comboReDraw(int sd, QVector<int> v);
 
-	void addTaskPlot(int);
+	void addCPUPlot(int sd, int cpu);
 
-	void removeCPUPlot(int);
+	void addTaskPlot(int sd, int pid);
 
-	void removeTaskPlot(int);
+	void removeCPUPlot(int sd, int cpu);
+
+	void removeTaskPlot(int sd, int pid);
 
 	void update(KsDataStore *data);
 
@@ -96,34 +99,24 @@ private:
 
 	void _stopUpdating();
 
-	void _resetPointer(uint64_t ts, int cpu, int pid);
+	void _resetPointer(int64_t ts, int sd, int cpu, int pid);
 
 	void _setPointerInfo(size_t);
 
-	void _updateTimeLegends();
-
-	void _updateGraphLegends();
-
 	void _selfUpdate();
 
 	void _markerReDraw();
 
-	QString _t2str(uint64_t sec, uint64_t usec);
-
-	enum class GraphActions {
-		ZoomIn,
-		ZoomOut,
-		ScrollLeft,
-		ScrollRight
-	};
-
-	void _updateGraphs(GraphActions action);
+	void _updateGraphs(KsWidgetsLib::KsDataWork action);
 
 	void _onCustomContextMenu(const QPoint &point);
 
+	QString _t2str(uint64_t sec, uint64_t usec);
+
 	QToolBar	_pointerBar, _navigationBar;
 
 	QPushButton	_zoomInButton, _quickZoomInButton;
+
 	QPushButton	_zoomOutButton, _quickZoomOutButton;
 
 	QPushButton	_scrollLeftButton, _scrollRightButton;
@@ -133,14 +126,8 @@ private:
 
 	KsGraphScrollArea	_scrollArea;
 
-	QWidget		_drawWindow, _legendWindow, _legendAxisX;
-
-	QLabel		_labelXMin, _labelXMid, _labelXMax;
-
 	KsGLWidget	_glWindow;
 
-	QGridLayout	_drawLayout;
-
 	QVBoxLayout	_layout;
 
 	KsDualMarkerSM	*_mState;
-- 
2.25.1


  parent reply	other threads:[~2021-02-11 10:39 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-11 10:31 [PATCH v2 00/27] Complete the KernelShark v2 transformation Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 01/27] kernel-shark: Add get_stream_object() Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 02/27] kernel-shark: Do proper reset in kshark_close_all() Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 03/27] kernel-shark: Restore the counting of event handlers Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 04/27] kernel-shark: Fix a misleading comment Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 05/27] kernel-shark: Count the number of readout interfaces Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 06/27] kernel-shark: Update KsUtils Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 07/27] kernel-shark: Update KsModels and KsSearchFSM Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 08/27] kernel-shark: Add trace data files for CI testing Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 09/27] kernel-shark: Add plugin tests Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 10/27] kernel-shark: Add model tests Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 11/27] kernel-shark: Update KsWidgetsLib Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 12/27] kernel-shark: Add combo point to Mark Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 13/27] kernel-shark: Add new methods to KsPlot::Mark Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 14/27] kernel-shark: Update the plotting example Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 15/27] kernel-shark: Search for font with Cmake at pre-build Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 16/27] kernel-shark: Update KsDualMarker and KsGLWidget Yordan Karadzhov (VMware)
2021-02-11 10:31 ` Yordan Karadzhov (VMware) [this message]
2021-02-11 10:31 ` [PATCH v2 18/27] kernel-shark: Update KsTraceViewer Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 19/27] kernel-shark: Update KsAdvFilteringDialog Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 20/27] kernel-shark: Update KsCaptureDialog Yordan Karadzhov (VMware)
2021-02-11 10:31 ` [PATCH v2 21/27] kernel-shark: Update KsSession Yordan Karadzhov (VMware)
2021-02-11 10:32 ` [PATCH v2 22/27] kernel-shark: Update MissedEvents plugin Yordan Karadzhov (VMware)
2021-02-11 10:32 ` [PATCH v2 23/27] kernel-shark: Update KsMainWindow and kernelshark.cpp Yordan Karadzhov (VMware)
2021-02-11 10:32 ` [PATCH v2 24/27] kernel-shark: Clickable sched_event plugin shapes Yordan Karadzhov (VMware)
2021-02-11 10:32 ` [PATCH v2 25/27] kernel-shark: Show Task plots from command lime Yordan Karadzhov (VMware)
2021-02-11 10:32 ` [PATCH v2 26/27] kernel-shark: Add pkg-config configuration for libkshark Yordan Karadzhov (VMware)
2021-02-11 10:32 ` [PATCH v2 27/27] kernel-shark: Install libkshark-tepdata.h Yordan Karadzhov (VMware)
2021-02-11 15:02 ` [PATCH v2 00/27] Complete the KernelShark v2 transformation Steven Rostedt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210211103205.418588-18-y.karadz@gmail.com \
    --to=y.karadz@gmail.com \
    --cc=linux-trace-devel@vger.kernel.org \
    --cc=rostedt@goodmis.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.