d/control: Recommend gdb
[gammaray-debian.git] / util.cpp
blobf857df6445c885ffcba1fee866b00287b0c0ff53
1 /*
2 util.cpp
4 This file is part of GammaRay, the Qt application inspection and
5 manipulation tool.
7 Copyright (C) 2010-2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
8 Author: Volker Krause <volker.krause@kdab.com>
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "util.h"
25 #include "metatypedeclarations.h"
27 #include <QtCore/qobject.h>
28 #include <QtCore/QStringList>
29 #include <qsize.h>
30 #include <qpoint.h>
31 #include <qrect.h>
32 #include <qsizepolicy.h>
33 #include <qmetaobject.h>
34 #include <qtextformat.h>
35 #include <QGraphicsItem>
36 #include <QGraphicsWidget>
37 #include <QWidget>
38 #include <QDebug>
39 #include <QPainter>
40 #include <QDir>
41 #include <QIcon>
43 using namespace GammaRay;
45 namespace GammaRay {
46 class ProtectedExposer : public QObject
48 public:
49 using QObject::staticQtMetaObject;
53 QString Util::displayString(const QObject *object)
55 if (!object) {
56 return "QObject(0x0)";
58 if (object->objectName().isEmpty()) {
59 return QString::fromLatin1("%1 (%2)").
60 arg(addressToString(object)).
61 arg(object->metaObject()->className());
63 return object->objectName();
66 QString Util::addressToUid(const void *p)
68 return QString::number(reinterpret_cast<qlonglong>(p), 16);
71 static QString sizePolicyToString(QSizePolicy::Policy policy)
73 const int index = QSizePolicy::staticMetaObject.indexOfEnumerator("Policy");
74 const QMetaEnum metaEnum = QSizePolicy::staticMetaObject.enumerator(index);
75 return QString::fromLatin1(metaEnum.valueToKey(policy));
78 QString GammaRay::Util::variantToString(const QVariant &value)
80 switch (value.type()) {
81 case QVariant::Line:
82 return QString::fromUtf8("%1 x %2 → %3 x %4")
83 .arg(value.toLine().x1()).arg(value.toLine().y1())
84 .arg(value.toLine().x2()).arg(value.toLine().y2());
86 case QVariant::LineF:
87 return QString::fromUtf8("%1 x %2 → %3 x %4")
88 .arg(value.toLineF().x1()).arg(value.toLineF().y1())
89 .arg(value.toLineF().x2()).arg(value.toLineF().y2());
91 case QVariant::Point:
92 return QString::fromLatin1("%1x%2").
93 arg(value.toPoint().x()).
94 arg(value.toPoint().y());
96 case QVariant::PointF:
97 return QString::fromLatin1("%1x%2").
98 arg(value.toPointF().x()).
99 arg(value.toPointF().y());
101 case QVariant::Rect:
102 return QString::fromLatin1("%1x%2 %3x%4").
103 arg(value.toRect().x()).
104 arg(value.toRect().y()).
105 arg(value.toRect().width()).
106 arg(value.toRect().height());
108 case QVariant::RectF:
109 return QString::fromLatin1("%1x%2 %3x%4").
110 arg(value.toRectF().x()).
111 arg(value.toRectF().y()).
112 arg(value.toRectF().width()).
113 arg(value.toRectF().height());
115 case QVariant::Region:
117 const QRegion region = value.value<QRegion>();
118 if (region.isEmpty()) {
119 return QLatin1String("<empty>");
121 if (region.rectCount() == 1) {
122 return variantToString(region.rects().first());
123 } else {
124 return QString::fromLatin1("<%1 rects>").arg(region.rectCount());
128 case QVariant::Size:
129 return QString::fromLatin1("%1x%2").
130 arg(value.toSize().width()).
131 arg(value.toSize().height());
133 case QVariant::SizeF:
134 return QString::fromLatin1("%1x%2").
135 arg(value.toSizeF().width()).
136 arg(value.toSizeF().height());
138 case QVariant::SizePolicy:
139 return QString::fromLatin1("%1 x %2").
140 arg(sizePolicyToString(value.value<QSizePolicy>().horizontalPolicy())).
141 arg(sizePolicyToString(value.value<QSizePolicy>().verticalPolicy()));
143 case QVariant::StringList:
144 return value.toStringList().join(", ");
146 case QVariant::Transform:
148 const QTransform t = value.value<QTransform>();
149 return QString::fromLatin1("[%1 %2 %3, %4 %5 %6, %7 %8 %9]").
150 arg(t.m11()).arg(t.m12()).arg(t.m13()).
151 arg(t.m21()).arg(t.m22()).arg(t.m23()).
152 arg(t.m31()).arg(t.m32()).arg(t.m33());
154 default:
155 break;
158 // types with dynamic type ids
159 if (value.type() == qMetaTypeId<QTextLength>()) {
160 const QTextLength l = value.value<QTextLength>();
161 QString typeStr;
162 switch (l.type()) {
163 case QTextLength::VariableLength:
164 typeStr = QObject::tr("variable");
165 break;
166 case QTextLength::FixedLength:
167 typeStr = QObject::tr("fixed");
168 break;
169 case QTextLength::PercentageLength:
170 typeStr = QObject::tr("percentage");
171 break;
173 return QString::fromLatin1("%1 (%2)").arg(l.rawValue()).arg(typeStr);
176 if (value.userType() == qMetaTypeId<QPainterPath>()) {
177 const QPainterPath path = value.value<QPainterPath>();
178 if (path.isEmpty()) {
179 return QObject::tr("<empty>");
181 return QObject::tr("<%1 elements>").arg(path.elementCount());
184 if (value.type() == qMetaTypeId<QWidget*>()) {
185 return displayString(value.value<QWidget*>());
188 if (value.userType() == qMetaTypeId<QGraphicsEffect*>()) {
189 return addressToString(value.value<QGraphicsEffect*>());
191 if (value.userType() == qMetaTypeId<QGraphicsItem*>()) {
192 return addressToString(value.value<QGraphicsItem*>());
194 if (value.userType() == qMetaTypeId<QGraphicsItemGroup*>()) {
195 return addressToString(value.value<QGraphicsItemGroup*>());
197 if (value.userType() == qMetaTypeId<QGraphicsObject*>()) {
198 return displayString(value.value<QGraphicsObject*>());
200 if (value.userType() == qMetaTypeId<QGraphicsWidget*>()) {
201 return displayString(value.value<QGraphicsWidget*>());
203 if (value.userType() == qMetaTypeId<const QStyle*>()) {
204 return displayString(value.value<const QStyle*>());
207 // enums
208 const QString enumStr = enumToString(value);
209 if (!enumStr.isEmpty()) {
210 return enumStr;
213 return value.toString();
216 QVariant Util::decorationForVariant(const QVariant &value)
218 switch (value.type()) {
219 case QVariant::Brush:
221 const QBrush b = value.value<QBrush>();
222 if (b.style() != Qt::NoBrush) {
223 QPixmap p(16, 16);
224 p.fill(QColor(0, 0, 0, 0));
225 QPainter painter(&p);
226 painter.setBrush(b);
227 painter.drawRect(0, 0, p.width() - 1, p.height() - 1);
228 return p;
231 case QVariant::Color:
233 const QColor c = value.value<QColor>();
234 if (c.isValid()) {
235 QPixmap p(16, 16);
236 QPainter painter(&p);
237 painter.setBrush(QBrush(c));
238 painter.drawRect(0, 0, p.width() - 1, p.height() - 1);
239 return p;
242 case QVariant::Cursor:
244 const QCursor c = value.value<QCursor>();
245 if (!c.pixmap().isNull()) {
246 return c.pixmap().scaled(16, 16, Qt::KeepAspectRatio, Qt::FastTransformation);
249 case QVariant::Icon:
251 return value;
253 case QVariant::Pen:
255 const QPen pen = value.value<QPen>();
256 if (pen.style() != Qt::NoPen) {
257 QPixmap p(16, 16);
258 p.fill(QColor(0, 0, 0, 0));
259 QPainter painter(&p);
260 painter.setPen(pen);
261 painter.translate(0, 8 - pen.width() / 2);
262 painter.drawLine(0, 0, p.width(), 0);
263 return p;
266 case QVariant::Pixmap:
268 const QPixmap p = value.value<QPixmap>();
269 return QVariant::fromValue(p.scaled(16, 16, Qt::KeepAspectRatio, Qt::FastTransformation));
271 default: break;
274 return QVariant();
277 QString Util::addressToString(const void *p)
279 return (QLatin1String("0x") + QString::number(reinterpret_cast<qlonglong>(p), 16));
282 QString Util::enumToString(const QVariant &value, const char *typeName, QObject *object)
284 QByteArray enumTypeName(typeName);
285 if (enumTypeName.isEmpty()) {
286 enumTypeName = value.typeName();
289 // strip of class name and namespace
290 const int pos = enumTypeName.lastIndexOf("::");
291 if (pos >= 0) {
292 enumTypeName = enumTypeName.mid(pos + 2);
295 const QMetaObject *mo = &ProtectedExposer::staticQtMetaObject;
296 int enumIndex = mo->indexOfEnumerator(enumTypeName);
297 if (enumIndex < 0 && object) {
298 mo = object->metaObject();
299 enumIndex = mo->indexOfEnumerator(enumTypeName);
301 if (enumIndex < 0) {
302 return QString();
305 const QMetaEnum me = mo->enumerator(enumIndex);
306 if (!me.isValid()) {
307 return QString();
309 return me.valueToKeys(value.toInt());
312 bool Util::descendantOf(QObject *ascendant, QObject *obj)
314 QObject *parent = obj->parent();
315 if (!parent) {
316 return false;
318 if (parent == ascendant) {
319 return true;
321 return descendantOf(ascendant, parent);
324 namespace GammaRay {
325 static QString stringifyProperty(QObject *obj, const QString &propName)
327 const QVariant value = obj->property(propName.toLatin1());
328 const QMetaProperty mp =
329 obj->metaObject()->property(
330 obj->metaObject()->indexOfProperty(propName.toLatin1()));
331 if (mp.isValid()) {
332 const QString enumStr = Util::enumToString(value, mp.typeName(), obj);
333 if (!enumStr.isEmpty()) {
334 return enumStr;
337 return Util::variantToString(value);
340 static QVariant iconForObject(const QMetaObject *mo, QObject *obj)
342 const QString basePath = QString::fromLatin1(":/gammaray/classes/%1/").arg(mo->className());
343 const QDir dir(basePath);
344 if (dir.exists()) {
345 // see if we find one with exactly matching properties
346 foreach (const QString &entry,
347 dir.entryList(QStringList() << QLatin1String("*.png"), QDir::Files)) {
348 if (entry == QLatin1String("default.png")) {
349 continue;
351 QString propString(entry);
352 propString.chop(4);
353 const QStringList props = propString.split(QLatin1String(";"));
354 if (props.isEmpty()) {
355 continue;
357 bool allMatch = true;
358 foreach (const QString &prop, props) {
359 const QStringList keyValue = prop.split(QLatin1Char('='));
360 if (keyValue.size() != 2) {
361 continue;
363 if (stringifyProperty(obj, keyValue.first()) != keyValue.last()) {
364 allMatch = false;
365 break;
368 if (allMatch) {
369 return QIcon(basePath + entry);
372 return QIcon(basePath + QLatin1String("default.png"));
373 } else if (mo->superClass()) {
374 return iconForObject(mo->superClass(), obj);
376 return QVariant();
380 QVariant Util::iconForObject(QObject *obj)
382 if (obj) {
383 return GammaRay::iconForObject(obj->metaObject(), obj);
385 return QVariant();