qttypes.py 87.6 KB
Newer Older
hjk's avatar
hjk committed
1
2
3
4
5
6
7

#######################################################################
#
# Dumper Implementations
#
#######################################################################

8
9
from __future__ import with_statement

10
11
12
13
14
15
16
17
18
19

def mapForms():
    return "Normal,Compact"

def mapCompact(format, keyType, valueType):
    if format == 2:
        return True # Compact.
    return isSimpleType(keyType) and isSimpleType(valueType)


hjk's avatar
hjk committed
20
21
def qdump__QAtomicInt(d, value):
    d.putValue(value["_q_value"])
hjk's avatar
hjk committed
22
23
24
    d.putNumChild(0)


hjk's avatar
hjk committed
25
26
def qdump__QBasicAtomicInt(d, value):
    d.putValue(value["_q_value"])
27
28
29
    d.putNumChild(0)


hjk's avatar
hjk committed
30
31
32
def qdump__QBasicAtomicPointer(d, value):
    d.putType(value.type)
    p = cleanAddress(value["_q_value"])
33
    d.putValue(p)
hjk's avatar
hjk committed
34
    d.putPointerValue(value.address)
35
    d.putNumChild(p)
hjk's avatar
hjk committed
36
    if d.isExpanded():
37
        with Children(d):
hjk's avatar
hjk committed
38
           d.putItem(value["_q_value"])
39
40


hjk's avatar
hjk committed
41
42
43
def qdump__QByteArray(d, value):
    d.putByteArrayValue(value)
    data, size, alloc = qByteArrayData(value)
44
    d.putNumChild(size)
hjk's avatar
hjk committed
45
    if d.isExpanded():
46
        d.putArrayData(lookupType("char"), data, size)
hjk's avatar
hjk committed
47
48


hjk's avatar
hjk committed
49
50
def qdump__QChar(d, value):
    ucs = int(value["ucs"])
51
    d.putValue("'%c' (%d)" % (printableChar(ucs), ucs))
hjk's avatar
hjk committed
52
53
54
    d.putNumChild(0)


hjk's avatar
hjk committed
55
def qform__QAbstractItemModel():
56
    return "Normal,Enhanced"
57

hjk's avatar
hjk committed
58
def qdump__QAbstractItemModel(d, value):
59
60
61
62
63
    format = d.currentItemFormat()
    if format == 1:
        d.putPlainChildren(value)
        return
    #format == 2:
64
    # Create a default-constructed QModelIndex on the stack.
65
    try:
66
        ri = makeValue(d.ns + "QModelIndex", "-1, -1, 0, 0")
hjk's avatar
hjk committed
67
        this_ = makeExpression(value)
68
        ri_ = makeExpression(ri)
69
70
71
        rowCount = int(parseAndEvaluate("%s.rowCount(%s)" % (this_, ri_)))
        columnCount = int(parseAndEvaluate("%s.columnCount(%s)" % (this_, ri_)))
    except:
hjk's avatar
hjk committed
72
        d.putPlainChildren(value)
73
        return
74
75
    d.putValue("%d x %d" % (rowCount, columnCount))
    d.putNumChild(rowCount * columnCount)
hjk's avatar
hjk committed
76
77
    if d.isExpanded():
        with Children(d, numChild=rowCount * columnCount, childType=ri.type):
78
79
80
            i = 0
            for row in xrange(rowCount):
                for column in xrange(columnCount):
hjk's avatar
hjk committed
81
                    with SubItem(d, i):
82
83
84
85
86
87
                        d.putName("[%s, %s]" % (row, column))
                        mi = parseAndEvaluate("%s.index(%d,%d,%s)"
                            % (this_, row, column, ri_))
                        #warn("MI: %s " % mi)
                        #name = "[%d,%d]" % (row, column)
                        #d.putValue("%s" % mi)
hjk's avatar
hjk committed
88
                        d.putItem(mi)
89
90
91
92
93
94
95
96
                        i = i + 1
                        #warn("MI: %s " % mi)
                        #d.putName("[%d,%d]" % (row, column))
                        #d.putValue("%s" % mi)
                        #d.putNumChild(0)
                        #d.putType(mi.type)
    #gdb.execute("call free($ri)")

97
98
99
def qform__QModelIndex():
    return "Normal,Enhanced"

hjk's avatar
hjk committed
100
def qdump__QModelIndex(d, value):
101
102
103
104
    format = d.currentItemFormat()
    if format == 1:
        d.putPlainChildren(value)
        return
hjk's avatar
hjk committed
105
106
107
108
    r = value["r"]
    c = value["c"]
    p = value["p"]
    m = value["m"]
109
110
    mm = m.dereference()
    mm = mm.cast(mm.type.unqualified())
111
    try:
112
113
114
        mi = makeValue(d.ns + "QModelIndex", "%s,%s,%s,%s" % (r, c, p, m))
        mm_ = makeExpression(mm)
        mi_ = makeExpression(mi)
115
116
117
        rowCount = int(parseAndEvaluate("%s.rowCount(%s)" % (mm_, mi_)))
        columnCount = int(parseAndEvaluate("%s.columnCount(%s)" % (mm_, mi_)))
    except:
hjk's avatar
hjk committed
118
        d.putPlainChildren(value)
119
        return
120
121
122

    try:
        # Access DisplayRole as value
hjk's avatar
hjk committed
123
124
        val = parseAndEvaluate("%s.data(%s, 0)" % (mm_, mi_))
        v = val["d"]["data"]["ptr"]
125
126
127
128
129
130
        d.putStringValue(makeValue(d.ns + 'QString', v))
    except:
        d.putValue("(invalid)")

    if r >= 0 and c >= 0 and not isNull(m):
        d.putNumChild(rowCount * columnCount)
