0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-27 08:41:02 +08:00

[ui] fixed search text highlighting, renamed some menu actions

This commit is contained in:
Victor Zarubkin 2019-10-29 23:50:55 +03:00
parent 357ac45834
commit 7d0c04bd73
3 changed files with 129 additions and 39 deletions

View File

@ -897,11 +897,11 @@ void BlocksTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
if (!m_items.empty()) if (!m_items.empty())
{ {
action = menu.addAction("Expand all"); action = menu.addAction("Expand All");
connect(action, &QAction::triggered, this, &This::onExpandAllClicked); connect(action, &QAction::triggered, this, &This::onExpandAllClicked);
action->setIcon(QIcon(imagePath("expand"))); action->setIcon(QIcon(imagePath("expand")));
action = menu.addAction("Collapse all"); action = menu.addAction("Collapse All");
connect(action, &QAction::triggered, this, &This::onCollapseAllClicked); connect(action, &QAction::triggered, this, &This::onCollapseAllClicked);
action->setIcon(QIcon(imagePath("collapse"))); action->setIcon(QIcon(imagePath("collapse")));
@ -909,11 +909,11 @@ void BlocksTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
{ {
menu.addSeparator(); menu.addSeparator();
action = menu.addAction("Expand all children"); action = menu.addAction("Expand All Children");
connect(action, &QAction::triggered, this, &This::onExpandAllChildrenClicked); connect(action, &QAction::triggered, this, &This::onExpandAllChildrenClicked);
action->setIcon(QIcon(imagePath("expand"))); action->setIcon(QIcon(imagePath("expand")));
action = menu.addAction("Collapse all children"); action = menu.addAction("Collapse All Children");
connect(action, &QAction::triggered, this, &This::onCollapseAllChildrenClicked); connect(action, &QAction::triggered, this, &This::onCollapseAllChildrenClicked);
action->setIcon(QIcon(imagePath("collapse"))); action->setIcon(QIcon(imagePath("collapse")));
} }
@ -924,21 +924,21 @@ void BlocksTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
auto actionGroup = new QActionGroup(&menu); auto actionGroup = new QActionGroup(&menu);
actionGroup->setExclusive(true); actionGroup->setExclusive(true);
auto actionHierarchy = new QAction("Call-stack", actionGroup); auto actionHierarchy = new QAction("Call-Stack", actionGroup);
actionHierarchy->setCheckable(true); actionHierarchy->setCheckable(true);
actionHierarchy->setChecked(m_mode == TreeMode::Full); actionHierarchy->setChecked(m_mode == TreeMode::Full);
actionHierarchy->setToolTip("Display full call stack"); actionHierarchy->setToolTip("Display Full Call Stack");
actionHierarchy->setData((quint32)TreeMode::Full); actionHierarchy->setData((quint32)TreeMode::Full);
menu.addAction(actionHierarchy); menu.addAction(actionHierarchy);
auto actionPlain = new QAction("Per-frame stats", actionGroup); auto actionPlain = new QAction("Per-Frame Stats", actionGroup);
actionPlain->setCheckable(true); actionPlain->setCheckable(true);
actionPlain->setChecked(m_mode == TreeMode::Plain); actionPlain->setChecked(m_mode == TreeMode::Plain);
actionPlain->setToolTip("Display plain list of blocks per frame.\nSome columns are disabled with this mode."); actionPlain->setToolTip("Display plain list of blocks per frame.\nSome columns are disabled with this mode.");
actionPlain->setData((quint32)TreeMode::Plain); actionPlain->setData((quint32)TreeMode::Plain);
menu.addAction(actionPlain); menu.addAction(actionPlain);
auto actionSelectedArea = new QAction("Aggregate stats", actionGroup); auto actionSelectedArea = new QAction("Aggregate Stats", actionGroup);
actionSelectedArea->setCheckable(true); actionSelectedArea->setCheckable(true);
actionSelectedArea->setChecked(m_mode == TreeMode::SelectedArea); actionSelectedArea->setChecked(m_mode == TreeMode::SelectedArea);
actionSelectedArea->setToolTip("Display aggregate stats for selected area.\nSome columns are disabled with this mode."); actionSelectedArea->setToolTip("Display aggregate stats for selected area.\nSome columns are disabled with this mode.");
@ -968,17 +968,19 @@ void BlocksTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
{ {
auto& block = item->block(); auto& block = item->block();
auto i = profiler_gui::numeric_max<uint32_t>(); auto i = profiler_gui::numeric_max<uint32_t>();
QString name;
switch (col) switch (col)
{ {
case COL_MIN_PER_THREAD: i = block.per_thread_stats->min_duration_block; break; case COL_MIN_PER_THREAD: name = QStringLiteral("Min"); i = block.per_thread_stats->min_duration_block; break;
case COL_MIN_PER_PARENT: i = block.per_parent_stats->min_duration_block; break; case COL_MIN_PER_PARENT: name = QStringLiteral("Min"); i = block.per_parent_stats->min_duration_block; break;
case COL_MIN_PER_FRAME: i = block.per_frame_stats->min_duration_block; break; case COL_MIN_PER_FRAME: name = QStringLiteral("Min"); i = block.per_frame_stats->min_duration_block; break;
case COL_MAX_PER_THREAD: i = block.per_thread_stats->max_duration_block; break; case COL_MAX_PER_THREAD: name = QStringLiteral("Max"); i = block.per_thread_stats->max_duration_block; break;
case COL_MAX_PER_PARENT: i = block.per_parent_stats->max_duration_block; break; case COL_MAX_PER_PARENT: name = QStringLiteral("Max"); i = block.per_parent_stats->max_duration_block; break;
case COL_MAX_PER_FRAME: i = block.per_frame_stats->max_duration_block; break; case COL_MAX_PER_FRAME: name = QStringLiteral("Max"); i = block.per_frame_stats->max_duration_block; break;
case COL_MIN_PER_AREA: case COL_MIN_PER_AREA:
{ {
name = QStringLiteral("Min");
auto data = item->data(COL_MIN_PER_AREA, MinMaxBlockIndexRole); auto data = item->data(COL_MIN_PER_AREA, MinMaxBlockIndexRole);
if (!data.isNull()) if (!data.isNull())
i = data.toUInt(); i = data.toUInt();
@ -987,6 +989,7 @@ void BlocksTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
case COL_MAX_PER_AREA: case COL_MAX_PER_AREA:
{ {
name = QStringLiteral("Max");
auto data = item->data(COL_MAX_PER_AREA, MinMaxBlockIndexRole); auto data = item->data(COL_MAX_PER_AREA, MinMaxBlockIndexRole);
if (!data.isNull()) if (!data.isNull())
i = data.toUInt(); i = data.toUInt();
@ -997,9 +1000,9 @@ void BlocksTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
if (i != profiler_gui::numeric_max(i)) if (i != profiler_gui::numeric_max(i))
{ {
menu.addSeparator(); menu.addSeparator();
auto itemAction = new QAction("Jump to such item", nullptr); auto itemAction = new QAction(QString("Jump To %1 Item").arg(name), nullptr);
itemAction->setData(i); itemAction->setData(i);
itemAction->setToolTip("Jump to item with min/max duration (depending on clicked column)"); itemAction->setToolTip(QString("Jump to item with %1 duration").arg(name.toLower()));
connect(itemAction, &QAction::triggered, this, &This::onJumpToItemClicked); connect(itemAction, &QAction::triggered, this, &This::onJumpToItemClicked);
menu.addAction(itemAction); menu.addAction(itemAction);
} }
@ -1013,7 +1016,7 @@ void BlocksTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
} }
const auto& desc = easyDescriptor(item->block().node->id()); const auto& desc = easyDescriptor(item->block().node->id());
auto submenu = menu.addMenu("Block status"); auto submenu = menu.addMenu("Block Status");
submenu->setToolTipsVisible(true); submenu->setToolTipsVisible(true);
#define ADD_STATUS_ACTION(NameValue, StatusValue, ToolTipValue)\ #define ADD_STATUS_ACTION(NameValue, StatusValue, ToolTipValue)\
@ -1037,7 +1040,7 @@ void BlocksTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
submenu->setTitle(QString("%1 (connection needed)").arg(submenu->title())); submenu->setTitle(QString("%1 (connection needed)").arg(submenu->title()));
} }
auto hidemenu = menu.addMenu("Select columns"); auto hidemenu = menu.addMenu("Select Columns");
auto hdr = headerItem(); auto hdr = headerItem();
#define ADD_COLUMN_ACTION(i) \ #define ADD_COLUMN_ACTION(i) \

View File

@ -56,6 +56,8 @@
#include <QAbstractTextDocumentLayout> #include <QAbstractTextDocumentLayout>
#include <QAction> #include <QAction>
#include <QActionGroup> #include <QActionGroup>
#include <QApplication>
#include <QClipboard>
#include <QContextMenuEvent> #include <QContextMenuEvent>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QHeaderView> #include <QHeaderView>
@ -201,31 +203,63 @@ bool DescriptorsTreeItem::operator < (const Parent& _other) const
QVariant DescriptorsTreeItem::data(int _column, int _role) const QVariant DescriptorsTreeItem::data(int _column, int _role) const
{ {
if (_column == DESC_COL_TYPE) switch (_column)
{ {
if (_role == Qt::ToolTipRole) case DESC_COL_TYPE:
{ {
switch (m_type) if (_role == Qt::ToolTipRole)
{ {
case Type::File: return QStringLiteral("File"); switch (m_type)
case Type::Event: return QStringLiteral("Event"); {
case Type::Block: return QStringLiteral("Block"); case Type::File: return QStringLiteral("File");
case Type::Value: return QStringLiteral("Arbitrary Value"); case Type::Event: return QStringLiteral("Event");
case Type::Block: return QStringLiteral("Block");
case Type::Value: return QStringLiteral("Arbitrary Value");
}
} }
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");
case Type::Value: return QStringLiteral("V");
}
}
break;
} }
else if (_role == Qt::DisplayRole)
case DESC_COL_FILE_LINE:
{ {
switch (m_type) if (parent() != nullptr)
{ {
case Type::File: return QStringLiteral("F"); if (_role == Qt::ToolTipRole)
case Type::Event: return QStringLiteral("E"); {
case Type::Block: return QStringLiteral("B"); const int row = data(_column, Qt::UserRole).toInt();
case Type::Value: return QStringLiteral("V"); return QString("%1:%2").arg(parent()->data(_column, Qt::UserRole).toString()).arg(row);
}
else if (_role == Qt::DisplayRole)
{
const int row = data(_column, Qt::UserRole).toInt();
return QString("%1:%2").arg(parent()->text(_column)).arg(row);
}
} }
else if (_role == Qt::ToolTipRole)
{
return data(_column, Qt::UserRole).toString();
}
break;
}
default:
{
break;
} }
} }
return QTreeWidgetItem::data(_column, _role); return Parent::data(_column, _role);
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -393,11 +427,11 @@ void DescriptorsTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
QMenu menu; QMenu menu;
menu.setToolTipsVisible(true); menu.setToolTipsVisible(true);
auto action = menu.addAction("Expand all"); auto action = menu.addAction("Expand All");
action->setIcon(QIcon(imagePath("expand"))); action->setIcon(QIcon(imagePath("expand")));
connect(action, &QAction::triggered, this, &This::expandAll); connect(action, &QAction::triggered, this, &This::expandAll);
action = menu.addAction("Collapse all"); action = menu.addAction("Collapse All");
action->setIcon(QIcon(imagePath("collapse"))); action->setIcon(QIcon(imagePath("collapse")));
connect(action, &QAction::triggered, this, &This::collapseAll); connect(action, &QAction::triggered, this, &This::collapseAll);
@ -407,7 +441,7 @@ void DescriptorsTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
const auto& desc = easyDescriptor(static_cast<DescriptorsTreeItem*>(item)->desc()); const auto& desc = easyDescriptor(static_cast<DescriptorsTreeItem*>(item)->desc());
menu.addSeparator(); menu.addSeparator();
auto submenu = menu.addMenu("Change status"); auto submenu = menu.addMenu("Change Status");
submenu->setToolTipsVisible(true); submenu->setToolTipsVisible(true);
#define ADD_STATUS_ACTION(NameValue, StatusValue, ToolTipValue)\ #define ADD_STATUS_ACTION(NameValue, StatusValue, ToolTipValue)\
@ -431,6 +465,17 @@ void DescriptorsTreeWidget::contextMenuEvent(QContextMenuEvent* _event)
submenu->setTitle(QString("%1 (connection needed)").arg(submenu->title())); submenu->setTitle(QString("%1 (connection needed)").arg(submenu->title()));
} }
if (item != nullptr)
{
menu.addSeparator();
action = menu.addAction(QStringLiteral("Copy Full Path"));
connect(action, &QAction::triggered, [this, item] (bool) {
auto fileItem = item->parent() == nullptr ? item : item->parent();
auto fullName = fileItem->data(DESC_COL_FILE_LINE, Qt::UserRole).toString();
qApp->clipboard()->setText(fullName);
});
}
menu.exec(QCursor::pos()); menu.exec(QCursor::pos());
} }
@ -494,16 +539,47 @@ void DescriptorsTreeWidget::build()
memset(m_items.data(), 0, sizeof(void*) * m_items.size()); memset(m_items.data(), 0, sizeof(void*) * m_items.size());
const QSignalBlocker b(this); const QSignalBlocker b(this);
::profiler::block_id_t id = 0; profiler::block_id_t id = 0, count = 0;
QString commonDir;
for (auto desc : EASY_GLOBALS.descriptors) for (auto desc : EASY_GLOBALS.descriptors)
{ {
if (desc != nullptr) if (desc != nullptr)
{ {
++count;
auto& p = fileItems[desc->file()]; auto& p = fileItems[desc->file()];
if (p.item == nullptr) if (p.item == nullptr)
{ {
auto item = new DescriptorsTreeItem(0); auto item = new DescriptorsTreeItem(0);
item->setText(DESC_COL_FILE_LINE, QString(desc->file()).remove(QRegExp("^(\\.{2}\\\\+|\\/+)+"))); auto fullName = QString(desc->file()).remove(QRegExp("^(\\.{2}\\\\+)+")); // without leading "..\"
auto fileName = QString(desc->file()).remove(QRegExp("^(.+(\\\\|\\/)+)+"));
auto dir = fullName.left(fullName.length() - fileName.length());
if (count == 1)
{
commonDir = dir;
}
else if (!commonDir.isEmpty())
{
if (dir.length() < commonDir.length())
{
commonDir.truncate(dir.length());
}
int i = 0;
for (; i < commonDir.length(); ++i)
{
if (commonDir[i] != dir[i])
{
break;
}
}
commonDir.truncate(i);
}
item->setData(DESC_COL_FILE_LINE, Qt::UserRole, fullName);
item->setType(DescriptorsTreeItem::Type::File); item->setType(DescriptorsTreeItem::Type::File);
p.item = item; p.item = item;
} }
@ -512,7 +588,6 @@ void DescriptorsTreeWidget::build()
if (it == p.children.end()) if (it == p.children.end())
{ {
auto item = new DescriptorsTreeItem(desc->id(), p.item); auto item = new DescriptorsTreeItem(desc->id(), p.item);
item->setText(DESC_COL_FILE_LINE, QString::number(desc->line()));
item->setData(DESC_COL_FILE_LINE, Qt::UserRole, desc->line()); item->setData(DESC_COL_FILE_LINE, Qt::UserRole, desc->line());
item->setText(DESC_COL_NAME, desc->name()); item->setText(DESC_COL_NAME, desc->name());
@ -551,6 +626,8 @@ void DescriptorsTreeWidget::build()
for (auto& p : fileItems) for (auto& p : fileItems)
{ {
auto fullName = p.second.item->data(DESC_COL_FILE_LINE, Qt::UserRole).toString();
p.second.item->setText(DESC_COL_FILE_LINE, fullName.right(fullName.length() - commonDir.length()));
addTopLevelItem(p.second.item); addTopLevelItem(p.second.item);
if (m_expandedFilesTemp.find(p.first) != m_expandedFilesTemp.end()) if (m_expandedFilesTemp.find(p.first) != m_expandedFilesTemp.end())
p.second.item->setExpanded(true); p.second.item->setExpanded(true);
@ -1256,9 +1333,14 @@ void DescWidgetItemDelegate::highlightMatchingText(
QTextDocument doc; QTextDocument doc;
doc.setDefaultFont(painter->font()); doc.setDefaultFont(painter->font());
auto textOption = doc.defaultTextOption();
textOption.setWrapMode(QTextOption::NoWrap);
doc.setDefaultTextOption(textOption);
doc.setTextWidth(option.rect.width()); doc.setTextWidth(option.rect.width());
const auto elidedText = painter->fontMetrics().elidedText(text, Qt::ElideRight, std::max(option.rect.width(), 0)); const auto elidedText = painter->fontMetrics().elidedText(text, Qt::ElideRight, option.rect.width());
doc.setHtml(elidedText); doc.setHtml(elidedText);
TextHighlighter highlighter( TextHighlighter highlighter(

View File

@ -561,6 +561,11 @@ void TreeWidgetItemDelegate::highlightMatchingText(
QTextDocument doc; QTextDocument doc;
doc.setDefaultFont(painter->font()); doc.setDefaultFont(painter->font());
auto textOption = doc.defaultTextOption();
textOption.setWrapMode(QTextOption::NoWrap);
doc.setDefaultTextOption(textOption);
doc.setTextWidth(option.rect.width() - padding); doc.setTextWidth(option.rect.width() - padding);
const auto elidedText = painter->fontMetrics().elidedText(text, Qt::ElideRight, std::max(option.rect.width() - padding, 0)); const auto elidedText = painter->fontMetrics().elidedText(text, Qt::ElideRight, std::max(option.rect.width() - padding, 0));