qttypes.py 88.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


437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
def qHashIteratorHelper(d, value):
    typeName = str(value.type)
    hashType = lookupType(typeName[0:typeName.rfind("::")])
    keyType = templateArgument(hashType, 0)
    valueType = templateArgument(hashType, 1)
    d.putNumChild(1)
    d.putValue(" ")
    if d.isExpanded():
        with Children(d):
            typeName = "%sQHash<%s,%s>::Node" % (d.ns, keyType, valueType)
            node = value["i"].cast(lookupType(typeName).pointer())
            d.putSubItem("key", node["key"])
            d.putSubItem("value", node["value"])

def qdump__QHash__const_iterator(d, value):
    qHashIteratorHelper(d, value)

def qdump__QHash__iterator(d, value):
    qHashIteratorHelper(d, value)


hjk's avatar
hjk committed
458
459
def qdump__QHostAddress(d, value):
    data = value["d"]["d"].dereference()
hjk's avatar
hjk committed
460
461
462
    if int(data["ipString"]["d"]["size"]):
        d.putStringValue(data["ipString"])
    else:
463
464
465
466
467
468
        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
469
    d.putNumChild(1)
hjk's avatar
hjk committed
470
    if d.isExpanded():
hjk's avatar
hjk committed
471
        with Children(d):
hjk's avatar
hjk committed
472
           d.putFields(data)
hjk's avatar
hjk committed
473
474


hjk's avatar
hjk committed
475
476
def qdump__QList(d, value):
    d_ptr = value["d"]
hjk's avatar
hjk committed
477
478
479
480
    begin = d_ptr["begin"]
    end = d_ptr["end"]
    array = d_ptr["array"]
    check(begin >= 0 and end >= 0 and end <= 1000 * 1000 * 1000)
481
482
    size = end - begin
    check(size >= 0)
483
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
484
485

    # Additional checks on pointer arrays.
hjk's avatar
hjk committed
486
    innerType = templateArgument(value.type, 0)
487
    innerTypeIsPointer = innerType.code == PointerCode \
hjk's avatar
hjk committed
488
489
490
        and str(innerType.target().unqualified()) != "char"
    if innerTypeIsPointer:
        p = gdb.Value(array).cast(innerType.pointer()) + begin
hjk's avatar
hjk committed
491
        checkPointerRange(p, min(size, 100))
hjk's avatar
hjk committed
492

493
494
    d.putItemCount(size)
    d.putNumChild(size)
hjk's avatar
hjk committed
495
    if d.isExpanded():
hjk's avatar
hjk committed
496
497
498
499
500
501
502
        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)
503
        dummyType = lookupType("void").pointer().pointer()
504
505
        innerTypePointer = innerType.pointer()
        p = gdb.Value(array).cast(dummyType) + begin
506
507
508
509
        if innerTypeIsPointer:
            inner = innerType.target()
        else:
            inner = innerType
510
        # about 0.5s / 1000 items
hjk's avatar
hjk committed
511
        with Children(d, size, maxNumChild=2000, childType=inner):
512
513
            for i in d.childRange():
                if isInternal:
hjk's avatar
hjk committed
514
                    d.putSubItem(i, p.cast(innerTypePointer).dereference())
515
                else:
hjk's avatar
hjk committed
516
                    d.putSubItem(i, p.cast(innerTypePointer.pointer()).dereference())
517
                p += 1
hjk's avatar
hjk committed
518

hjk's avatar
hjk committed
519
520
def qform__QImage():
    return "Normal,Displayed"
hjk's avatar
hjk committed
521

hjk's avatar
hjk committed
522
def qdump__QImage(d, value):
523
    try:
hjk's avatar
hjk committed
524
        painters = value["painters"]
525
    except:
hjk's avatar
hjk committed
526
        d.putPlainChildren(value)
527
        return
hjk's avatar
hjk committed
528
    check(0 <= painters and painters < 1000)
hjk's avatar
hjk committed
529
    d_ptr = value["d"]
hjk's avatar
hjk committed
530
    if isNull(d_ptr):
531
        d.putValue("(null)")
hjk's avatar
hjk committed
532
    else:
533
        checkSimpleRef(d_ptr["ref"])
534
        d.putValue("(%dx%d)" % (d_ptr["width"], d_ptr["height"]))
535
536
    bits = d_ptr["data"]
    nbytes = d_ptr["nbytes"]
537
    d.putNumChild(0)
hjk's avatar
hjk committed
538
    #d.putNumChild(1)
hjk's avatar
hjk committed
539
    if d.isExpanded():
540
        with Children(d):
hjk's avatar
hjk committed
541
            with SubItem(d, "data"):
542
                d.putNoType()