hjk's avatar
hjk committed
131
        if d.isExpanded():
132
133
134
135
            with Children(d):
                i = 0
                for row in xrange(rowCount):
                    for column in xrange(columnCount):
hjk's avatar
hjk committed
136
                        with UnnamedSubItem(d, i):
137
138
139
                            d.putName("[%s, %s]" % (row, column))
                            mi2 = parseAndEvaluate("%s.index(%d,%d,%s)"
                                % (mm_, row, column, mi_))
hjk's avatar
hjk committed
140
                            d.putItem(mi2)
141
                            i = i + 1
hjk's avatar
hjk committed
142
143
                #d.putCallItem("parent", val, "parent")
                #with SubItem(d, "model"):
144
145
146
147
148
149
                #    d.putValue(m)
                #    d.putType(d.ns + "QAbstractItemModel*")
                #    d.putNumChild(1)
    else:
        d.putValue("(invalid)")
        d.putNumChild(0)
hjk's avatar
hjk committed
150
        if d.isExpanded():
151
152
153
154
            with Children(d):
                pass
    #gdb.execute("call free($mi)")

hjk's avatar
hjk committed
155

hjk's avatar
hjk committed
156
def qdump__QDate(d, value):
157
    d.putValue(value["jd"], JulianDate)
158
    d.putNumChild(1)
hjk's avatar
hjk committed
159
    if d.isExpanded():
160
        qt = d.ns + "Qt::"
161
        # FIXME: This improperly uses complex return values.
hjk's avatar
hjk committed
162
163
164
165
        with Children(d):
            d.putCallItem("toString", value, "toString", qt + "TextDate")
            d.putCallItem("(ISO)", value, "toString", qt + "ISODate")
            d.putCallItem("(SystemLocale)", value, "toString",
hjk's avatar
hjk committed
166
                qt + "SystemLocaleDate")
hjk's avatar
hjk committed
167
            d.putCallItem("(Locale)", value, "toString", qt + "LocaleDate")
hjk's avatar
hjk committed
168
169


hjk's avatar
hjk committed
170
def qdump__QTime(d, value):
171
    d.putValue(value["mds"], MillisecondsSinceMidnight)
172
    d.putNumChild(1)
hjk's avatar
hjk committed
173
    if d.isExpanded():
174
        qt = d.ns + "Qt::"
175
        # FIXME: This improperly uses complex return values.
hjk's avatar
hjk committed
176
177
178
179
        with Children(d):
            d.putCallItem("toString", value, "toString", qt + "TextDate")
            d.putCallItem("(ISO)", value, "toString", qt + "ISODate")
            d.putCallItem("(SystemLocale)", value, "toString",
hjk's avatar
hjk committed
180
                 qt + "SystemLocaleDate")
hjk's avatar
hjk committed
181
182
            d.putCallItem("(Locale)", value, "toString", qt + "LocaleDate")
            d.putCallItem("toUTC", value, "toTimeSpec", qt + "UTC")
183
184


hjk's avatar
hjk committed
185
def qdump__QDateTime(d, value):
186
187
    try:
        # Fails without debug info.
188
        p = value["d"]["d"].dereference()
189
    except:
hjk's avatar
hjk committed
190
        d.putPlainChildren(value)
191
        return
192
193
    d.putValue("%s/%s" % (p["date"]["jd"], p["time"]["mds"]),
        JulianDateAndMillisecondsSinceMidnight)
194
    d.putNumChild(1)
hjk's avatar
hjk committed
195
    if d.isExpanded():
196
        # FIXME: This improperly uses complex return values.
hjk's avatar
hjk committed
197
        with Children(d):
198
            qt = d.ns + "Qt::"
hjk's avatar
hjk committed
199
200
201
202
203
204
205
206
207
208
            d.putCallItem("toTime_t", value, "toTime_t")
            d.putCallItem("toString", value, "toString", qt + "TextDate")
            d.putCallItem("(ISO)", value, "toString", qt + "ISODate")
            d.putCallItem("(SystemLocale)", value, "toString", qt + "SystemLocaleDate")
            d.putCallItem("(Locale)", value, "toString", qt + "LocaleDate")
            d.putCallItem("toUTC", value, "toTimeSpec", qt + "UTC")
            d.putCallItem("toLocalTime", value, "toTimeSpec", qt + "LocalTime")


def qdump__QDir(d, value):
hjk's avatar
hjk committed
209
    d.putNumChild(1)
210
211
212
213
214
215
216
    data = value["d_ptr"]["d"].dereference()
    try:
        # Up to Qt 4.7
        d.putStringValue(data["path"])
    except:
        # Qt 4.8 and later.
        d.putStringValue(data["dirEntry"]["m_filePath"])
hjk's avatar
hjk committed
217
218
219
220
    if d.isExpanded():
        with Children(d):
            d.putCallItem("absolutePath", value, "absolutePath")
            d.putCallItem("canonicalPath", value, "canonicalPath")
hjk's avatar
hjk committed
221
222


hjk's avatar
hjk committed
223
def qdump__QFile(d, value):
hjk's avatar
hjk committed
224
225
226
227
228
229
230
    try:
        ptype = lookupType(d.ns + "QFilePrivate").pointer()
        d_ptr = value["d_ptr"]["d"]
        d.putStringValue(d_ptr.cast(ptype).dereference()["fileName"])
    except:
        d.putPlainChildren(value)
        return
231
    d.putNumChild(1)
hjk's avatar
hjk committed
232
233
    if d.isExpanded():
        with Children(d):
