2011-02-18 10:36:52 +01:00
|
|
|
/**************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** This file is part of Qt Creator
|
|
|
|
|
**
|
|
|
|
|
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
|
|
|
|
**
|
2011-11-02 15:59:12 +01:00
|
|
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
2011-02-18 10:36:52 +01:00
|
|
|
**
|
|
|
|
|
**
|
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
|
**
|
2011-04-13 08:42:33 +02:00
|
|
|
** This file may be used under the terms of the GNU Lesser General Public
|
|
|
|
|
** License version 2.1 as published by the Free Software Foundation and
|
|
|
|
|
** appearing in the file LICENSE.LGPL included in the packaging of this file.
|
|
|
|
|
** Please review the following information to ensure the GNU Lesser General
|
|
|
|
|
** Public License version 2.1 requirements will be met:
|
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2011-02-18 10:36:52 +01:00
|
|
|
**
|
|
|
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
2011-04-13 08:42:33 +02:00
|
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
2011-02-18 10:36:52 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
2011-04-13 08:42:33 +02:00
|
|
|
** Other Usage
|
|
|
|
|
**
|
|
|
|
|
** Alternatively, this file may be used in accordance with the terms and
|
|
|
|
|
** conditions contained in a signed written agreement between you and Nokia.
|
|
|
|
|
**
|
2011-02-18 10:36:52 +01:00
|
|
|
** If you have questions regarding the use of this file, please contact
|
2011-11-02 15:59:12 +01:00
|
|
|
** Nokia at qt-info@nokia.com.
|
2011-02-18 10:36:52 +01:00
|
|
|
**
|
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
2010-04-26 18:54:08 +02:00
|
|
|
#include "watchdata.h"
|
|
|
|
|
|
|
|
|
|
#include <QtCore/QTextStream>
|
|
|
|
|
#include <QtCore/QDebug>
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// WatchData
|
|
|
|
|
//
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
namespace Debugger {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2011-01-17 15:15:19 +01:00
|
|
|
static QString htmlEscape(const QString &plain)
|
2010-10-15 13:00:14 +02:00
|
|
|
{
|
|
|
|
|
QString rich;
|
|
|
|
|
rich.reserve(int(plain.length() * 1.1));
|
|
|
|
|
for (int i = 0; i < plain.length(); ++i) {
|
|
|
|
|
if (plain.at(i) == QLatin1Char('<'))
|
|
|
|
|
rich += QLatin1String("<");
|
|
|
|
|
else if (plain.at(i) == QLatin1Char('>'))
|
|
|
|
|
rich += QLatin1String(">");
|
|
|
|
|
else if (plain.at(i) == QLatin1Char('&'))
|
|
|
|
|
rich += QLatin1String("&");
|
|
|
|
|
else if (plain.at(i) == QLatin1Char('"'))
|
|
|
|
|
rich += QLatin1String(""");
|
|
|
|
|
else
|
|
|
|
|
rich += plain.at(i);
|
|
|
|
|
}
|
|
|
|
|
return rich;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isPointerType(const QByteArray &type)
|
|
|
|
|
{
|
|
|
|
|
return type.endsWith('*') || type.endsWith("* const");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isCharPointerType(const QByteArray &type)
|
|
|
|
|
{
|
|
|
|
|
return type == "char *" || type == "const char *" || type == "char const *";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isIntType(const QByteArray &type)
|
|
|
|
|
{
|
|
|
|
|
if (type.isEmpty())
|
|
|
|
|
return false;
|
|
|
|
|
switch (type.at(0)) {
|
|
|
|
|
case 'b':
|
|
|
|
|
return type == "bool";
|
|
|
|
|
case 'c':
|
|
|
|
|
return type == "char";
|
|
|
|
|
case 'i':
|
|
|
|
|
return type == "int" || type == "int64";
|
|
|
|
|
case 'l':
|
|
|
|
|
return type == "long"
|
2011-03-23 13:06:16 +01:00
|
|
|
|| type.startsWith("long ");
|
2010-10-15 13:00:14 +02:00
|
|
|
case 'p':
|
|
|
|
|
return type == "ptrdiff_t";
|
|
|
|
|
case 'q':
|
|
|
|
|
return type == "qint16" || type == "quint16"
|
|
|
|
|
|| type == "qint32" || type == "quint32"
|
2011-03-23 13:06:16 +01:00
|
|
|
|| type == "qint64" || type == "quint64"
|
|
|
|
|
|| type == "qlonglong" || type == "qulonglong";
|
2010-10-15 13:00:14 +02:00
|
|
|
case 's':
|
|
|
|
|
return type == "short"
|
|
|
|
|
|| type == "signed"
|
|
|
|
|
|| type == "size_t"
|
|
|
|
|
|| type == "std::size_t"
|
|
|
|
|
|| type == "std::ptrdiff_t"
|
|
|
|
|
|| type.startsWith("signed ");
|
|
|
|
|
case 'u':
|
|
|
|
|
return type == "unsigned"
|
|
|
|
|
|| type.startsWith("unsigned ");
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isFloatType(const QByteArray &type)
|
|
|
|
|
{
|
|
|
|
|
return type == "float" || type == "double" || type == "qreal";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isIntOrFloatType(const QByteArray &type)
|
|
|
|
|
{
|
|
|
|
|
return isIntType(type) || isFloatType(type);
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-26 18:54:08 +02:00
|
|
|
WatchData::WatchData() :
|
2010-10-15 13:00:14 +02:00
|
|
|
id(0),
|
|
|
|
|
state(InitialState),
|
2010-04-26 18:54:08 +02:00
|
|
|
editformat(0),
|
2010-09-22 11:19:35 +02:00
|
|
|
address(0),
|
2011-04-12 15:56:03 +02:00
|
|
|
referencingAddress(0),
|
2011-04-04 16:15:03 +02:00
|
|
|
size(0),
|
2011-03-01 17:04:36 +01:00
|
|
|
bitpos(0),
|
|
|
|
|
bitsize(0),
|
2010-04-26 18:54:08 +02:00
|
|
|
generation(-1),
|
2010-10-15 13:00:14 +02:00
|
|
|
hasChildren(false),
|
2010-04-26 18:54:08 +02:00
|
|
|
valueEnabled(true),
|
|
|
|
|
valueEditable(true),
|
|
|
|
|
error(false),
|
2010-10-08 14:55:57 +02:00
|
|
|
changed(false),
|
2010-10-15 13:00:14 +02:00
|
|
|
sortId(0),
|
|
|
|
|
source(0)
|
2010-04-26 18:54:08 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool WatchData::isEqual(const WatchData &other) const
|
|
|
|
|
{
|
|
|
|
|
return iname == other.iname
|
|
|
|
|
&& exp == other.exp
|
|
|
|
|
&& name == other.name
|
|
|
|
|
&& value == other.value
|
|
|
|
|
&& editvalue == other.editvalue
|
|
|
|
|
&& valuetooltip == other.valuetooltip
|
|
|
|
|
&& type == other.type
|
|
|
|
|
&& displayedType == other.displayedType
|
|
|
|
|
&& variable == other.variable
|
2010-09-22 11:19:35 +02:00
|
|
|
&& address == other.address
|
2011-04-04 16:15:03 +02:00
|
|
|
&& size == other.size
|
2010-04-26 18:54:08 +02:00
|
|
|
&& hasChildren == other.hasChildren
|
|
|
|
|
&& valueEnabled == other.valueEnabled
|
|
|
|
|
&& valueEditable == other.valueEditable
|
|
|
|
|
&& error == other.error;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-11 17:51:29 +01:00
|
|
|
bool WatchData::isVTablePointer() const
|
|
|
|
|
{
|
|
|
|
|
// First case: Cdb only. No user type can be named like this, this is safe.
|
|
|
|
|
// Second case: Python dumper only.
|
|
|
|
|
return type.startsWith("__fptr()")
|
|
|
|
|
|| (type.isEmpty() && name == QLatin1String("[vptr]"));
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-26 18:54:08 +02:00
|
|
|
void WatchData::setError(const QString &msg)
|
|
|
|
|
{
|
|
|
|
|
setAllUnneeded();
|
|
|
|
|
value = msg;
|
|
|
|
|
setHasChildren(false);
|
|
|
|
|
valueEnabled = false;
|
|
|
|
|
valueEditable = false;
|
|
|
|
|
error = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WatchData::setValue(const QString &value0)
|
|
|
|
|
{
|
|
|
|
|
value = value0;
|
|
|
|
|
if (value == "{...}") {
|
|
|
|
|
value.clear();
|
|
|
|
|
hasChildren = true; // at least one...
|
|
|
|
|
}
|
|
|
|
|
// strip off quoted characters for chars.
|
2010-09-01 17:36:09 +02:00
|
|
|
if (value.endsWith(QLatin1Char('\'')) && type.endsWith("char")) {
|
2010-04-26 18:54:08 +02:00
|
|
|
const int blankPos = value.indexOf(QLatin1Char(' '));
|
|
|
|
|
if (blankPos != -1)
|
|
|
|
|
value.truncate(blankPos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// avoid duplicated information
|
|
|
|
|
if (value.startsWith(QLatin1Char('(')) && value.contains(") 0x"))
|
|
|
|
|
value = value.mid(value.lastIndexOf(") 0x") + 2);
|
|
|
|
|
|
|
|
|
|
// doubles are sometimes displayed as "@0x6141378: 1.2".
|
|
|
|
|
// I don't want that.
|
|
|
|
|
if (/*isIntOrFloatType(type) && */ value.startsWith("@0x")
|
|
|
|
|
&& value.contains(':')) {
|
|
|
|
|
value = value.mid(value.indexOf(':') + 2);
|
|
|
|
|
setHasChildren(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// "numchild" is sometimes lying
|
|
|
|
|
//MODEL_DEBUG("\n\n\nPOINTER: " << type << value);
|
|
|
|
|
if (isPointerType(type))
|
|
|
|
|
setHasChildren(value != "0x0" && value != "<null>"
|
|
|
|
|
&& !isCharPointerType(type));
|
|
|
|
|
|
|
|
|
|
// pointer type information is available in the 'type'
|
|
|
|
|
// column. No need to duplicate it here.
|
|
|
|
|
if (value.startsWith(QLatin1Char('(') + type + ") 0x"))
|
|
|
|
|
value = value.section(QLatin1Char(' '), -1, -1);
|
|
|
|
|
|
|
|
|
|
setValueUnneeded();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WatchData::setValueToolTip(const QString &tooltip)
|
|
|
|
|
{
|
|
|
|
|
valuetooltip = tooltip;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-08 15:38:50 +02:00
|
|
|
enum GuessChildrenResult { HasChildren, HasNoChildren, HasPossiblyChildren };
|
|
|
|
|
|
|
|
|
|
static GuessChildrenResult guessChildren(const QByteArray &type)
|
|
|
|
|
{
|
|
|
|
|
if (isIntOrFloatType(type))
|
|
|
|
|
return HasNoChildren;
|
|
|
|
|
if (isCharPointerType(type))
|
|
|
|
|
return HasNoChildren;
|
|
|
|
|
if (isPointerType(type))
|
|
|
|
|
return HasChildren;
|
|
|
|
|
if (type.endsWith("QString"))
|
|
|
|
|
return HasNoChildren;
|
|
|
|
|
return HasPossiblyChildren;
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-01 17:36:09 +02:00
|
|
|
void WatchData::setType(const QByteArray &str, bool guessChildrenFromType)
|
2010-04-26 18:54:08 +02:00
|
|
|
{
|
|
|
|
|
type = str.trimmed();
|
|
|
|
|
bool changed = true;
|
|
|
|
|
while (changed) {
|
2010-09-01 17:36:09 +02:00
|
|
|
if (type.endsWith("const"))
|
2010-04-26 18:54:08 +02:00
|
|
|
type.chop(5);
|
2010-09-01 17:36:09 +02:00
|
|
|
else if (type.endsWith(' '))
|
2010-04-26 18:54:08 +02:00
|
|
|
type.chop(1);
|
2010-09-01 17:36:09 +02:00
|
|
|
else if (type.endsWith('&'))
|
2010-04-26 18:54:08 +02:00
|
|
|
type.chop(1);
|
2010-09-01 17:36:09 +02:00
|
|
|
else if (type.startsWith("const "))
|
2010-04-26 18:54:08 +02:00
|
|
|
type = type.mid(6);
|
2010-09-01 17:36:09 +02:00
|
|
|
else if (type.startsWith("volatile "))
|
2010-04-26 18:54:08 +02:00
|
|
|
type = type.mid(9);
|
2010-09-01 17:36:09 +02:00
|
|
|
else if (type.startsWith("class "))
|
2010-04-26 18:54:08 +02:00
|
|
|
type = type.mid(6);
|
2010-09-01 17:36:09 +02:00
|
|
|
else if (type.startsWith("struct "))
|
2010-04-26 18:54:08 +02:00
|
|
|
type = type.mid(6);
|
2010-09-01 17:36:09 +02:00
|
|
|
else if (type.startsWith(' '))
|
2010-04-26 18:54:08 +02:00
|
|
|
type = type.mid(1);
|
|
|
|
|
else
|
|
|
|
|
changed = false;
|
|
|
|
|
}
|
|
|
|
|
setTypeUnneeded();
|
|
|
|
|
if (guessChildrenFromType) {
|
|
|
|
|
switch (guessChildren(type)) {
|
|
|
|
|
case HasChildren:
|
|
|
|
|
setHasChildren(true);
|
|
|
|
|
break;
|
|
|
|
|
case HasNoChildren:
|
|
|
|
|
setHasChildren(false);
|
|
|
|
|
break;
|
|
|
|
|
case HasPossiblyChildren:
|
|
|
|
|
setHasChildren(true); // FIXME: bold assumption
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-22 11:19:35 +02:00
|
|
|
void WatchData::setAddress(const quint64 &a)
|
2010-04-26 18:54:08 +02:00
|
|
|
{
|
2010-09-22 11:19:35 +02:00
|
|
|
address = a;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WatchData::setHexAddress(const QByteArray &a)
|
|
|
|
|
{
|
|
|
|
|
bool ok;
|
2011-07-07 15:00:11 +02:00
|
|
|
const qint64 av = a.toULongLong(&ok, 0);
|
2010-09-22 11:19:35 +02:00
|
|
|
if (ok) {
|
|
|
|
|
address = av;
|
|
|
|
|
} else {
|
|
|
|
|
qWarning("WatchData::setHexAddress(): Failed to parse address value '%s' for '%s', '%s'",
|
|
|
|
|
a.constData(), iname.constData(), type.constData());
|
|
|
|
|
address = 0;
|
|
|
|
|
}
|
2010-04-26 18:54:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString WatchData::toString() const
|
|
|
|
|
{
|
|
|
|
|
const char *doubleQuoteComma = "\",";
|
|
|
|
|
QString res;
|
|
|
|
|
QTextStream str(&res);
|
|
|
|
|
str << QLatin1Char('{');
|
|
|
|
|
if (!iname.isEmpty())
|
|
|
|
|
str << "iname=\"" << iname << doubleQuoteComma;
|
2010-10-08 14:55:57 +02:00
|
|
|
str << "sortId=\"" << sortId << doubleQuoteComma;
|
2010-04-26 18:54:08 +02:00
|
|
|
if (!name.isEmpty() && name != iname)
|
|
|
|
|
str << "name=\"" << name << doubleQuoteComma;
|
|
|
|
|
if (error)
|
|
|
|
|
str << "error,";
|
2010-09-22 11:19:35 +02:00
|
|
|
if (address) {
|
|
|
|
|
str.setIntegerBase(16);
|
|
|
|
|
str << "addr=\"0x" << address << doubleQuoteComma;
|
|
|
|
|
str.setIntegerBase(10);
|
|
|
|
|
}
|
2011-04-12 15:56:03 +02:00
|
|
|
if (referencingAddress) {
|
2011-04-06 18:39:56 +02:00
|
|
|
str.setIntegerBase(16);
|
2011-04-12 15:56:03 +02:00
|
|
|
str << "referencingaddr=\"0x" << referencingAddress << doubleQuoteComma;
|
2011-04-06 18:39:56 +02:00
|
|
|
str.setIntegerBase(10);
|
|
|
|
|
}
|
2010-04-26 18:54:08 +02:00
|
|
|
if (!exp.isEmpty())
|
|
|
|
|
str << "exp=\"" << exp << doubleQuoteComma;
|
|
|
|
|
|
|
|
|
|
if (!variable.isEmpty())
|
|
|
|
|
str << "variable=\"" << variable << doubleQuoteComma;
|
|
|
|
|
|
|
|
|
|
if (isValueNeeded())
|
|
|
|
|
str << "value=<needed>,";
|
|
|
|
|
if (isValueKnown() && !value.isEmpty())
|
|
|
|
|
str << "value=\"" << value << doubleQuoteComma;
|
|
|
|
|
|
|
|
|
|
if (!editvalue.isEmpty())
|
|
|
|
|
str << "editvalue=\"<...>\",";
|
|
|
|
|
// str << "editvalue=\"" << editvalue << doubleQuoteComma;
|
|
|
|
|
|
2010-09-22 11:19:35 +02:00
|
|
|
if (!dumperFlags.isEmpty())
|
|
|
|
|
str << "dumperFlags=\"" << dumperFlags << doubleQuoteComma;
|
|
|
|
|
|
2010-04-26 18:54:08 +02:00
|
|
|
if (isTypeNeeded())
|
|
|
|
|
str << "type=<needed>,";
|
|
|
|
|
if (isTypeKnown() && !type.isEmpty())
|
|
|
|
|
str << "type=\"" << type << doubleQuoteComma;
|
|
|
|
|
|
|
|
|
|
if (isHasChildrenNeeded())
|
|
|
|
|
str << "hasChildren=<needed>,";
|
|
|
|
|
if (isHasChildrenKnown())
|
|
|
|
|
str << "hasChildren=\"" << (hasChildren ? "true" : "false") << doubleQuoteComma;
|
|
|
|
|
|
|
|
|
|
if (isChildrenNeeded())
|
|
|
|
|
str << "children=<needed>,";
|
|
|
|
|
str.flush();
|
|
|
|
|
if (res.endsWith(QLatin1Char(',')))
|
|
|
|
|
res.truncate(res.size() - 1);
|
|
|
|
|
return res + QLatin1Char('}');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Format a tooltip fow with aligned colon.
|
|
|
|
|
static void formatToolTipRow(QTextStream &str,
|
|
|
|
|
const QString &category, const QString &value)
|
|
|
|
|
{
|
|
|
|
|
str << "<tr><td>" << category << "</td><td> : </td><td>"
|
2011-01-17 15:15:19 +01:00
|
|
|
<< htmlEscape(value) << "</td></tr>";
|
2010-04-26 18:54:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString WatchData::toToolTip() const
|
|
|
|
|
{
|
|
|
|
|
if (!valuetooltip.isEmpty())
|
|
|
|
|
return QString::number(valuetooltip.size());
|
|
|
|
|
QString res;
|
|
|
|
|
QTextStream str(&res);
|
|
|
|
|
str << "<html><body><table>";
|
2010-10-15 13:00:14 +02:00
|
|
|
formatToolTipRow(str, tr("Name"), name);
|
|
|
|
|
formatToolTipRow(str, tr("Expression"), exp);
|
2011-01-17 15:23:22 +01:00
|
|
|
formatToolTipRow(str, tr("Internal Type"), type);
|
|
|
|
|
formatToolTipRow(str, tr("Displayed Type"), displayedType);
|
2010-04-26 18:54:08 +02:00
|
|
|
QString val = value;
|
|
|
|
|
if (value.size() > 1000) {
|
|
|
|
|
val.truncate(1000);
|
2010-10-15 13:00:14 +02:00
|
|
|
val += tr(" ... <cut off>");
|
2010-04-26 18:54:08 +02:00
|
|
|
}
|
2010-10-15 13:00:14 +02:00
|
|
|
formatToolTipRow(str, tr("Value"), val);
|
|
|
|
|
formatToolTipRow(str, tr("Object Address"),
|
2010-09-22 11:19:35 +02:00
|
|
|
QString::fromAscii(hexAddress()));
|
2011-04-12 15:56:03 +02:00
|
|
|
if (referencingAddress)
|
|
|
|
|
formatToolTipRow(str, tr("Referencing Address"),
|
|
|
|
|
QString::fromAscii(hexReferencingAddress()));
|
2011-04-04 16:15:03 +02:00
|
|
|
if (size)
|
2011-08-19 16:06:31 +02:00
|
|
|
formatToolTipRow(str, tr("Size"), QString::number(size));
|
2010-10-15 13:00:14 +02:00
|
|
|
formatToolTipRow(str, tr("Internal ID"), iname);
|
|
|
|
|
formatToolTipRow(str, tr("Generation"),
|
2010-04-26 18:54:08 +02:00
|
|
|
QString::number(generation));
|
|
|
|
|
str << "</table></body></html>";
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString WatchData::msgNotInScope()
|
|
|
|
|
{
|
2011-05-11 15:24:50 +02:00
|
|
|
//: Value of variable in Debugger Locals display for variables out
|
|
|
|
|
//: of scope (stopped above initialization).
|
|
|
|
|
static const QString rc =
|
|
|
|
|
QCoreApplication::translate("Debugger::Internal::WatchData", "<not in scope>");
|
2010-04-26 18:54:08 +02:00
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QString &WatchData::shadowedNameFormat()
|
|
|
|
|
{
|
2010-09-10 10:51:43 +02:00
|
|
|
//: Display of variables shadowed by variables of the same name
|
|
|
|
|
//: in nested scopes: Variable %1 is the variable name, %2 is a
|
|
|
|
|
//: simple count.
|
2011-05-11 15:24:50 +02:00
|
|
|
static const QString format =
|
|
|
|
|
QCoreApplication::translate("Debugger::Internal::WatchData", "%1 <shadowed %2>");
|
2010-04-26 18:54:08 +02:00
|
|
|
return format;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString WatchData::shadowedName(const QString &name, int seen)
|
|
|
|
|
{
|
|
|
|
|
if (seen <= 0)
|
|
|
|
|
return name;
|
2011-04-12 11:57:57 +02:00
|
|
|
return shadowedNameFormat().arg(name).arg(seen);
|
2010-04-26 18:54:08 +02:00
|
|
|
}
|
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
quint64 WatchData::coreAddress() const
|
|
|
|
|
{
|
2010-09-22 11:19:35 +02:00
|
|
|
return address;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QByteArray WatchData::hexAddress() const
|
|
|
|
|
{
|
2011-05-11 15:24:50 +02:00
|
|
|
if (address)
|
|
|
|
|
return QByteArray("0x") + QByteArray::number(address, 16);
|
|
|
|
|
return QByteArray();
|
2010-06-16 11:08:54 +02:00
|
|
|
}
|
|
|
|
|
|
2011-04-12 15:56:03 +02:00
|
|
|
QByteArray WatchData::hexReferencingAddress() const
|
2011-04-06 18:39:56 +02:00
|
|
|
{
|
2011-05-11 15:24:50 +02:00
|
|
|
if (referencingAddress)
|
|
|
|
|
return QByteArray("0x") + QByteArray::number(referencingAddress, 16);
|
|
|
|
|
return QByteArray();
|
2011-04-06 18:39:56 +02:00
|
|
|
}
|
|
|
|
|
|
2011-08-19 16:06:31 +02:00
|
|
|
bool WatchData::hasChanged(const WatchData &old) const
|
|
|
|
|
{
|
|
|
|
|
return !value.isEmpty() && value != old.value && value != msgNotInScope();
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-26 18:54:08 +02:00
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace Debugger
|
|
|
|
|
|