543
544
                d.putNumChild(0)
                d.putValue("size: %s bytes" % nbytes);
hjk's avatar
hjk committed
545
    format = d.currentItemFormat()
546
    if format == 1:
547
        d.putDisplay(StopDisplay)
548
    elif format == 2:
hjk's avatar
hjk committed
549
550
551
552
        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.
553
            d.put('%s="' % name)
hjk's avatar
hjk committed
554
555
556
            d.put("%08x" % int(d_ptr["width"]))
            d.put("%08x" % int(d_ptr["height"]))
            d.put("%08x" % int(d_ptr["format"]))
557
            p = bits.cast(lookupType("unsigned int").pointer())
hjk's avatar
hjk committed
558
559
560
            for i in xrange(nbytes / 4):
                d.put("%08x" % int(p.dereference()))
                p += 1
561
            d.put('",')
hjk's avatar
hjk committed
562
563
564
        else:
            # Write to an external file. Much faster ;-(
            file = tempfile.mkstemp(prefix="gdbpy_")
565
            filename = file[1].replace("\\", "\\\\")
566
            p = bits.cast(lookupType("unsigned char").pointer())
hjk's avatar
hjk committed
567
568
            gdb.execute("dump binary memory %s %s %s" %
                (filename, cleanAddress(p), cleanAddress(p + nbytes)))
569
570
            d.putDisplay(DisplayImage, " %d %d %d %s"
                % (d_ptr["width"], d_ptr["height"], d_ptr["format"], filename))
hjk's avatar
hjk committed
571
572


hjk's avatar
hjk committed
573
574
575
def qdump__QLinkedList(d, value):
    d_ptr = value["d"]
    e_ptr = value["e"]
576
    n = d_ptr["size"]
hjk's avatar
hjk committed
577
    check(0 <= n and n <= 100*1000*1000)
578
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
579
    d.putItemCount(n)
580
    d.putNumChild(n)
hjk's avatar
hjk committed
581
582
583
    if d.isExpanded():
        innerType = templateArgument(value.type, 0)
        with Children(d, n, maxNumChild=1000, childType=innerType):
584
585
            p = e_ptr["n"]
            for i in d.childRange():
hjk's avatar
hjk committed
586
                d.putSubItem(i, p["t"])
587
                p = p["n"]
hjk's avatar
hjk committed
588

589
qqLocalesCount = None
hjk's avatar
hjk committed
590

hjk's avatar
hjk committed
591
def qdump__QLocale(d, value):
592
593
594
595
596
597
598
599
    # 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
600
    index = int(value["p"]["index"])
601
    check(index >= 0 and index <= qqLocalesCount)
hjk's avatar
hjk committed
602
    d.putStringValue(call(value, "name"))
603
604
605
    d.putNumChild(0)
    return
    # FIXME: Poke back for variants.
hjk's avatar
hjk committed
606
607
608
609
610
611
612
    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
613
                "timeFormat", d.ns + "QLocale::ShortFormat")
hjk's avatar
hjk committed
614
            d.putCallItem("timeFormat_(long)", value,
hjk's avatar
hjk committed
615
                "timeFormat", d.ns + "QLocale::LongFormat")
hjk's avatar
hjk committed
616
617
618
619
620
621
            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
622
623


hjk's avatar
hjk committed
624
def qdump__QMapNode(d, value):
625
626
    d.putValue(" ")
    d.putNumChild(2)
hjk's avatar
hjk committed
627
628
629
630
631
632
633
634
635
    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
636
637
    n = d_ptr["size"]
    check(0 <= n and n <= 100*1000*1000)
638
    checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
639
640

    d.putItemCount(n)
641
    d.putNumChild(n)
hjk's avatar
hjk committed
642
    if d.isExpanded():
hjk's avatar
hjk committed
643
644
645
        if n > 1000:
            n = 1000

hjk's avatar
hjk committed
646
647
        keyType = templateArgument(value.type, 0)
        valueType = templateArgument(value.type, 1)
648
        isCompact = mapCompact(d.currentItemFormat(), keyType, valueType)
hjk's avatar
hjk committed
649
650
651
652
653
654

        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 *)
655
656
657
        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
658

659
        if isCompact:
660
661
662
            innerType = valueType
        else:
            innerType = nodeType
hjk's avatar
hjk committed
663

hjk's avatar
hjk committed
664
        with Children(d, n, childType=innerType):
665
666
667
668
            for i in xrange(n):
                itd = it.dereference()
                base = it.cast(charPtr) - payloadSize
                node = base.cast(nodeType.pointer()).dereference()
hjk's avatar
hjk committed
669
                with SubItem(d, i):
670
                    if isCompact:
671
                        #d.putType(valueType)
hjk's avatar
hjk committed
672
                        if forceLong:
