diff --git a/profiler_gui/CMakeLists.txt b/profiler_gui/CMakeLists.txt index 27a72fe..a6f47f9 100644 --- a/profiler_gui/CMakeLists.txt +++ b/profiler_gui/CMakeLists.txt @@ -2,9 +2,11 @@ cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR) project(profiler_gui) +#set(CMAKE_PREFIX_PATH f:/qt/5.5/5.6/msvc2013_64/lib/cmake) + set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) find_package(Qt5Widgets REQUIRED) -add_executable(${PROJECT_NAME} main.cpp treemodel.h treemodel.cpp treeitem.h treeitem.cpp) +add_executable(${PROJECT_NAME} main.cpp treemodel.h treemodel.cpp treeitem.h treeitem.cpp graphics_view.h)# widgets_view.h) target_link_libraries(${PROJECT_NAME} Qt5::Widgets easy_profiler) diff --git a/profiler_gui/graphics_view.h b/profiler_gui/graphics_view.h new file mode 100644 index 0000000..52579db --- /dev/null +++ b/profiler_gui/graphics_view.h @@ -0,0 +1,254 @@ + + +#ifndef MY____GRAPHICS___VIEW_H +#define MY____GRAPHICS___VIEW_H + +#include +#include +#include +#include +#include +#include +#include "profiler/reader.h" + +class GlobalSignals : public QObject +{ + Q_OBJECT + +public: + + GlobalSignals() : QObject() {} + +signals: + + void scaleIncreased(qreal _scale) const; + void scaleDecreased(qreal _scale) const; + +} const GLOBALS; + +class MyPolygon : public QGraphicsPolygonItem +{ +public: + + MyPolygon(QGraphicsItem* _parent = nullptr) : QGraphicsPolygonItem(_parent) + { + } + + virtual ~MyPolygon() + { + } + +}; + +class MyText : public QObject, public QGraphicsSimpleTextItem +{ + Q_OBJECT + +public: + + MyText(const char* _text, QGraphicsItem* _parent = nullptr) : QGraphicsSimpleTextItem(_text, _parent), QObject() + { + connect(&GLOBALS, &GlobalSignals::scaleIncreased, this, &MyText::onScaleIncrease); + connect(&GLOBALS, &GlobalSignals::scaleDecreased, this, &MyText::onScaleDecrease); + } + +private slots: + + void onScaleIncrease(qreal _scale) + { + setScale(100.0 / _scale); + + if (!isVisible()) + { + QRectF selfRect = boundingRect(); + QRectF parentRect = parentItem()->boundingRect(); + if (selfRect.width() * 100.0 < parentRect.width() * _scale) + show(); + } + } + + void onScaleDecrease(qreal _scale) + { + setScale(100.0 / _scale); + + if (isVisible()) + { + QRectF selfRect = boundingRect(); + QRectF parentRect = parentItem()->boundingRect(); + if (selfRect.width() * 100.0 > parentRect.width() * _scale) + hide(); + } + } + + + +}; + +const qreal LEFT = -2500000; +const qreal WIDTH = 5000000; +const int N_ITEMS = 200000; + +class MyGraphicsScene : public QGraphicsScene +{ + Q_OBJECT + +private: + + profiler::timestamp_t m_start; + +public: + + int items_couinter = 0; + + MyGraphicsScene(QGraphicsView* _parent) : QGraphicsScene(_parent), m_start(0) + { + setSceneRect(QRectF(LEFT, -200, WIDTH, 220)); + test(); + } + + MyGraphicsScene(const thread_blocks_tree_t& _blocksTree, QGraphicsView* _parent) : QGraphicsScene(_parent), m_start(0) + { + setTree(_blocksTree); + } + + virtual ~MyGraphicsScene() + { + } + + void test() + { + QPolygonF poly(QRectF(-5, -180, 10, 180)); + for (int i = 0; i < N_ITEMS; ++i) + { + MyPolygon* item = new MyPolygon(); + int h = 50 + rand() % 131; + item->setPolygon(QRectF(-5, -h, 10, h)); + item->setPos(LEFT + i * 10, 0); + item->setBrush(QBrush(QColor(30 + rand() % 225, 30 + rand() % 225, 30 + rand() % 225))); + addItem(item); + } + } + + void setTree(const thread_blocks_tree_t& _blocksTree) + { + m_start = -1; + profiler::timestamp_t finish = 0; + for (const auto& threadTree : _blocksTree) + { + ++items_couinter; + const auto timestart = threadTree.second.children.front().node->block()->getBegin(); + const auto timefinish = threadTree.second.children.back().node->block()->getEnd(); + if (m_start > timestart) m_start = timestart; + if (finish < timefinish) finish = timefinish; + } + + const qreal endX = time2position(finish + 1000000); + setSceneRect(QRectF(0, 0, endX, 110 * _blocksTree.size())); + + qreal y = 0; + for (const auto& threadTree : _blocksTree) + { + setTree(threadTree.second.children, y); + y += 110; + } + } + +private: + + inline qreal time2position(const profiler::timestamp_t& _time) const + { + return qreal(_time - m_start) * 1e-6; + } + + void setTree(const BlocksTree::children_t& _children, qreal _y, int _level = 0) + { + for (const auto& child : _children) + { + ++items_couinter; + MyPolygon* item = new MyPolygon(); + + const qreal xbegin = time2position(child.node->block()->getBegin()); + const qreal height = 100 - _level * 5; + qreal duration = time2position(child.node->block()->getEnd()) - xbegin; + if (duration < 1) + duration = 1; + + item->setPolygon(QRectF(0, _level * 5, duration, height)); + item->setPos(xbegin, _y); + item->setZValue(_level); + + const auto color = child.node->block()->getColor(); + item->setBrush(QBrush(QColor(profiler::colors::get_red(color), profiler::colors::get_green(color), profiler::colors::get_blue(color)))); + item->setPen(QPen(Qt::NoPen)); // disable borders painting + + addItem(item); + MyText* text = new MyText(child.node->getBlockName(), item); + QRectF textRect = text->boundingRect(); + text->setPos(0, _level * 5); + + QRectF itemRect = item->boundingRect(); + if (textRect.width() > itemRect.width()) + text->hide(); + + setTree(child.children, _y, _level + 1); + } + } +}; + + +class MyGraphicsView : public QGraphicsView +{ + Q_OBJECT + +private: + + qreal m_scale; + qreal m_scaleCoeff; + +public: + + MyGraphicsView() : QGraphicsView(), m_scale(100), m_scaleCoeff(1.25) + { + initMode(); + setScene(new MyGraphicsScene(this)); + centerOn(0, 0); + } + + MyGraphicsView(const thread_blocks_tree_t& _blocksTree) : QGraphicsView(), m_scale(100), m_scaleCoeff(1.25) + { + initMode(); + setScene(new MyGraphicsScene(_blocksTree, this)); + centerOn(0, 0); + } + + void initMode() + { + setCacheMode(QGraphicsView::CacheBackground); + setTransformationAnchor(QGraphicsView::AnchorUnderMouse); + setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); + } + + virtual ~MyGraphicsView() + { + } + + void wheelEvent(QWheelEvent* event) + { + //MyGraphicsScene* myscene = (MyGraphicsScene*)scene(); + if (event->delta() > 0) + { + scale(m_scaleCoeff, m_scaleCoeff); + m_scale *= m_scaleCoeff; + emit GLOBALS.scaleIncreased(m_scale); + } + else + { + const qreal scaleCoeff = 1.0 / m_scaleCoeff; + scale(scaleCoeff, scaleCoeff); + m_scale *= scaleCoeff; + emit GLOBALS.scaleDecreased(m_scale); + } + } +}; + +#endif // MY____GRAPHICS___VIEW_H diff --git a/profiler_gui/main.cpp b/profiler_gui/main.cpp index 956fd15..6c19c70 100644 --- a/profiler_gui/main.cpp +++ b/profiler_gui/main.cpp @@ -2,6 +2,8 @@ #include #include #include "treemodel.h" +#include "graphics_view.h" +#include "profiler/reader.h" int main(int argc, char **argv) { @@ -10,23 +12,44 @@ int main(int argc, char **argv) //QFileSystemModel *model = new QFileSystemModel; //model->setRootPath(QDir::currentPath()); - const char* filename = 0; - if(argc > 1 && argv[1]){ - filename = argv[1]; - }else{ - return 255; - } +// const char* filename = 0; +// if(argc > 1 && argv[1]){ +// filename = argv[1]; +// }else{ +// return 255; +// } - QFile file(filename); - file.open(QIODevice::ReadOnly); - TreeModel model(file.readAll()); - file.close(); +// QFile file(filename); +// file.open(QIODevice::ReadOnly); +// TreeModel model(file.readAll()); +// file.close(); - QTreeView *tree = new QTreeView(); - tree->setModel(&model); +// QTreeView *tree = new QTreeView(); +// tree->setModel(&model); +// +// tree->show(); - tree->show(); + const bool test = false; - return app.exec( ); + if (test) + { + // srand for random colors in test + unsigned int* rseed = new unsigned int; + srand(*rseed); + delete rseed; + + MyGraphicsView gview; + gview.show(); + + return app.exec(); + } + + thread_blocks_tree_t threaded_trees; + int blocks_counter = fillTreesFromFile("test.prof", threaded_trees, false); + + MyGraphicsView gview(threaded_trees); + gview.show(); + + return app.exec(); }