diff --git a/profiler_gui/blocks_graphics_view.cpp b/profiler_gui/blocks_graphics_view.cpp index 930d7e2..6781e22 100644 --- a/profiler_gui/blocks_graphics_view.cpp +++ b/profiler_gui/blocks_graphics_view.cpp @@ -88,7 +88,7 @@ const qreal MIN_SCALE = pow(::profiler_gui::SCALING_COEFFICIENT_INV, 70); // Up const qreal MAX_SCALE = pow(::profiler_gui::SCALING_COEFFICIENT, 45); // ~23000 --- Up to 10 ns scale const qreal BASE_SCALE = pow(::profiler_gui::SCALING_COEFFICIENT_INV, 25); // ~0.003 -EASY_CONSTEXPR uint16_t TIMELINE_ROW_SIZE = 20; +EASY_CONSTEXPR uint16_t TIMELINE_ROW_SIZE = 24; EASY_CONSTEXPR QRgb BACKGROUND_1 = 0xffe4e4ec; EASY_CONSTEXPR QRgb BACKGROUND_2 = ::profiler::colors::White; @@ -150,6 +150,7 @@ void EasyBackgroundItem::paint(QPainter* _painter, const QStyleOptionGraphicsIte const auto h = visibleSceneRect.height(); const auto visibleBottom = h - 1; const auto borderColor = QColor::fromRgb(TIMELINE_BORDER); + const auto textShiftY = h + TIMELINE_ROW_SIZE - 5; QRectF rect; @@ -241,7 +242,8 @@ void EasyBackgroundItem::paint(QPainter* _painter, const QStyleOptionGraphicsIte { next = n; _painter->setPen(::profiler_gui::TEXT_COLOR); - _painter->drawText(QPointF(current + 1, h + 17), QString::number(static_cast(0.5 + (current + left) * factor / currentScale))); + _painter->drawText(QPointF(current + 1, textShiftY), + QString::number(static_cast(0.5 + (current + left) * factor / currentScale))); _painter->setPen(borderColor); } @@ -1515,7 +1517,7 @@ void EasyGraphicsView::onIdleTimeout() { ::profiler::block_index_t i = ~0U; auto block = item->intersect(pos, i); - if (block) + if (block != nullptr) { const auto& itemBlock = block->tree; const auto& itemDesc = easyDescriptor(itemBlock.node->id()); @@ -1736,7 +1738,7 @@ void EasyGraphicsView::onIdleTimeout() } auto cse = item->intersectEvent(pos); - if (cse) + if (cse != nullptr) { const auto& itemBlock = cse->tree; diff --git a/profiler_gui/blocks_tree_widget.cpp b/profiler_gui/blocks_tree_widget.cpp index 66929a4..836f3c3 100644 --- a/profiler_gui/blocks_tree_widget.cpp +++ b/profiler_gui/blocks_tree_widget.cpp @@ -233,14 +233,17 @@ EasyTreeWidget::EasyTreeWidget(QWidget* _parent) loadSettings(); + m_columnsHiddenStatus[0] = 0; + setColumnHidden(0, false); + if (m_mode == EasyTreeMode_Full) { - for (int i = 0; i < COL_COLUMNS_NUMBER; ++i) + for (int i = 1; i < COL_COLUMNS_NUMBER; ++i) m_columnsHiddenStatus[i] = isColumnHidden(i) ? 1 : 0; } else { - for (int i = 0; i < COL_COLUMNS_NUMBER; ++i) + for (int i = 1; i < COL_COLUMNS_NUMBER; ++i) { if (SIMPLIFIED_REGIME_COLUMNS[i]) { @@ -254,24 +257,18 @@ EasyTreeWidget::EasyTreeWidget(QWidget* _parent) } } - m_progress = new QProgressDialog("Building blocks hierarchy...", "", 0, 100, this, Qt::FramelessWindowHint); - m_progress->setAttribute(Qt::WA_TranslucentBackground); - m_progress->setCancelButton(nullptr); - m_progress->setValue(100); - //m_progress->hide(); - m_hintLabel = new QLabel("Use Right Mouse Button on the Diagram to build a hierarchy...\nPress and hold, move, release", this); m_hintLabel->setAlignment(Qt::AlignCenter); m_hintLabel->setStyleSheet("QLabel { color: gray; font: 12pt; }"); QTimer::singleShot(1500, this, &This::alignProgressBar); + + setItemDelegateForColumn(0, new EasyItemDelegate(this)); } EasyTreeWidget::~EasyTreeWidget() { saveSettings(); - delete m_progress; - delete m_hintLabel; } ////////////////////////////////////////////////////////////////////////// @@ -295,11 +292,7 @@ void EasyTreeWidget::onFillTimerTimeout() } } - if (m_progress) - { - m_progress->setValue(100); - //m_progress->hide(); - } + destroyProgressDialog(); m_bLocked = false; m_inputBlocks.clear(); @@ -319,7 +312,7 @@ void EasyTreeWidget::onFillTimerTimeout() onSelectedThreadChange(EASY_GLOBALS.selected_thread); onSelectedBlockChange(EASY_GLOBALS.selected_block); } - else + else if (m_progress != nullptr) { m_progress->setValue(m_hierarchyBuilder.progress()); } @@ -333,8 +326,7 @@ void EasyTreeWidget::setTree(const unsigned int _blocksNumber, const ::profiler: { m_bLocked = true; m_hintLabel->hide(); - m_progress->setValue(0); - m_progress->show(); + createProgressDialog(); m_hierarchyBuilder.fillTree(m_beginTime, _blocksNumber, _blocksTree, m_bColorRows, m_mode); m_fillTimer.start(HIERARCHY_BUILDER_TIMER_INTERVAL); } @@ -367,8 +359,7 @@ void EasyTreeWidget::setTreeBlocks(const ::profiler_gui::TreeBlocks& _blocks, :: { m_bLocked = true; m_hintLabel->hide(); - m_progress->setValue(0); - m_progress->show(); + createProgressDialog(); m_hierarchyBuilder.fillTreeBlocks(m_inputBlocks, _session_begin_time, _left, _right, _strict, m_bColorRows, m_mode); m_fillTimer.start(HIERARCHY_BUILDER_TIMER_INTERVAL); } @@ -403,13 +394,7 @@ void EasyTreeWidget::clearSilent(bool _global) const QSignalBlocker b(this); m_hierarchyBuilder.interrupt(); - - if (m_progress) - { - m_progress->setValue(100); - //m_progress->hide(); - } - + destroyProgressDialog(); m_hintLabel->show(); m_bLocked = false; @@ -451,7 +436,7 @@ void EasyTreeWidget::clearSilent(bool _global) m_roots.clear(); ::std::vector topLevelItems; - topLevelItems.reserve(topLevelItemCount()); + topLevelItems.reserve(static_cast(topLevelItemCount())); for (int i = topLevelItemCount() - 1; i >= 0; --i) topLevelItems.push_back(takeTopLevelItem(i)); @@ -723,13 +708,13 @@ void EasyTreeWidget::contextMenuEvent(QContextMenuEvent* _event) auto hidemenu = menu.addMenu("Select columns"); auto hdr = headerItem(); - for (int i = 0; i < COL_COLUMNS_NUMBER; ++i) + for (int i = 1; i < COL_COLUMNS_NUMBER; ++i) { auto columnAction = new QAction(hdr->text(i), nullptr); columnAction->setData(i); columnAction->setCheckable(true); - columnAction->setChecked(m_columnsHiddenStatus[i] == 0);// !isColumnHidden(i)); - if (m_mode == EasyTreeMode_Full || SIMPLIFIED_REGIME_COLUMNS[i]) + columnAction->setChecked(m_columnsHiddenStatus[i] == 0); + if ((m_mode == EasyTreeMode_Full || SIMPLIFIED_REGIME_COLUMNS[i])) connect(columnAction, &QAction::triggered, this, &This::onHideShowColumn); else columnAction->setEnabled(false); @@ -759,10 +744,36 @@ void EasyTreeWidget::alignProgressBar() { auto center = rect().center(); auto pos = mapToGlobal(center); - m_progress->move(pos.x() - (m_progress->width() >> 1), pos.y() - (m_progress->height() >> 1)); + + if (m_progress != nullptr) + m_progress->move(pos.x() - (m_progress->width() >> 1), pos.y() - (m_progress->height() >> 1)); + m_hintLabel->move(center.x() - (m_hintLabel->width() >> 1), std::max(center.y() - (m_hintLabel->height() >> 1), header()->height())); } +void EasyTreeWidget::destroyProgressDialog() +{ + if (m_progress != nullptr) + { + m_progress->setValue(100); + m_progress->deleteLater(); + m_progress = nullptr; + } +} + +void EasyTreeWidget::createProgressDialog() +{ + destroyProgressDialog(); + + m_progress = new QProgressDialog("Building blocks hierarchy...", "", 0, 100, this, Qt::FramelessWindowHint); + m_progress->setAttribute(Qt::WA_TranslucentBackground); + m_progress->setCancelButton(nullptr); + m_progress->setValue(0); + m_progress->show(); + + alignProgressBar(); +} + ////////////////////////////////////////////////////////////////////////// void EasyTreeWidget::onJumpToItemClicked(bool) @@ -976,8 +987,11 @@ void EasyTreeWidget::onSelectedThreadChange(::profiler::thread_id_t _id) { for (auto& it : m_roots) { - it.second->colorize(it.first == _id); + auto item = it.second; + item->setMain(it.first == _id); + item->colorize(it.first == _id); } + } void EasyTreeWidget::onSelectedBlockChange(uint32_t _block_index) @@ -1078,12 +1092,12 @@ void EasyTreeWidget::onModeChange(bool) if (m_mode == EasyTreeMode_Full) { - for (int i = 0; i < COL_COLUMNS_NUMBER; ++i) + for (int i = 1; i < COL_COLUMNS_NUMBER; ++i) setColumnHidden(i, m_columnsHiddenStatus[i] != 0); } else { - for (int i = 0; i < COL_COLUMNS_NUMBER; ++i) + for (int i = 1; i < COL_COLUMNS_NUMBER; ++i) setColumnHidden(i, m_columnsHiddenStatus[i] != 0 || !SIMPLIFIED_REGIME_COLUMNS[i]); } diff --git a/profiler_gui/blocks_tree_widget.h b/profiler_gui/blocks_tree_widget.h index a847269..533f376 100644 --- a/profiler_gui/blocks_tree_widget.h +++ b/profiler_gui/blocks_tree_widget.h @@ -157,6 +157,11 @@ protected: void saveSettings(); void alignProgressBar(); +private: + + void destroyProgressDialog(); + void createProgressDialog(); + }; // END of class EasyTreeWidget. ////////////////////////////////////////////////////////////////////////// diff --git a/profiler_gui/descriptors_tree_widget.cpp b/profiler_gui/descriptors_tree_widget.cpp index 0545eeb..26ba1b8 100644 --- a/profiler_gui/descriptors_tree_widget.cpp +++ b/profiler_gui/descriptors_tree_widget.cpp @@ -67,7 +67,9 @@ #include #include #include +#include #include +#include #include #include "descriptors_tree_widget.h" #include "globals.h" @@ -183,7 +185,10 @@ const char* statusText(::profiler::EasyBlockStatus _status) ////////////////////////////////////////////////////////////////////////// -EasyDescWidgetItem::EasyDescWidgetItem(::profiler::block_id_t _desc, Parent* _parent) : Parent(_parent), m_desc(_desc) +EasyDescWidgetItem::EasyDescWidgetItem(::profiler::block_id_t _desc, Parent* _parent) + : Parent(_parent) + , m_desc(_desc) + , m_type(EasyDescWidgetItem::Type::File) { } @@ -209,6 +214,33 @@ bool EasyDescWidgetItem::operator < (const Parent& _other) const return Parent::operator < (_other); } +QVariant EasyDescWidgetItem::data(int _column, int _role) const +{ + if (_column == DESC_COL_TYPE) + { + if (_role == Qt::ToolTipRole) + { + switch (m_type) + { + case Type::File: return QStringLiteral("File"); + case Type::Event: return QStringLiteral("Event"); + case Type::Block: return QStringLiteral("Block"); + } + } + else if (_role == Qt::DisplayRole) + { + switch (m_type) + { + case Type::File: return QStringLiteral("F"); + case Type::Event: return QStringLiteral("E"); + case Type::Block: return QStringLiteral("B"); + } + } + } + + return QTreeWidgetItem::data(_column, _role); +} + ////////////////////////////////////////////////////////////////////////// EasyDescTreeWidget::EasyDescTreeWidget(QWidget* _parent) @@ -224,6 +256,7 @@ EasyDescTreeWidget::EasyDescTreeWidget(QWidget* _parent) setAnimated(true); setSortingEnabled(false); setColumnCount(DESC_COL_COLUMNS_NUMBER); + setSelectionBehavior(QAbstractItemView::SelectRows); auto header_item = new QTreeWidgetItem(); header_item->setText(DESC_COL_FILE_LINE, "File/Line"); @@ -239,6 +272,8 @@ EasyDescTreeWidget::EasyDescTreeWidget(QWidget* _parent) connect(this, &Parent::currentItemChanged, this, &This::onCurrentItemChange); loadSettings(); + + setItemDelegateForColumn(0, new EasyDescItemDelegate(this)); } EasyDescTreeWidget::~EasyDescTreeWidget() @@ -393,10 +428,10 @@ void EasyDescTreeWidget::build() auto& p = fileItems[desc->file()]; if (p.item == nullptr) { - p.item = new QTreeWidgetItem(); - p.item->setText(DESC_COL_FILE_LINE, QString(desc->file()).remove(QRegExp("^(\\.{2}\\\\+|\\/+)+"))); - p.item->setText(DESC_COL_TYPE, "F"); - p.item->setToolTip(DESC_COL_TYPE, "File"); + auto item = new EasyDescWidgetItem(0); + item->setText(DESC_COL_FILE_LINE, QString(desc->file()).remove(QRegExp("^(\\.{2}\\\\+|\\/+)+"))); + item->setType(EasyDescWidgetItem::Type::File); + p.item = item; } auto it = p.children.find(desc->line()); @@ -408,15 +443,9 @@ void EasyDescTreeWidget::build() item->setText(DESC_COL_NAME, desc->name()); if (desc->type() == ::profiler::BlockType::Block) - { - item->setText(DESC_COL_TYPE, "B"); - item->setToolTip(DESC_COL_TYPE, "Block"); - } + item->setType(EasyDescWidgetItem::Type::Block); else - { - item->setText(DESC_COL_TYPE, "E"); - item->setToolTip(DESC_COL_TYPE, "Event"); - } + item->setType(EasyDescWidgetItem::Type::Event); item->setFont(DESC_COL_STATUS, f); item->setText(DESC_COL_STATUS, statusText(desc->status())); @@ -751,7 +780,7 @@ EasyDescWidget::EasyDescWidget(QWidget* _parent) : Parent(_parent) - QMenu* menu = new QMenu(this); + auto menu = new QMenu(this); m_searchButton = menu->menuAction(); m_searchButton->setText("Find next"); m_searchButton->setIcon(QIcon(imagePath("find-next"))); @@ -917,3 +946,32 @@ void EasyDescWidget::findPrevFromMenu(bool _checked) } ////////////////////////////////////////////////////////////////////////// + +EasyDescItemDelegate::EasyDescItemDelegate(QObject* parent) : QStyledItemDelegate(parent) +{ + +} + +EasyDescItemDelegate::~EasyDescItemDelegate() +{ + +} + +void EasyDescItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + // Draw item as usual + QStyledItemDelegate::paint(painter, option, index); + + // Draw line under tree indicator + const auto bottomLeft = option.rect.bottomLeft(); + if (bottomLeft.x() > 0) + { + painter->save(); + painter->setBrush(Qt::NoBrush); + painter->setPen(::profiler_gui::SYSTEM_BORDER_COLOR); + painter->drawLine(QPoint(0, bottomLeft.y()), bottomLeft); + painter->restore(); + } +} + +////////////////////////////////////////////////////////////////////////// diff --git a/profiler_gui/descriptors_tree_widget.h b/profiler_gui/descriptors_tree_widget.h index 5ed1121..0dccd18 100644 --- a/profiler_gui/descriptors_tree_widget.h +++ b/profiler_gui/descriptors_tree_widget.h @@ -57,6 +57,7 @@ #define EASY_DESCRIPTORS_WIDGET_H #include +#include #include #include @@ -68,10 +69,22 @@ class EasyDescWidgetItem : public QTreeWidgetItem { - typedef QTreeWidgetItem Parent; - typedef EasyDescWidgetItem This; + using Parent = QTreeWidgetItem; + using This = EasyDescWidgetItem; + +public: + + enum class Type : uint8_t + { + File, + Event, + Block + }; + +private: ::profiler::block_id_t m_desc; + Type m_type; public: @@ -79,6 +92,7 @@ public: virtual ~EasyDescWidgetItem(); bool operator < (const Parent& _other) const override; + QVariant data(int _column, int _role) const override; public: @@ -89,10 +103,29 @@ public: return m_desc; } + inline void setType(Type _type) + { + m_type = _type; + } + }; // END of class EasyDescWidgetItem. ////////////////////////////////////////////////////////////////////////// +class EasyDescItemDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + + explicit EasyDescItemDelegate(QObject* parent = nullptr); + ~EasyDescItemDelegate() override; + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + +}; // END of class EasyDescItemDelegate. + +////////////////////////////////////////////////////////////////////////// + class EasyDescTreeWidget : public QTreeWidget { Q_OBJECT diff --git a/profiler_gui/easy_graphics_item.cpp b/profiler_gui/easy_graphics_item.cpp index 403f675..6b23f55 100644 --- a/profiler_gui/easy_graphics_item.cpp +++ b/profiler_gui/easy_graphics_item.cpp @@ -222,7 +222,7 @@ void EasyGraphicsItem::paintChildren(const float _minWidth, const int _narrowSiz const auto& itemDesc = easyDescriptor(itemBlock.tree.node->id()); - int h = 0, flags = 0; + int h = 0; bool do_paint_children = false; if ((EASY_GLOBALS.hide_narrow_children && w < EASY_GLOBALS.blocks_narrow_size) || !itemBlock.expanded) { @@ -304,11 +304,6 @@ void EasyGraphicsItem::paintChildren(const float _minWidth, const int _narrowSiz if (wprev < EASY_GLOBALS.blocks_narrow_size) continue; - if (totalHeight > ::profiler_gui::GRAPHICS_ROW_SIZE) - flags = Qt::AlignCenter; - else if (!(item.width() < 1)) - flags = Qt::AlignHCenter; - if (dw > 1) { w -= dw; @@ -395,9 +390,6 @@ void EasyGraphicsItem::paintChildren(const float _minWidth, const int _narrowSiz continue; } - if (!(item.width() < 1)) - flags = Qt::AlignHCenter; - if (dw > 1) { w -= dw; @@ -420,7 +412,7 @@ void EasyGraphicsItem::paintChildren(const float _minWidth, const int _narrowSiz // drawing text auto name = *itemBlock.tree.node->name() != 0 ? itemBlock.tree.node->name() : itemDesc.name(); - _painter->drawText(p.rect, flags, ::profiler_gui::toUnicode(name)); + _painter->drawText(p.rect, Qt::AlignCenter, ::profiler_gui::toUnicode(name)); // restore previous pen color if (p.previousPenStyle == Qt::NoPen) @@ -630,7 +622,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* #endif const auto& itemDesc = easyDescriptor(itemBlock.tree.node->id()); - int h = 0, flags = 0; + int h = 0; #ifdef EASY_GRAPHICS_ITEM_RECURSIVE_PAINT bool do_paint_children = false; @@ -716,11 +708,6 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* if (wprev < EASY_GLOBALS.blocks_narrow_size) continue; - if (totalHeight > ::profiler_gui::GRAPHICS_ROW_SIZE) - flags = Qt::AlignCenter; - else if (!(item.width() < 1)) - flags = Qt::AlignHCenter; - if (dw > 1) { w -= dw; x += 2; @@ -813,8 +800,6 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* #ifndef EASY_GRAPHICS_ITEM_RECURSIVE_PAINT dont_skip_children(next_level, item.children_begin, BLOCK_ITEM_DO_PAINT); #endif - if (!(item.width() < 1)) - flags = Qt::AlignHCenter; if (dw > 1) { w -= dw; @@ -839,7 +824,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* // drawing text auto name = *itemBlock.tree.node->name() != 0 ? itemBlock.tree.node->name() : itemDesc.name(); - _painter->drawText(p.rect, flags, ::profiler_gui::toUnicode(name)); + _painter->drawText(p.rect, Qt::AlignCenter, ::profiler_gui::toUnicode(name)); // restore previous pen color if (p.previousPenStyle == Qt::NoPen) @@ -979,7 +964,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* //firstSync = m_pRoot->sync.begin(); p.previousColor = 0; - qreal prevRight = -1e100, top = y() - 4, h = 3; + qreal prevRight = -1e100, top = y() - 6, h = 3; if (top + h < p.visibleBottom) { _painter->setPen(BORDERS_COLOR); @@ -1056,7 +1041,7 @@ void EasyGraphicsItem::paint(QPainter* _painter, const QStyleOptionGraphicsItem* } p.previousColor = 0; - qreal prevRight = -1e100, top = y() + boundingRect().height() - 1, h = 3; + qreal prevRight = -1e100, top = y() + boundingRect().height() + 1, h = 3; if (top + h < p.visibleBottom) { _painter->setPen(BORDERS_COLOR); @@ -1190,7 +1175,7 @@ const ::profiler_gui::EasyBlock* EasyGraphicsItem::intersect(const QPointF& _pos return nullptr; } - static const auto OVERLAP = ::profiler_gui::THREADS_ROW_SPACING >> 1; + EASY_STATIC_CONSTEXPR auto OVERLAP = (::profiler_gui::THREADS_ROW_SPACING >> 1) + 2; const auto bottom = top + m_levels.size() * ::profiler_gui::GRAPHICS_ROW_SIZE_FULL + OVERLAP; if (bottom < _pos.y()) { diff --git a/profiler_gui/globals.h b/profiler_gui/globals.h index 5526175..3c5f802 100644 --- a/profiler_gui/globals.h +++ b/profiler_gui/globals.h @@ -85,10 +85,10 @@ namespace profiler_gui { EASY_CONSTEXPR uint32_t V130 = 0x01030000; EASY_CONSTEXPR QSize ICONS_SIZE(28, 28); - EASY_CONSTEXPR uint16_t GRAPHICS_ROW_SIZE = 18; + EASY_CONSTEXPR uint16_t GRAPHICS_ROW_SIZE = 20; EASY_CONSTEXPR uint16_t GRAPHICS_ROW_SPACING = 0; EASY_CONSTEXPR uint16_t GRAPHICS_ROW_SIZE_FULL = GRAPHICS_ROW_SIZE + GRAPHICS_ROW_SPACING; - EASY_CONSTEXPR uint16_t THREADS_ROW_SPACING = 8; + EASY_CONSTEXPR uint16_t THREADS_ROW_SPACING = 10; #ifdef _WIN32 EASY_CONSTEXPR qreal FONT_METRICS_FACTOR = 1.05; diff --git a/profiler_gui/main_window.cpp b/profiler_gui/main_window.cpp index 16cb5bc..e5168cb 100644 --- a/profiler_gui/main_window.cpp +++ b/profiler_gui/main_window.cpp @@ -726,14 +726,6 @@ EasyMainWindow::EasyMainWindow() : Parent(), m_theme("default"), m_lastAddress(" connect(&m_fpsRequestTimer, &QTimer::timeout, this, &This::onFrameTimeRequestTimeout); - m_progress = new QProgressDialog("Loading file...", "Cancel", 0, 100, this); - m_progress->setFixedWidth(300); - m_progress->setWindowTitle(EASY_DEFAULT_WINDOW_TITLE); - m_progress->setModal(true); - m_progress->setValue(100); - //m_progress->hide(); - connect(m_progress, &QProgressDialog::canceled, this, &This::onFileReaderCancel); - loadGeometry(); if(QCoreApplication::arguments().size() > 1) @@ -748,7 +740,6 @@ EasyMainWindow::EasyMainWindow() : Parent(), m_theme("default"), m_lastAddress(" EasyMainWindow::~EasyMainWindow() { - delete m_progress; } ////////////////////////////////////////////////////////////////////////// @@ -802,8 +793,12 @@ void EasyMainWindow::onThemeChange(bool) if (action == nullptr) return; - m_theme = action->text(); - QMessageBox::information(this, "Theme", "You should restart the application to apply the theme."); + auto newTheme = action->text(); + if (m_theme != newTheme) + { + m_theme = std::move(newTheme); + QMessageBox::information(this, "Theme", "You should restart the application to apply the theme."); + } } ////////////////////////////////////////////////////////////////////////// @@ -876,20 +871,16 @@ void EasyMainWindow::loadFile(const QString& filename) { const auto i = filename.lastIndexOf(QChar('/')); const auto j = filename.lastIndexOf(QChar('\\')); - m_progress->setLabelText(QString("Loading %1...").arg(filename.mid(::std::max(i, j) + 1))); - m_progress->setValue(0); - m_progress->show(); + createProgressDialog(QString("Loading %1...").arg(filename.mid(::std::max(i, j) + 1))); + m_readerTimer.start(LOADER_TIMER_INTERVAL); m_reader.load(filename); } void EasyMainWindow::readStream(::std::stringstream& data) { - m_progress->setLabelText(tr("Reading from stream...")); - - m_progress->setValue(0); - m_progress->show(); + createProgressDialog(tr("Reading from stream...")); m_readerTimer.start(LOADER_TIMER_INTERVAL); m_reader.load(data); } @@ -1492,6 +1483,30 @@ void EasyMainWindow::saveSettingsAndGeometry() settings.endGroup(); } +void EasyMainWindow::destroyProgressDialog() +{ + if (m_progress != nullptr) + { + m_progress->setValue(100); + m_progress->deleteLater(); + m_progress = nullptr; + } +} + +void EasyMainWindow::createProgressDialog(const QString& text) +{ + destroyProgressDialog(); + + m_progress = new QProgressDialog(text, QStringLiteral("Cancel"), 0, 100, this); + connect(m_progress, &QProgressDialog::canceled, this, &This::onFileReaderCancel); + + m_progress->setFixedWidth(300); + m_progress->setWindowTitle(EASY_DEFAULT_WINDOW_TITLE); + m_progress->setModal(true); + m_progress->setValue(0); + m_progress->show(); +} + void EasyMainWindow::setDisconnected(bool _showMessage) { if (m_fpsRequestTimer.isActive()) @@ -1812,15 +1827,14 @@ void EasyMainWindow::onFileReaderTimeout() m_reader.interrupt(); m_readerTimer.stop(); - m_progress->setValue(100); - //m_progress->hide(); + destroyProgressDialog(); if (EASY_GLOBALS.all_items_expanded_by_default) { onExpandAllClicked(true); } } - else + else if (m_progress != nullptr) { m_progress->setValue(m_reader.progress()); } @@ -1830,8 +1844,7 @@ void EasyMainWindow::onFileReaderCancel() { m_readerTimer.stop(); m_reader.interrupt(); - m_progress->setValue(100); - //m_progress->hide(); + destroyProgressDialog(); } ////////////////////////////////////////////////////////////////////////// diff --git a/profiler_gui/main_window.h b/profiler_gui/main_window.h index ad46319..474b972 100644 --- a/profiler_gui/main_window.h +++ b/profiler_gui/main_window.h @@ -325,6 +325,9 @@ private: void setDisconnected(bool _showMessage = true); + void destroyProgressDialog(); + void createProgressDialog(const QString& text); + }; // END of class EasyMainWindow. ////////////////////////////////////////////////////////////////////////// diff --git a/profiler_gui/themes/default.css b/profiler_gui/themes/default.css index f9ca05b..7431287 100644 --- a/profiler_gui/themes/default.css +++ b/profiler_gui/themes/default.css @@ -24,20 +24,24 @@ EasyMainWindow, QToolBar, QDialog { background-color: #f8f2f2; } QToolTip { + background-color: #ffeccc; border: 1px solid #cccccc; } +QGraphicsView { + border-color: #cccccc; } + /* ****************************************************************************************************************** */ QLineEdit, QComboBox, QSpinBox { height: 24px; border: 1px solid #cccccc; background-color: white; - selection-background-color: rgba(136, 189, 136, 0.4); + selection-background-color: rgba(152, 222, 152, 0.5); selection-color: #504040; } QLineEdit:disabled, QComboBox:disabled, QSpinBox:disabled { background-color: #f0f0f0; color: #a08888; - selection-background-color: rgba(136, 189, 136, 0.4); + selection-background-color: rgba(152, 222, 152, 0.5); selection-color: #a08888; } QLineEdit:focus { @@ -126,12 +130,19 @@ QPushButton:pressed { /* ****************************************************************************************************************** */ QListView { background-color: white; - border: 1px solid #cccccc; - selection-background-color: rgba(136, 189, 136, 0.4); + border: 1px solid #cccccc; } + +QListView, QTableView, QTreeView { + alternate-background-color: #e4e4ec; + selection-background-color: rgba(152, 222, 152, 0.8); selection-color: #504040; } -QListView::item, QListView::item, QTableView::item, QTreeView::item { - height: 24px; } +QListView::item, QTableView::item, QTreeView::item { + height: 26px; + border-bottom: 1px solid #cccccc; } + +QListView::item:selected, QTableView::item:selected, QTreeView::item:selected { + background-color: rgba(152, 222, 152, 0.8); } /* ****************************************************************************************************************** */ QMenu { @@ -147,8 +158,8 @@ QMenu::item { /* reserve space for selection border */ } QMenu::item:selected { - border: 1px solid rgba(136, 189, 136, 0.4); - background-color: rgba(136, 189, 136, 0.4); } + border: 1px solid rgba(152, 222, 152, 0.5); + background-color: rgba(152, 222, 152, 0.5); } QMenu::icon { width: 14px; @@ -243,6 +254,7 @@ EasyDockWidget QWidget#EasyDockWidgetTitle { background: none; border: none; max-height: 12px; + min-width: 12px; max-width: 12px; margin-right: 4px; padding: 0; } @@ -310,15 +322,14 @@ QScrollBar::handle:pressed { background-color: rgba(0, 0, 0, 0.6); } QScrollBar::handle:vertical { - min-height: 20px; + min-height: 30px; margin-left: 4px; } QScrollBar::handle:vertical:hover, QScrollBar::handle:vertical:pressed { margin-left: 0; } QScrollBar::handle:horizontal { - min-width: 20px; - max-width: 100px; + min-width: 30px; margin-top: 4px; } QScrollBar::handle:horizontal:hover, QScrollBar::handle:horizontal:pressed { diff --git a/profiler_gui/themes/default.scss b/profiler_gui/themes/default.scss index 6d0b799..b1ba48c 100644 --- a/profiler_gui/themes/default.scss +++ b/profiler_gui/themes/default.scss @@ -19,7 +19,7 @@ $TextColor: #504040; $DisabledTextColor: #a08888; $BorderColor: #cccccc; $MainColor: #f44336; -$HoveredMenuRowColor: rgb_a(#88BD88, 0.4); +$HoveredMenuRowColor: rgb_a(#98DE98, 0.5); $BackgroundColor: white; $DisabledBackgroundColor: #f0f0f0; $ButtonHoverColor: #922c2c;//#d77d7d; @@ -47,9 +47,14 @@ EasyMainWindow, QToolBar, QDialog { } QToolTip { + background-color: #ffeccc; border: 1px solid $BorderColor; } +QGraphicsView { + border-color: $BorderColor; +} + /* ****************************************************************************************************************** */ QLineEdit, QComboBox, QSpinBox { height: $DefaultHeight; @@ -139,12 +144,21 @@ QPushButton:pressed { QListView { background-color: $BackgroundColor; border: 1px solid $BorderColor; - selection-background-color: $HoveredMenuRowColor; +} + +QListView, QTableView, QTreeView { + alternate-background-color: #e4e4ec; + selection-background-color: rgb_a(#98DE98, 0.8); selection-color: $TextColor; } -QListView::item, QListView::item, QTableView::item, QTreeView::item { - height: $DefaultHeight; +QListView::item, QTableView::item, QTreeView::item { + height: $DefaultHeight + 2px; + border-bottom: 1px solid $BorderColor; +} + +QListView::item:selected, QTableView::item:selected, QTreeView::item:selected { + background-color: rgb_a(#98DE98, 0.8); } /* ****************************************************************************************************************** */ @@ -274,6 +288,7 @@ EasyDockWidget background: none; border: none; max-height: 12px; + min-width: 12px; max-width: 12px; margin-right: 4px; padding: 0; @@ -346,10 +361,10 @@ QScrollBar::handle:pressed { background-color: rgb_a(#000000, 0.6); } -QScrollBar::handle:vertical { min-height: 20px; margin-left: 4px; } +QScrollBar::handle:vertical { min-height: 30px; margin-left: 4px; } QScrollBar::handle:vertical:hover, QScrollBar::handle:vertical:pressed { margin-left: 0; } -QScrollBar::handle:horizontal { min-width: 20px; max-width: 100px; margin-top: 4px; } +QScrollBar::handle:horizontal { min-width: 30px; margin-top: 4px; } QScrollBar::handle:horizontal:hover, QScrollBar::handle:horizontal:pressed { margin-top: 0; } QScrollBar::add-line, QScrollBar::sub-line { diff --git a/profiler_gui/tree_widget_item.cpp b/profiler_gui/tree_widget_item.cpp index be70848..5d3f317 100644 --- a/profiler_gui/tree_widget_item.cpp +++ b/profiler_gui/tree_widget_item.cpp @@ -55,16 +55,66 @@ #include "tree_widget_item.h" #include "globals.h" +#include +#include +#include +#include +#include +#include ////////////////////////////////////////////////////////////////////////// -EASY_CONSTEXPR QRgb TEXT_RGB = 0xff504040; +EASY_CONSTEXPR int BlockColorRole = Qt::UserRole + 1; + +////////////////////////////////////////////////////////////////////////// + +EASY_CONSTEXPR int ColumnBit[COL_COLUMNS_NUMBER] = { + -1 // COL_NAME = 0, + + , 0 // COL_BEGIN, + + , 1 // COL_DURATION, + , 2 // COL_SELF_DURATION, + , 3 // COL_DURATION_SUM_PER_PARENT, + , 4 // COL_DURATION_SUM_PER_FRAME, + , 5 // COL_DURATION_SUM_PER_THREAD, + + , -1 // COL_SELF_DURATION_PERCENT, + , -1 // COL_PERCENT_PER_PARENT, + , -1 // COL_PERCENT_PER_FRAME, + , -1 // COL_PERCENT_SUM_PER_PARENT, + , -1 // COL_PERCENT_SUM_PER_FRAME, + , -1 // COL_PERCENT_SUM_PER_THREAD, + + , 6 // COL_END, + + , 7 // COL_MIN_PER_FRAME, + , 8 // COL_MAX_PER_FRAME, + , 9 // COL_AVERAGE_PER_FRAME, + , -1 // COL_NCALLS_PER_FRAME, + + , 10 // COL_MIN_PER_THREAD, + , 11 // COL_MAX_PER_THREAD, + , 12 // COL_AVERAGE_PER_THREAD, + , -1 // COL_NCALLS_PER_THREAD, + + , 13 // COL_MIN_PER_PARENT, + , 14 // COL_MAX_PER_PARENT, + , 15 // COL_AVERAGE_PER_PARENT, + , -1 // COL_NCALLS_PER_PARENT, + + , 16 // COL_ACTIVE_TIME, + , -1 // COL_ACTIVE_PERCENT, +}; + +////////////////////////////////////////////////////////////////////////// EasyTreeWidgetItem::EasyTreeWidgetItem(const ::profiler::block_index_t _treeBlock, Parent* _parent) : Parent(_parent) , m_block(_treeBlock) , m_customBGColor(0) - , m_customTextColor(TEXT_RGB) + , m_bColorized(false) + , m_bMain(false) { } @@ -119,6 +169,55 @@ bool EasyTreeWidgetItem::operator < (const Parent& _other) const return false; } +bool EasyTreeWidgetItem::hasToolTip(int _column) const +{ + const int bit = ColumnBit[_column]; + return bit < 0 ? false : m_bHasToolTip.test(static_cast(bit)); +} + +void EasyTreeWidgetItem::setHasToolTip(int _column) +{ + const int bit = ColumnBit[_column]; + if (bit >= 0) + m_bHasToolTip.set(static_cast(bit), true); +} + +QVariant EasyTreeWidgetItem::data(int _column, int _role) const +{ + if (_column == COL_NAME) + { + if (_role == Qt::SizeHintRole) + { + const float k = m_font.bold() ? 1.15f : 1.f; + return QSize(static_cast(QFontMetrics(m_font).width(text(COL_NAME)) * k) + 20, 26); + } + + if (_role == BlockColorRole) + { + if (m_bColorized) + return QBrush(QColor::fromRgba(m_customBGColor)); + return QVariant(); + } + } + + switch (_role) + { + case Qt::FontRole: + return m_font; + + case Qt::ForegroundRole: + return m_bMain ? QVariant::fromValue(QColor::fromRgb(::profiler_gui::SELECTED_THREAD_FOREGROUND)) : QVariant(); + + case Qt::ToolTipRole: + return hasToolTip(_column) ? + QVariant::fromValue(QString("%1 ns").arg(QTreeWidgetItem::data(_column, Qt::UserRole).toULongLong())) : + QVariant(); + + default: + return QTreeWidgetItem::data(_column, _role); + } +} + ::profiler::block_index_t EasyTreeWidgetItem::block_index() const { return m_block; @@ -151,7 +250,7 @@ void EasyTreeWidgetItem::setTimeSmart(int _column, ::profiler_gui::TimeUnits _un const ::profiler::timestamp_t nanosecondsTime = PROF_NANOSECONDS(_time); setData(_column, Qt::UserRole, (quint64)nanosecondsTime); - setToolTip(_column, QString("%1 ns").arg(nanosecondsTime)); + setHasToolTip(_column); setText(_column, QString("%1%2").arg(_prefix).arg(::profiler_gui::timeStringRealNs(_units, nanosecondsTime, 3))); // if (_time < 1e3) @@ -177,7 +276,7 @@ void EasyTreeWidgetItem::setTimeSmart(int _column, ::profiler_gui::TimeUnits _un const ::profiler::timestamp_t nanosecondsTime = PROF_NANOSECONDS(_time); setData(_column, Qt::UserRole, (quint64)nanosecondsTime); - setToolTip(_column, QString("%1 ns").arg(nanosecondsTime)); + setHasToolTip(_column); setText(_column, ::profiler_gui::timeStringRealNs(_units, nanosecondsTime, 3)); } @@ -185,7 +284,7 @@ void EasyTreeWidgetItem::setTimeMs(int _column, const ::profiler::timestamp_t& _ { const ::profiler::timestamp_t nanosecondsTime = PROF_NANOSECONDS(_time); setData(_column, Qt::UserRole, (quint64)nanosecondsTime); - setToolTip(_column, QString("%1 ns").arg(nanosecondsTime)); + setHasToolTip(_column); setText(_column, QString::number(double(nanosecondsTime) * 1e-6, 'g', 9)); } @@ -193,7 +292,7 @@ void EasyTreeWidgetItem::setTimeMs(int _column, const ::profiler::timestamp_t& _ { const ::profiler::timestamp_t nanosecondsTime = PROF_NANOSECONDS(_time); setData(_column, Qt::UserRole, (quint64)nanosecondsTime); - setToolTip(_column, QString("%1 ns").arg(nanosecondsTime)); + setHasToolTip(_column); setText(_column, QString("%1%2").arg(_prefix).arg(double(nanosecondsTime) * 1e-6, 0, 'g', 9)); } @@ -202,31 +301,14 @@ void EasyTreeWidgetItem::setBackgroundColor(QRgb _color) m_customBGColor = _color; } -void EasyTreeWidgetItem::setTextColor(QRgb _color) +void EasyTreeWidgetItem::setMain(bool _main) { - m_customTextColor = _color; + m_bMain = _main; } void EasyTreeWidgetItem::colorize(bool _colorize) { - if (_colorize) - { - for (int i = 0; i < COL_COLUMNS_NUMBER; ++i) - { - setBackground(i, QColor::fromRgba(m_customBGColor)); - setForeground(i, QColor::fromRgb(m_customTextColor)); - } - } - else - { - const QBrush nobrush; - const QBrush textbrush(::profiler_gui::TEXT_COLOR); - for (int i = 0; i < COL_COLUMNS_NUMBER; ++i) - { - setBackground(i, nobrush); - setForeground(i, textbrush); - } - } + m_bColorized = _colorize; } void EasyTreeWidgetItem::collapseAll() @@ -255,10 +337,74 @@ void EasyTreeWidgetItem::expandAll() void EasyTreeWidgetItem::setBold(bool _bold) { - auto f = font(0); - f.setBold(_bold); - for (int i = 0; i < COL_COLUMNS_NUMBER; ++i) - setFont(i, f); + m_font.setBold(_bold); } ////////////////////////////////////////////////////////////////////////// + +EasyItemDelegate::EasyItemDelegate(QTreeWidget* parent) : QStyledItemDelegate(parent), m_treeWidget(parent) +{ + +} + +EasyItemDelegate::~EasyItemDelegate() +{ + +} + +void EasyItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + auto brushData = m_treeWidget->model()->data(index, BlockColorRole); + if (brushData.isNull()) + { + // Draw item as usual + QStyledItemDelegate::paint(painter, option, index); + + // Draw line under tree indicator + const auto bottomLeft = option.rect.bottomLeft(); + if (bottomLeft.x() > 0) + { + painter->save(); + painter->setBrush(Qt::NoBrush); + painter->setPen(::profiler_gui::SYSTEM_BORDER_COLOR); + painter->drawLine(QPoint(0, bottomLeft.y()), bottomLeft); + painter->restore(); + } + + return; + } + + // Adjust rect size for drawing color marker + QStyleOptionViewItem opt = option; + opt.rect.adjust(16, 0, 0, 0); + + // Draw item as usual + QStyledItemDelegate::paint(painter, opt, index); + + painter->save(); + + const auto currentTreeIndex = m_treeWidget->currentIndex(); + if (index.parent() == currentTreeIndex.parent() && index.row() == currentTreeIndex.row()) + { + // Draw selection background for selected row + painter->setBrush(QColor::fromRgba(0xCC98DE98)); + painter->setPen(Qt::NoPen); + painter->drawRect(QRect(option.rect.left(), option.rect.top(), 16, option.rect.height())); + } + + // Draw color marker with block color + const auto brush = m_treeWidget->model()->data(index, Qt::UserRole + 1).value(); + painter->setBrush(brush); + painter->setPen(::profiler_gui::SYSTEM_BORDER_COLOR); + painter->drawRect(QRect(option.rect.left(), option.rect.top() + 5, 16, option.rect.height() - 10)); + + // Draw line under tree indicator + const auto bottomLeft = opt.rect.bottomLeft(); + if (bottomLeft.x() > 0) + { + painter->setBrush(Qt::NoBrush); + painter->drawLine(QPoint(0, bottomLeft.y()), bottomLeft); + } + + painter->restore(); +} diff --git a/profiler_gui/tree_widget_item.h b/profiler_gui/tree_widget_item.h index 2051745..9137e00 100644 --- a/profiler_gui/tree_widget_item.h +++ b/profiler_gui/tree_widget_item.h @@ -59,7 +59,9 @@ #include #include +#include #include +#include #include "common_types.h" @@ -116,19 +118,20 @@ class EasyTreeWidgetItem : public QTreeWidgetItem typedef QTreeWidgetItem Parent; typedef EasyTreeWidgetItem This; + QFont m_font; const ::profiler::block_index_t m_block; QRgb m_customBGColor; - QRgb m_customTextColor; + std::bitset<17> m_bHasToolTip; + bool m_bColorized; + bool m_bMain; public: - using Parent::setBackgroundColor; - using Parent::setTextColor; - explicit EasyTreeWidgetItem(const ::profiler::block_index_t _treeBlock = ::profiler_gui::numeric_max(), Parent* _parent = nullptr); virtual ~EasyTreeWidgetItem(); bool operator < (const Parent& _other) const override; + QVariant data(int _column, int _role) const override; public: @@ -147,7 +150,7 @@ public: void setBackgroundColor(QRgb _color); - void setTextColor(QRgb _color); + void setMain(bool _main); void colorize(bool _colorize); @@ -157,8 +160,28 @@ public: void setBold(bool _bold); +private: + + bool hasToolTip(int _column) const; + void setHasToolTip(int _column); + }; // END of class EasyTreeWidgetItem. ////////////////////////////////////////////////////////////////////////// +class EasyItemDelegate : public QStyledItemDelegate +{ + Q_OBJECT + QTreeWidget* m_treeWidget; + +public: + + explicit EasyItemDelegate(QTreeWidget* parent = nullptr); + ~EasyItemDelegate() override; + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + +}; // END of class EasyItemDelegate. + +////////////////////////////////////////////////////////////////////////// + #endif // EASY_TREE_WIDGET_ITEM_H diff --git a/profiler_gui/tree_widget_loader.cpp b/profiler_gui/tree_widget_loader.cpp index 2744e91..fb9b3e3 100644 --- a/profiler_gui/tree_widget_loader.cpp +++ b/profiler_gui/tree_widget_loader.cpp @@ -227,7 +227,6 @@ void EasyTreeWidgetLoader::setTreeInternal1(::profiler::timestamp_t& _beginTime, item->setTimeSmart(COL_DURATION, _units, duration); item->setBackgroundColor(::profiler_gui::SELECTED_THREAD_BACKGROUND); - item->setTextColor(::profiler_gui::SELECTED_THREAD_FOREGROUND); //_items.push_back(item); @@ -316,7 +315,6 @@ void EasyTreeWidgetLoader::setTreeInternal2(const ::profiler::timestamp_t& _begi thread_item->setTimeSmart(COL_DURATION, _units, duration); thread_item->setBackgroundColor(::profiler_gui::SELECTED_THREAD_BACKGROUND); - thread_item->setTextColor(::profiler_gui::SELECTED_THREAD_FOREGROUND); // Sum of all children durations: thread_item->setTimeSmart(COL_SELF_DURATION, _units, block.root->profiled_time); @@ -442,10 +440,7 @@ void EasyTreeWidgetLoader::setTreeInternal2(const ::profiler::timestamp_t& _begi } const auto color = easyDescriptor(gui_block.tree.node->id()).color(); - //const auto bgColor = ::profiler_gui::fromProfilerRgb(::profiler::colors::get_red(color), ::profiler::colors::get_green(color), ::profiler::colors::get_blue(color)); - const auto fgColor = ::profiler_gui::textColorForRgb(color);//0x00ffffff - bgColor; item->setBackgroundColor(color); - item->setTextColor(fgColor); #ifdef EASY_TREE_WIDGET__USE_VECTOR auto item_index = static_cast(m_items.size()); @@ -693,10 +688,7 @@ size_t EasyTreeWidgetLoader::setTreeInternal(const ::profiler::BlocksTreeRoot& _ } const auto color = easyDescriptor(child.node->id()).color(); - //const auto bgColor = ::profiler_gui::fromProfilerRgb(::profiler::colors::get_red(color), ::profiler::colors::get_green(color), ::profiler::colors::get_blue(color)); - const auto fgColor = ::profiler_gui::textColorForRgb(color);// 0x00ffffff - bgColor; item->setBackgroundColor(color); - item->setTextColor(fgColor); #ifdef EASY_TREE_WIDGET__USE_VECTOR auto item_index = static_cast(m_items.size()); @@ -931,9 +923,7 @@ size_t EasyTreeWidgetLoader::setTreeInternalPlain(const ::profiler::BlocksTreeRo } const auto color = easyDescriptor(child.node->id()).color(); - const auto fgColor = ::profiler_gui::textColorForRgb(color);// 0x00ffffff - bgColor; item->setBackgroundColor(color); - item->setTextColor(fgColor); #ifdef EASY_TREE_WIDGET__USE_VECTOR auto item_index = static_cast(m_items.size());