234
235
            base = value.type.fields()[0].type
            d.putSubItem("[%s]" % str(base), value.cast(base), False)
hjk's avatar
hjk committed
236
            d.putCallItem("exists", value, "exists")
hjk's avatar
hjk committed
237
238


hjk's avatar
hjk committed
239
def qdump__QFileInfo(d, value):
240
    try:
hjk's avatar
hjk committed
241
        d.putStringValue(value["d_ptr"]["d"].dereference()["fileNames"][3])
242
    except:
hjk's avatar
hjk committed
243
        d.putPlainChildren(value)
244
        return
hjk's avatar
hjk committed
245
    d.putNumChild(1)
hjk's avatar
hjk committed
246
247
248
249
250
251
252
253
254
    if d.isExpanded():
        with Children(d, childType=lookupType(d.ns + "QString")):
            d.putCallItem("absolutePath", value, "absolutePath")
            d.putCallItem("absoluteFilePath", value, "absoluteFilePath")
            d.putCallItem("canonicalPath", value, "canonicalPath")
            d.putCallItem("canonicalFilePath", value, "canonicalFilePath")
            d.putCallItem("completeBaseName", value, "completeBaseName")
            d.putCallItem("completeSuffix", value, "completeSuffix")
            d.putCallItem("baseName", value, "baseName")
255
256
            if False:
                #ifdef Q_OS_MACX
hjk's avatar
hjk committed
257
258
259
260
                d.putCallItem("isBundle", value, "isBundle")
                d.putCallItem("bundleName", value, "bundleName")
            d.putCallItem("fileName", value, "fileName")
            d.putCallItem("filePath", value, "filePath")
261
            # Crashes gdb (archer-tromey-python, at dad6b53fe)
hjk's avatar
hjk committed
262
263
264
            #d.putCallItem("group", value, "group")
            #d.putCallItem("owner", value, "owner")
            d.putCallItem("path", value, "path")
265

hjk's avatar
hjk committed
266
267
            d.putCallItem("groupid", value, "groupId")
            d.putCallItem("ownerid", value, "ownerId")
268
269

            #QFile::Permissions permissions () const
hjk's avatar
hjk committed
270
            perms = call(value, "permissions")
271
272
273
            if perms is None:
                d.putValue("<not available>")
            else:
hjk's avatar
hjk committed
274
                with SubItem(d, "permissions"):
275
276
277
                    d.putValue(" ")
                    d.putType(d.ns + "QFile::Permissions")
                    d.putNumChild(10)
hjk's avatar
hjk committed
278
                    if d.isExpanded():
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
                        with Children(d, 10):
                            perms = perms['i']
                            d.putBoolItem("ReadOwner",  perms & 0x4000)
                            d.putBoolItem("WriteOwner", perms & 0x2000)
                            d.putBoolItem("ExeOwner",   perms & 0x1000)
                            d.putBoolItem("ReadUser",   perms & 0x0400)
                            d.putBoolItem("WriteUser",  perms & 0x0200)
                            d.putBoolItem("ExeUser",    perms & 0x0100)
                            d.putBoolItem("ReadGroup",  perms & 0x0040)
                            d.putBoolItem("WriteGroup", perms & 0x0020)
                            d.putBoolItem("ExeGroup",   perms & 0x0010)
                            d.putBoolItem("ReadOther",  perms & 0x0004)
                            d.putBoolItem("WriteOther", perms & 0x0002)
                            d.putBoolItem("ExeOther",   perms & 0x0001)

            #QDir absoluteDir () const
            #QDir dir () const
hjk's avatar
hjk committed
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
            d.putCallItem("caching", value, "caching")
            d.putCallItem("exists", value, "exists")
            d.putCallItem("isAbsolute", value, "isAbsolute")
            d.putCallItem("isDir", value, "isDir")
            d.putCallItem("isExecutable", value, "isExecutable")
            d.putCallItem("isFile", value, "isFile")
            d.putCallItem("isHidden", value, "isHidden")
            d.putCallItem("isReadable", value, "isReadable")
            d.putCallItem("isRelative", value, "isRelative")
            d.putCallItem("isRoot", value, "isRoot")
            d.putCallItem("isSymLink", value, "isSymLink")
            d.putCallItem("isWritable", value, "isWritable")
            d.putCallItem("created", value, "created")
            d.putCallItem("lastModified", value, "lastModified")
            d.putCallItem("lastRead", value, "lastRead")


def qdump__QFixed(d, value):
    v = int(value["val"])
hjk's avatar
hjk committed
315
316
317
318
    d.putValue("%s/64 = %s" % (v, v/64.0))
    d.putNumChild(0)


319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# Stock gdb 7.2 seems to have a problem with types here:
#
#  echo -e "namespace N { struct S { enum E { zero, one, two }; }; }\n"\
#      "int main() { N::S::E x = N::S::one;\n return x; }" >> main.cpp
#  g++ -g main.cpp
#  gdb-7.2 -ex 'file a.out' -ex 'b main' -ex 'run' -ex 'step' \
#     -ex 'ptype N::S::E' -ex 'python print gdb.lookup_type("N::S::E")' -ex 'q'
#  gdb-7.1 -ex 'file a.out' -ex 'b main' -ex 'run' -ex 'step' \
#     -ex 'ptype N::S::E' -ex 'python print gdb.lookup_type("N::S::E")' -ex 'q'
#  gdb-cvs -ex 'file a.out' -ex 'b main' -ex 'run' -ex 'step' \
#     -ex 'ptype N::S::E' -ex 'python print gdb.lookup_type("N::S::E")' -ex 'q'
#
# gives as of 2010-11-02
#
#  type = enum N::S::E {N::S::zero, N::S::one, N::S::two} \n
hjk's avatar
hjk committed
334
335
#    Traceback (most recent call last): File "<string>", line 1,
#      in <module> RuntimeError: No type named N::S::E.
336
337
338
339
340
#  type = enum N::S::E {N::S::zero, N::S::one, N::S::two} \n  N::S::E
#  type = enum N::S::E {N::S::zero, N::S::one, N::S::two} \n  N::S::E
#
# i.e. there's something broken in stock 7.2 that is was ok in 7.1 and is ok later.

