blob: 428e8ddf7dd557a2a7d5f623283ff5a4ce64adeb [file] [log] [blame]
/* SPDX-License-Identifier: LGPL-2.1 */
/*
* Copyright (C) 2017 VMware Inc, Yordan Karadzhov <ykaradzhov@vmware.com>
*/
/**
* @file KsWidgetsLib.hpp
* @brief Defines small widgets and dialogues used by the KernelShark GUI.
*/
#ifndef _KS_WIDGETS_LIB_H
#define _KS_WIDGETS_LIB_H
// Qt
#include <QtWidgets>
// KernelShark
#include "libkshark.h"
#include "KsUtils.hpp"
namespace KsWidgetsLib
{
/**
* The KsProgressBar class provides a visualization of the progress of a
* running job.
*/
class KsProgressBar : public QWidget
{
Q_OBJECT
QStatusBar _sb;
QProgressBar _pb;
public:
KsProgressBar(QString message, QWidget *parent = nullptr);
virtual ~KsProgressBar();
void setValue(int i);
void workInProgress();
private:
bool _notDone;
};
/** Defines the progress bar's maximum value. */
#define KS_PROGRESS_BAR_MAX 200
/** The height of the KsProgressBar widget. */
#define KS_PROGBAR_HEIGHT (FONT_HEIGHT * 5)
/** The width of the KsProgressBar widget. */
#define KS_PROGBAR_WIDTH (FONT_WIDTH * 50)
/** Data Work identifiers. */
enum class KsDataWork
{
AnyWork,
EditPlotList,
ZoomIn,
QuickZoomIn,
ZoomOut,
QuickZoomOut,
ScrollLeft,
ScrollRight,
JumpTo,
GraphUpdateGeom,
UpdatePlugins,
ResizeGL,
RenderGL,
};
/** Defines hash function needed by the QSet tempate container class. */
inline uint qHash(KsDataWork key, uint seed)
{
/*
* Cast the enum class to uint and use the definition of qHash outside
* the current scope.
*/
return ::qHash(static_cast<uint>(key), seed);
}
/**
* The KsWorkInProgress class provides a widget showing the
* "work in progress" notification.
*/
class KsWorkInProgress : public QWidget
{
public:
explicit KsWorkInProgress(QWidget *parent = nullptr);
void show(KsDataWork w);
void hide(KsDataWork w);
bool isBusy(KsDataWork w = KsDataWork::AnyWork) const;
void addToStatusBar(QStatusBar *sb);
private:
QLabel _icon, _message;
QSet<KsDataWork> _works;
};
/**
* The KsDataWidget class provides a base widget that provides the capability
* to show the "work in progress" notification. The class must be inherited by
* the widgets performing heavy data processing operations.
*/
class KsDataWidget : public QWidget
{
public:
/**
* @brief Create KsDataWidget.
*
* @param parent: The parent of this widget.
*/
explicit KsDataWidget(QWidget *parent = nullptr)
: QWidget(parent), _workInProgress(nullptr) {}
/** Set a pointer to the KsWorkInProgress widget. */
const KsWorkInProgress *wipPtr(KsWorkInProgress *wip) const
{
return _workInProgress;
}
/** Set the pointer to the KsWorkInProgress widget. */
void setWipPtr(KsWorkInProgress *wip)
{
_workInProgress = wip;
}
/**
* Call this function when a given work is about to start in order to
* show the "work in progress" notification.
*/
void startOfWork(KsDataWork w)
{
if (_workInProgress)
_workInProgress->show(w);
}
/**
* Call this function when a given work is done in order to hide the
* "work in progress" notification.
*/
void endOfWork(KsDataWork w)
{
if (_workInProgress)
_workInProgress->hide(w);
}
/** Check if the GUI is busy processing data. */
bool isBusy(KsDataWork w = KsDataWork::AnyWork) const
{
return _workInProgress ? _workInProgress->isBusy(w) : false;
}
private:
KsWorkInProgress *_workInProgress;
};
/**
* The KsMessageDialog class provides a widget showing a message and having
* a "Close" button.
*/
class KsMessageDialog : public QDialog
{
QVBoxLayout _layout;
QLabel _text;
QPushButton _closeButton;
public:
explicit KsMessageDialog(QWidget *parent) = delete;
KsMessageDialog(QString message, QWidget *parent = nullptr);
};
/** The height of the KsMessageDialog widget. */
#define KS_MSG_DIALOG_HEIGHT (FONT_HEIGHT * 8)
/** The width of the KsMessageDialog widget. */
#define KS_MSG_DIALOG_WIDTH (SCREEN_WIDTH / 10)
bool fileExistsDialog(QString fileName);
/**
* The KsTimeOffsetDialog class provides a dialog used to enter the value of
* the time offset between two Data streams.
*/
class KsTimeOffsetDialog : public QDialog
{
Q_OBJECT
public:
explicit KsTimeOffsetDialog(QWidget *parent = nullptr);
static double getValueNanoSec(QString dataFile, bool *ok);
signals:
/** Signal emitted when the "Apply" button is pressed. */
void apply(int sd, double val);
private:
QInputDialog _input;
QComboBox _streamCombo;
private slots:
void _setDefault(int index);
};
/**
* The KsCheckBoxWidget class is the base class of all CheckBox widget used
* by KernelShark.
*/
class KsCheckBoxWidget : public QWidget
{
Q_OBJECT
public:
KsCheckBoxWidget(int sd, const QString &name = "",
QWidget *parent = nullptr);
/** Get the name of the widget. */
QString name() const {return _name;}
/** Get the state of the "all" checkboxe. */
bool all() const
{
if(_allCb.checkState() == Qt::Checked)
return true;
return false;
}
/** The "all" checkboxe to be visible or not. */
void setVisibleCbAll(bool v) {_allCbAction->setVisible(v);}
void setDefault(bool);
void set(QVector<int> v);
/**
* Get a vector containing all Ids (can be PID CPU Ids etc.) managed
* by this widget.
*/
QVector<int> getIds() const {return _id;}
QVector<int> getCheckedIds();
QVector<int> getStates();
/**
* Get the identifier of the Data stream for which the selection
* applies.
*/
int sd() const {return _sd;}
/**
* Reimplemented event handler used to update the geometry of the widget on
* resize events.
*/
void resizeEvent(QResizeEvent* event)
{
KsUtils::setElidedText(&_streamLabel, _streamName,
Qt::ElideLeft, width());
QApplication::processEvents();
}
/** The user provided an input. The widget has been modified. */
bool _userInput;
private:
QToolBar _tb;
protected:
/** Identifier of the Data stream for which the selection applies. */
int _sd;
/** The "all" checkboxe. */
QCheckBox _allCb;
/** A vector of Id numbers coupled to each checkboxe. */
QVector<int> _id;
/** A nested widget used to position the checkboxes. */
QWidget _cbWidget;
/** The layout of the nested widget. */
QVBoxLayout _cbLayout;
/** The top level layout of this widget. */
QVBoxLayout _topLayout;
private:
QAction *_allCbAction;
/**
* The name of this Data stream. Typically this will be the name of
* the data file.
*/
QString _streamName;
/**
* A label to show the name of the Data stream for which the selection
* applies. */
QLabel _streamLabel;
/** The name of this widget. */
QString _name;
/** A label to show the name of the widget. */
QLabel _nameLabel;
virtual void _setCheckState(int i, Qt::CheckState st) = 0;
virtual Qt::CheckState _checkState(int i) const = 0;
virtual void _verify() {};
void _checkAll(bool);
void _setStream(int8_t sd);
};
/**
* The KsCheckBoxDialog class is the base class of all CheckBox dialogs
* used by KernelShark.
*/
class KsCheckBoxDialog : public QDialog
{
Q_OBJECT
public:
KsCheckBoxDialog() = delete;
KsCheckBoxDialog(QVector<KsCheckBoxWidget *> cbws,
QWidget *parent = nullptr);
/**
* The "apply" signal will emit a vector containing the Ids of all
* checked checkboxe.
*/
void applyIds(bool v = true) {_applyIds = v;}
/**
* The "apply" signal will emit a vector containing the statuse of all
* checkboxe.
*/
void applyStatus(bool v = true) {_applyIds = !v;}
signals:
/** Signal emitted when the "Apply" button is pressed. */
void apply(int sd, QVector<int>);
private:
void _applyPress();
virtual void _preApplyAction() {}
virtual void _postApplyAction() {}
bool _applyIds;
QVBoxLayout _topLayout;
QHBoxLayout _cbLayout, _buttonLayout;
QVector<KsCheckBoxWidget *> _checkBoxWidgets;
QPushButton _applyButton, _cancelButton;
QMetaObject::Connection _applyButtonConnection;
};
/**
* The KsPluginsCheckBoxDialog provides dialog for selecting plugins.
* used by KernelShark. The class is used to override _postApplyAction().
*/
class KsPluginsCheckBoxDialog : public KsCheckBoxDialog
{
public:
KsPluginsCheckBoxDialog() = delete;
/** Create KsPluginsCheckBoxDialog. */
KsPluginsCheckBoxDialog(QVector<KsCheckBoxWidget *> cbws,
KsDataStore *d, QWidget *parent = nullptr)
: KsCheckBoxDialog(cbws, parent), _data(d) {}
private:
virtual void _postApplyAction() override;
KsDataStore *_data;
};
/** The KsCheckBoxTable class provides a table of checkboxes. */
class KsCheckBoxTable : public QTableWidget
{
Q_OBJECT
public:
explicit KsCheckBoxTable(QWidget *parent = nullptr);
void init(QStringList headers, int size);
/** A vector of checkboxes. */
QVector<QCheckBox*> _cb;
signals:
/** Signal emitted when a checkboxes changes state. */
void changeState(int row);
protected:
void keyPressEvent(QKeyEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
private:
void _doubleClicked(int row, int col);
};
/**
* The KsCheckBoxTableWidget class provides a widget to hold a table of
* checkboxes.
*/
class KsCheckBoxTableWidget : public KsCheckBoxWidget
{
Q_OBJECT
public:
KsCheckBoxTableWidget(int sd, const QString &name = "",
QWidget *parent = nullptr);
/** Only one checkboxe at the time can be checked. */
void setSingleSelection()
{
_table.setSelectionMode(QAbstractItemView::SingleSelection);
setVisibleCbAll(false);
}
protected:
void _adjustSize();
void _initTable(QStringList headers, int size);
/** The KsCheckBoxTable, shown by this widget. */
KsCheckBoxTable _table;
private:
void _setCheckState(int i, Qt::CheckState st) override
{
_table._cb[i]->setCheckState(st);
}
Qt::CheckState _checkState(int i) const override
{
return _table._cb[i]->checkState();
}
void _update(bool);
void _changeState(int row);
};
/** The KsCheckBoxTree class provides a tree of checkboxes. */
class KsCheckBoxTree : public QTreeWidget
{
Q_OBJECT
public:
explicit KsCheckBoxTree(QWidget *parent = nullptr);
signals:
/**
* Signal emitted when a checkboxes of the tree changes its state
* and the state of all toplevel and child checkboxes has to be
* reprocesed.
*/
void verify();
protected:
void keyPressEvent(QKeyEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
private:
void _doubleClicked(QTreeWidgetItem *item, int col);
};
/**
* The KsCheckBoxTreeWidget class provides a widget to hold a tree of
* checkboxes.
*/
class KsCheckBoxTreeWidget : public KsCheckBoxWidget
{
Q_OBJECT
public:
KsCheckBoxTreeWidget() = delete;
KsCheckBoxTreeWidget(int sd, const QString &name = "",
QWidget *parent = nullptr);
/** Only one checkboxe at the time can be checked. */
void setSingleSelection()
{
_tree.setSelectionMode(QAbstractItemView::SingleSelection);
setVisibleCbAll(false);
}
protected:
void _adjustSize();
void _initTree();
/** The KsCheckBoxTree, shown by this widget. */
KsCheckBoxTree _tree;
/** A vector of Tree items (checkboxes). */
QVector<QTreeWidgetItem*> _cb;
private:
void _setCheckState(int i, Qt::CheckState st) override
{
_cb[i]->setCheckState(0, st);
}
Qt::CheckState _checkState(int i) const override
{
return _cb[i]->checkState(0);
}
void _update(QTreeWidgetItem *item, int column);
void _verify();
};
/**
* The KsCPUCheckBoxWidget class provides a widget for selecting CPU plots to
* show.
*/
struct KsCPUCheckBoxWidget : public KsCheckBoxTreeWidget
{
KsCPUCheckBoxWidget() = delete;
KsCPUCheckBoxWidget(kshark_data_stream *stream,
QWidget *parent = nullptr);
};
/**
* The KsTasksCheckBoxWidget class provides a widget for selecting Tasks
* to show or hide.
*/
struct KsTasksCheckBoxWidget : public KsCheckBoxTableWidget
{
KsTasksCheckBoxWidget() = delete;
KsTasksCheckBoxWidget(kshark_data_stream *stream,
bool cond = true,
QWidget *parent = nullptr);
private:
/**
* A positive condition means that you want to show Tasks and
* a negative condition means that you want to hide Tasks.
*/
bool _cond;
};
/**
* The KsEventsCheckBoxWidget class provides a widget for selecting Trace
* events to show or hide.
*/
struct KsEventsCheckBoxWidget : public KsCheckBoxTreeWidget
{
KsEventsCheckBoxWidget() = delete;
KsEventsCheckBoxWidget(kshark_data_stream *stream,
QWidget *parent = nullptr);
QStringList getCheckedEvents(bool option);
void removeSystem(QString name);
private:
void _makeItems(kshark_data_stream *stream, QVector<int> eventIds);
void _makeTepEventItems(kshark_data_stream *stream, QVector<int> eventIds);
};
/**
* The KsPluginCheckBoxWidget class provides a widget for selecting plugins.
*/
struct KsPluginCheckBoxWidget : public KsCheckBoxTableWidget
{
KsPluginCheckBoxWidget() = delete;
KsPluginCheckBoxWidget(int sd, QStringList pluginList,
QWidget *parent = nullptr);
void setInfo(int row, QString info);
void setActive(QVector<int> rows, bool a);
};
/**
* The KsDStreamCheckBoxWidget class provides a widget for selecting Data streams.
*/
struct KsDStreamCheckBoxWidget : public KsCheckBoxTableWidget
{
explicit KsDStreamCheckBoxWidget(QWidget *parent = nullptr);
};
/**
* The KsEventFieldSelectWidget class provides a widget for selecting a data
* field of the trace event.
*/
class KsEventFieldSelectWidget : public QWidget
{
Q_OBJECT
public:
explicit KsEventFieldSelectWidget(QWidget *parent = nullptr);
/** Get the currently selected stream Id. */
int streamId() const {return _streamComboBox.currentData().toInt();}
/** Get the currently selected event name. */
QString eventName() const {return _eventComboBox.currentText();}
/** Get the currently selected field name. */
QString fieldName() const {return _fieldComboBox.currentText();}
void setStreamCombo();
private slots:
void _streamChanged(const QString &stream);
void _eventChanged(const QString &event);
private:
QVBoxLayout _topLayout;
QComboBox _streamComboBox, _eventComboBox, _fieldComboBox;
QLabel _streamLabel, _eventLabel, _fieldLabel;
};
}; // KsWidgetsLib
#endif