673
                            d.putName("[%s] %s" % (i, node["key"]))
hjk's avatar
hjk committed
674
                        else:
675
676
                            d.putMapName(node["key"])
                        d.putItem(node["value"])
677
                    else:
hjk's avatar
hjk committed
678
                        d.putItem(node)
679
                it = it.dereference()["forward"].dereference()
hjk's avatar
hjk committed
680
681


682
683
684
def qform__QMap():
    return mapForms()

hjk's avatar
hjk committed
685
686
def qdump__QMap(d, value):
    qdumpHelper__QMap(d, value, False)
hjk's avatar
hjk committed
687

688
689
690
def qform__QMultiMap():
    return mapForms()

hjk's avatar
hjk committed
691
692
def qdump__QMultiMap(d, value):
    qdumpHelper__QMap(d, value, True)
hjk's avatar
hjk committed
693
694
695
696
697
698
699
700
701
702
703
704
705


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
706
707
def qdump__QObject(d, value):
    #warn("OBJECT: %s " % value)
708
    try:
709
        privateTypeName = d.ns + "QObjectPrivate"
710
        privateType = lookupType(privateTypeName)
hjk's avatar
hjk committed
711
712
        staticMetaObject = value["staticMetaObject"]
        d_ptr = value["d_ptr"]["d"].cast(privateType.pointer()).dereference()
713
714
        #warn("D_PTR: %s " % d_ptr)
        objectName = d_ptr["objectName"]
715
    except:
hjk's avatar
hjk committed
716
        d.putPlainChildren(value)
717
        return
hjk's avatar
hjk committed
718
    #warn("SMO: %s " % staticMetaObject)
719
720
721
722
723
724
725
    #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)

726
727
    if privateType is None:
        d.putNumChild(4)
hjk's avatar
hjk committed
728
        #d.putValue(cleanAddress(value.address))
729
        d.putPlainChildren(value)
hjk's avatar
hjk committed
730
        if d.isExpanded():
731
            with Children(d):
hjk's avatar
hjk committed
732
                d.putFields(value)
733
        return
hjk's avatar
hjk committed
734
    #warn("OBJECTNAME: %s " % objectName)
735
    #warn("D_PTR: %s " % d_ptr)
hjk's avatar
hjk committed
736
    mo = d_ptr["metaObject"]
737
738
739
    if not isAccessible(mo):
        d.putInaccessible()
        return
hjk's avatar
hjk committed
740
741
742
743
744
745
    if isNull(mo):
        mo = staticMetaObject
    #warn("MO: %s " % mo)
    #warn("MO.D: %s " % mo["d"])
    metaData = mo["d"]["data"]
    metaStringData = mo["d"]["stringdata"]
746
    #extradata = mo["d"]["extradata"]   # Capitalization!
hjk's avatar
hjk committed
747
748
    #warn("METADATA: %s " % metaData)
    #warn("STRINGDATA: %s " % metaStringData)
hjk's avatar
hjk committed
749
750
    #warn("TYPE: %s " % value.type)
    #warn("INAME: %s " % d.currentIName())
751
752
    #d.putValue("")
    d.putStringValue(objectName)
hjk's avatar
hjk committed
753
    #QSignalMapper::staticMetaObject
754
    #checkRef(d_ptr["ref"])
hjk's avatar
hjk committed
755
    d.putNumChild(4)
hjk's avatar
hjk committed
756
    if d.isExpanded():
757
      with Children(d):
758

hjk's avatar
hjk committed
759
        # Local data.
760
761
        if privateTypeName != d.ns + "QObjectPrivate":
            if not privateType is None:
hjk's avatar
hjk committed
762
              with SubItem(d, "data"):
763
                d.putValue(" ")
764
                d.putNoType()
765
                d.putNumChild(1)
hjk's avatar
hjk committed
766
                if d.isExpanded():
767
                    with Children(d):
hjk's avatar
hjk committed
768
                        d.putFields(d_ptr, False)
769
770


hjk's avatar
hjk committed
771
        d.putFields(value)
772
        # Parent and children.
hjk's avatar
hjk committed
773
774
775
        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
776

777
        # Properties.
hjk's avatar
hjk committed
778
        with SubItem(d, "properties"):
779
            # Prolog
780
781
            extraData = d_ptr["extraData"]   # Capitalization!
            if isNull(extraData):
782
                dynamicPropertyCount = 0
783
            else:
