Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Tobias Hunger
qt-creator
Commits
eb75f40a
Commit
eb75f40a
authored
Jun 25, 2010
by
hjk
Browse files
debugger: allow per item selection of display method in Locals&Watchers
parent
21843d63
Changes
6
Hide whitespace changes
Inline
Side-by-side
share/qtcreator/gdbmacros/dumper.py
View file @
eb75f40a
...
...
@@ -771,6 +771,49 @@ class Item:
self
.
name
=
name
#######################################################################
#
# SetupCommand
#
#######################################################################
# This is a mapping from 'type name' to 'display alternatives'.
qqDumpers
=
{}
qqFormats
=
{}
class
SetupCommand
(
gdb
.
Command
):
"""Setup Creator Pretty Printing"""
def
__init__
(
self
):
super
(
SetupCommand
,
self
).
__init__
(
"bbsetup"
,
gdb
.
COMMAND_OBSCURE
)
def
invoke
(
self
,
args
,
from_tty
):
module
=
sys
.
modules
[
__name__
]
for
key
,
value
in
module
.
__dict__
.
items
():
if
key
.
startswith
(
"qdump__"
):
name
=
key
[
7
:]
qqDumpers
[
name
]
=
value
elif
key
.
startswith
(
"qform__"
):
name
=
key
[
7
:]
formats
=
""
try
:
formats
=
value
()
except
:
pass
qqFormats
[
name
]
=
formats
result
=
"dumpers=["
# Too early: ns = qtNamespace()
for
key
,
value
in
qqFormats
.
items
():
result
+=
'{type="%s",formats="%s"},'
%
(
key
,
value
)
result
+=
']'
#result += '],namespace="%s"' % ns
print
(
result
)
SetupCommand
()
#######################################################################
#
# FrameCommand
...
...
@@ -778,7 +821,7 @@ class Item:
#######################################################################
class
FrameCommand
(
gdb
.
Command
):
"""Do fancy stuff.
Usage bb --verbose expandedINames
"""
"""Do fancy stuff."""
def
__init__
(
self
):
super
(
FrameCommand
,
self
).
__init__
(
"bb"
,
gdb
.
COMMAND_OBSCURE
)
...
...
@@ -846,7 +889,6 @@ class Dumper:
self
.
currentValueEncoding
=
None
self
.
currentType
=
None
self
.
currentTypePriority
=
-
100
self
.
dumpers
=
""
self
.
typeformats
=
{}
self
.
formats
=
{}
self
.
expandedINames
=
""
...
...
@@ -890,28 +932,6 @@ class Dumper:
#warn("VARIABLES: %s" % varList)
#warn("EXPANDED INAMES: %s" % self.expandedINames)
module
=
sys
.
modules
[
__name__
]
self
.
dumpers
=
{}
if
False
:
for
key
,
value
in
module
.
__dict__
.
items
():
if
key
.
startswith
(
"qdump__"
):
self
.
dumpers
+=
'"'
+
key
[
7
:]
+
'",'
output
=
"dumpers=[%s],"
%
self
.
dumpers
#output += "qtversion=[%d,%d,%d]"
#output += "qtversion=[4,6,0],"
output
+=
"namespace=
\"
%s
\"
,"
%
qtNamespace
()
output
+=
"dumperversion=
\"
2.0
\"
,"
output
+=
"sizes=[],"
output
+=
"expressions=[]"
output
+=
"]"
print
output
return
if
self
.
useFancy
:
for
key
,
value
in
module
.
__dict__
.
items
():
if
key
.
startswith
(
"qdump__"
):
self
.
dumpers
[
key
[
7
:]]
=
value
#
# Locals
...
...
@@ -1184,7 +1204,7 @@ class Dumper:
self
.
putNumChild
(
0
)
def
itemFormat
(
self
,
item
):
format
=
self
.
formats
.
get
(
str
(
cleanAddress
(
item
.
value
.
address
))
)
format
=
self
.
formats
.
get
(
item
.
iname
)
if
format
is
None
:
format
=
self
.
typeformats
.
get
(
stripClassTag
(
str
(
item
.
value
.
type
)))
return
format
...
...
@@ -1224,6 +1244,7 @@ class Dumper:
value
=
item
.
value
type
=
value
.
type
format
=
self
.
itemFormat
(
item
)
if
type
.
code
==
gdb
.
TYPE_CODE_REF
:
try
:
...
...
@@ -1243,62 +1264,66 @@ class Dumper:
type
.
strip_typedefs
().
unqualified
()).
replace
(
"::"
,
"__"
)
#warn(" STRIPPED: %s" % strippedType)
#warn(" DUMPERS: %s" % self.dumpers)
#warn(" DUMPERS: %s" % (strippedType in self.dumpers))
#warn(" DUMPERS: %s" % (strippedType in qqDumpers))
if
isSimpleType
(
type
.
unqualified
()):
#warn("IS SIMPLE: %s " % type)
#self.putAddress(value.address)
self
.
putType
(
item
.
value
.
type
)
self
.
putValue
(
value
)
self
.
putNumChild
(
0
)
elif
strippedType
in
self
.
d
umpers
:
elif
((
format
is
None
)
or
(
format
>=
1
))
and
strippedType
in
qqD
umpers
:
#warn("IS DUMPABLE: %s " % type)
#self.putAddress(value.address)
self
.
putType
(
item
.
value
.
type
)
self
.
d
umpers
[
strippedType
](
self
,
item
)
qqD
umpers
[
strippedType
](
self
,
item
)
#warn(" RESULT: %s " % self.output)
elif
type
.
code
==
gdb
.
TYPE_CODE_ENUM
:
#warn("GENERIC ENUM: %s" % value)
#self.putAddress(value.address)
self
.
putType
(
item
.
value
.
type
)
self
.
putValue
(
value
)
self
.
putNumChild
(
0
)
elif
type
.
code
==
gdb
.
TYPE_CODE_PTR
:
warn
(
"POINTER: %s"
%
format
)
isHandled
=
False
format
=
self
.
itemFormat
(
item
)
if
not
format
is
None
:
self
.
putAddress
(
value
.
address
)
self
.
putType
(
item
.
value
.
type
)
self
.
putNumChild
(
0
)
isHandled
=
True
if
format
==
0
:
# Bald pointer.
self
.
putPointerValue
(
value
.
address
)
self
.
putNumChild
(
1
)
elif
format
==
1
or
format
==
2
:
# Latin1 or UTF-8
f
=
select
(
format
==
1
,
Hex2EncodedLatin1
,
Hex2EncodedUtf8
)
self
.
putValue
(
encodeCharArray
(
value
,
100
),
f
)
self
.
putNumChild
(
0
)
elif
format
==
3
:
# UTF-16.
self
.
putValue
(
encodeChar2Array
(
value
,
100
),
Hex4EncodedBigEndian
)
self
.
putNumChild
(
0
)
elif
format
==
4
:
# UCS-4:
self
.
putValue
(
encodeChar4Array
(
value
,
100
),
Hex8EncodedBigEndian
)
self
.
putNumChild
(
0
)
if
format
==
0
:
# Bald pointer.
self
.
putPointerValue
(
value
.
address
)
elif
format
==
1
or
format
==
2
:
# Latin1 or UTF-8
f
=
select
(
format
==
1
,
Hex2EncodedLatin1
,
Hex2EncodedUtf8
)
self
.
putValue
(
encodeCharArray
(
value
,
100
),
f
)
elif
format
==
3
:
# UTF-16.
self
.
putValue
(
encodeChar2Array
(
value
,
100
),
Hex4EncodedBigEndian
)
elif
format
==
4
:
# UCS-4:
self
.
putValue
(
encodeChar4Array
(
value
,
100
),
Hex8EncodedBigEndian
)
strippedType
=
str
(
type
.
strip_typedefs
())
\
.
replace
(
"(anonymous namespace)"
,
""
)
if
(
not
isHandled
)
and
strippedType
.
find
(
"("
)
!=
-
1
:
# A function pointer.
self
.
putValue
(
str
(
item
.
value
))
self
.
putAddress
(
value
.
address
)
self
.
putType
(
item
.
value
.
type
)
self
.
putNumChild
(
0
)
isHandled
=
True
if
(
not
isHandled
):
strippedType
=
str
(
type
.
strip_typedefs
())
\
.
replace
(
"(anonymous namespace)"
,
""
)
if
strippedType
.
find
(
"("
)
!=
-
1
:
# A function pointer.
self
.
putValue
(
str
(
item
.
value
))
self
.
putAddress
(
value
.
address
)
self
.
putType
(
item
.
value
.
type
)
self
.
putNumChild
(
0
)
isHandled
=
True
if
(
not
isHandled
)
and
self
.
useFancy
:
if
isNull
(
value
):
...
...
share/qtcreator/gdbmacros/gdbmacros.py
View file @
eb75f40a
...
...
@@ -66,7 +66,7 @@ def qdump__QAbstractItem(d, item):
rr
=
call
(
m
,
"rowCount(child)"
)
cc
=
call
(
m
,
"columnCount(child)"
)
d
.
putNumChild
(
rr
*
cc
)
d
.
put
Field
(
"v
alue
"
,
d
.
put
V
alue
(
call
(
m
,
"data(child, Qt::DisplayRole).toString())"
),
6
)
#with SubItem(d):
...
...
@@ -424,6 +424,8 @@ def qdump__QList(d, item):
d
.
putItem
(
Item
(
pp
,
item
.
iname
,
i
))
p
+=
1
def
qdump__QImage
():
return
"Normal,Displayed"
;
def
qdump__QImage
(
d
,
item
):
painters
=
item
.
value
[
"painters"
]
...
...
@@ -436,7 +438,6 @@ def qdump__QImage(d, item):
d
.
putValue
(
"(%dx%d)"
%
(
d_ptr
[
"width"
],
d_ptr
[
"height"
]))
bits
=
d_ptr
[
"data"
]
nbytes
=
d_ptr
[
"nbytes"
]
d
.
putField
(
"typeformats"
,
"Normal,Displayed"
);
d
.
putNumChild
(
0
)
#d.putNumChild(1)
if
d
.
isExpanded
(
item
):
...
...
@@ -447,9 +448,9 @@ def qdump__QImage(d, item):
d
.
putNumChild
(
0
)
d
.
putValue
(
"size: %s bytes"
%
nbytes
);
format
=
d
.
itemFormat
(
item
)
if
format
==
0
:
if
format
==
1
:
d
.
putDisplay
(
StopDisplay
)
elif
format
==
1
:
elif
format
==
2
:
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.
...
...
@@ -1458,15 +1459,16 @@ def qdump__QSizeF(d, item):
def
qdump__QStack
(
d
,
item
):
qdump__QVector
(
d
,
item
)
def
qform__QString
():
return
"Inline,Separate Window"
;
def
qdump__QString
(
d
,
item
):
d
.
putStringValue
(
item
.
value
)
d
.
putNumChild
(
0
)
d
.
putField
(
"typeformats"
,
"Normal,Displayed"
);
format
=
d
.
itemFormat
(
item
)
if
format
==
0
:
if
format
==
1
:
d
.
putDisplay
(
StopDisplay
)
elif
format
==
1
:
elif
format
==
2
:
d
.
putField
(
"editformat"
,
2
)
str
=
encodeString
(
item
.
value
)
d
.
putField
(
"editvalue"
,
str
)
...
...
src/plugins/debugger/gdb/gdbengine.cpp
View file @
eb75f40a
...
...
@@ -1525,6 +1525,16 @@ void GdbEngine::handleHasPython(const GdbResponse &response)
{
if
(
response
.
resultClass
==
GdbResultDone
)
{
m_hasPython
=
true
;
GdbMi
contents
=
response
.
data
.
findChild
(
"consolestreamoutput"
);
GdbMi
data
;
data
.
fromStringMultiple
(
contents
.
data
());
const
GdbMi
dumpers
=
data
.
findChild
(
"dumpers"
);
foreach
(
const
GdbMi
&
dumper
,
dumpers
.
children
())
{
QString
type
=
_
(
dumper
.
findChild
(
"type"
).
data
());
QStringList
formats
(
tr
(
"Raw structure"
));
formats
.
append
(
_
(
dumper
.
findChild
(
"formats"
).
data
()).
split
(
_
(
","
)));
watchHandler
()
->
addTypeFormats
(
type
,
formats
);
}
}
else
{
m_hasPython
=
false
;
if
(
m_gdbAdapter
->
dumperHandling
()
==
AbstractGdbAdapter
::
DumperLoadedByGdbPreload
...
...
@@ -4125,7 +4135,7 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr
"
\"
python execfile('"
+
dumperSourcePath
+
"gdbmacros.py')
\"
"
,
NonCriticalResponse
);
postCommand
(
"-interpreter-exec console
\"
help bb
\"
"
,
postCommand
(
"-interpreter-exec console
\"
bbsetup
\"
"
,
CB
(
handleHasPython
));
return
true
;
...
...
src/plugins/debugger/watchhandler.cpp
View file @
eb75f40a
...
...
@@ -613,7 +613,8 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
return
QVariant
(
QLatin1Char
(
'*'
)
+
item
->
parent
->
name
);
return
data
.
name
;
case
1
:
{
int
format
=
m_handler
->
m_individualFormats
.
value
(
data
.
addr
,
-
1
);
int
format
=
m_handler
->
m_individualFormats
.
value
(
data
.
iname
,
-
1
);
if
(
format
==
-
1
)
format
=
m_handler
->
m_typeFormats
.
value
(
data
.
type
,
-
1
);
return
truncateValue
(
formattedValue
(
data
,
format
));
...
...
@@ -650,26 +651,30 @@ QVariant WatchModel::data(const QModelIndex &idx, int role) const
case
LocalsExpandedRole
:
return
m_handler
->
m_expandedINames
.
contains
(
data
.
iname
);
case
LocalsTypeFormatListRole
:
if
(
!
data
.
typeFormats
.
isEmpty
())
return
data
.
typeFormats
.
split
(
','
);
case
LocalsTypeFormatListRole
:
{
if
(
isIntType
(
data
.
type
))
return
QStringList
()
<<
tr
(
"decimal"
)
<<
tr
(
"hexadecimal"
)
<<
tr
(
"binary"
)
<<
tr
(
"octal"
);
if
(
data
.
type
.
endsWith
(
QLatin1Char
(
'*'
)))
return
QStringList
()
<<
tr
(
"
Bald
pointer"
)
<<
tr
(
"
Raw
pointer"
)
<<
tr
(
"Latin1 string"
)
<<
tr
(
"UTF8 string"
)
<<
tr
(
"UTF16 string"
)
<<
tr
(
"UCS4 string"
);
break
;
// Hack: Compensate for namespaces.
QString
type
=
data
.
type
;
int
pos
=
type
.
indexOf
(
"::Q"
);
if
(
pos
>=
0
&&
type
.
count
(
':'
)
==
2
)
type
=
type
.
mid
(
pos
+
2
);
return
m_handler
->
m_reportedTypeFormats
.
value
(
type
);
}
case
LocalsTypeFormatRole
:
return
m_handler
->
m_typeFormats
.
value
(
data
.
type
,
-
1
);
case
LocalsIndividualFormatRole
:
return
m_handler
->
m_individualFormats
.
value
(
data
.
addr
,
-
1
);
return
m_handler
->
m_individualFormats
.
value
(
data
.
iname
,
-
1
);
case
LocalsRawValueRole
:
return
data
.
value
;
...
...
@@ -772,9 +777,9 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro
case
LocalsIndividualFormatRole
:
{
const
int
format
=
value
.
toInt
();
if
(
format
==
-
1
)
{
m_handler
->
m_individualFormats
.
remove
(
data
.
addr
);
m_handler
->
m_individualFormats
.
remove
(
data
.
iname
);
}
else
{
m_handler
->
m_individualFormats
[
data
.
addr
]
=
format
;
m_handler
->
m_individualFormats
[
data
.
iname
]
=
format
;
}
engine
()
->
updateWatchData
(
data
);
break
;
...
...
@@ -1503,7 +1508,7 @@ int WatchHandler::format(const QByteArray &iname) const
{
int
result
=
-
1
;
if
(
const
WatchData
*
item
=
findItem
(
iname
))
{
int
result
=
m_individualFormats
.
value
(
iname
,
-
1
);
int
result
=
m_individualFormats
.
value
(
item
->
iname
,
-
1
);
if
(
result
==
-
1
)
result
=
m_typeFormats
.
value
(
item
->
type
,
-
1
);
}
...
...
@@ -1561,5 +1566,10 @@ QByteArray WatchHandler::individualFormatRequests() const
return
ba
;
}
void
WatchHandler
::
addTypeFormats
(
const
QString
&
type
,
const
QStringList
&
formats
)
{
m_reportedTypeFormats
.
insert
(
type
,
formats
);
}
}
// namespace Internal
}
// namespace Debugger
src/plugins/debugger/watchhandler.h
View file @
eb75f40a
...
...
@@ -36,12 +36,8 @@
#include
<QtCore/QObject>
#include
<QtCore/QHash>
#include
<QtCore/QSet>
#include
<QtCore/QStringList>
#include
<QtCore/QAbstractItemModel>
#include
<QtScript/QScriptValue>
QT_BEGIN_NAMESPACE
class
QDebug
;
QT_END_NAMESPACE
namespace
Debugger
{
namespace
Internal
{
...
...
@@ -49,6 +45,7 @@ namespace Internal {
class
DebuggerEngine
;
class
WatchItem
;
class
WatchHandler
;
class
WatchData
;
enum
WatchType
{
...
...
@@ -174,6 +171,8 @@ public:
static
QString
watcherEditPlaceHolder
();
int
format
(
const
QByteArray
&
iname
)
const
;
void
addTypeFormats
(
const
QString
&
type
,
const
QStringList
&
formats
);
private:
friend
class
WatchModel
;
...
...
@@ -195,7 +194,8 @@ private:
QHash
<
QByteArray
,
int
>
m_watcherNames
;
QByteArray
watcherName
(
const
QByteArray
&
exp
);
QHash
<
QString
,
int
>
m_typeFormats
;
QHash
<
QByteArray
,
int
>
m_individualFormats
;
QHash
<
QByteArray
,
int
>
m_individualFormats
;
// Indexed by iname.
QHash
<
QString
,
QStringList
>
m_reportedTypeFormats
;
// Items expanded in the Locals & Watchers view.
QSet
<
QByteArray
>
m_expandedINames
;
...
...
src/plugins/debugger/watchwindow.cpp
View file @
eb75f40a
...
...
@@ -231,7 +231,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
if
(
alternativeFormats
.
isEmpty
())
{
typeFormatMenu
.
setEnabled
(
false
);
}
else
{
clearTypeFormatAction
=
typeFormatMenu
.
addAction
(
tr
(
"
Clear
"
));
clearTypeFormatAction
=
typeFormatMenu
.
addAction
(
tr
(
"
Automatic
"
));
clearTypeFormatAction
->
setEnabled
(
typeFormat
!=
-
1
);
clearTypeFormatAction
->
setCheckable
(
true
);
clearTypeFormatAction
->
setChecked
(
typeFormat
==
-
1
);
...
...
@@ -254,13 +254,14 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
QMenu
individualFormatMenu
;
QList
<
QAction
*>
individualFormatActions
;
QAction
*
clearIndividualFormatAction
=
0
;
if
(
idx
.
isValid
()
&&
address
)
{
if
(
idx
.
isValid
())
{
individualFormatMenu
.
setTitle
(
tr
(
"Change Format for Object
at 0x%1"
).
arg
(
address
,
0
,
16
));
tr
(
"Change Format for Object
Named
\"
%1
\"
"
).
arg
(
mi0
.
data
().
toString
()
));
if
(
alternativeFormats
.
isEmpty
())
{
individualFormatMenu
.
setEnabled
(
false
);
}
else
{
clearIndividualFormatAction
=
individualFormatMenu
.
addAction
(
tr
(
"Clear"
));
clearIndividualFormatAction
=
individualFormatMenu
.
addAction
(
tr
(
"Automatic"
));
clearIndividualFormatAction
->
setEnabled
(
individualFormat
!=
-
1
);
clearIndividualFormatAction
->
setCheckable
(
true
);
clearIndividualFormatAction
->
setChecked
(
individualFormat
==
-
1
);
...
...
@@ -302,10 +303,12 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
if
(
canShowMemory
&&
address
)
actOpenMemoryEditAtVariableAddress
=
new
QAction
(
tr
(
"Open Memory Editor at Object's Address (0x%1)"
).
arg
(
address
,
0
,
16
),
&
menu
);
new
QAction
(
tr
(
"Open Memory Editor at Object's Address (0x%1)"
)
.
arg
(
address
,
0
,
16
),
&
menu
);
if
(
createPointerActions
)
actOpenMemoryEditAtPointerValue
=
new
QAction
(
tr
(
"Open Memory Editor at Referenced Address (0x%1)"
).
arg
(
pointerValue
,
0
,
16
),
&
menu
);
new
QAction
(
tr
(
"Open Memory Editor at Referenced Address (0x%1)"
)
.
arg
(
pointerValue
,
0
,
16
),
&
menu
);
menu
.
addSeparator
();
QAction
*
actSetWatchPointAtVariableAddress
=
0
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment