Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tooltips for each of the models. #41

Merged
merged 1 commit into from
Apr 10, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/models/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ add_library(models STATIC
data.cpp
callercalleemodel.cpp
costdelegate.cpp
../util.cpp
)

target_link_libraries(models
Expand Down
54 changes: 37 additions & 17 deletions src/models/callercalleemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
*/

#include "callercalleemodel.h"
#include "../util.h"

CallerCalleeModel::CallerCalleeModel(QObject* parent)
: HashModel(parent)
Expand All @@ -42,30 +43,45 @@ QVariant CallerCalleeModel::headerCell(Columns column, int role)
return Qt::DescendingOrder;
}
}
if (role != Qt::DisplayRole) {
if (role != Qt::DisplayRole && role != Qt::ToolTipRole) {
return {};
}

switch (column) {
case Symbol:
return tr("Symbol");
case Binary:
return tr("Binary");
case SelfCost:
return tr("Self Cost");
case InclusiveCost:
return tr("Inclusive Cost");
case Callers:
return tr("Callers");
case Callees:
return tr("Callees");
if (role == Qt::DisplayRole) {
switch (column) {
case Symbol:
return tr("Symbol");
case Binary:
return tr("Binary");
case SelfCost:
return tr("Self Cost");
case InclusiveCost:
return tr("Inclusive Cost");
case Callers:
return tr("Callers");
case Callees:
return tr("Callees");
}
} else if (role == Qt::ToolTipRole) {
switch (column) {
case Symbol:
return tr("The symbol's function name. May be empty when debug information is missing.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are the native speaker, but isn't it "The symbols function name", i.e. without the apostroph?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"The symbol's function name." is correct. The apostrophe is used to show possession. i.e. "This is the function name of the symbol." is equal to "The symbol's function name."

case Binary:
return tr("The name of the executable the symbol resides in. May be empty when debug information is missing.");
case SelfCost:
return tr("The number of samples directly attributed to this symbol.");
case InclusiveCost:
return tr("The number of samples attributed to this symbol, both directly and indirectly. This includes the costs of all functions called by this symbol plus its self cost.");
default:
break;
}
}

return {};
}

QVariant CallerCalleeModel::cell(Columns column, int role, const Data::Symbol& symbol,
const Data::CallerCalleeEntry& entry)
const Data::CallerCalleeEntry& entry, quint64 sampleCount)
{
if (role == SortRole) {
switch (column) {
Expand Down Expand Up @@ -107,10 +123,14 @@ QVariant CallerCalleeModel::cell(Columns column, int role, const Data::Symbol& s
return QVariant::fromValue(entry.callers);
} else if (role == SourceMapRole) {
return QVariant::fromValue(entry.sourceMap);
} else if (role == Qt::ToolTipRole) {
QString toolTip = tr("%1 in %2\nself cost: %3 out of %4 total samples (%5%)\ninclusive cost: %6 out of %7 total samples (%8%)").arg(
Util::formatString(symbol.symbol), Util::formatString(symbol.binary),
Util::formatCost(entry.selfCost.samples), Util::formatCost(sampleCount), Util::formatCostRelative(entry.selfCost.samples, sampleCount),
Util::formatCost(entry.inclusiveCost.samples), Util::formatCost(sampleCount), Util::formatCostRelative(entry.inclusiveCost.samples, sampleCount));
return toolTip;
}

// TODO: tooltips

return {};
}

Expand Down
68 changes: 47 additions & 21 deletions src/models/callercalleemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class CallerCalleeModel : public HashModel<Data::CallerCalleeEntryMap, CallerCal

static QVariant headerCell(Columns column, int role);
static QVariant cell(Columns column, int role, const Data::Symbol& symbol,
const Data::CallerCalleeEntry& entry);
const Data::CallerCalleeEntry& entry, quint64 sampleCount);
QModelIndex indexForSymbol(const Data::Symbol& symbol) const;
};

Expand Down Expand Up @@ -99,24 +99,35 @@ class SymbolCostModelImpl : public HashModel<Data::SymbolCostMap, ModelImpl>
if (role == Qt::InitialSortOrderRole && column == Cost) {
return Qt::DescendingOrder;
}
if (role != Qt::DisplayRole) {
if (role != Qt::DisplayRole && role != Qt::ToolTipRole) {
return {};
}

switch (column) {
case Symbol:
return ModelImpl::symbolHeader();
case Binary:
return QObject::tr("Binary");
case Cost:
return QObject::tr("Cost");
if (role == Qt::DisplayRole) {
switch (column) {
case Symbol:
return ModelImpl::symbolHeader();
case Binary:
return QObject::tr("Binary");
case Cost:
return QObject::tr("Cost");
}
} else if (role == Qt::ToolTipRole) {
switch (column) {
case Symbol:
return QObject::tr("The function name of the %1. May be empty when debug information is missing.").arg(ModelImpl::symbolHeader());
case Binary:
return QObject::tr("The name of the executable the symbol resides in. May be empty when debug information is missing.");
case Cost:
return QObject::tr("The symbol's inclusive cost, i.e. the number of samples attributed to this symbol, both directly and indirectly.");
}
}

return {};
}

static QVariant cell(Columns column, int role, const Data::Symbol& symbol,
const Data::Cost& cost)
const Data::Cost& cost, quint64 sampleCount)
{
if (role == SortRole) {
switch (column) {
Expand All @@ -142,10 +153,13 @@ class SymbolCostModelImpl : public HashModel<Data::SymbolCostMap, ModelImpl>
}
} else if (role == SymbolRole) {
return QVariant::fromValue(symbol);
} else if (role == Qt::ToolTipRole) {
QString toolTip = QObject::tr("%1 in %2\ncost: %3 out of %4 total samples (%5%)").arg(
Util::formatString(symbol.symbol), Util::formatString(symbol.binary),
Util::formatCost(cost.samples), Util::formatCost(sampleCount), Util::formatCostRelative(cost.samples, sampleCount));
return toolTip;
}

// TODO: tooltips

return {};
}
};
Expand Down Expand Up @@ -201,22 +215,32 @@ class LocationCostModelImpl : public HashModel<Data::LocationCostMap, ModelImpl>
if (role == Qt::InitialSortOrderRole && column == Cost) {
return Qt::DescendingOrder;
}
if (role != Qt::DisplayRole) {

if (role != Qt::DisplayRole && role != Qt::ToolTipRole) {
return {};
}

switch (column) {
case Location:
return QObject::tr("Location");
case Cost:
return QObject::tr("Cost");
if (role == Qt::DisplayRole) {
switch (column) {
case Location:
return QObject::tr("Location");
case Cost:
return QObject::tr("Cost");
}
} else if (role == Qt::ToolTipRole) {
switch (column) {
case Location:
return QObject::tr("The source file name and line number where the cost was measured. May be empty when debug information is missing.");
case Cost:
return QObject::tr("The number of samples directly attributed to this code location.");
}
}

return {};
}

static QVariant cell(Columns column, int role, const QString& location,
const Data::Cost& cost)
const Data::Cost& cost, quint64 sampleCount)
{
if (role == SortRole) {
switch (column) {
Expand All @@ -237,10 +261,12 @@ class LocationCostModelImpl : public HashModel<Data::LocationCostMap, ModelImpl>
}
} else if (role == LocationRole) {
return QVariant::fromValue(location);
} else if (role == Qt::ToolTipRole) {
QString toolTip = QObject::tr("%1\ncost: %2 out of %3 total samples (%4%)").arg(
Util::formatString(location), Util::formatCost(cost.samples), Util::formatCost(sampleCount), Util::formatCostRelative(cost.samples, sampleCount));
return toolTip;
}

// TODO: tooltips

return {};
}
};
Expand Down
2 changes: 1 addition & 1 deletion src/models/hashmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class HashModel : public QAbstractTableModel
std::advance(it, index.row());