hjk's avatar
hjk committed
341
342
def qdump__QFlags(d, value):
    i = value["i"]
343
    try:
hjk's avatar
hjk committed
344
        enumType = templateArgument(value.type.unqualified(), 0)
345
346
347
        d.putValue("%s (%s)" % (i.cast(enumType), i))
    except:
        d.putValue("%s" % i)
hjk's avatar
hjk committed
348
349
350
    d.putNumChild(0)


351
352
353
def qform__QHash():
    return mapForms()

hjk's avatar
hjk committed
354
def qdump__QHash(d, value):
hjk's avatar
hjk committed
355
356

    def hashDataFirstNode(value):
hjk's avatar
hjk committed
357
358
359
360
        val = value.cast(hashDataType)
        bucket = val["buckets"]
        e = val.cast(hashNodeType)
        for n in xrange(val["numBuckets"] - 1, -1, -1):
hjk's avatar
hjk committed
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
            n = n - 1
            if n < 0:
                break
            if bucket.dereference() != e:
                return bucket.dereference()
            bucket = bucket + 1
        return e;

    def hashDataNextNode(node):
        next = node["next"]
        if next["next"]:
            return next
        d = node.cast(hashDataType.pointer()).dereference()
        numBuckets = d["numBuckets"]
        start = (node["h"] % numBuckets) + 1
        bucket = d["buckets"] + start
377
        for n in xrange(numBuckets - start):
hjk's avatar
hjk committed
378
379
380
381
382
            if bucket.dereference() != next:
                return bucket.dereference()
            bucket += 1
        return node

hjk's avatar
hjk committed
383
384
    keyType = templateArgument(value.type, 0)
    valueType = templateArgument(value.type, 1)
hjk's avatar
hjk committed
385

hjk's avatar
hjk committed
386
387
    d_ptr = value["d"]
    e_ptr = value["e"]
388
    size = d_ptr["size"]
hjk's avatar
hjk committed
389
390
391
392

    hashDataType = d_ptr.type
    hashNodeType = e_ptr.type

393
    check(0 <= size and size <= 100 * 1000 * 1000)
394
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
395

396
397
    d.putItemCount(size)
    d.putNumChild(size)
hjk's avatar
hjk committed
398
    if d.isExpanded():
399
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
400
        node = hashDataFirstNode(value)
hjk's avatar
hjk committed
401
        innerType = e_ptr.dereference().type
402
        childType = innerType
403
        if isCompact:
404
            childType = valueType
hjk's avatar
hjk committed
405
        with Children(d, size, maxNumChild=1000, childType=childType):
406
407
            for i in d.childRange():
                it = node.dereference().cast(innerType)
hjk's avatar
hjk committed
408
                with SubItem(d, i):
409
410
411
                    if isCompact:
                        d.putMapName(it["key"])
                        d.putItem(it["value"])
412
413
                        d.putType(valueType)
                    else:
hjk's avatar
hjk committed
414
                        d.putItem(it)
415
                node = hashDataNextNode(node)
hjk's avatar
hjk committed
416
417


hjk's avatar
hjk committed
418
419
420
421
422
def qdump__QHashNode(d, value):
    keyType = templateArgument(value.type, 0)
    valueType = templateArgument(value.type, 1)
    key = value["key"]
    val = value["value"]
hjk's avatar
hjk committed
423

424
425
426
427
428
    #if isSimpleType(keyType) and isSimpleType(valueType):
    #    d.putName(key)
    #    d.putValue(val)
    #else:
    d.putValue(" ")
hjk's avatar
hjk committed
429

430
    d.putNumChild(2)
hjk's avatar
hjk committed
431
    if d.isExpanded():
432
        with Children(d):
hjk's avatar
hjk committed
433
434
            d.putSubItem("key", key)
            d.putSubItem("value", val)
hjk's avatar
hjk committed
435
436


hjk's avatar
hjk committed
437
438
def qdump__QHostAddress(d, value):
    data = value["d"]["d"].dereference()
hjk's avatar
hjk committed
439
440
441
    if int(data["ipString"]["d"]["size"]):
        d.putStringValue(data["ipString"])
    else:
442
443
444
445
446
447
        a = long(data["a"])
        a, n4 = divmod(a, 256)
        a, n3 = divmod(a, 256)
        a, n2 = divmod(a, 256)
        a, n1 = divmod(a, 256)
        d.putValue("%d.%d.%d.%d" % (n1, n2, n3, n4));
hjk's avatar
hjk committed
448
    d.putNumChild(1)
hjk's avatar
hjk committed
449
    if d.isExpanded():
hjk's avatar
hjk committed
450
        with Children(d):
hjk's avatar
hjk committed
451
           d.putFields(data)
hjk's avatar
hjk committed
452
453


hjk's avatar
hjk committed
454
455
def qdump__QList(d, value):
    d_ptr = value["d"]
hjk's avatar
hjk committed
456
457
458
459
    begin = d_ptr["begin"]
    end = d_ptr["end"]
    array = d_ptr["array"]
    check(begin >= 0 and end >= 0 and end <= 1000 * 1000 * 1000)
460
461
    size = end - begin
    check(size >= 0)
