File indexing completed on 2024-04-28 05:44:29
0001 /* 0002 This file is part of Massif Visualizer 0003 0004 Copyright 2010 Milian Wolff <mail@milianw.de> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Lesser General Public 0008 License as published by the Free Software Foundation; either 0009 version 2.1 of the License, or (at your option) version 3, or any 0010 later version accepted by the membership of KDE e.V. (or its 0011 successor approved by the membership of KDE e.V.), which shall 0012 act as a proxy defined in Section 6 of version 3 of the license. 0013 0014 This library is distributed in the hope that it will be useful, 0015 but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0017 Lesser General Public License for more details. 0018 0019 You should have received a copy of the GNU Lesser General Public 0020 License along with this library. If not, see <http://www.gnu.org/licenses/>. 0021 */ 0022 0023 #include "util.h" 0024 0025 #include "snapshotitem.h" 0026 #include "treeleafitem.h" 0027 0028 #include <KSharedConfig> 0029 #include <KLocalizedString> 0030 #include <KConfigGroup> 0031 #include <KFormat> 0032 0033 namespace Massif { 0034 0035 QString prettyCost(quint64 cost) 0036 { 0037 Q_ASSERT(KSharedConfig::openConfig()); 0038 KConfigGroup conf = KSharedConfig::openConfig()->group(QLatin1String("Settings")); 0039 int precision = conf.readEntry(QLatin1String("prettyCostPrecision"), 1); 0040 KFormat format(QLocale::system()); 0041 return format.formatByteSize(cost, precision); 0042 } 0043 0044 QByteArray shortenTemplates(const QByteArray& identifier) 0045 { 0046 QByteArray ret = identifier; 0047 Q_ASSERT(KSharedConfig::openConfig()); 0048 KConfigGroup conf = KSharedConfig::openConfig()->group(QLatin1String("Settings")); 0049 if (conf.readEntry(QLatin1String("shortenTemplates"), false)) { 0050 // remove template arguments between <...> 0051 int depth = 0; 0052 int open = 0; 0053 for (int i = 0; i < ret.length(); ++i) { 0054 if (ret.at(i) == '<') { 0055 if (!depth) { 0056 open = i; 0057 } 0058 ++depth; 0059 } else if (ret.at(i) == '>') { 0060 --depth; 0061 if (!depth) { 0062 ret.remove(open + 1, i - open - 1); 0063 i = open + 1; 0064 open = 0; 0065 } 0066 } 0067 } 0068 } 0069 return ret; 0070 } 0071 0072 ParsedLabel parseLabel(const QByteArray& label) 0073 { 0074 ParsedLabel ret; 0075 int functionStart = 0; 0076 int functionEnd = label.length(); 0077 if (label.startsWith("0x")) { 0078 int colonPos = label.indexOf(": "); 0079 if (colonPos != -1) { 0080 ret.address = label.left(colonPos); 0081 functionStart = colonPos + 2; 0082 } 0083 } 0084 if (label.endsWith(')')) { 0085 int locationPos = label.lastIndexOf(" ("); 0086 if (locationPos != -1) { 0087 ret.location = label.mid(locationPos + 2, label.length() - locationPos - 3); 0088 functionEnd = locationPos; 0089 } 0090 } 0091 ret.function = label.mid(functionStart, functionEnd - functionStart); 0092 return ret; 0093 } 0094 0095 uint qHash(const ParsedLabel& label) 0096 { 0097 return qHash(label.function) + 17 * qHash(label.location) + 19 * qHash(label.address); 0098 } 0099 0100 QByteArray prettyLabel(const QByteArray& label) 0101 { 0102 ParsedLabel parsed = parseLabel(label); 0103 const QByteArray func = shortenTemplates(parsed.function); 0104 0105 if (!parsed.location.isEmpty()) { 0106 return func + " (" + parsed.location + ")"; 0107 } else { 0108 return func; 0109 } 0110 } 0111 0112 QByteArray functionInLabel(const QByteArray& label) 0113 { 0114 return parseLabel(label).function; 0115 } 0116 0117 QByteArray addressInLabel(const QByteArray& label) 0118 { 0119 return parseLabel(label).address; 0120 } 0121 0122 QByteArray locationInLabel(const QByteArray& label) 0123 { 0124 return parseLabel(label).location; 0125 } 0126 0127 bool isBelowThreshold(const QByteArray& label) 0128 { 0129 return label.indexOf("all below massif's threshold") != -1; 0130 } 0131 0132 QString formatLabelForTooltip(const ParsedLabel& parsed) 0133 { 0134 QString ret; 0135 if (!parsed.function.isEmpty()) { 0136 ret += i18n("<dt>function:</dt><dd>%1</dd>\n", QString::fromUtf8(parsed.function).toHtmlEscaped()); 0137 } 0138 if (!parsed.location.isEmpty()) { 0139 ret += i18n("<dt>location:</dt><dd>%1</dd>\n", QString::fromUtf8(parsed.location).toHtmlEscaped()); 0140 } 0141 if (!parsed.address.isEmpty()) { 0142 ret += i18n("<dt>address:</dt><dd>%1</dd>\n", QString::fromUtf8(parsed.address).toHtmlEscaped()); 0143 } 0144 return ret; 0145 } 0146 0147 QString finalizeTooltip(const QString& contents) 0148 { 0149 return QLatin1String("<html><head><style>dt{font-weight:bold;} dd {font-family:monospace;}</style></head><body><dl>\n") 0150 + contents + QLatin1String("</dl></body></html>"); 0151 } 0152 0153 QString tooltipForTreeLeaf(const TreeLeafItem* node, const SnapshotItem* snapshot, const QByteArray& label) 0154 { 0155 QString tooltip = i18n("<dt>cost:</dt><dd>%1, i.e. %2% of snapshot #%3</dd>", prettyCost(node ? node->cost() : 0), 0156 // yeah nice how I round to two decimals, right? :D 0157 double(int(double(node ? node->cost() : 0)/snapshot->cost()*10000))/100, snapshot->number()); 0158 tooltip += formatLabelForTooltip(parseLabel(label)); 0159 return finalizeTooltip(tooltip); 0160 } 0161 0162 }