const auto column = static_cast<typename ModelImpl::Columns>(index.column());
return ModelImpl::cell(column, role, it.key(), it.value());
return ModelImpl::cell(column, role, it.key(), it.value(), m_sampleCount);
}

using QAbstractTableModel::setData;
Expand Down
48 changes: 48 additions & 0 deletions src/models/treemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
*/

#include "treemodel.h"
#include "../util.h"

AbstractTreeModel::AbstractTreeModel(QObject* parent)
: QAbstractItemModel(parent)
Expand Down Expand Up @@ -55,6 +56,20 @@ QString BottomUpModel::headerTitle(Columns column)
return {};
}

QString BottomUpModel::headerToolTip(Columns column)
{
switch (column) {
case Symbol:
return tr("The symbol's function name. May be empty when debug information is missing.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apostrophe or not?

case Binary:
return tr("The name of the executable the symbol resides in. May be empty when debug information is missing.");
case Cost:
return tr("The symbol's inclusive cost, i.e. the number of samples attributed to this symbol, both directly and indirectly.");
}
Q_UNREACHABLE();
return {};
}

QVariant BottomUpModel::displayData(const Data::BottomUp* row, Columns column)
{
switch (column) {
Expand All @@ -69,6 +84,14 @@ QVariant BottomUpModel::displayData(const Data::BottomUp* row, Columns column)
return {};
}

QVariant BottomUpModel::displayToolTip(const Data::BottomUp* row, quint64 sampleCount)
{
QString toolTip = tr("%1 in %2\ncost: %3 out of %4 total samples (%5%)").arg(
Util::formatString(row->symbol.symbol), Util::formatString(row->symbol.binary),
Util::formatCost(row->cost.samples), Util::formatCost(sampleCount), Util::formatCostRelative(row->cost.samples, sampleCount));
return toolTip;
}

TopDownModel::TopDownModel(QObject* parent)
: TreeModel(parent)
{
Expand All @@ -92,6 +115,22 @@ QString TopDownModel::headerTitle(Columns column)
return {};
}

QString TopDownModel::headerToolTip(Columns column)
{
switch (column) {
case Symbol:
return tr("The symbol's function name. May be empty when debug information is missing.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here again: apostrophe or not?

case Binary:
return tr("The name of the executable the symbol resides in. May be empty when debug information is missing.");
case InclusiveCost:
return tr("The number of samples attributed to this symbol, both directly and indirectly. This includes the costs of all functions called by this symbol plus its self cost.");
case SelfCost:
return tr("The number of samples directly attributed to this symbol.");
}
Q_UNREACHABLE();
return {};
}

QVariant TopDownModel::displayData(const Data::TopDown* row, Columns column)
{
switch (column) {
Expand All @@ -107,3 +146,12 @@ QVariant TopDownModel::displayData(const Data::TopDown* row, Columns column)
Q_UNREACHABLE();
return {};
}

QVariant TopDownModel::displayToolTip(const Data::TopDown* row, quint64 sampleCount)
{
QString toolTip = tr("%1 in %2\nself cost: %3 out of %4 total samples (%5%)\ninclusive cost: %6 out of %7 total samples (%8%)").arg(
Util::formatString(row->symbol.symbol), Util::formatString(row->symbol.binary),
Util::formatCost(row->selfCost.samples), Util::formatCost(sampleCount), Util::formatCostRelative(row->selfCost.samples, sampleCount),
Util::formatCost(row->inclusiveCost.samples), Util::formatCost(sampleCount), Util::formatCostRelative(row->inclusiveCost.samples, sampleCount));
return toolTip;
}
14 changes: 12 additions & 2 deletions src/models/treemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,17 @@ class TreeModel : public AbstractTreeModel

QVariant headerData(int section, Qt::Orientation orientation, int role) const final override
{
if (role != Qt::DisplayRole || orientation != Qt::Horizontal
if ((role != Qt::DisplayRole && role != Qt::ToolTipRole) || orientation != Qt::Horizontal
|| section < 0 || section > ModelImpl::NUM_COLUMNS)
{
return {};
}

return ModelImpl::headerTitle(static_cast<typename ModelImpl::Columns>(section));
if (role == Qt::ToolTipRole) {
return ModelImpl::headerToolTip(static_cast<typename ModelImpl::Columns>(section));
} else {
return ModelImpl::headerTitle(static_cast<typename ModelImpl::Columns>(section));
}
}

QVariant data(const QModelIndex& index, int role) const final override
Expand All @@ -146,6 +150,8 @@ class TreeModel : public AbstractTreeModel
return m_sampleCount;
} else if (role == SymbolRole) {
return QVariant::fromValue(item->symbol);
} else if (role == Qt::ToolTipRole) {
return ModelImpl::displayToolTip(item, m_sampleCount);
}

// TODO: tooltips
Expand Down Expand Up @@ -205,7 +211,9 @@ class BottomUpModel : public TreeModel<Data::BottomUp, BottomUpModel>
};

static QString headerTitle(Columns column);
static QString headerToolTip(Columns column);
static QVariant displayData(const Data::BottomUp* row, Columns column);
static QVariant displayToolTip(const Data::BottomUp* row, quint64 sampleCount);
};

class TopDownModel : public TreeModel<Data::TopDown, TopDownModel>
Expand All @@ -227,5 +235,7 @@ class TopDownModel : public TreeModel<Data::TopDown, TopDownModel>
};

static QString headerTitle(Columns column);
static QString headerToolTip(Columns column);
static QVariant displayData(const Data::TopDown* row, Columns column);
static QVariant displayToolTip(const Data::TopDown* row, quint64 sampleCount);
};
15 changes: 15 additions & 0 deletions src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,18 @@ QString Util::findLibexecBinary(const QString& name)
}
return info.absoluteFilePath();
}

QString Util::formatString(const QString& input)
{
return input.isEmpty() ? QObject::tr("??") : input;
}

QString Util::formatCost(quint32 cost)
{
return QString::number(cost);
}

QString Util::formatCostRelative(quint32 selfCost, quint64 totalCost)
{
return QString::number(double(selfCost) * 100. / totalCost, 'g', 3);
}
4 changes: 4 additions & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,8 @@ struct HashCombine {
{ return seed ^ (qHash(t) + 0x9e3779b9 + (seed << 6) + (seed >> 2)) ; }
};

QString formatString(const QString& input);
QString formatCost(quint32 cost);
QString formatCostRelative(quint32 selfCost, quint64 totalCost);

}