From 004c4a257f9de22a955632d3b944a2c7999ec77a Mon Sep 17 00:00:00 2001 From: Victor Zarubkin Date: Sun, 21 Aug 2016 22:44:03 +0300 Subject: [PATCH] (EasyGraphicsView) Second click on selected item on graphics scene makes it expanded or collapsed; (EasyGraphicsView) Scale indicator rework; (EasyMainWindow) Added menu "View" with actions "Expand all" nad "Collapse all"; (EasyGraphicsScrollbar) Fixed wrong mouse position calculation when scaling (with mouse wheel) on minimap. --- profiler_gui/blocks_graphics_view.cpp | 59 +++++++++++++++------ profiler_gui/blocks_tree_widget.cpp | 74 ++++++++++++++++++++------- profiler_gui/blocks_tree_widget.h | 1 + profiler_gui/globals.h | 3 ++ profiler_gui/graphics_scrollbar.cpp | 6 ++- profiler_gui/main_window.cpp | 53 +++++++++++++++++-- profiler_gui/main_window.h | 2 + profiler_gui/tree_widget_loader.cpp | 11 ++-- 8 files changed, 164 insertions(+), 45 deletions(-) diff --git a/profiler_gui/blocks_graphics_view.cpp b/profiler_gui/blocks_graphics_view.cpp index 462c215..bdaf27d 100644 --- a/profiler_gui/blocks_graphics_view.cpp +++ b/profiler_gui/blocks_graphics_view.cpp @@ -45,11 +45,9 @@ using namespace profiler_gui; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -const qreal SCALING_COEFFICIENT = 1.25; -const qreal SCALING_COEFFICIENT_INV = 1.0 / SCALING_COEFFICIENT; -const qreal MIN_SCALE = pow(SCALING_COEFFICIENT_INV, 70); -const qreal MAX_SCALE = pow(SCALING_COEFFICIENT, 30); // ~800 -const qreal BASE_SCALE = pow(SCALING_COEFFICIENT_INV, 25); // ~0.003 +const qreal MIN_SCALE = pow(::profiler_gui::SCALING_COEFFICIENT_INV, 70); +const qreal MAX_SCALE = pow(::profiler_gui::SCALING_COEFFICIENT, 30); // ~800 +const qreal BASE_SCALE = pow(::profiler_gui::SCALING_COEFFICIENT_INV, 25); // ~0.003 const unsigned short GRAPHICS_ROW_SIZE = 16; const unsigned short GRAPHICS_ROW_SPACING = 2; @@ -305,7 +303,10 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* if (w < 20) continue; - flags = Qt::AlignCenter; + if (item.totalHeight > GRAPHICS_ROW_SIZE) + flags = Qt::AlignCenter; + else if (!(item.width() < 1)) + flags = Qt::AlignHCenter; } else { @@ -370,7 +371,8 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* rect.setRect(x, top, w, h); _painter->drawRect(rect); - flags = item.width() < 1 ? 0 : Qt::AlignHCenter; + if (!(item.width() < 1)) + flags = Qt::AlignHCenter; } // Draw text----------------------------------- @@ -1013,8 +1015,7 @@ void EasyBackgroundItem::paint(QPainter* _painter, const QStyleOptionGraphicsIte for (int j = 0; j < 20; ++j) { auto xmark = current + j * step * 0.1; - marks[j].setP1(QPointF(xmark, h)); - marks[j].setP2(QPointF(xmark, h + ((j % 5) ? 4 : 8))); + marks[j].setLine(xmark, h, xmark, h + ((j % 5) ? 4 : 8)); } _painter->drawLines(marks, 20); @@ -1053,14 +1054,23 @@ void EasyTimelineIndicatorItem::paint(QPainter* _painter, const QStyleOptionGrap _painter->save(); _painter->setTransform(QTransform::fromTranslate(-x(), -y())); _painter->setCompositionMode(QPainter::CompositionMode_Difference); - _painter->setBrush(Qt::white); - _painter->setPen(Qt::NoPen); + _painter->setBrush(Qt::NoBrush); - QRectF rect(visibleSceneRect.width() - 10 - step, visibleSceneRect.height() - 20, step, 5); - _painter->drawRect(rect); + //_painter->setBrush(Qt::white); + //_painter->setPen(Qt::NoPen); - rect.translate(0, 5); - _painter->setPen(Qt::white); + QPen pen(Qt::white); + pen.setWidth(2); + pen.setJoinStyle(Qt::MiterJoin); + _painter->setPen(pen); + + QRectF rect(visibleSceneRect.width() - 10 - step, visibleSceneRect.height() - 20, step, 10); + const auto rect_right = rect.right(); + const QPointF points[] = {{rect.left(), rect.bottom()}, {rect.left(), rect.top()}, {rect_right, rect.top()}, {rect_right, rect.top() + 5}}; + _painter->drawPolyline(points, sizeof(points) / sizeof(QPointF)); + //_painter->drawRect(rect); + + rect.translate(0, 3); _painter->drawText(rect, Qt::AlignRight | Qt::TextDontClip, text); _painter->restore(); @@ -1073,6 +1083,7 @@ EasyGraphicsView::EasyGraphicsView(QWidget* _parent) , m_beginTime(::std::numeric_limits::max()) , m_scale(1) , m_offset(0) + , m_timelineStep(0) , m_mouseButtons(Qt::NoButton) , m_pScrollbar(nullptr) , m_chronometerItem(nullptr) @@ -1611,7 +1622,7 @@ void EasyGraphicsView::onGraphicsScrollbarWheel(qreal _mouseX, int _wheelDelta) void EasyGraphicsView::onWheel(qreal _mouseX, int _wheelDelta) { - const decltype(m_scale) scaleCoeff = _wheelDelta > 0 ? SCALING_COEFFICIENT : SCALING_COEFFICIENT_INV; + const decltype(m_scale) scaleCoeff = _wheelDelta > 0 ? ::profiler_gui::SCALING_COEFFICIENT : ::profiler_gui::SCALING_COEFFICIENT_INV; // Remember current mouse position const auto mousePosition = m_offset + _mouseX / m_scale; @@ -1729,6 +1740,8 @@ void EasyGraphicsView::mouseReleaseEvent(QMouseEvent* _event) } } + const ::profiler_gui::ProfBlockItem* selectedBlock = nullptr; + const auto previouslySelectedBlock = ::profiler_gui::EASY_GLOBALS.selected_block; if (m_mouseButtons & Qt::LeftButton) { bool clicked = false; @@ -1760,10 +1773,17 @@ void EasyGraphicsView::mouseReleaseEvent(QMouseEvent* _event) if (block) { changedSelectedItem = true; + selectedBlock = block; ::profiler_gui::EASY_GLOBALS.selected_block = block->block->block_index; break; } } + + if (!changedSelectedItem && ::profiler_gui::EASY_GLOBALS.selected_block != ::profiler_gui::numeric_max(::profiler_gui::EASY_GLOBALS.selected_block)) + { + changedSelectedItem = true; + ::profiler_gui::set_max(::profiler_gui::EASY_GLOBALS.selected_block); + } } } @@ -1782,6 +1802,11 @@ void EasyGraphicsView::mouseReleaseEvent(QMouseEvent* _event) if (changedSelectedItem) { m_bUpdatingRect = true; + if (selectedBlock != nullptr && previouslySelectedBlock == ::profiler_gui::EASY_GLOBALS.selected_block && !selectedBlock->block->children.empty()) + { + ::profiler_gui::EASY_GLOBALS.gui_blocks[previouslySelectedBlock].expanded = !::profiler_gui::EASY_GLOBALS.gui_blocks[previouslySelectedBlock].expanded; + emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged(); + } emit ::profiler_gui::EASY_GLOBALS.events.selectedBlockChanged(::profiler_gui::EASY_GLOBALS.selected_block); m_bUpdatingRect = false; @@ -1968,6 +1993,8 @@ void EasyGraphicsView::onFlickerTimeout() // Fast slow-down and stop if mouse button is pressed, no flicking. m_flickerSpeedX >>= 1; m_flickerSpeedY >>= 1; + if (m_flickerSpeedX == -1) m_flickerSpeedX = 0; + if (m_flickerSpeedY == -1) m_flickerSpeedY = 0; } else { diff --git a/profiler_gui/blocks_tree_widget.cpp b/profiler_gui/blocks_tree_widget.cpp index 74cf71e..d310f28 100644 --- a/profiler_gui/blocks_tree_widget.cpp +++ b/profiler_gui/blocks_tree_widget.cpp @@ -45,7 +45,17 @@ ////////////////////////////////////////////////////////////////////////// -EasyTreeWidget::EasyTreeWidget(QWidget* _parent) : Parent(_parent), m_beginTime(::std::numeric_limits::max()), m_progress(nullptr), m_bColorRows(true), m_bLocked(false) +const int HIERARCHY_BUILDER_TIMER_INTERVAL = 40; + +////////////////////////////////////////////////////////////////////////// + +EasyTreeWidget::EasyTreeWidget(QWidget* _parent) + : Parent(_parent) + , m_beginTime(::std::numeric_limits::max()) + , m_progress(nullptr) + , m_bColorRows(true) + , m_bLocked(false) + , m_bSilentExpandCollapse(false) { setAutoFillBackground(false); setAlternatingRowColors(true); @@ -102,7 +112,8 @@ EasyTreeWidget::EasyTreeWidget(QWidget* _parent) : Parent(_parent), m_beginTime( m_progress = new QProgressDialog("Building blocks hierarchy...", "", 0, 100, this, Qt::FramelessWindowHint); m_progress->setAttribute(Qt::WA_TranslucentBackground); m_progress->setCancelButton(nullptr); - m_progress->hide(); + m_progress->setValue(100); + //m_progress->hide(); QTimer::singleShot(40, this, &This::alignProgressBar); } @@ -113,7 +124,7 @@ EasyTreeWidget::~EasyTreeWidget() delete m_progress; } -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// void EasyTreeWidget::onFillTimerTimeout() { @@ -137,7 +148,7 @@ void EasyTreeWidget::onFillTimerTimeout() if (m_progress) { m_progress->setValue(100); - m_progress->hide(); + //m_progress->hide(); } m_bLocked = false; @@ -145,7 +156,8 @@ void EasyTreeWidget::onFillTimerTimeout() setSortingEnabled(true); sortByColumn(COL_BEGIN, Qt::AscendingOrder); - resizeColumnToContents(COL_NAME); + //resizeColumnToContents(COL_NAME); + resizeColumnsToContents(); connect(this, &Parent::itemExpanded, this, &This::onItemExpand); connect(this, &Parent::itemCollapsed, this, &This::onItemCollapse); @@ -166,9 +178,9 @@ void EasyTreeWidget::setTree(const unsigned int _blocksNumber, const ::profiler: { m_bLocked = true; m_progress->setValue(0); - m_progress->show(); + //m_progress->show(); m_hierarchyBuilder.fillTree(m_beginTime, _blocksNumber, _blocksTree, m_bColorRows); - m_fillTimer.start(20); + m_fillTimer.start(HIERARCHY_BUILDER_TIMER_INTERVAL); } //StubLocker l; @@ -199,9 +211,9 @@ void EasyTreeWidget::setTreeBlocks(const ::profiler_gui::TreeBlocks& _blocks, :: { m_bLocked = true; m_progress->setValue(0); - m_progress->show(); + //m_progress->show(); m_hierarchyBuilder.fillTreeBlocks(m_inputBlocks, _session_begin_time, _left, _right, _strict, m_bColorRows); - m_fillTimer.start(20); + m_fillTimer.start(HIERARCHY_BUILDER_TIMER_INTERVAL); } //StubLocker l; @@ -227,7 +239,7 @@ void EasyTreeWidget::setTreeBlocks(const ::profiler_gui::TreeBlocks& _blocks, :: //onSelectedBlockChange(::profiler_gui::EASY_GLOBALS.selected_block); } -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// void EasyTreeWidget::clearSilent(bool _global) { @@ -236,7 +248,7 @@ void EasyTreeWidget::clearSilent(bool _global) if (m_progress) { m_progress->setValue(100); - m_progress->hide(); + //m_progress->hide(); } m_bLocked = false; @@ -404,7 +416,10 @@ void EasyTreeWidget::onJumpToItemClicked(unsigned int _block_index) void EasyTreeWidget::onCollapseAllClicked(bool) { const QSignalBlocker b(this); + + m_bSilentExpandCollapse = true; collapseAll(); + m_bSilentExpandCollapse = false; for (auto item : m_items) ::profiler_gui::EASY_GLOBALS.gui_blocks[item->block()->block_index].expanded = false; @@ -414,11 +429,14 @@ void EasyTreeWidget::onCollapseAllClicked(bool) void EasyTreeWidget::onExpandAllClicked(bool) { const QSignalBlocker b(this); + + m_bSilentExpandCollapse = true; expandAll(); resizeColumnsToContents(); + m_bSilentExpandCollapse = false; for (auto item : m_items) - ::profiler_gui::EASY_GLOBALS.gui_blocks[item->block()->block_index].expanded = true; + ::profiler_gui::EASY_GLOBALS.gui_blocks[item->block()->block_index].expanded = !item->block()->children.empty(); emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged(); } @@ -428,7 +446,11 @@ void EasyTreeWidget::onCollapseAllChildrenClicked(bool) if (current != nullptr) { const QSignalBlocker b(this); + + m_bSilentExpandCollapse = true; current->collapseAll(); + m_bSilentExpandCollapse = false; + emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged(); } } @@ -439,23 +461,33 @@ void EasyTreeWidget::onExpandAllChildrenClicked(bool) if (current != nullptr) { const QSignalBlocker b(this); + + m_bSilentExpandCollapse = true; current->expandAll(); resizeColumnsToContents(); + m_bSilentExpandCollapse = false; + emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged(); } } void EasyTreeWidget::onItemExpand(QTreeWidgetItem* _item) { - resizeColumnsToContents(); ::profiler_gui::EASY_GLOBALS.gui_blocks[static_cast(_item)->block()->block_index].expanded = true; - emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged(); + + if (!m_bSilentExpandCollapse) + { + resizeColumnsToContents(); + emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged(); + } } void EasyTreeWidget::onItemCollapse(QTreeWidgetItem* _item) { ::profiler_gui::EASY_GLOBALS.gui_blocks[static_cast(_item)->block()->block_index].expanded = false; - emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged(); + + if (!m_bSilentExpandCollapse) + emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged(); } void EasyTreeWidget::onColorizeRowsTriggered(bool _colorize) @@ -505,13 +537,19 @@ void EasyTreeWidget::onSelectedBlockChange(unsigned int _block_index) if (item != nullptr) { - const QSignalBlocker b(this); - expandItem(item); + //const QSignalBlocker b(this); + + m_bSilentExpandCollapse = true; setCurrentItem(item); scrollToItem(item, QAbstractItemView::PositionAtCenter); + if (::profiler_gui::EASY_GLOBALS.gui_blocks[item->block()->block_index].expanded) + expandItem(item); + else + collapseItem(item); resizeColumnsToContents(); + m_bSilentExpandCollapse = false; - ::profiler_gui::EASY_GLOBALS.gui_blocks[item->block()->block_index].expanded = true; + //::profiler_gui::EASY_GLOBALS.gui_blocks[item->block()->block_index].expanded = item->isExpanded(); emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged(); } else diff --git a/profiler_gui/blocks_tree_widget.h b/profiler_gui/blocks_tree_widget.h index 97f4c9b..6723b0e 100644 --- a/profiler_gui/blocks_tree_widget.h +++ b/profiler_gui/blocks_tree_widget.h @@ -73,6 +73,7 @@ protected: class QProgressDialog* m_progress; bool m_bColorRows; bool m_bLocked; + bool m_bSilentExpandCollapse; public: diff --git a/profiler_gui/globals.h b/profiler_gui/globals.h index 2895a45..4b69af5 100644 --- a/profiler_gui/globals.h +++ b/profiler_gui/globals.h @@ -37,6 +37,9 @@ namespace profiler_gui { const QRgb SELECTED_THREAD_BACKGROUND = 0x00e0e060; const QRgb SELECTED_THREAD_FOREGROUND = 0x00ffffff - SELECTED_THREAD_BACKGROUND; + const qreal SCALING_COEFFICIENT = 1.25; + const qreal SCALING_COEFFICIENT_INV = 1.0 / SCALING_COEFFICIENT; + ////////////////////////////////////////////////////////////////////////// #pragma pack(push, 1) diff --git a/profiler_gui/graphics_scrollbar.cpp b/profiler_gui/graphics_scrollbar.cpp index 340ec19..63c56c0 100644 --- a/profiler_gui/graphics_scrollbar.cpp +++ b/profiler_gui/graphics_scrollbar.cpp @@ -462,8 +462,10 @@ void EasyGraphicsScrollbar::mouseMoveEvent(QMouseEvent* _event) void EasyGraphicsScrollbar::wheelEvent(QWheelEvent* _event) { - setValue(mapToScene(_event->pos()).x() - m_minimumValue - m_slider->halfwidth()); - emit wheeled(m_slider->halfwidth() * m_windowScale, _event->delta()); + qreal deltaSign = _event->delta() < 0 ? -1 : 1; + auto w = m_slider->halfwidth() * (_event->delta() < 0 ? ::profiler_gui::SCALING_COEFFICIENT : ::profiler_gui::SCALING_COEFFICIENT_INV); + setValue(mapToScene(_event->pos()).x() - m_minimumValue - w); + emit wheeled(w * m_windowScale, _event->delta()); _event->accept(); } diff --git a/profiler_gui/main_window.cpp b/profiler_gui/main_window.cpp index 937a94f..a8ada50 100644 --- a/profiler_gui/main_window.cpp +++ b/profiler_gui/main_window.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "main_window.h" #include "blocks_tree_widget.h" #include "blocks_graphics_view.h" @@ -39,6 +40,10 @@ ////////////////////////////////////////////////////////////////////////// +const int LOADER_TIMER_INTERVAL = 40; + +////////////////////////////////////////////////////////////////////////// + EasyMainWindow::EasyMainWindow() : Parent(), m_treeWidget(nullptr), m_graphicsView(nullptr), m_progress(nullptr) { setObjectName("ProfilerGUI_MainWindow"); @@ -72,6 +77,12 @@ EasyMainWindow::EasyMainWindow() : Parent(), m_treeWidget(nullptr), m_graphicsVi auto actionExit = new QAction("Exit", nullptr); connect(actionExit, &QAction::triggered, this, &This::onExitClicked); + auto actionExpand = new QAction("Expand all", nullptr); + connect(actionExpand, &QAction::triggered, this, &This::onExpandAllClicked); + + auto actionCollapse = new QAction("Collapse all", nullptr); + connect(actionCollapse, &QAction::triggered, this, &This::onCollapseAllClicked); + auto menu = new QMenu("File"); menu->addAction(actionOpen); menu->addAction(actionReload); @@ -79,6 +90,10 @@ EasyMainWindow::EasyMainWindow() : Parent(), m_treeWidget(nullptr), m_graphicsVi menu->addAction(actionExit); menuBar()->addMenu(menu); + menu = new QMenu("View"); + menu->addAction(actionExpand); + menu->addAction(actionCollapse); + menuBar()->addMenu(menu); QSettings settings(::profiler_gui::ORGANAZATION_NAME, ::profiler_gui::APPLICATION_NAME); settings.beginGroup("main"); @@ -127,7 +142,8 @@ EasyMainWindow::EasyMainWindow() : Parent(), m_treeWidget(nullptr), m_graphicsVi m_progress->setFixedWidth(300); m_progress->setWindowTitle("EasyProfiler"); m_progress->setModal(true); - m_progress->hide(); + m_progress->setValue(100); + //m_progress->hide(); connect(m_progress, &QProgressDialog::canceled, this, &This::onFileReaderCancel); if(QCoreApplication::arguments().size() > 1) @@ -155,8 +171,8 @@ void EasyMainWindow::onOpenFileClicked(bool) void EasyMainWindow::loadFile(const std::string& stdfilename) { m_progress->setValue(0); - m_progress->show(); - m_readerTimer.start(20); + //m_progress->show(); + m_readerTimer.start(LOADER_TIMER_INTERVAL); m_reader.load(stdfilename); // ::profiler::SerializedData data; @@ -213,6 +229,32 @@ void EasyMainWindow::onDrawBordersChanged(bool _checked) ////////////////////////////////////////////////////////////////////////// +void EasyMainWindow::onExpandAllClicked(bool) +{ + for (auto& block : ::profiler_gui::EASY_GLOBALS.gui_blocks) + block.expanded = true; + + emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged(); + + auto tree = static_cast(m_treeWidget->widget()); + const QSignalBlocker b(tree); + tree->expandAll(); +} + +void EasyMainWindow::onCollapseAllClicked(bool) +{ + for (auto& block : ::profiler_gui::EASY_GLOBALS.gui_blocks) + block.expanded = false; + + emit ::profiler_gui::EASY_GLOBALS.events.itemsExpandStateChanged(); + + auto tree = static_cast(m_treeWidget->widget()); + const QSignalBlocker b(tree); + tree->collapseAll(); +} + +////////////////////////////////////////////////////////////////////////// + void EasyMainWindow::closeEvent(QCloseEvent* close_event) { saveSettings(); @@ -285,7 +327,7 @@ void EasyMainWindow::onFileReaderTimeout() m_readerTimer.stop(); m_progress->setValue(100); - m_progress->hide(); + //m_progress->hide(); } else { @@ -297,7 +339,8 @@ void EasyMainWindow::onFileReaderCancel() { m_readerTimer.stop(); m_reader.interrupt(); - m_progress->hide(); + m_progress->setValue(100); + //m_progress->hide(); } ////////////////////////////////////////////////////////////////////////// diff --git a/profiler_gui/main_window.h b/profiler_gui/main_window.h index bf606aa..ff751e7 100644 --- a/profiler_gui/main_window.h +++ b/profiler_gui/main_window.h @@ -90,6 +90,8 @@ protected slots: void onExitClicked(bool); void onEncodingChanged(bool); void onDrawBordersChanged(bool); + void onExpandAllClicked(bool); + void onCollapseAllClicked(bool); void onFileReaderTimeout(); void onFileReaderCancel(); diff --git a/profiler_gui/tree_widget_loader.cpp b/profiler_gui/tree_widget_loader.cpp index 194de9b..b0bf140 100644 --- a/profiler_gui/tree_widget_loader.cpp +++ b/profiler_gui/tree_widget_loader.cpp @@ -373,9 +373,11 @@ void FillTreeClass::setTreeInternal2(T& _safelocker, Items& _items, ThreadedI ::profiler_gui::EASY_GLOBALS.gui_blocks[block.tree->block_index].tree_item = item_index; if (_colorizeRows) - { item->colorize(_colorizeRows); - } + + if (::profiler_gui::EASY_GLOBALS.gui_blocks[block.tree->block_index].expanded) + item->setExpanded(true); + } else { @@ -562,9 +564,10 @@ size_t FillTreeClass::setTreeInternal(T& _safelocker, Items& _items, const :: ::profiler_gui::EASY_GLOBALS.gui_blocks[child.block_index].tree_item = item_index; if (_colorizeRows) - { item->colorize(_colorizeRows); - } + + if (::profiler_gui::EASY_GLOBALS.gui_blocks[child.block_index].expanded) + item->setExpanded(true); } else {