1
# -*- coding: iso-8859-1 -*-
2
# Pretty-printers for Qt4.
4
# Copyright (C) 2009 Niko Sams <niko.sams@gmail.com>
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with this program. If not, see <http://www.gnu.org/licenses/>.
25
def __init__(self, val):
31
size = self.val['d']['size']
33
# char = self.val['d']['data'][i]
35
# ret += "\\u%x" % int(char)
40
dataAsCharPointer = self.val['d']['data'].cast(gdb.lookup_type("char").pointer())
41
return dataAsCharPointer.string(encoding = 'UTF-16', length = size * 2)
43
def display_hint (self):
47
class QByteArrayPrinter:
49
def __init__(self, val):
53
def __init__(self, data, size):
62
if self.count >= self.size:
65
self.count = self.count + 1
66
return ('[%d]' % count, self.data[count])
69
return self._iterator(self.val['d']['data'], self.val['d']['size'])
72
#todo: handle charset correctly
73
return self.val['d']['data'].string()
75
def display_hint (self):
82
def __init__(self, nodetype, d):
83
self.nodetype = nodetype
91
if self.count >= self.d['end'] - self.d['begin']:
94
array = self.d['array'][self.d['begin'] + count]
96
#from QTypeInfo::isLarge
97
isLarge = self.nodetype.sizeof > gdb.lookup_type('void').pointer().sizeof
99
#isStatic is not needed anymore since Qt 4.6
100
#isPointer = self.nodetype.code == gdb.TYPE_CODE_PTR
102
##unfortunately we can't use QTypeInfo<T>::isStatic as it's all inlined, so use
103
##this list of types that use Q_DECLARE_TYPEINFO(T, Q_MOVABLE_TYPE)
104
##(obviously it won't work for custom types)
105
#movableTypes = ['QRect', 'QRectF', 'QString', 'QMargins', 'QLocale', 'QChar', 'QDate', 'QTime', 'QDateTime', 'QVector',
106
# 'QRegExpr', 'QPoint', 'QPointF', 'QByteArray', 'QSize', 'QSizeF', 'QBitArray', 'QLine', 'QLineF', 'QModelIndex', 'QPersitentModelIndex',
107
# 'QVariant', 'QFileInfo', 'QUrl', 'QXmlStreamAttribute', 'QXmlStreamNamespaceDeclaration', 'QXmlStreamNotationDeclaration',
108
# 'QXmlStreamEntityDeclaration']
109
#if movableTypes.count(self.nodetype.tag):
112
# isStatic = not isPointer
115
if isLarge or isStatic: #see QList::Node::t()
116
node = array.cast(gdb.lookup_type('QList<%s>::Node' % self.nodetype).pointer())
118
node = array.cast(gdb.lookup_type('QList<%s>::Node' % self.nodetype))
119
self.count = self.count + 1
120
return ('[%d]' % count, node['v'].cast(self.nodetype))
122
def __init__(self, val, itype):
125
self.itype = self.val.type.template_argument(0)
127
self.itype = gdb.lookup_type(itype)
130
return self._iterator(self.itype, self.val['d'])
133
if self.val['d']['end'] == self.val['d']['begin']:
138
return "%sQList<%s>" % ( empty , self.itype )
144
def __init__(self, val):
146
self.ktype = self.val.type.template_argument(0)
147
self.vtype = self.val.type.template_argument(1)
148
self.data_node = self.val['e']['forward'][0]
156
#we can't use QMapPayloadNode as it's inlined
157
#as a workaround take the sum of sizeof(members)
158
ret = self.ktype.sizeof
159
ret += self.vtype.sizeof
160
ret += gdb.lookup_type('void').pointer().sizeof
162
#but because of data alignment the value can be higher
163
#so guess it's aliged by sizeof(void*)
164
#TODO: find a real solution for this problem
165
ret += ret % gdb.lookup_type('void').pointer().sizeof
167
ret -= gdb.lookup_type('void').pointer().sizeof
170
def concrete (self, data_node):
171
node_type = gdb.lookup_type('QMapNode<%s, %s>' % (self.ktype, self.vtype)).pointer()
172
return (data_node.cast(gdb.lookup_type('char').pointer()) - self.payload()).cast(node_type)
175
if self.data_node == self.val['e']:
177
node = self.concrete(self.data_node).dereference()
178
if self.count % 2 == 0:
182
self.data_node = node['forward'][0]
184
result = ('[%d]' % self.count, item)
185
self.count = self.count + 1
189
def __init__(self, val):
193
return self._iterator(self.val)
196
if self.val['d']['size'] == 0:
201
return "%sQMap<%s, %s>" % ( empty , self.val.type.template_argument(0), self.val.type.template_argument(1) )
203
def display_hint (self):
210
def __init__(self, val):
212
self.d = self.val['d']
213
self.ktype = self.val.type.template_argument(0)
214
self.vtype = self.val.type.template_argument(1)
215
self.end_node = self.d.cast(gdb.lookup_type('QHashData::Node').pointer())
216
self.data_node = self.firstNode()
223
"Casts the current QHashData::Node to a QHashNode and returns the result. See also QHash::concrete()"
224
return self.data_node.cast(gdb.lookup_type('QHashNode<%s, %s>' % (self.ktype, self.vtype)).pointer())
226
def firstNode (self):
227
"Get the first node, See QHashData::firstNode()."
228
e = self.d.cast(gdb.lookup_type('QHashData::Node').pointer())
229
#print "QHashData::firstNode() e %s" % e
231
bucket = self.d['buckets'][bucketNum]
232
#print "QHashData::firstNode() *bucket %s" % bucket
233
n = self.d['numBuckets']
234
#print "QHashData::firstNode() n %s" % n
237
#print "QHashData::firstNode() in while, n %s" % n;
239
#print "QHashData::firstNode() in while, return *bucket %s" % bucket
242
bucket = self.d['buckets'][bucketNum]
243
#print "QHashData::firstNode() in while, new bucket %s" % bucket
245
#print "QHashData::firstNode() return e %s" % e
249
def nextNode (self, node):
250
"Get the nextNode after the current, see also QHashData::nextNode()."
251
#print "******************************** nextNode"
252
e = self.d.cast(gdb.lookup_type('QHashData::Node').pointer())
254
#print "nextNode: node %s" % node
257
#print "nextNode: next %s" % next
259
#return "nextNode: return next"
262
#print "nextNode: node->h %s" % node['h']
263
#print "nextNode: numBuckets %s" % self.d['numBuckets']
264
start = (node['h'] % self.d['numBuckets']) + 1
266
#print "nextNode: start %s" % start
267
bucket = self.d['buckets'][start]
268
#print "nextNode: bucket %s" % bucket
269
n = self.d['numBuckets'] - start
270
#print "nextNode: n %s" % n
272
#print "nextNode: in while; n %s" % n
273
#print "nextNode: in while; e %s" % e
274
#print "nextNode: in while; *bucket %s" % bucket
276
#print "nextNode: in while; return bucket %s" % bucket
279
bucket = self.d['buckets'][bucketNum]
281
#print "nextNode: return e %s" % e
285
"GDB iteration, first call returns key, second value and then jumps to the next hash node."
286
if self.data_node == self.end_node:
289
node = self.hashNode()
291
if self.count % 2 == 0:
295
self.data_node = self.nextNode(self.data_node)
297
self.count = self.count + 1
298
return ('[%d]' % self.count, item)
300
def __init__(self, val):
304
return self._iterator(self.val)
307
if self.val['d']['size'] == 0:
312
return "%sQMap<%s, %s>" % ( empty , self.val.type.template_argument(0), self.val.type.template_argument(1) )
314
def display_hint (self):
319
def __init__(self, val):
323
julianDay = self.val['jd']
326
return "invalid QDate"
328
# Copied from Qt sources
329
if julianDay >= 2299161:
330
# Gregorian calendar starting from October 15, 1582
331
# This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern
332
ell = julianDay + 68569;
333
n = (4 * ell) / 146097;
334
ell = ell - (146097 * n + 3) / 4;
335
i = (4000 * (ell + 1)) / 1461001;
336
ell = ell - (1461 * i) / 4 + 31;
337
j = (80 * ell) / 2447;
338
d = ell - (2447 * j) / 80;
340
m = j + 2 - (12 * ell);
341
y = 100 * (n - 49) + i + ell;
343
# Julian calendar until October 4, 1582
344
# Algorithm from Frequently Asked Questions about Calendars by Claus Toendering
346
dd = (4 * julianDay + 3) / 1461;
347
ee = julianDay - (1461 * dd) / 4;
348
mm = ((5 * ee) + 2) / 153;
349
d = ee - (153 * mm + 2) / 5 + 1;
350
m = mm + 3 - 12 * (mm / 10);
351
y = dd - 4800 + (mm / 10);
354
return "%d-%02d-%02d" % (y, m, d)
358
def __init__(self, val):
365
return "invalid QTime"
367
MSECS_PER_HOUR = 3600000
369
MSECS_PER_MIN = 60000
371
hour = ds / MSECS_PER_HOUR
372
minute = (ds % MSECS_PER_HOUR) / MSECS_PER_MIN
373
second = (ds / 1000)%SECS_PER_MIN
375
return "%02d:%02d:%02d.%03d" % (hour, minute, second, msec)
377
class QDateTimePrinter:
379
def __init__(self, val):
383
#val['d'] is a QDateTimePrivate, but for some reason casting to that doesn't work
384
#so work around by manually adjusting the pointer
385
date = self.val['d'].cast(gdb.lookup_type('char').pointer());
386
date += gdb.lookup_type('int').sizeof #increment for QAtomicInt ref;
387
date = date.cast(gdb.lookup_type('QDate').pointer()).dereference();
389
time = self.val['d'].cast(gdb.lookup_type('char').pointer());
390
time += gdb.lookup_type('int').sizeof + gdb.lookup_type('QDate').sizeof #increment for QAtomicInt ref; and QDate date;
391
time = time.cast(gdb.lookup_type('QTime').pointer()).dereference();
392
return "%s %s" % (date, time)
396
def __init__(self, val):
401
return self.val['d']['encodedOriginal']
402
except RuntimeError, error:
403
#if no debug information is avaliable for Qt, try guessing the correct address for encodedOriginal
404
#problem with this is that if QUrlPrivate members get changed, this fails
405
offset = gdb.lookup_type('int').sizeof
406
offset += offset % gdb.lookup_type('void').pointer().sizeof #alignment
407
offset += gdb.lookup_type('QString').sizeof * 6
408
offset += gdb.lookup_type('QByteArray').sizeof
409
encodedOriginal = self.val['d'].cast(gdb.lookup_type('char').pointer());
410
encodedOriginal += offset
411
encodedOriginal = encodedOriginal.cast(gdb.lookup_type('QByteArray').pointer()).dereference();
412
encodedOriginal = encodedOriginal['d']['data'].string()
413
return encodedOriginal
418
def __init__(self, val):
422
def __init__(self, hashIterator):
423
self.hashIterator = hashIterator
430
if self.hashIterator.data_node == self.hashIterator.end_node:
433
node = self.hashIterator.hashNode()
436
self.hashIterator.data_node = self.hashIterator.nextNode(self.hashIterator.data_node)
438
self.count = self.count + 1
439
return ('[%d]' % (self.count-1), item)
442
hashPrinter = QHashPrinter(self.val['q_hash'])
443
hashIterator = hashPrinter._iterator(self.val['q_hash'])
444
return self._iterator(hashIterator)
452
def __init__(self, val):
456
return unichr(self.val['ucs'])
458
def display_hint (self):
461
def register_qt4_printers (obj):
465
obj.pretty_printers.append (lookup_function)
467
def lookup_function (val):
468
"Look-up and return a pretty-printer that can print val."
473
# If it points to a reference, get the reference.
474
if type.code == gdb.TYPE_CODE_REF:
475
type = type.target ()
477
# Get the unqualified type, stripped of typedefs.
478
type = type.unqualified ().strip_typedefs ()
485
# Iterate over local dictionary of types to determine
486
# if a printer is registered for that type. Return an
487
# instantiation of the printer if found.
488
for function in pretty_printers_dict:
489
if function.search (typename):
490
return pretty_printers_dict[function] (val)
492
# Cannot find a pretty printer. Return None.
495
def build_dictionary ():
496
pretty_printers_dict[re.compile('^QString$')] = lambda val: QStringPrinter(val)
497
pretty_printers_dict[re.compile('^QByteArray$')] = lambda val: QByteArrayPrinter(val)
498
pretty_printers_dict[re.compile('^QList<.*>$')] = lambda val: QListPrinter(val, None)
499
pretty_printers_dict[re.compile('^QStringList$')] = lambda val: QListPrinter(val, 'QString')
500
pretty_printers_dict[re.compile('^QMap<.*>$')] = lambda val: QMapPrinter(val)
501
pretty_printers_dict[re.compile('^QHash<.*>$')] = lambda val: QHashPrinter(val)
502
pretty_printers_dict[re.compile('^QDate$')] = lambda val: QDatePrinter(val)
503
pretty_printers_dict[re.compile('^QTime$')] = lambda val: QTimePrinter(val)
504
pretty_printers_dict[re.compile('^QDateTime$')] = lambda val: QDateTimePrinter(val)
505
pretty_printers_dict[re.compile('^QUrl$')] = lambda val: QUrlPrinter(val)
506
pretty_printers_dict[re.compile('^QSet<.*>$')] = lambda val: QSetPrinter(val)
507
pretty_printers_dict[re.compile('^QChar$')] = lambda val: QCharPrinter(val)
510
pretty_printers_dict = {}