hjk's avatar
hjk committed
462
463
464
    #if n > 0:
    #    checkAccess(&list.front())
    #    checkAccess(&list.back())
465
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
466
467

    # Additional checks on pointer arrays.
hjk's avatar
hjk committed
468
    innerType = templateArgument(value.type, 0)
469
    innerTypeIsPointer = innerType.code == PointerCode \
hjk's avatar
hjk committed
470
471
472
        and str(innerType.target().unqualified()) != "char"
    if innerTypeIsPointer:
        p = gdb.Value(array).cast(innerType.pointer()) + begin
hjk's avatar
hjk committed
473
        checkPointerRange(p, min(size, 100))
hjk's avatar
hjk committed
474

475
476
    d.putItemCount(size)
    d.putNumChild(size)
hjk's avatar
hjk committed
477
    if d.isExpanded():
hjk's avatar
hjk committed
478
479
480
481
482
483
484
        innerSize = innerType.sizeof
        # The exact condition here is:
        #  QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic
        # but this data is available neither in the compiled binary nor
        # in the frontend.
        # So as first approximation only do the 'isLarge' check:
        isInternal = innerSize <= d_ptr.type.sizeof and d.isMovableType(innerType)
485
        dummyType = lookupType("void").pointer().pointer()
486
487
        innerTypePointer = innerType.pointer()
        p = gdb.Value(array).cast(dummyType) + begin
488
489
490
491
        if innerTypeIsPointer:
            inner = innerType.target()
        else:
            inner = innerType
492
        # about 0.5s / 1000 items
hjk's avatar
hjk committed
493
        with Children(d, size, maxNumChild=2000, childType=inner):
494
495
            for i in d.childRange():
                if isInternal:
hjk's avatar
hjk committed
496
                    d.putSubItem(i, p.cast(innerTypePointer).dereference())
497
                else:
hjk's avatar
hjk committed
498
                    d.putSubItem(i, p.cast(innerTypePointer.pointer()).dereference())
499
                p += 1
hjk's avatar
hjk committed
500

hjk's avatar
hjk committed
501
502
def qform__QImage():
    return "Normal,Displayed"
hjk's avatar
hjk committed
503

hjk's avatar
hjk committed
504
def qdump__QImage(d, value):
505
    try:
hjk's avatar
hjk committed
506
        painters = value["painters"]
507
    except:
hjk's avatar
hjk committed
508
        d.putPlainChildren(value)
509
        return
hjk's avatar
hjk committed
510
    check(0 <= painters and painters < 1000)
hjk's avatar
hjk committed
511
    d_ptr = value["d"]
hjk's avatar
hjk committed
512
    if isNull(d_ptr):
513
        d.putValue("(null)")
hjk's avatar
hjk committed
514
    else:
515
        checkSimpleRef(d_ptr["ref"])
516
        d.putValue("(%dx%d)" % (d_ptr["width"], d_ptr["height"]))
517
518
    bits = d_ptr["data"]
    nbytes = d_ptr["nbytes"]
519
    d.putNumChild(0)
hjk's avatar
hjk committed
520
    #d.putNumChild(1)
hjk's avatar
hjk committed
521
    if d.isExpanded():
522
        with Children(d):
hjk's avatar
hjk committed
523
            with SubItem(d, "data"):
524
                d.putNoType()
525
526
                d.putNumChild(0)
                d.putValue("size: %s bytes" % nbytes);
hjk's avatar
hjk committed
527
    format = d.currentItemFormat()
528
    if format == 1:
529
        d.putDisplay(StopDisplay)
530
    elif format == 2:
hjk's avatar
hjk committed
531
532
533
534
        if False:
            # Take four bytes at a time, this is critical for performance.
            # In fact, even four at a time is too slow beyond 100x100 or so.
            d.putField("editformat", 1)  # Magic marker for direct "QImage" data.
535
            d.put('%s="' % name)
hjk's avatar
hjk committed
536
537
538
            d.put("%08x" % int(d_ptr["width"]))
            d.put("%08x" % int(d_ptr["height"]))
            d.put("%08x" % int(d_ptr["format"]))
539
            p = bits.cast(lookupType("unsigned int").pointer())
hjk's avatar
hjk committed
540
541
542
            for i in xrange(nbytes / 4):
                d.put("%08x" % int(p.dereference()))
                p += 1
543
            d.put('",')
hjk's avatar
hjk committed
544
545
546
        else:
            # Write to an external file. Much faster ;-(
            file = tempfile.mkstemp(prefix="gdbpy_")
547
            filename = file[1].replace("\\", "\\\\")
548
            p = bits.cast(lookupType("unsigned char").pointer())
hjk's avatar
hjk committed
549
550
            gdb.execute("dump binary memory %s %s %s" %
                (filename, cleanAddress(p), cleanAddress(p + nbytes)))
551
552
            d.putDisplay(DisplayImage, " %d %d %d %s"
                % (d_ptr["width"], d_ptr["height"], d_ptr["format"], filename))
hjk's avatar
hjk committed
553
554


hjk's avatar
hjk committed
555
556
557
def qdump__QLinkedList(d, value):
    d_ptr = value["d"]
    e_ptr = value["e"]
558
    n = d_ptr["size"]
hjk's avatar
hjk committed
559
    check(0 <= n and n <= 100*1000*1000)
560
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
561
    d.putItemCount(n)
562
    d.putNumChild(n)
hjk's avatar
hjk committed
563
564
565
    if d.isExpanded():
        innerType = templateArgument(value.type, 0)
        with Children(d, n, maxNumChild=1000, childType=innerType):
566
567
            p = e_ptr["n"]
            for i in d.childRange():
