Commit 332889ae authored by Friedemann Kleint's avatar Friedemann Kleint

Debugger: Sanitize Datatypes, part 1: Breakpoints.

Make address a quint64, linnumber and ignoreCounts int.

Reviewed-by: hjk
parent e2dc7a1d
......@@ -139,11 +139,11 @@ BreakpointData *BreakHandler::findBreakpointByNumber(int bpNumber) const
return 0;
}
int BreakHandler::findWatchPointIndexByAddress(const QByteArray &a) const
int BreakHandler::findWatchPointIndexByAddress(quint64 address) const
{
for (int index = size() - 1; index >= 0; --index) {
BreakpointData *bd = at(index);
if (bd->type == BreakpointData::WatchpointType && bd->address == a)
if (bd->type == BreakpointData::WatchpointType && bd->address == address)
return index;
}
return -1;
......@@ -151,8 +151,7 @@ int BreakHandler::findWatchPointIndexByAddress(const QByteArray &a) const
bool BreakHandler::watchPointAt(quint64 address) const
{
const QByteArray addressBA = QByteArray("0x") + QByteArray::number(address, 16);
return findWatchPointIndexByAddress(addressBA) != -1;
return findWatchPointIndexByAddress(address) != -1;
}
void BreakHandler::saveBreakpoints()
......@@ -170,16 +169,16 @@ void BreakHandler::saveBreakpoints()
map.insert(_("type"), data->type);
if (!data->fileName.isEmpty())
map.insert(_("filename"), data->fileName);
if (!data->lineNumber.isEmpty())
map.insert(_("linenumber"), data->lineNumber);
if (data->lineNumber)
map.insert(_("linenumber"), QVariant(data->lineNumber));
if (!data->funcName.isEmpty())
map.insert(_("funcname"), data->funcName);
if (!data->address.isEmpty())
if (data->address)
map.insert(_("address"), data->address);
if (!data->condition.isEmpty())
map.insert(_("condition"), data->condition);
if (!data->ignoreCount.isEmpty())
map.insert(_("ignorecount"), data->ignoreCount);
if (data->ignoreCount)
map.insert(_("ignorecount"), QVariant(data->ignoreCount));
if (!data->threadSpec.isEmpty())
map.insert(_("threadspec"), data->threadSpec);
if (!data->enabled)
......@@ -207,16 +206,16 @@ void BreakHandler::loadBreakpoints()
data->fileName = v.toString();
v = map.value(_("linenumber"));
if (v.isValid())
data->lineNumber = v.toString().toLatin1();
data->lineNumber = v.toString().toInt();
v = map.value(_("condition"));
if (v.isValid())
data->condition = v.toString().toLatin1();
v = map.value(_("address"));
if (v.isValid())
data->address = v.toString().toLatin1();
data->address = v.toString().toULongLong();
v = map.value(_("ignorecount"));
if (v.isValid())
data->ignoreCount = v.toString().toLatin1();
data->ignoreCount = v.toString().toInt();
v = map.value(_("threadspec"));
if (v.isValid())
data->threadSpec = v.toString().toLatin1();
......@@ -233,7 +232,7 @@ void BreakHandler::loadBreakpoints()
if (v.isValid())
data->type = BreakpointData::Type(v.toInt());
data->setMarkerFileName(data->fileName);
data->setMarkerLineNumber(data->lineNumber.toInt());
data->setMarkerLineNumber(data->lineNumber);
append(data);
}
//qDebug() << "LOADED BREAKPOINTS" << this << list.size();
......@@ -302,7 +301,7 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
return data->condition;
if (role == BreakpointIgnoreCountRole)
return data->ignoreCount;
return data->ignoreCount ? QVariant(data->ignoreCount) : QVariant(QString());
if (role == BreakpointThreadSpecRole)
return data->threadSpec;
......@@ -345,8 +344,8 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
// FIXME: better?
//if (data->bpMultiple && str.isEmpty() && !data->markerFileName.isEmpty())
// str = data->markerLineNumber;
const QString str = data->pending ? data->lineNumber : data->bpLineNumber;
return str.isEmpty() ? empty : str;
const int nr = data->pending ? data->lineNumber : data->bpLineNumber;
return nr ? QString::number(nr) : empty;
}
if (role == Qt::UserRole + 1)
return data->lineNumber;
......@@ -360,8 +359,10 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
return data->condition;
break;
case 5:
if (role == Qt::DisplayRole)
return data->pending ? data->ignoreCount : data->bpIgnoreCount;
if (role == Qt::DisplayRole) {
const int ignoreCount = data->pending ? data->ignoreCount : data->bpIgnoreCount;
return ignoreCount ? QVariant(ignoreCount) : QVariant(QString());
}
if (role == Qt::ToolTipRole)
return tr("Breakpoint will only be hit after being ignored so many times.");
if (role == Qt::UserRole + 1)
......@@ -381,9 +382,17 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
break;
case 7:
if (role == Qt::DisplayRole) {
if (data->type == BreakpointData::WatchpointType)
return data->address;
return data->bpAddress;
QString displayValue;
const quint64 effectiveAddress = data->type == BreakpointData::WatchpointType ?
data->address : data->bpAddress;
if (effectiveAddress)
displayValue += QString::fromAscii("0x%1").arg(effectiveAddress, 0, 16);
if (!data->bpState.isEmpty()) {
if (!displayValue.isEmpty())
displayValue += QLatin1Char(' ');
displayValue += QString::fromAscii(data->bpState);
}
return displayValue;
}
break;
}
......@@ -462,9 +471,9 @@ bool BreakHandler::setData(const QModelIndex &index, const QVariant &value, int
return true;
case BreakpointIgnoreCountRole: {
QByteArray val = value.toString().toLatin1();
if (val != data->ignoreCount) {
data->ignoreCount = val;
const int ignoreCount = value.toInt();
if (ignoreCount != data->ignoreCount) {
data->ignoreCount = ignoreCount;
emit layoutChanged();
}
}
......@@ -580,6 +589,14 @@ void BreakHandler::removeAllBreakpoints()
updateMarkers();
}
BreakpointData *BreakHandler::findBreakpoint(quint64 address) const
{
foreach (BreakpointData *data, m_bp)
if (data->address == address)
return data;
return 0;
}
BreakpointData *BreakHandler::findBreakpoint(const QString &fileName,
int lineNumber, bool useMarkerPosition)
{
......@@ -589,17 +606,30 @@ BreakpointData *BreakHandler::findBreakpoint(const QString &fileName,
return 0;
}
void BreakHandler::toggleBreakpoint(const QString &fileName, int lineNumber)
void BreakHandler::toggleBreakpoint(const QString &fileName, int lineNumber,
quint64 address /* = 0 */)
{
BreakpointData *data = findBreakpoint(fileName, lineNumber, true);
if (!data)
data = findBreakpoint(fileName, lineNumber, false);
BreakpointData *data = 0;
do {
if (address) {
data = findBreakpoint(address);
break;
}
data = findBreakpoint(fileName, lineNumber, true);
if (!data)
data = findBreakpoint(fileName, lineNumber, false);
} while (false);
if (data) {
removeBreakpoint(data);
} else {
data = new BreakpointData;
data->fileName = fileName;
data->lineNumber = QByteArray::number(lineNumber);
if (address) {
data->address = address;
} else {
data->fileName = fileName;
data->lineNumber = lineNumber;
}
data->pending = true;
data->setMarkerFileName(fileName);
data->setMarkerLineNumber(lineNumber);
......@@ -629,7 +659,7 @@ void BreakHandler::breakByFunction(const QString &functionName)
const BreakpointData *data = at(index);
QTC_ASSERT(data, break);
if (data->funcName == functionName && data->condition.isEmpty()
&& data->ignoreCount.isEmpty())
&& data->ignoreCount == 0)
return;
}
BreakpointData *data = new BreakpointData;
......@@ -658,7 +688,7 @@ void BreakHandler::initializeFromTemplate(BreakHandler *other)
void BreakHandler::storeToTemplate(BreakHandler *other)
{
other->removeAllBreakpoints();
foreach (BreakpointData *data, m_bp)
foreach (const BreakpointData *data, m_bp)
other->append(data->clone());
removeAllBreakpoints();
other->updateMarkers();
......
......@@ -73,7 +73,7 @@ public:
// Find a breakpoint matching approximately the data in needle.
BreakpointData *findSimilarBreakpoint(const BreakpointData *needle) const;
BreakpointData *findBreakpointByNumber(int bpNumber) const;
int findWatchPointIndexByAddress(const QByteArray &a) const;
int findWatchPointIndexByAddress(quint64 address) const;
bool watchPointAt(quint64 address) const;
void updateMarkers();
bool isActive() const;
......@@ -91,10 +91,11 @@ public:
void initializeFromTemplate(BreakHandler *other);
void storeToTemplate(BreakHandler *other);
void toggleBreakpoint(const QString &fileName, int lineNumber);
void toggleBreakpoint(const QString &fileName, int lineNumber, quint64 address = 0);
void toggleBreakpointEnabled(const QString &fileName, int lineNumber);
BreakpointData *findBreakpoint(const QString &fileName, int lineNumber,
bool useMarkerPosition = true);
BreakpointData *findBreakpoint(quint64 address) const;
public slots:
void appendBreakpoint(BreakpointData *data);
......
......@@ -130,7 +130,7 @@ public:
// FIXME: Should we tell gdb about the change?
// Ignore it for now, as we would require re-compilation
// and debugger re-start anyway.
if (0 && !m_data->bpLineNumber.isEmpty()) {
if (0 && m_data->bpLineNumber) {
if (!m_data->bpNumber.trimmed().isEmpty()) {
m_data->pending = true;
}
......@@ -141,7 +141,7 @@ public:
// the next line that generated code.
// FIXME: Do we need yet another data member?
if (m_data->bpNumber.trimmed().isEmpty()) {
m_data->lineNumber = QByteArray::number(lineNumber);
m_data->lineNumber = lineNumber;
m_data->handler()->updateMarkers();
}
}
......@@ -159,17 +159,16 @@ private:
//
//////////////////////////////////////////////////////////////////
BreakpointData::BreakpointData()
BreakpointData::BreakpointData() :
m_handler(0), enabled(true),
pending(true), type(BreakpointType),
ignoreCount(0), lineNumber(0), address(0),
useFullPath(false),
bpIgnoreCount(0), bpLineNumber(0),
bpCorrectedLineNumber(0), bpAddress(0),
bpMultiple(false), bpEnabled(true),
m_markerLineNumber(0), marker(0)
{
m_handler = 0;
enabled = true;
pending = true;
type = BreakpointType;
marker = 0;
m_markerLineNumber = 0;
bpMultiple = false;
bpEnabled = true;
useFullPath = false;
}
BreakpointData *BreakpointData::clone() const
......@@ -193,7 +192,7 @@ BreakpointData *BreakpointData::clone() const
data->m_markerLineNumber = m_markerLineNumber;
} else {
data->m_markerFileName = fileName;
data->m_markerLineNumber = lineNumber.toInt();
data->m_markerLineNumber = lineNumber;
}
return data;
}
......@@ -233,6 +232,16 @@ void BreakpointData::setMarkerLineNumber(int lineNumber)
m_markerLineNumber = lineNumber;
}
static inline void formatAddress(QTextStream &str, quint64 address)
{
if (address) {
str << "0x";
str.setIntegerBase(16);
str << address;
str.setIntegerBase(10);
}
}
QString BreakpointData::toToolTip() const
{
QString rc;
......@@ -250,6 +259,8 @@ QString BreakpointData::toToolTip() const
: type == WatchpointType ? BreakHandler::tr("Watchpoint")
: BreakHandler::tr("Unknown breakpoint type"))
<< "</td></tr>"
<< "<tr><td>" << BreakHandler::tr("State:")
<< "</td><td>" << bpState << "</td></tr>"
<< "</table><br><hr><table>"
<< "<tr><th>" << BreakHandler::tr("Property")
<< "</th><th>" << BreakHandler::tr("Requested")
......@@ -260,54 +271,46 @@ QString BreakpointData::toToolTip() const
<< "</td><td>" << fileName << "</td><td>" << QDir::toNativeSeparators(bpFileName) << "</td></tr>"
<< "<tr><td>" << BreakHandler::tr("Function Name:")
<< "</td><td>" << funcName << "</td><td>" << bpFuncName << "</td></tr>"
<< "<tr><td>" << BreakHandler::tr("Line Number:")
<< "</td><td>" << lineNumber << "</td><td>" << bpLineNumber << "</td></tr>"
<< "<tr><td>" << BreakHandler::tr("Line Number:") << "</td><td>";
if (lineNumber)
str << lineNumber;
str << "</td><td>";
if (bpLineNumber)
str << bpLineNumber;
str << "</td></tr>"
<< "<tr><td>" << BreakHandler::tr("Breakpoint Address:")
<< "</td><td>" << address << "</td><td>" << bpAddress << "</td></tr>"
<< "</td><td>";
formatAddress(str, address);
str << "</td><td>";
formatAddress(str, bpAddress);
str << "</td></tr>"
<< "<tr><td>" << BreakHandler::tr("Corrected Line Number:")
<< "</td><td>-</td><td>" << bpCorrectedLineNumber << "</td></tr>"
<< "</td><td>-</td><td>";
if (bpCorrectedLineNumber > 0) {
str << bpCorrectedLineNumber;
} else {
str << '-';
}
str << "</td></tr>"
<< "<tr><td>" << BreakHandler::tr("Condition:")
<< "</td><td>" << condition << "</td><td>" << bpCondition << "</td></tr>"
<< "<tr><td>" << BreakHandler::tr("Ignore Count:")
<< "</td><td>" << ignoreCount << "</td><td>" << bpIgnoreCount << "</td></tr>"
<< "<tr><td>" << BreakHandler::tr("Ignore Count:") << "</td><td>";
if (ignoreCount)
str << ignoreCount;
str << "</td><td>";
if (bpIgnoreCount)
str << bpIgnoreCount;
str << "</td></tr>"
<< "<tr><td>" << BreakHandler::tr("Thread Specification:")
<< "</td><td>" << threadSpec << "</td><td>" << bpThreadSpec << "</td></tr>"
<< "</table></body></html>";
return rc;
}
QString BreakpointData::toString() const
{
QString rc;
QTextStream str(&rc);
str << BreakHandler::tr("Marker File:") << ' ' << m_markerFileName << '\n'
<< BreakHandler::tr("Marker Line:") << ' ' << m_markerLineNumber << '\n'
<< BreakHandler::tr("Breakpoint Number:") << ' ' << bpNumber << '\n'
<< BreakHandler::tr("Breakpoint Type:") << ' '
<< (type == BreakpointType ? BreakHandler::tr("Breakpoint")
: type == WatchpointType ? BreakHandler::tr("Watchpoint")
: BreakHandler::tr("Unknown breakpoint type")) << '\n'
<< BreakHandler::tr("File Name:") << ' '
<< fileName << " -- " << bpFileName << '\n'
<< BreakHandler::tr("Function Name:") << ' '
<< funcName << " -- " << bpFuncName << '\n'
<< BreakHandler::tr("Line Number:") << ' '
<< lineNumber << " -- " << bpLineNumber << '\n'
<< BreakHandler::tr("Breakpoint Address:") << ' '
<< address << " -- " << bpAddress << '\n'
<< BreakHandler::tr("Condition:") << ' '
<< condition << " -- " << bpCondition << '\n'
<< BreakHandler::tr("Ignore Count:") << ' '
<< ignoreCount << " -- " << bpIgnoreCount << '\n'
<< BreakHandler::tr("Thread Specification:") << ' '
<< threadSpec << " -- " << bpThreadSpec << '\n';
return rc;
}
bool BreakpointData::isLocatedAt(const QString &fileName_, int lineNumber_,
bool useMarkerPosition) const
{
int line = useMarkerPosition ? m_markerLineNumber : lineNumber.toInt();
int line = useMarkerPosition ? m_markerLineNumber : lineNumber;
return lineNumber_ == line && fileNameMatch(fileName_, m_markerFileName);
}
......@@ -331,6 +334,9 @@ bool BreakpointData::isSimilarTo(const BreakpointData *needle) const
&& !needle->bpNumber.startsWith(bpNumber))
return false;
if (address && needle->address && address == needle->address)
return true;
// At least at a position we were looking for.
// FIXME: breaks multiple breakpoints at the same location
if (!fileName.isEmpty()
......
......@@ -55,7 +55,6 @@ public:
void removeMarker();
void updateMarker();
QString toToolTip() const;
QString toString() const;
BreakHandler *handler() { return m_handler; }
bool isLocatedAt(const QString &fileName, int lineNumber,
......@@ -86,9 +85,9 @@ public:
// This "user requested information" will get stored in the session.
QString fileName; // Short name of source file.
QByteArray condition; // Condition associated with breakpoint.
QByteArray ignoreCount; // Ignore count associated with breakpoint.
QByteArray lineNumber; // Line in source file.
QByteArray address; // Address for watchpoints.
int ignoreCount; // Ignore count associated with breakpoint.
int lineNumber; // Line in source file.
quint64 address; // Address for watchpoints.
QByteArray threadSpec; // Thread specification.
QString funcName; // Name of containing function.
bool useFullPath; // Should we use the full path when setting the bp?
......@@ -96,16 +95,17 @@ public:
// This is what gdb produced in response.
QByteArray bpNumber; // Breakpoint number assigned by the debugger engine.
QByteArray bpCondition; // Condition acknowledged by the debugger engine.
QByteArray bpIgnoreCount;// Ignore count acknowledged by the debugger engine.
int bpIgnoreCount; // Ignore count acknowledged by the debugger engine.
QString bpFileName; // File name acknowledged by the debugger engine.
QString bpFullName; // Full file name acknowledged by the debugger engine.
QByteArray bpLineNumber; // Line number acknowledged by the debugger engine.
QByteArray bpCorrectedLineNumber; // Acknowledged by the debugger engine.
int bpLineNumber; // Line number acknowledged by the debugger engine.
int bpCorrectedLineNumber; // Acknowledged by the debugger engine.
QByteArray bpThreadSpec; // Thread spec acknowledged by the debugger engine.
QString bpFuncName; // Function name acknowledged by the debugger engine.
QByteArray bpAddress; // Address acknowledged by the debugger engine.
quint64 bpAddress; // Address acknowledged by the debugger engine.
bool bpMultiple; // Happens in constructors/gdb.
bool bpEnabled; // Enable/disable command sent.
QByteArray bpState; // gdb: <PENDING>, <MULTIPLE>
void setMarkerFileName(const QString &fileName);
QString markerFileName() const { return m_markerFileName; }
......
......@@ -47,6 +47,7 @@
#include <QtGui/QItemSelectionModel>
#include <QtGui/QToolButton>
#include <QtGui/QTreeView>
#include <QtGui/QIntValidator>
namespace Debugger {
......@@ -362,6 +363,7 @@ void BreakWindow::editBreakpoint(const QModelIndexList &list)
QAbstractItemModel *m = model();
ui.lineEditCondition->setText(
m->data(idx, BreakpointConditionRole).toString());
ui.lineEditIgnoreCount->setValidator(new QIntValidator(0, 2147483647, ui.lineEditIgnoreCount));
ui.lineEditIgnoreCount->setText(
m->data(idx, BreakpointIgnoreCountRole).toString());
ui.lineEditThreadSpec->setText(
......
......@@ -44,26 +44,18 @@ CdbCore::BreakPoint breakPointFromBreakPointData(const Debugger::Internal::Break
rc.type = bpd.type == Debugger::Internal::BreakpointData::BreakpointType ?
CdbCore::BreakPoint::Code : CdbCore::BreakPoint::Data;
if (rc.type == CdbCore::BreakPoint::Data) {
QByteArray addressBA = bpd.address;
if (addressBA.startsWith("0x"))
addressBA.remove(0, 2);
bool ok;
rc.address = addressBA.toULongLong(&ok, 16);
if (!ok)
qWarning("Cdb: Cannot convert watchpoint address '%s'", bpd.address.constData());
}
rc.address = bpd.address;
if (!bpd.threadSpec.isEmpty()) {
bool ok;
rc.threadId = bpd.threadSpec.toInt(&ok);
if (!ok)
qWarning("Cdb: Cannot convert breakpoint thread specification '%s'", bpd.address.constData());
qWarning("Cdb: Cannot convert breakpoint thread specification '%s'", bpd.threadSpec.constData());
}
rc.fileName = QDir::toNativeSeparators(bpd.fileName);
rc.condition = bpd.condition;
rc.funcName = bpd.funcName;
rc.ignoreCount = bpd.ignoreCount.isEmpty() ? 0 : bpd.ignoreCount.toInt();
rc.lineNumber = bpd.lineNumber.isEmpty() ? -1 : bpd.lineNumber.toInt();
rc.ignoreCount = bpd.ignoreCount;
rc.lineNumber = bpd.lineNumber;
rc.oneShot = false;
rc.enabled = bpd.enabled;
return rc;
......@@ -129,7 +121,7 @@ bool synchronizeBreakPoints(CIDebugControl* debugControl,
updateMarkers = true;
nbd->pending = false;
nbd->bpNumber = QByteArray::number(uint(id));
nbd->bpAddress = "0x" + QByteArray::number(address, 16);
nbd->bpAddress = address;
// Take over rest as is
nbd->bpCondition = nbd->condition;
nbd->bpIgnoreCount = nbd->ignoreCount;
......
......@@ -394,5 +394,19 @@ QString DisassemblerViewAgent::address() const
return d->frame.address;
}
// Return address of an assembly line "0x0dfd bla"
quint64 DisassemblerViewAgent::addressFromDisassemblyLine(const QString &line)
{
const int pos = line.indexOf(QLatin1Char(' '));
if (pos < 0)
return 0;
QString addressS = line.left(pos);
if (addressS.startsWith(QLatin1String("0x")))
addressS.remove(0, 2);
bool ok;
const quint64 address = addressS.toULongLong(&ok, 16);
return ok ? address : quint64(0);
}
} // namespace Internal
} // namespace Debugger
......@@ -97,6 +97,9 @@ public:
void cleanup();
bool isMixed() const;
// Return address of an assembly line "0x0dfd bla"
static quint64 addressFromDisassemblyLine(const QString &line);
private:
DisassemblerViewAgentPrivate *d;
};
......
......@@ -325,10 +325,11 @@ void DebuggerEnginePrivate::breakpointSetRemoveMarginActionTriggered()
QAction *act = qobject_cast<QAction *>(sender());
QTC_ASSERT(act, return);
QList<QVariant> list = act->data().toList();
QTC_ASSERT(list.size() == 2, return);
QTC_ASSERT(list.size() >= 3, return);
const QString fileName = list.at(0).toString();
const int lineNumber = list.at(1).toInt();
m_breakHandler.toggleBreakpoint(fileName, lineNumber);
const quint64 address = list.at(2).toULongLong();
m_breakHandler.toggleBreakpoint(fileName, lineNumber, address);
}
void DebuggerEnginePrivate::breakpointEnableDisableMarginActionTriggered()
......@@ -352,30 +353,30 @@ void DebuggerEnginePrivate::handleContextMenuRequest(const QVariant &parameters)
QMenu *menu = (QMenu *)(list.at(2).value<quint64>());
BreakpointData *data = 0;
QString position;
QString fileName;
quint64 address = 0;
if (editor->property("DisassemblerView").toBool()) {
fileName = editor->file()->fileName();
QString line = editor->contents()
.section('\n', lineNumber - 1, lineNumber - 1);
position = _("*") + fileName;
BreakpointData needle;
needle.bpAddress = line.left(line.indexOf(QLatin1Char(' '))).toLatin1();
needle.bpLineNumber = "-1";
address = needle.address = DisassemblerViewAgent::addressFromDisassemblyLine(line);
needle.bpLineNumber = -1;
data = m_breakHandler.findSimilarBreakpoint(&needle);
} else {
fileName = editor->file()->fileName();
position = fileName + QString(":%1").arg(lineNumber);
data = m_breakHandler.findBreakpoint(fileName, lineNumber);
}
QList<QVariant> args;
args.append(fileName);
args.append(lineNumber);
args.append(address);
if (data) {
// existing breakpoint
QAction *act = new QAction(tr("Remove Breakpoint"), menu);
const QString number = QString::fromAscii(data->bpNumber);
QAction *act = new QAction(tr("Remove Breakpoint %1").arg(number), menu);
act->setData(args);
connect(act, SIGNAL(triggered()),
this, SLOT(breakpointSetRemoveMarginActionTriggered()));
......@@ -383,16 +384,19 @@ void DebuggerEnginePrivate::handleContextMenuRequest(const QVariant &parameters)
QAction *act2;
if (data->enabled)
act2 = new QAction(tr("Disable Breakpoint"), menu);
act2 = new QAction(tr("Disable Breakpoint %1").arg(number), menu);
else
act2 = new QAction(tr("Enable Breakpoint"), menu);
act2 = new QAction(tr("Enable Breakpoint %1").arg(number), menu);
act2->setData(args);