784
                extraDataType = lookupType(
785
786
787
788
789
790
791
792
793
                    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"]
794
795
                dynamicPropertyCount = namesEnd - namesBegin

hjk's avatar
hjk committed
796
            #staticPropertyCount = call(mo, "propertyCount")
797
            staticPropertyCount = metaData[6]
798
799
800
            #warn("PROPERTY COUNT: %s" % staticPropertyCount)
            propertyCount = staticPropertyCount + dynamicPropertyCount

801
            d.putNoType()
802
803
804
            d.putItemCount(propertyCount)
            d.putNumChild(propertyCount)

hjk's avatar
hjk committed
805
            if d.isExpanded():
806
807
                # FIXME: Make this global. Don't leak.
                variant = "'%sQVariant'" % d.ns
808
                # Avoid malloc symbol clash with QVector
hjk's avatar
hjk committed
809
810
                gdb.execute("set $d = (%s*)calloc(sizeof(%s), 1)"
                    % (variant, variant))
811
                gdb.execute("set $d.d.is_shared = 0")
812

hjk's avatar
hjk committed
813
                with Children(d):
814
                    # Dynamic properties.
815
816
817
818
819
820
821
822
823
824
                    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
825
                            with SubItem(d, i):
826
827
828
829
830
831
                                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))
832
833
                                d.putField("exp", "*(%s*)%s"
                                     % (variant, cleanAddress(qq)))
hjk's avatar
hjk committed
834
835
                                t = qdump__QVariant(d, qq)
                                # Override the "QVariant (foo)" output.
hjk's avatar
hjk committed
836
                                d.putBetterType(t)
837
838
                            p += 1
                            q += 1
839
840
841
842

                    # Static properties.
                    propertyData = metaData[7]
                    for i in xrange(staticPropertyCount):
843
                      with NoAddress(d):
hjk's avatar
hjk committed
844
845
846
847
848
849
                        offset = propertyData + 3 * i
                        propertyName = extractCString(metaStringData,
                                                      metaData[offset])
                        propertyType = extractCString(metaStringData,
                                                      metaData[offset + 1])
                        with SubItem(d, propertyName):
850
851
852
853
                            #flags = metaData[offset + 2]
                            #warn("FLAGS: %s " % flags)
                            #warn("PROPERTY: %s %s " % (propertyType, propertyName))
                            # #exp = '((\'%sQObject\'*)%s)->property("%s")' \
hjk's avatar
hjk committed
854
                            #     % (d.ns, value.address, propertyName)
hjk's avatar
hjk committed
855
                            #exp = '"((\'%sQObject\'*)%s)"' %
hjk's avatar
hjk committed
856
                            #(d.ns, value.address,)
857
                            #warn("EXPRESSION:  %s" % exp)
hjk's avatar
hjk committed
858
                            prop = call(value, "property",
hjk's avatar
hjk committed
859
                                str(cleanAddress(metaStringData + metaData[offset])))
hjk's avatar
hjk committed
860
                            value1 = prop["d"]
861
                            #warn("   CODE: %s" % value1["type"])
hjk's avatar
hjk committed
862
863
                            # Type 1 and 2 are bool and int.
                            # Try to save a few cycles in this case:
864
                            if int(value1["type"]) > 2:
hjk's avatar
hjk committed
865
                                # Poke back prop
hjk's avatar
hjk committed
866
867
868
869
870
871
                                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
872
                                prop = parseAndEvaluate("$d").dereference()
hjk's avatar
hjk committed
873
                            val, inner, innert, handled = \
hjk's avatar
hjk committed
874
                                qdumpHelper__QVariant(d, prop)
hjk's avatar
hjk committed
875
876
877
878

                            if handled:
                                pass
                            elif len(inner):
879
880
                                # Build-in types.
                                d.putType(inner)
hjk's avatar
hjk committed
881
                                d.putItem(val)
882
883
                            else:
                                # User types.
884
885
                           #    func = "typeToName(('%sQVariant::Type')%d)"
                           #       % (d.ns, variantType)
hjk's avatar
hjk committed
886
                           #    type = str(call(value, func))
887
888
                           #    type = type[type.find('"') + 1 : type.rfind('"')]
                           #    type = type.replace("Q", d.ns + "Q") # HACK!
hjk's avatar
hjk committed
889
                           #    data = call(value, "constData")
890
891
                           #    tdata = data.cast(lookupType(type).pointer())
                           #      .dereference()
892
893
894
                           #    d.putValue("(%s)" % tdata.type)
                           #    d.putType(tdata.type)
                           #    d.putNumChild(1)
hjk's avatar
hjk committed
895
                           #    if d.isExpanded():
896
                           #        with Children(d):
hjk's avatar
hjk committed
897
                           #           d.putSubItem("data", tdata)
898
                                warn("FIXME: CUSTOM QOBJECT PROPERTY: %s %s"
899
900
901
902
903
                                    % (propertyType, innert))
                                d.putType(propertyType)
                                d.putValue("...")
                                d.putNumChild(0)

904
        # Connections.