hjk's avatar
hjk committed
568
                d.putSubItem(i, p["t"])
569
                p = p["n"]
hjk's avatar
hjk committed
570

571
qqLocalesCount = None
hjk's avatar
hjk committed
572

hjk's avatar
hjk committed
573
def qdump__QLocale(d, value):
574
575
576
577
578
579
580
581
    # Check for uninitialized 'index' variable. Retrieve size of QLocale data array
    # from variable in qlocale.cpp (default: 368/Qt 4.8), 368 being 'System'.
    global qqLocalesCount
    if qqLocalesCount is None:
        try:
            qqLocalesCount = int(value(qtNamespace() + 'locale_data_size'))
        except:
            qqLocalesCount = 368
hjk's avatar
hjk committed
582
    index = int(value["p"]["index"])
583
    check(index >= 0 and index <= qqLocalesCount)
hjk's avatar
hjk committed
584
    d.putStringValue(call(value, "name"))
585
586
587
    d.putNumChild(0)
    return
    # FIXME: Poke back for variants.
hjk's avatar
hjk committed
588
589
590
591
592
593
594
    if d.isExpanded():
        with Children(d, childType=lookupType(d.ns + "QChar"), childNumChild=0):
            d.putCallItem("country", value, "country")
            d.putCallItem("language", value, "language")
            d.putCallItem("measurementSystem", value, "measurementSystem")
            d.putCallItem("numberOptions", value, "numberOptions")
            d.putCallItem("timeFormat_(short)", value,
hjk's avatar
hjk committed
595
                "timeFormat", d.ns + "QLocale::ShortFormat")
hjk's avatar
hjk committed
596
            d.putCallItem("timeFormat_(long)", value,
hjk's avatar
hjk committed
597
                "timeFormat", d.ns + "QLocale::LongFormat")
hjk's avatar
hjk committed
598
599
600
601
602
603
            d.putCallItem("decimalPoint", value, "decimalPoint")
            d.putCallItem("exponential", value, "exponential")
            d.putCallItem("percent", value, "percent")
            d.putCallItem("zeroDigit", value, "zeroDigit")
            d.putCallItem("groupSeparator", value, "groupSeparator")
            d.putCallItem("negativeSign", value, "negativeSign")
hjk's avatar
hjk committed
604
605


hjk's avatar
hjk committed
606
def qdump__QMapNode(d, value):
607
608
    d.putValue(" ")
    d.putNumChild(2)
hjk's avatar
hjk committed
609
610
611
612
613
614
615
616
617
    if d.isExpanded():
        with Children(d):
            d.putSubItem("key", value["key"])
            d.putSubItem("value", value["value"])


def qdumpHelper__QMap(d, value, forceLong):
    d_ptr = value["d"].dereference()
    e_ptr = value["e"].dereference()
hjk's avatar
hjk committed
618
619
    n = d_ptr["size"]
    check(0 <= n and n <= 100*1000*1000)
620
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
621
622

    d.putItemCount(n)
623
    d.putNumChild(n)
hjk's avatar
hjk committed
624
    if d.isExpanded():
hjk's avatar
hjk committed
625
626
627
        if n > 1000:
            n = 1000

hjk's avatar
hjk committed
628
629
        keyType = templateArgument(value.type, 0)
        valueType = templateArgument(value.type, 1)
630
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
631
632
633
634
635
636

        it = e_ptr["forward"].dereference()

        # QMapPayloadNode is QMapNode except for the 'forward' member, so
        # its size is most likely the offset of the 'forward' member therein.
        # Or possibly 2 * sizeof(void *)
637
638
639
        nodeType = lookupType(d.ns + "QMapNode<%s, %s>" % (keyType, valueType))
        payloadSize = nodeType.sizeof - 2 * lookupType("void").pointer().sizeof
        charPtr = lookupType("char").pointer()
hjk's avatar
hjk committed
640

641
        if isCompact:
642
643
644
            innerType = valueType
        else:
            innerType = nodeType
hjk's avatar
hjk committed
645

hjk's avatar
hjk committed
646
        with Children(d, n, childType=innerType):
647
648
649
650
            for i in xrange(n):
                itd = it.dereference()
                base = it.cast(charPtr) - payloadSize
                node = base.cast(nodeType.pointer()).dereference()
hjk's avatar
hjk committed
651
                with SubItem(d, i):
652
                    if isCompact:
653
                        #d.putType(valueType)
hjk's avatar
hjk committed
654
                        if forceLong:
655
                            d.putName("[%s] %s" % (i, node["key"]))
hjk's avatar
hjk committed
656
                        else:
657
658
                            d.putMapName(node["key"])
                        d.putItem(node["value"])
659
                    else:
hjk's avatar
hjk committed
660
                        d.putItem(node)
661
                it = it.dereference()["forward"].dereference()
hjk's avatar
hjk committed
662
663


664
665
666
def qform__QMap():
    return mapForms()

hjk's avatar
hjk committed
667
668
def qdump__QMap(d, value):
    qdumpHelper__QMap(d, value, False)
hjk's avatar
hjk committed
669

670
671
672
def qform__QMultiMap():
    return mapForms()

hjk's avatar
hjk committed
673
674
def qdump__QMultiMap(d, value):
    qdumpHelper__QMap(d, value, True)
hjk's avatar
hjk committed
675
676
677
678
679
680
681
682
683
684
685
686
687


def extractCString(table, offset):
    result = ""
    while True:
        d = table[offset]
        if d == 0:
            break
        result += "%c" % d
        offset += 1
    return result


hjk's avatar
hjk committed
688
689
def qdump__QObject(d, value):
    #warn("OBJECT: %s " % value)
690
    try:
691
        privateTypeName = d.ns + "QObjectPrivate"
692
        privateType = lookupType(privateTypeName)
hjk's avatar
hjk committed
693
694
        staticMetaObject = value["staticMetaObject"]
        d_ptr = value["d_ptr"]["d"].cast(privateType.pointer()).dereference()
695
696
        #warn("D_PTR: %s " % d_ptr)
        objectName = d_ptr["objectName"]
697
    except:
hjk's avatar
hjk committed
698
        d.putPlainChildren(value)
699
        return
hjk's avatar
hjk committed
700
    #warn("SMO: %s " % staticMetaObject)
701
702
703
704
705
706
707
    #warn("SMO DATA: %s " % staticMetaObject["d"]["stringdata"])
    superData = staticMetaObject["d"]["superdata"]
    #warn("SUPERDATA: %s" % superData)
    #while not isNull(superData):
    #    superData = superData.dereference()["d"]["superdata"]
    #    warn("SUPERDATA: %s" % superData)

708
709
    if privateType is None:
        d.putNumChild(4)
hjk's avatar
hjk committed
710
        #d.putValue(cleanAddress(value.address))
711
        d.putPlainChildren(value)
hjk's avatar
hjk committed
712
        if d.isExpanded():
713
            with Children(d):
hjk's avatar
hjk committed
714
                d.putFields(value)
715
        return
hjk's avatar
hjk committed
716
    #warn("OBJECTNAME: %s " % objectName)
717
    #warn("D_PTR: %s " % d_ptr)
hjk's avatar
hjk committed
718
    mo = d_ptr["metaObject"]
719
720
721
    if not isAccessible(mo):
        d.putInaccessible()
        return
hjk's avatar
hjk committed
722
723
724
725
726
727
    if isNull(mo):
        mo = staticMetaObject
    #warn("MO: %s " % mo)
    #warn("MO.D: %s " % mo["d"])
    metaData = mo["d"]["data"]
    metaStringData = mo["d"]["stringdata"]
728
    #extradata = mo["d"]["extradata"]   # Capitalization!
hjk's avatar
hjk committed
729
730
    #warn("METADATA: %s " % metaData)
    #warn("STRINGDATA: %s " % metaStringData)
hjk's avatar
hjk committed
731
732
    #warn("TYPE: %s " % value.type)
    #warn("INAME: %s " % d.currentIName())
733
734
    #d.putValue("")
    d.putStringValue(objectName)
hjk's avatar
hjk committed
735
    #QSignalMapper::staticMetaObject
736
    #checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
737
    d.putNumChild(4)
hjk's avatar
hjk committed
738
    if d.isExpanded():
739
      with Children(d):
740

hjk's avatar
hjk committed
741
        # Local data.
742
743
        if privateTypeName != d.ns + "QObjectPrivate":
            if not privateType is None:
hjk's avatar
hjk committed
744
              with SubItem(d, "data"):
745
                d.putValue(" ")
746
                d.putNoType()
747
                d.putNumChild(1)
hjk's avatar
hjk committed
748
                if d.isExpanded():
749
                    with Children(d):
hjk's avatar
hjk committed
750
                        d.putFields(d_ptr, False)
751
752


hjk's avatar
hjk committed
753
        d.putFields(value)
754
        # Parent and children.
hjk's avatar
hjk committed
755
756
757
        if stripClassTag(str(value.type)) == d.ns + "QObject":
            d.putSubItem("parent", d_ptr["parent"])
            d.putSubItem("children", d_ptr["children"])
hjk's avatar
hjk committed
758

759
        # Properties.
hjk's avatar
hjk committed
760
        with SubItem(d, "properties"):
761
            # Prolog
762
763
            extraData = d_ptr["extraData"]   # Capitalization!
            if isNull(extraData):
764
                dynamicPropertyCount = 0
765
            else:
766
                extraDataType = lookupType(
767
768
769
770
771
772
773
774
775
                    d.ns + "QObjectPrivate::ExtraData").pointer()
                extraData = extraData.cast(extraDataType)
                ed = extraData.dereference()
                names = ed["propertyNames"]
                values = ed["propertyValues"]
                #userData = ed["userData"]
                namesBegin = names["d"]["begin"]
                namesEnd = names["d"]["end"]
                namesArray = names["d"]["array"]
776
777
                dynamicPropertyCount = namesEnd - namesBegin

hjk's avatar
hjk committed
778
            #staticPropertyCount = call(mo, "propertyCount")
779
            staticPropertyCount = metaData[6]
780
781
782
            #warn("PROPERTY COUNT: %s" % staticPropertyCount)
            propertyCount = staticPropertyCount + dynamicPropertyCount

783
            d.putNoType()
784
785
786
            d.putItemCount(propertyCount)
            d.putNumChild(propertyCount)

hjk's avatar
hjk committed
787
            if d.isExpanded():
788
789
                # FIXME: Make this global. Don't leak.
                variant = "'%sQVariant'" % d.ns
790
                # Avoid malloc symbol clash with QVector
hjk's avatar
hjk committed
791
792
                gdb.execute("set $d = (%s*)calloc(sizeof(%s), 1)"
                    % (variant, variant))
793
                gdb.execute("set $d.d.is_shared = 0")
794

hjk's avatar
hjk committed
795
                with Children(d):
796
                    # Dynamic properties.
797
798
799
800
801
802
803
804
805
806
                    if dynamicPropertyCount != 0:
                        dummyType = lookupType("void").pointer().pointer()
                        namesType = lookupType(d.ns + "QByteArray")
                        valuesBegin = values["d"]["begin"]
                        valuesEnd = values["d"]["end"]
                        valuesArray = values["d"]["array"]
                        valuesType = lookupType(d.ns + "QVariant")
                        p = namesArray.cast(dummyType) + namesBegin
                        q = valuesArray.cast(dummyType) + valuesBegin
                        for i in xrange(dynamicPropertyCount):
hjk's avatar
hjk committed
807
                            with SubItem(d, i):
808
809
810
811
812
813
                                pp = p.cast(namesType.pointer()).dereference();
                                d.putField("key", encodeByteArray(pp))
                                d.putField("keyencoded", Hex2EncodedLatin1)
                                qq = q.cast(valuesType.pointer().pointer())
                                qq = qq.dereference();
                                d.putField("addr", cleanAddress(qq))
814
815
                                d.putField("exp", "*(%s*)%s"
                                     % (variant, cleanAddress(qq)))
hjk's avatar
hjk committed
816
817
                                t = qdump__QVariant(d, qq)
                                # Override the "QVariant (foo)" output.
hjk's avatar
hjk committed
818
                                d.putBetterType(t)
819
820
                            p += 1
                            q += 1
821
822
823
824

                    # Static properties.
                    propertyData = metaData[7]
                    for i in xrange(staticPropertyCount):
825
                      with NoAddress(d):
hjk's avatar
hjk committed
826
827
828
829
830
831
                        offset = propertyData + 3 * i
                        propertyName = extractCString(metaStringData,
                                                      metaData[offset])
                        propertyType = extractCString(metaStringData,
                                                      metaData[offset + 1])
                        with SubItem(d, propertyName):
832
833
834
835
                            #flags = metaData[offset + 2]
                            #warn("FLAGS: %s " % flags)
                            #warn("PROPERTY: %s %s " % (propertyType, propertyName))
                            # #exp = '((\'%sQObject\'*)%s)->property("%s")' \
hjk's avatar
hjk committed
836
                            #     % (d.ns, value.address, propertyName)
hjk's avatar
hjk committed
837
                            #exp = '"((\'%sQObject\'*)%s)"' %
hjk's avatar
hjk committed
838
                            #(d.ns, value.address,)
839
                            #warn("EXPRESSION:  %s" % exp)
hjk's avatar
hjk committed
840
                            prop = call(value, "property",
hjk's avatar
hjk committed
841
                                str(cleanAddress(metaStringData + metaData[offset])))
hjk's avatar
hjk committed
842
                            value1 = prop["d"]
843
                            #warn("   CODE: %s" % value1["type"])
hjk's avatar
hjk committed
844
845
                            # Type 1 and 2 are bool and int.
                            # Try to save a few cycles in this case:
846
                            if int(value1["type"]) > 2:
hjk's avatar
hjk committed
847
                                # Poke back prop
hjk's avatar
hjk committed
848
849
850
851
852
853
                                gdb.execute("set $d.d.data.ull = %s"
                                        % value1["data"]["ull"])
                                gdb.execute("set $d.d.type = %s"
                                        % value1["type"])
                                gdb.execute("set $d.d.is_null = %s"
                                        % value1["is_null"])
hjk's avatar
hjk committed
854
                                prop = parseAndEvaluate("$d").dereference()
hjk's avatar
hjk committed
855
                            val, inner, innert, handled = \
hjk's avatar
hjk committed
856
                                qdumpHelper__QVariant(d, prop)
hjk's avatar
hjk committed
857
858
859
860

                            if handled:
                                pass
                            elif len(inner):
861
862
                                # Build-in types.
                                d.putType(inner)
hjk's avatar
hjk committed
863
                                d.putItem(val)
864
865
                            else:
                                # User types.
866
867
                           #    func = "typeToName(('%sQVariant::Type')%d)"
                           #       % (d.ns, variantType)
hjk's avatar
hjk committed
868
                           #    type = str(call(value, func))
869
870
                           #    type = type[type.find('"') + 1 : type.rfind('"')]
                           #    type = type.replace("Q", d.ns + "Q") # HACK!
hjk's avatar
hjk committed
871
                           #    data = call(value, "constData")
872
873
                           #    tdata = data.cast(lookupType(type).pointer())
                           #      .dereference()
874
875
876
                           #    d.putValue("(%s)" % tdata.type)
                           #    d.putType(tdata.type)
                           #    d.putNumChild(1)
hjk's avatar
hjk committed
877
                           #    if d.isExpanded():
878
                           #        with Children(d):
hjk's avatar
hjk committed
879
                           #           d.putSubItem("data", tdata)
880
                                warn("FIXME: CUSTOM QOBJECT PROPERTY: %s %s"
881
882
883
884
885
                                    % (propertyType, innert))
                                d.putType(propertyType)
                                d.putValue("...")
                                d.putNumChild(0)

886
        # Connections.
hjk's avatar
hjk committed
887
        with SubItem(d, "connections"):
888
            d.putNoType()
889
890
891
892
            connections = d_ptr["connectionLists"]
            connectionListCount = 0
            if not isNull(connections):
                connectionListCount = connections["d"]["size"]
893
            d.putItemCount(connectionListCount, 0)
894
            d.putNumChild(connectionListCount)
hjk's avatar
hjk committed
895
            if d.isExpanded():
896
                pp = 0
897
898
                with Children(d):
                    vectorType = connections.type.target().fields()[0].type
899
                    innerType = templateArgument(vectorType, 0)
900
901
902
903
904
                    # Should check:  innerType == ns::QObjectPrivate::ConnectionList
                    p = gdb.Value(connections["p"]["array"]).cast(innerType.pointer())
                    for i in xrange(connectionListCount):
                        first = p.dereference()["first"]
                        while not isNull(first):