2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2016-01-15 14:57:40 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2010-12-17 16:01:08 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2008-12-02 15:08:31 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "breakhandler.h"
|
|
|
|
|
|
2009-09-23 16:11:25 +02:00
|
|
|
#include "debuggeractions.h"
|
2010-11-10 11:39:01 +01:00
|
|
|
#include "debuggercore.h"
|
2010-11-15 14:27:06 +01:00
|
|
|
#include "debuggerengine.h"
|
2015-11-23 16:41:54 +01:00
|
|
|
#include "debuggericons.h"
|
2015-04-17 11:19:58 +02:00
|
|
|
#include "debuggerinternalconstants.h"
|
2014-07-03 00:46:51 +02:00
|
|
|
#include "simplifytype.h"
|
2009-08-14 13:04:05 +02:00
|
|
|
|
2015-04-17 11:19:58 +02:00
|
|
|
#include <coreplugin/coreconstants.h>
|
|
|
|
|
#include <coreplugin/coreplugin.h>
|
|
|
|
|
#include <coreplugin/editormanager/editormanager.h>
|
2016-07-18 12:36:31 +02:00
|
|
|
#include <coreplugin/icore.h>
|
2015-04-17 11:19:58 +02:00
|
|
|
#include <coreplugin/idocument.h>
|
|
|
|
|
|
2012-10-09 22:34:36 +02:00
|
|
|
#include <extensionsystem/invoker.h>
|
2015-01-09 10:49:18 +01:00
|
|
|
#include <texteditor/textmark.h>
|
2015-04-17 11:19:58 +02:00
|
|
|
#include <texteditor/texteditor.h>
|
2016-07-18 12:36:31 +02:00
|
|
|
|
|
|
|
|
#include <utils/basetreeview.h>
|
|
|
|
|
#include <utils/checkablemessagebox.h>
|
|
|
|
|
#include <utils/fileutils.h>
|
2012-08-23 15:53:58 +02:00
|
|
|
#include <utils/hostosinfo.h>
|
2016-07-18 12:36:31 +02:00
|
|
|
#include <utils/pathchooser.h>
|
2010-03-26 08:52:49 +01:00
|
|
|
#include <utils/qtcassert.h>
|
2016-07-18 12:36:31 +02:00
|
|
|
#include <utils/savedaction.h>
|
2015-04-17 12:46:28 +02:00
|
|
|
#include <utils/theme/theme.h>
|
2008-12-09 16:18:28 +01:00
|
|
|
|
2011-06-15 14:02:26 +02:00
|
|
|
#if USE_BREAK_MODEL_TEST
|
2013-09-02 14:04:12 +02:00
|
|
|
#include <modeltest.h>
|
2011-06-15 14:02:26 +02:00
|
|
|
#endif
|
|
|
|
|
|
2013-03-26 11:32:14 +01:00
|
|
|
#include <QTimerEvent>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDir>
|
2013-03-21 17:10:19 +01:00
|
|
|
#include <QDebug>
|
2016-07-18 12:36:31 +02:00
|
|
|
#include <QSpinBox>
|
|
|
|
|
#include <QStyledItemDelegate>
|
|
|
|
|
#include <QComboBox>
|
|
|
|
|
#include <QGroupBox>
|
|
|
|
|
#include <QCheckBox>
|
|
|
|
|
#include <QFormLayout>
|
|
|
|
|
#include <QMenu>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-04-17 11:19:58 +02:00
|
|
|
using namespace Core;
|
2015-01-09 10:49:18 +01:00
|
|
|
using namespace Utils;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-11-10 11:39:01 +01:00
|
|
|
namespace Debugger {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2016-06-13 10:58:34 +02:00
|
|
|
class LocationItem : public TreeItem
|
2015-01-10 01:07:01 +01:00
|
|
|
{
|
2016-06-13 10:58:34 +02:00
|
|
|
public:
|
2015-01-10 01:07:01 +01:00
|
|
|
QVariant data(int column, int role) const
|
|
|
|
|
{
|
|
|
|
|
if (role == Qt::DisplayRole) {
|
|
|
|
|
switch (column) {
|
2016-07-18 12:36:31 +02:00
|
|
|
case BreakpointNumberColumn:
|
2015-01-10 01:07:01 +01:00
|
|
|
return params.id.toString();
|
2016-07-18 12:36:31 +02:00
|
|
|
case BreakpointFunctionColumn:
|
2015-01-10 01:07:01 +01:00
|
|
|
return params.functionName;
|
2016-07-18 12:36:31 +02:00
|
|
|
case BreakpointAddressColumn:
|
2015-01-10 01:07:01 +01:00
|
|
|
if (params.address)
|
|
|
|
|
return QString::fromLatin1("0x%1").arg(params.address, 0, 16);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return QVariant();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BreakpointResponse params;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class BreakpointMarker;
|
|
|
|
|
|
2016-06-10 17:03:21 +02:00
|
|
|
class BreakpointItem : public QObject, public TypedTreeItem<LocationItem>
|
2015-01-10 01:07:01 +01:00
|
|
|
{
|
|
|
|
|
Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::BreakHandler)
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
~BreakpointItem();
|
|
|
|
|
|
|
|
|
|
QVariant data(int column, int role) const;
|
|
|
|
|
|
|
|
|
|
QIcon icon() const;
|
|
|
|
|
|
|
|
|
|
void removeBreakpoint();
|
|
|
|
|
void updateLineNumberFromMarker(int lineNumber);
|
|
|
|
|
void updateFileNameFromMarker(const QString &fileName);
|
|
|
|
|
void changeLineNumberFromMarker(int lineNumber);
|
|
|
|
|
bool isLocatedAt(const QString &fileName, int lineNumber, bool useMarkerPosition) const;
|
|
|
|
|
|
|
|
|
|
void setMarkerFileAndLine(const QString &fileName, int lineNumber);
|
|
|
|
|
|
|
|
|
|
void insertSubBreakpoint(const BreakpointResponse ¶ms);
|
|
|
|
|
QString markerFileName() const;
|
|
|
|
|
int markerLineNumber() const;
|
|
|
|
|
|
|
|
|
|
bool needsChange() const;
|
2016-07-18 12:36:31 +02:00
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
private:
|
|
|
|
|
friend class BreakHandler;
|
|
|
|
|
friend class Breakpoint;
|
|
|
|
|
BreakpointItem(BreakHandler *handler);
|
|
|
|
|
|
|
|
|
|
void destroyMarker();
|
|
|
|
|
void updateMarker();
|
|
|
|
|
void updateMarkerIcon();
|
|
|
|
|
void scheduleSynchronization();
|
|
|
|
|
|
|
|
|
|
QString toToolTip() const;
|
|
|
|
|
void setState(BreakpointState state);
|
|
|
|
|
void deleteThis();
|
|
|
|
|
bool isEngineRunning() const;
|
|
|
|
|
|
|
|
|
|
BreakHandler * const m_handler;
|
|
|
|
|
const BreakpointModelId m_id;
|
|
|
|
|
BreakpointParameters m_params;
|
|
|
|
|
BreakpointState m_state; // Current state of breakpoint.
|
|
|
|
|
DebuggerEngine *m_engine; // Engine currently handling the breakpoint.
|
|
|
|
|
BreakpointResponse m_response;
|
|
|
|
|
BreakpointMarker *m_marker;
|
|
|
|
|
};
|
|
|
|
|
|
2015-01-09 10:49:18 +01:00
|
|
|
//
|
|
|
|
|
// BreakpointMarker
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
// The red blob on the left side in the cpp editor.
|
|
|
|
|
class BreakpointMarker : public TextEditor::TextMark
|
|
|
|
|
{
|
|
|
|
|
public:
|
2015-01-10 01:07:01 +01:00
|
|
|
BreakpointMarker(BreakpointItem *b, const QString &fileName, int lineNumber)
|
2015-04-17 12:46:28 +02:00
|
|
|
: TextMark(fileName, lineNumber, Constants::TEXT_MARK_CATEGORY_BREAKPOINT), m_bp(b)
|
2015-01-09 10:49:18 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
setIcon(b->icon());
|
2015-01-09 10:49:18 +01:00
|
|
|
setPriority(TextEditor::TextMark::NormalPriority);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void removedFromEditor()
|
|
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_bp)
|
|
|
|
|
m_bp->removeBreakpoint();
|
2015-01-09 10:49:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void updateLineNumber(int lineNumber)
|
|
|
|
|
{
|
|
|
|
|
TextMark::updateLineNumber(lineNumber);
|
2015-01-10 01:07:01 +01:00
|
|
|
m_bp->updateLineNumberFromMarker(lineNumber);
|
2015-01-09 10:49:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void updateFileName(const QString &fileName)
|
|
|
|
|
{
|
|
|
|
|
TextMark::updateFileName(fileName);
|
2015-01-10 01:07:01 +01:00
|
|
|
m_bp->updateFileNameFromMarker(fileName);
|
2015-01-09 10:49:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isDraggable() const { return true; }
|
2015-01-10 01:07:01 +01:00
|
|
|
void dragToLine(int line) { m_bp->changeLineNumberFromMarker(line); }
|
2015-01-09 10:49:18 +01:00
|
|
|
bool isClickable() const { return true; }
|
2015-01-10 01:07:01 +01:00
|
|
|
void clicked() { m_bp->removeBreakpoint(); }
|
2015-01-09 10:49:18 +01:00
|
|
|
|
|
|
|
|
public:
|
2015-01-10 01:07:01 +01:00
|
|
|
BreakpointItem *m_bp;
|
2015-01-09 10:49:18 +01:00
|
|
|
};
|
|
|
|
|
|
2011-02-17 13:49:47 +01:00
|
|
|
static QString stateToString(BreakpointState state)
|
|
|
|
|
{
|
|
|
|
|
switch (state) {
|
|
|
|
|
case BreakpointNew:
|
|
|
|
|
return BreakHandler::tr("New");
|
|
|
|
|
case BreakpointInsertRequested:
|
|
|
|
|
return BreakHandler::tr("Insertion requested");
|
|
|
|
|
case BreakpointInsertProceeding:
|
|
|
|
|
return BreakHandler::tr("Insertion proceeding");
|
|
|
|
|
case BreakpointChangeRequested:
|
|
|
|
|
return BreakHandler::tr("Change requested");
|
|
|
|
|
case BreakpointChangeProceeding:
|
|
|
|
|
return BreakHandler::tr("Change proceeding");
|
|
|
|
|
case BreakpointInserted:
|
|
|
|
|
return BreakHandler::tr("Breakpoint inserted");
|
|
|
|
|
case BreakpointRemoveRequested:
|
|
|
|
|
return BreakHandler::tr("Removal requested");
|
|
|
|
|
case BreakpointRemoveProceeding:
|
|
|
|
|
return BreakHandler::tr("Removal proceeding");
|
|
|
|
|
case BreakpointDead:
|
|
|
|
|
return BreakHandler::tr("Dead");
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
//: Invalid breakpoint state.
|
|
|
|
|
return BreakHandler::tr("<invalid state>");
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-18 12:36:31 +02:00
|
|
|
static QString msgBreakpointAtSpecialFunc(const QString &func)
|
2011-03-07 17:20:10 +01:00
|
|
|
{
|
2016-07-18 12:36:31 +02:00
|
|
|
return BreakHandler::tr("Breakpoint at \"%1\"").arg(func);
|
2011-03-07 17:20:10 +01:00
|
|
|
}
|
|
|
|
|
|
2011-03-04 19:38:58 +01:00
|
|
|
static QString typeToString(BreakpointType type)
|
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
|
|
|
|
case BreakpointByFileAndLine:
|
|
|
|
|
return BreakHandler::tr("Breakpoint by File and Line");
|
|
|
|
|
case BreakpointByFunction:
|
|
|
|
|
return BreakHandler::tr("Breakpoint by Function");
|
|
|
|
|
case BreakpointByAddress:
|
|
|
|
|
return BreakHandler::tr("Breakpoint by Address");
|
|
|
|
|
case BreakpointAtThrow:
|
2011-03-07 17:20:10 +01:00
|
|
|
return msgBreakpointAtSpecialFunc("throw");
|
2011-03-04 19:38:58 +01:00
|
|
|
case BreakpointAtCatch:
|
2011-03-07 17:20:10 +01:00
|
|
|
return msgBreakpointAtSpecialFunc("catch");
|
2011-03-04 19:38:58 +01:00
|
|
|
case BreakpointAtFork:
|
2011-03-07 17:20:10 +01:00
|
|
|
return msgBreakpointAtSpecialFunc("fork");
|
2011-03-04 19:38:58 +01:00
|
|
|
case BreakpointAtExec:
|
2011-03-07 17:20:10 +01:00
|
|
|
return msgBreakpointAtSpecialFunc("exec");
|
2011-03-29 09:58:21 +02:00
|
|
|
//case BreakpointAtVFork:
|
|
|
|
|
// return msgBreakpointAtSpecialFunc("vfork");
|
2011-03-04 19:38:58 +01:00
|
|
|
case BreakpointAtSysCall:
|
2011-03-07 17:20:10 +01:00
|
|
|
return msgBreakpointAtSpecialFunc("syscall");
|
2011-03-04 19:38:58 +01:00
|
|
|
case BreakpointAtMain:
|
|
|
|
|
return BreakHandler::tr("Breakpoint at Function \"main()\"");
|
2011-05-09 08:35:58 +02:00
|
|
|
case WatchpointAtAddress:
|
|
|
|
|
return BreakHandler::tr("Watchpoint at Address");
|
|
|
|
|
case WatchpointAtExpression:
|
|
|
|
|
return BreakHandler::tr("Watchpoint at Expression");
|
2012-04-16 12:00:23 +02:00
|
|
|
case BreakpointOnQmlSignalEmit:
|
|
|
|
|
return BreakHandler::tr("Breakpoint on QML Signal Emit");
|
2011-10-10 15:25:18 +02:00
|
|
|
case BreakpointAtJavaScriptThrow:
|
|
|
|
|
return BreakHandler::tr("Breakpoint at JavaScript throw");
|
2013-04-09 10:59:36 +02:00
|
|
|
case UnknownBreakpointType:
|
|
|
|
|
case LastBreakpointType:
|
2011-03-04 19:38:58 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return BreakHandler::tr("Unknown Breakpoint Type");
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-18 12:36:31 +02:00
|
|
|
class LeftElideDelegate : public QStyledItemDelegate
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
LeftElideDelegate() {}
|
|
|
|
|
|
|
|
|
|
void paint(QPainter *pain, const QStyleOptionViewItem &option, const QModelIndex &index) const override
|
|
|
|
|
{
|
|
|
|
|
QStyleOptionViewItem opt = option;
|
|
|
|
|
opt.textElideMode = Qt::ElideLeft;
|
|
|
|
|
QStyledItemDelegate::paint(pain, opt, index);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class SmallTextEdit : public QTextEdit
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
explicit SmallTextEdit(QWidget *parent) : QTextEdit(parent) {}
|
|
|
|
|
QSize sizeHint() const { return QSize(QTextEdit::sizeHint().width(), 100); }
|
|
|
|
|
QSize minimumSizeHint() const { return sizeHint(); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// BreakpointDialog: Show a dialog for editing breakpoints. Shows controls
|
|
|
|
|
// for the file-and-line, function and address parameters depending on the
|
|
|
|
|
// breakpoint type. The controls not applicable to the current type
|
|
|
|
|
// (say function name for file-and-line) are disabled and cleared out.
|
|
|
|
|
// However,the values are saved and restored once the respective mode
|
|
|
|
|
// is again chosen, which is done using m_savedParameters and
|
|
|
|
|
// setters/getters taking the parts mask enumeration parameter.
|
|
|
|
|
//
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class BreakpointDialog : public QDialog
|
|
|
|
|
{
|
|
|
|
|
Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::BreakHandler)
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit BreakpointDialog(Breakpoint b, QWidget *parent = 0);
|
|
|
|
|
bool showDialog(BreakpointParameters *data, BreakpointParts *parts);
|
|
|
|
|
|
|
|
|
|
void setParameters(const BreakpointParameters &data);
|
|
|
|
|
BreakpointParameters parameters() const;
|
|
|
|
|
|
|
|
|
|
void typeChanged(int index);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void setPartsEnabled(unsigned partsMask);
|
|
|
|
|
void clearOtherParts(unsigned partsMask);
|
|
|
|
|
void getParts(unsigned partsMask, BreakpointParameters *data) const;
|
|
|
|
|
void setParts(unsigned partsMask, const BreakpointParameters &data);
|
|
|
|
|
|
|
|
|
|
void setType(BreakpointType type);
|
|
|
|
|
BreakpointType type() const;
|
|
|
|
|
|
|
|
|
|
unsigned m_enabledParts;
|
|
|
|
|
BreakpointParameters m_savedParameters;
|
|
|
|
|
BreakpointType m_previousType;
|
|
|
|
|
bool m_firstTypeChange;
|
|
|
|
|
|
|
|
|
|
QLabel *m_labelType;
|
|
|
|
|
QComboBox *m_comboBoxType;
|
|
|
|
|
QLabel *m_labelFileName;
|
|
|
|
|
Utils::PathChooser *m_pathChooserFileName;
|
|
|
|
|
QLabel *m_labelLineNumber;
|
|
|
|
|
QLineEdit *m_lineEditLineNumber;
|
|
|
|
|
QLabel *m_labelEnabled;
|
|
|
|
|
QCheckBox *m_checkBoxEnabled;
|
|
|
|
|
QLabel *m_labelAddress;
|
|
|
|
|
QLineEdit *m_lineEditAddress;
|
|
|
|
|
QLabel *m_labelExpression;
|
|
|
|
|
QLineEdit *m_lineEditExpression;
|
|
|
|
|
QLabel *m_labelFunction;
|
|
|
|
|
QLineEdit *m_lineEditFunction;
|
|
|
|
|
QLabel *m_labelTracepoint;
|
|
|
|
|
QCheckBox *m_checkBoxTracepoint;
|
|
|
|
|
QLabel *m_labelOneShot;
|
|
|
|
|
QCheckBox *m_checkBoxOneShot;
|
|
|
|
|
QLabel *m_labelUseFullPath;
|
|
|
|
|
QLabel *m_labelModule;
|
|
|
|
|
QLineEdit *m_lineEditModule;
|
|
|
|
|
QLabel *m_labelCommands;
|
|
|
|
|
QTextEdit *m_textEditCommands;
|
|
|
|
|
QComboBox *m_comboBoxPathUsage;
|
|
|
|
|
QLabel *m_labelMessage;
|
|
|
|
|
QLineEdit *m_lineEditMessage;
|
|
|
|
|
QLabel *m_labelCondition;
|
|
|
|
|
QLineEdit *m_lineEditCondition;
|
|
|
|
|
QLabel *m_labelIgnoreCount;
|
|
|
|
|
QSpinBox *m_spinBoxIgnoreCount;
|
|
|
|
|
QLabel *m_labelThreadSpec;
|
|
|
|
|
QLineEdit *m_lineEditThreadSpec;
|
|
|
|
|
QDialogButtonBox *m_buttonBox;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
BreakpointDialog::BreakpointDialog(Breakpoint b, QWidget *parent)
|
|
|
|
|
: QDialog(parent), m_enabledParts(~0), m_previousType(UnknownBreakpointType),
|
|
|
|
|
m_firstTypeChange(true)
|
|
|
|
|
{
|
|
|
|
|
setWindowTitle(tr("Edit Breakpoint Properties"));
|
|
|
|
|
|
|
|
|
|
auto groupBoxBasic = new QGroupBox(tr("Basic"), this);
|
|
|
|
|
|
|
|
|
|
// Match BreakpointType (omitting unknown type).
|
|
|
|
|
const QStringList types = {
|
|
|
|
|
tr("File name and line number"),
|
|
|
|
|
tr("Function name"),
|
|
|
|
|
tr("Break on memory address"),
|
|
|
|
|
tr("Break when C++ exception is thrown"),
|
|
|
|
|
tr("Break when C++ exception is caught"),
|
|
|
|
|
tr("Break when function \"main\" starts"),
|
|
|
|
|
tr("Break when a new process is forked"),
|
|
|
|
|
tr("Break when a new process is executed"),
|
|
|
|
|
tr("Break when a system call is executed"),
|
|
|
|
|
tr("Break on data access at fixed address"),
|
|
|
|
|
tr("Break on data access at address given by expression"),
|
|
|
|
|
tr("Break on QML signal emit"),
|
|
|
|
|
tr("Break when JavaScript exception is thrown")
|
|
|
|
|
};
|
|
|
|
|
// We don't list UnknownBreakpointType, so 1 less:
|
|
|
|
|
QTC_CHECK(types.size() + 1 == LastBreakpointType);
|
|
|
|
|
m_comboBoxType = new QComboBox(groupBoxBasic);
|
|
|
|
|
m_comboBoxType->setMaxVisibleItems(20);
|
|
|
|
|
m_comboBoxType->addItems(types);
|
|
|
|
|
m_labelType = new QLabel(tr("Breakpoint &type:"), groupBoxBasic);
|
|
|
|
|
m_labelType->setBuddy(m_comboBoxType);
|
|
|
|
|
|
|
|
|
|
m_pathChooserFileName = new PathChooser(groupBoxBasic);
|
|
|
|
|
m_pathChooserFileName->setHistoryCompleter(QLatin1String("Debugger.Breakpoint.File.History"));
|
|
|
|
|
m_pathChooserFileName->setExpectedKind(PathChooser::File);
|
|
|
|
|
m_labelFileName = new QLabel(tr("&File name:"), groupBoxBasic);
|
|
|
|
|
m_labelFileName->setBuddy(m_pathChooserFileName);
|
|
|
|
|
|
|
|
|
|
m_lineEditLineNumber = new QLineEdit(groupBoxBasic);
|
|
|
|
|
m_labelLineNumber = new QLabel(tr("&Line number:"), groupBoxBasic);
|
|
|
|
|
m_labelLineNumber->setBuddy(m_lineEditLineNumber);
|
|
|
|
|
|
|
|
|
|
m_checkBoxEnabled = new QCheckBox(groupBoxBasic);
|
|
|
|
|
m_labelEnabled = new QLabel(tr("&Enabled:"), groupBoxBasic);
|
|
|
|
|
m_labelEnabled->setBuddy(m_checkBoxEnabled);
|
|
|
|
|
|
|
|
|
|
m_lineEditAddress = new QLineEdit(groupBoxBasic);
|
|
|
|
|
m_labelAddress = new QLabel(tr("&Address:"), groupBoxBasic);
|
|
|
|
|
m_labelAddress->setBuddy(m_lineEditAddress);
|
|
|
|
|
|
|
|
|
|
m_lineEditExpression = new QLineEdit(groupBoxBasic);
|
|
|
|
|
m_labelExpression = new QLabel(tr("&Expression:"), groupBoxBasic);
|
|
|
|
|
m_labelExpression->setBuddy(m_lineEditExpression);
|
|
|
|
|
|
|
|
|
|
m_lineEditFunction = new QLineEdit(groupBoxBasic);
|
|
|
|
|
m_labelFunction = new QLabel(tr("Fun&ction:"), groupBoxBasic);
|
|
|
|
|
m_labelFunction->setBuddy(m_lineEditFunction);
|
|
|
|
|
|
|
|
|
|
auto groupBoxAdvanced = new QGroupBox(tr("Advanced"), this);
|
|
|
|
|
|
|
|
|
|
m_checkBoxTracepoint = new QCheckBox(groupBoxAdvanced);
|
|
|
|
|
m_labelTracepoint = new QLabel(tr("T&racepoint only:"), groupBoxAdvanced);
|
|
|
|
|
m_labelTracepoint->setBuddy(m_checkBoxTracepoint);
|
|
|
|
|
|
|
|
|
|
m_checkBoxOneShot = new QCheckBox(groupBoxAdvanced);
|
|
|
|
|
m_labelOneShot = new QLabel(tr("&One shot only:"), groupBoxAdvanced);
|
|
|
|
|
m_labelOneShot->setBuddy(m_checkBoxOneShot);
|
|
|
|
|
|
|
|
|
|
const QString pathToolTip =
|
|
|
|
|
tr("<p>Determines how the path is specified "
|
|
|
|
|
"when setting breakpoints:</p><ul>"
|
|
|
|
|
"<li><i>Use Engine Default</i>: Preferred setting of the "
|
|
|
|
|
"debugger engine.</li>"
|
|
|
|
|
"<li><i>Use Full Path</i>: Pass full path, avoiding ambiguities "
|
|
|
|
|
"should files of the same name exist in several modules. "
|
|
|
|
|
"This is the engine default for CDB and LLDB.</li>"
|
|
|
|
|
"<li><i>Use File Name</i>: Pass the file name only. This is "
|
|
|
|
|
"useful when using a source tree whose location does "
|
|
|
|
|
"not match the one used when building the modules. "
|
|
|
|
|
"It is the engine default for GDB as using full paths can "
|
|
|
|
|
"be slow with this engine.</li></ul>");
|
|
|
|
|
m_comboBoxPathUsage = new QComboBox(groupBoxAdvanced);
|
|
|
|
|
m_comboBoxPathUsage->addItem(tr("Use Engine Default"));
|
|
|
|
|
m_comboBoxPathUsage->addItem(tr("Use Full Path"));
|
|
|
|
|
m_comboBoxPathUsage->addItem(tr("Use File Name"));
|
|
|
|
|
m_comboBoxPathUsage->setToolTip(pathToolTip);
|
|
|
|
|
m_labelUseFullPath = new QLabel(tr("Pat&h:"), groupBoxAdvanced);
|
|
|
|
|
m_labelUseFullPath->setBuddy(m_comboBoxPathUsage);
|
|
|
|
|
m_labelUseFullPath->setToolTip(pathToolTip);
|
|
|
|
|
|
|
|
|
|
const QString moduleToolTip =
|
|
|
|
|
tr("<p>Specifying the module (base name of the library or executable) "
|
|
|
|
|
"for function or file type breakpoints can significantly speed up "
|
|
|
|
|
"debugger start-up times (CDB, LLDB).");
|
|
|
|
|
m_lineEditModule = new QLineEdit(groupBoxAdvanced);
|
|
|
|
|
m_lineEditModule->setToolTip(moduleToolTip);
|
|
|
|
|
m_labelModule = new QLabel(tr("&Module:"), groupBoxAdvanced);
|
|
|
|
|
m_labelModule->setBuddy(m_lineEditModule);
|
|
|
|
|
m_labelModule->setToolTip(moduleToolTip);
|
|
|
|
|
|
|
|
|
|
const QString commandsToolTip =
|
|
|
|
|
tr("<p>Debugger commands to be executed when the breakpoint is hit. "
|
|
|
|
|
"This feature is only available for GDB.");
|
|
|
|
|
m_textEditCommands = new SmallTextEdit(groupBoxAdvanced);
|
|
|
|
|
m_textEditCommands->setToolTip(commandsToolTip);
|
|
|
|
|
m_labelCommands = new QLabel(tr("&Commands:"), groupBoxAdvanced);
|
|
|
|
|
m_labelCommands->setBuddy(m_textEditCommands);
|
|
|
|
|
m_labelCommands->setToolTip(commandsToolTip);
|
|
|
|
|
|
|
|
|
|
m_lineEditMessage = new QLineEdit(groupBoxAdvanced);
|
|
|
|
|
m_labelMessage = new QLabel(tr("&Message:"), groupBoxAdvanced);
|
|
|
|
|
m_labelMessage->setBuddy(m_lineEditMessage);
|
|
|
|
|
|
|
|
|
|
m_lineEditCondition = new QLineEdit(groupBoxAdvanced);
|
|
|
|
|
m_labelCondition = new QLabel(tr("C&ondition:"), groupBoxAdvanced);
|
|
|
|
|
m_labelCondition->setBuddy(m_lineEditCondition);
|
|
|
|
|
|
|
|
|
|
m_spinBoxIgnoreCount = new QSpinBox(groupBoxAdvanced);
|
|
|
|
|
m_spinBoxIgnoreCount->setMinimum(0);
|
|
|
|
|
m_spinBoxIgnoreCount->setMaximum(2147483647);
|
|
|
|
|
m_labelIgnoreCount = new QLabel(tr("&Ignore count:"), groupBoxAdvanced);
|
|
|
|
|
m_labelIgnoreCount->setBuddy(m_spinBoxIgnoreCount);
|
|
|
|
|
|
|
|
|
|
m_lineEditThreadSpec = new QLineEdit(groupBoxAdvanced);
|
|
|
|
|
m_labelThreadSpec = new QLabel(tr("&Thread specification:"), groupBoxAdvanced);
|
|
|
|
|
m_labelThreadSpec->setBuddy(m_lineEditThreadSpec);
|
|
|
|
|
|
|
|
|
|
m_buttonBox = new QDialogButtonBox(this);
|
|
|
|
|
m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
|
|
|
|
|
|
|
|
|
|
if (b) {
|
|
|
|
|
if (DebuggerEngine *engine = b.engine()) {
|
|
|
|
|
if (!engine->hasCapability(BreakConditionCapability))
|
|
|
|
|
m_enabledParts &= ~ConditionPart;
|
|
|
|
|
if (!engine->hasCapability(BreakModuleCapability))
|
|
|
|
|
m_enabledParts &= ~ModulePart;
|
|
|
|
|
if (!engine->hasCapability(TracePointCapability))
|
|
|
|
|
m_enabledParts &= ~TracePointPart;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto basicLayout = new QFormLayout(groupBoxBasic);
|
|
|
|
|
basicLayout->addRow(m_labelType, m_comboBoxType);
|
|
|
|
|
basicLayout->addRow(m_labelFileName, m_pathChooserFileName);
|
|
|
|
|
basicLayout->addRow(m_labelLineNumber, m_lineEditLineNumber);
|
|
|
|
|
basicLayout->addRow(m_labelEnabled, m_checkBoxEnabled);
|
|
|
|
|
basicLayout->addRow(m_labelAddress, m_lineEditAddress);
|
|
|
|
|
basicLayout->addRow(m_labelExpression, m_lineEditExpression);
|
|
|
|
|
basicLayout->addRow(m_labelFunction, m_lineEditFunction);
|
|
|
|
|
basicLayout->addRow(m_labelOneShot, m_checkBoxOneShot);
|
|
|
|
|
|
|
|
|
|
auto advancedLeftLayout = new QFormLayout();
|
|
|
|
|
advancedLeftLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
|
|
|
|
advancedLeftLayout->addRow(m_labelCondition, m_lineEditCondition);
|
|
|
|
|
advancedLeftLayout->addRow(m_labelIgnoreCount, m_spinBoxIgnoreCount);
|
|
|
|
|
advancedLeftLayout->addRow(m_labelThreadSpec, m_lineEditThreadSpec);
|
|
|
|
|
advancedLeftLayout->addRow(m_labelUseFullPath, m_comboBoxPathUsage);
|
|
|
|
|
advancedLeftLayout->addRow(m_labelModule, m_lineEditModule);
|
|
|
|
|
|
|
|
|
|
auto advancedRightLayout = new QFormLayout();
|
|
|
|
|
advancedRightLayout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
|
|
|
|
advancedRightLayout->addRow(m_labelCommands, m_textEditCommands);
|
|
|
|
|
advancedRightLayout->addRow(m_labelTracepoint, m_checkBoxTracepoint);
|
|
|
|
|
advancedRightLayout->addRow(m_labelMessage, m_lineEditMessage);
|
|
|
|
|
|
|
|
|
|
auto horizontalLayout = new QHBoxLayout(groupBoxAdvanced);
|
|
|
|
|
horizontalLayout->addLayout(advancedLeftLayout);
|
|
|
|
|
horizontalLayout->addSpacing(15);
|
|
|
|
|
horizontalLayout->addLayout(advancedRightLayout);
|
|
|
|
|
|
|
|
|
|
auto verticalLayout = new QVBoxLayout(this);
|
|
|
|
|
verticalLayout->addWidget(groupBoxBasic);
|
|
|
|
|
verticalLayout->addSpacing(10);
|
|
|
|
|
verticalLayout->addWidget(groupBoxAdvanced);
|
|
|
|
|
verticalLayout->addSpacing(10);
|
|
|
|
|
verticalLayout->addWidget(m_buttonBox);
|
|
|
|
|
verticalLayout->setStretchFactor(groupBoxAdvanced, 10);
|
|
|
|
|
|
|
|
|
|
connect(m_comboBoxType, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated),
|
|
|
|
|
this, &BreakpointDialog::typeChanged);
|
|
|
|
|
connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
|
|
|
|
connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakpointDialog::setType(BreakpointType type)
|
|
|
|
|
{
|
|
|
|
|
const int comboIndex = type - 1; // Skip UnknownType.
|
|
|
|
|
if (comboIndex != m_comboBoxType->currentIndex() || m_firstTypeChange) {
|
|
|
|
|
m_comboBoxType->setCurrentIndex(comboIndex);
|
|
|
|
|
typeChanged(comboIndex);
|
|
|
|
|
m_firstTypeChange = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BreakpointType BreakpointDialog::type() const
|
|
|
|
|
{
|
|
|
|
|
const int type = m_comboBoxType->currentIndex() + 1; // Skip unknown type.
|
|
|
|
|
return static_cast<BreakpointType>(type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakpointDialog::setParameters(const BreakpointParameters &data)
|
|
|
|
|
{
|
|
|
|
|
m_savedParameters = data;
|
|
|
|
|
setType(data.type);
|
|
|
|
|
setParts(AllParts, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BreakpointParameters BreakpointDialog::parameters() const
|
|
|
|
|
{
|
|
|
|
|
BreakpointParameters data(type());
|
|
|
|
|
getParts(AllParts, &data);
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakpointDialog::setPartsEnabled(unsigned partsMask)
|
|
|
|
|
{
|
|
|
|
|
partsMask &= m_enabledParts;
|
|
|
|
|
m_labelFileName->setEnabled(partsMask & FileAndLinePart);
|
|
|
|
|
m_pathChooserFileName->setEnabled(partsMask & FileAndLinePart);
|
|
|
|
|
m_labelLineNumber->setEnabled(partsMask & FileAndLinePart);
|
|
|
|
|
m_lineEditLineNumber->setEnabled(partsMask & FileAndLinePart);
|
|
|
|
|
m_labelUseFullPath->setEnabled(partsMask & FileAndLinePart);
|
|
|
|
|
m_comboBoxPathUsage->setEnabled(partsMask & FileAndLinePart);
|
|
|
|
|
|
|
|
|
|
m_labelFunction->setEnabled(partsMask & FunctionPart);
|
|
|
|
|
m_lineEditFunction->setEnabled(partsMask & FunctionPart);
|
|
|
|
|
|
|
|
|
|
m_labelOneShot->setEnabled(partsMask & OneShotPart);
|
|
|
|
|
m_checkBoxOneShot->setEnabled(partsMask & OneShotPart);
|
|
|
|
|
|
|
|
|
|
m_labelAddress->setEnabled(partsMask & AddressPart);
|
|
|
|
|
m_lineEditAddress->setEnabled(partsMask & AddressPart);
|
|
|
|
|
m_labelExpression->setEnabled(partsMask & ExpressionPart);
|
|
|
|
|
m_lineEditExpression->setEnabled(partsMask & ExpressionPart);
|
|
|
|
|
|
|
|
|
|
m_labelCondition->setEnabled(partsMask & ConditionPart);
|
|
|
|
|
m_lineEditCondition->setEnabled(partsMask & ConditionPart);
|
|
|
|
|
m_labelIgnoreCount->setEnabled(partsMask & IgnoreCountPart);
|
|
|
|
|
m_spinBoxIgnoreCount->setEnabled(partsMask & IgnoreCountPart);
|
|
|
|
|
m_labelThreadSpec->setEnabled(partsMask & ThreadSpecPart);
|
|
|
|
|
m_lineEditThreadSpec->setEnabled(partsMask & ThreadSpecPart);
|
|
|
|
|
|
|
|
|
|
m_labelModule->setEnabled(partsMask & ModulePart);
|
|
|
|
|
m_lineEditModule->setEnabled(partsMask & ModulePart);
|
|
|
|
|
|
|
|
|
|
m_labelTracepoint->setEnabled(partsMask & TracePointPart);
|
|
|
|
|
m_labelTracepoint->hide();
|
|
|
|
|
m_checkBoxTracepoint->setEnabled(partsMask & TracePointPart);
|
|
|
|
|
m_checkBoxTracepoint->hide();
|
|
|
|
|
|
|
|
|
|
m_labelCommands->setEnabled(partsMask & CommandPart);
|
|
|
|
|
m_textEditCommands->setEnabled(partsMask & CommandPart);
|
|
|
|
|
|
|
|
|
|
m_labelMessage->setEnabled(partsMask & TracePointPart);
|
|
|
|
|
m_labelMessage->hide();
|
|
|
|
|
m_lineEditMessage->setEnabled(partsMask & TracePointPart);
|
|
|
|
|
m_lineEditMessage->hide();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakpointDialog::clearOtherParts(unsigned partsMask)
|
|
|
|
|
{
|
|
|
|
|
const unsigned invertedPartsMask = ~partsMask;
|
|
|
|
|
if (invertedPartsMask & FileAndLinePart) {
|
|
|
|
|
m_pathChooserFileName->setPath(QString());
|
|
|
|
|
m_lineEditLineNumber->clear();
|
|
|
|
|
m_comboBoxPathUsage->setCurrentIndex(BreakpointPathUsageEngineDefault);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (invertedPartsMask & FunctionPart)
|
|
|
|
|
m_lineEditFunction->clear();
|
|
|
|
|
|
|
|
|
|
if (invertedPartsMask & AddressPart)
|
|
|
|
|
m_lineEditAddress->clear();
|
|
|
|
|
if (invertedPartsMask & ExpressionPart)
|
|
|
|
|
m_lineEditExpression->clear();
|
|
|
|
|
|
|
|
|
|
if (invertedPartsMask & ConditionPart)
|
|
|
|
|
m_lineEditCondition->clear();
|
|
|
|
|
if (invertedPartsMask & IgnoreCountPart)
|
|
|
|
|
m_spinBoxIgnoreCount->clear();
|
|
|
|
|
if (invertedPartsMask & ThreadSpecPart)
|
|
|
|
|
m_lineEditThreadSpec->clear();
|
|
|
|
|
if (invertedPartsMask & ModulePart)
|
|
|
|
|
m_lineEditModule->clear();
|
|
|
|
|
|
|
|
|
|
if (partsMask & OneShotPart)
|
|
|
|
|
m_checkBoxOneShot->setChecked(false);
|
|
|
|
|
if (invertedPartsMask & CommandPart)
|
|
|
|
|
m_textEditCommands->clear();
|
|
|
|
|
if (invertedPartsMask & TracePointPart) {
|
|
|
|
|
m_checkBoxTracepoint->setChecked(false);
|
|
|
|
|
m_lineEditMessage->clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakpointDialog::getParts(unsigned partsMask, BreakpointParameters *data) const
|
|
|
|
|
{
|
|
|
|
|
data->enabled = m_checkBoxEnabled->isChecked();
|
|
|
|
|
|
|
|
|
|
if (partsMask & FileAndLinePart) {
|
|
|
|
|
data->lineNumber = m_lineEditLineNumber->text().toInt();
|
|
|
|
|
data->pathUsage = static_cast<BreakpointPathUsage>(m_comboBoxPathUsage->currentIndex());
|
|
|
|
|
data->fileName = m_pathChooserFileName->path();
|
|
|
|
|
}
|
|
|
|
|
if (partsMask & FunctionPart)
|
|
|
|
|
data->functionName = m_lineEditFunction->text();
|
|
|
|
|
|
|
|
|
|
if (partsMask & AddressPart)
|
|
|
|
|
data->address = m_lineEditAddress->text().toULongLong(0, 0);
|
|
|
|
|
if (partsMask & ExpressionPart)
|
|
|
|
|
data->expression = m_lineEditExpression->text();
|
|
|
|
|
|
|
|
|
|
if (partsMask & ConditionPart)
|
|
|
|
|
data->condition = m_lineEditCondition->text();
|
|
|
|
|
if (partsMask & IgnoreCountPart)
|
|
|
|
|
data->ignoreCount = m_spinBoxIgnoreCount->text().toInt();
|
|
|
|
|
if (partsMask & ThreadSpecPart)
|
|
|
|
|
data->threadSpec =
|
|
|
|
|
BreakHandler::threadSpecFromDisplay(m_lineEditThreadSpec->text());
|
|
|
|
|
if (partsMask & ModulePart)
|
|
|
|
|
data->module = m_lineEditModule->text();
|
|
|
|
|
|
|
|
|
|
if (partsMask & OneShotPart)
|
|
|
|
|
data->oneShot = m_checkBoxOneShot->isChecked();
|
|
|
|
|
if (partsMask & CommandPart)
|
|
|
|
|
data->command = m_textEditCommands->toPlainText().trimmed();
|
|
|
|
|
if (partsMask & TracePointPart) {
|
|
|
|
|
data->tracepoint = m_checkBoxTracepoint->isChecked();
|
|
|
|
|
data->message = m_lineEditMessage->text();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakpointDialog::setParts(unsigned mask, const BreakpointParameters &data)
|
|
|
|
|
{
|
|
|
|
|
m_checkBoxEnabled->setChecked(data.enabled);
|
|
|
|
|
m_comboBoxPathUsage->setCurrentIndex(data.pathUsage);
|
|
|
|
|
m_lineEditMessage->setText(data.message);
|
|
|
|
|
|
|
|
|
|
if (mask & FileAndLinePart) {
|
|
|
|
|
m_pathChooserFileName->setPath(data.fileName);
|
|
|
|
|
m_lineEditLineNumber->setText(QString::number(data.lineNumber));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mask & FunctionPart)
|
|
|
|
|
m_lineEditFunction->setText(data.functionName);
|
|
|
|
|
|
|
|
|
|
if (mask & AddressPart) {
|
|
|
|
|
if (data.address) {
|
|
|
|
|
m_lineEditAddress->setText(QString("0x%1").arg(data.address, 0, 16));
|
|
|
|
|
} else {
|
|
|
|
|
m_lineEditAddress->clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mask & ExpressionPart) {
|
|
|
|
|
if (!data.expression.isEmpty())
|
|
|
|
|
m_lineEditExpression->setText(data.expression);
|
|
|
|
|
else
|
|
|
|
|
m_lineEditExpression->clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mask & ConditionPart)
|
|
|
|
|
m_lineEditCondition->setText(data.condition);
|
|
|
|
|
if (mask & IgnoreCountPart)
|
|
|
|
|
m_spinBoxIgnoreCount->setValue(data.ignoreCount);
|
|
|
|
|
if (mask & ThreadSpecPart)
|
|
|
|
|
m_lineEditThreadSpec->
|
|
|
|
|
setText(BreakHandler::displayFromThreadSpec(data.threadSpec));
|
|
|
|
|
if (mask & ModulePart)
|
|
|
|
|
m_lineEditModule->setText(data.module);
|
|
|
|
|
|
|
|
|
|
if (mask & OneShotPart)
|
|
|
|
|
m_checkBoxOneShot->setChecked(data.oneShot);
|
|
|
|
|
if (mask & TracePointPart)
|
|
|
|
|
m_checkBoxTracepoint->setChecked(data.tracepoint);
|
|
|
|
|
if (mask & CommandPart)
|
|
|
|
|
m_textEditCommands->setPlainText(data.command);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakpointDialog::typeChanged(int)
|
|
|
|
|
{
|
|
|
|
|
BreakpointType previousType = m_previousType;
|
|
|
|
|
const BreakpointType newType = type();
|
|
|
|
|
m_previousType = newType;
|
|
|
|
|
// Save current state.
|
|
|
|
|
switch (previousType) {
|
|
|
|
|
case UnknownBreakpointType:
|
|
|
|
|
case LastBreakpointType:
|
|
|
|
|
break;
|
|
|
|
|
case BreakpointByFileAndLine:
|
|
|
|
|
getParts(FileAndLinePart|ModulePart|AllConditionParts|TracePointPart|CommandPart, &m_savedParameters);
|
|
|
|
|
break;
|
|
|
|
|
case BreakpointByFunction:
|
|
|
|
|
getParts(FunctionPart|ModulePart|AllConditionParts|TracePointPart|CommandPart, &m_savedParameters);
|
|
|
|
|
break;
|
|
|
|
|
case BreakpointAtThrow:
|
|
|
|
|
case BreakpointAtCatch:
|
|
|
|
|
case BreakpointAtMain:
|
|
|
|
|
case BreakpointAtFork:
|
|
|
|
|
case BreakpointAtExec:
|
|
|
|
|
//case BreakpointAtVFork:
|
|
|
|
|
case BreakpointAtSysCall:
|
|
|
|
|
case BreakpointAtJavaScriptThrow:
|
|
|
|
|
break;
|
|
|
|
|
case BreakpointByAddress:
|
|
|
|
|
case WatchpointAtAddress:
|
|
|
|
|
getParts(AddressPart|AllConditionParts|TracePointPart|CommandPart, &m_savedParameters);
|
|
|
|
|
break;
|
|
|
|
|
case WatchpointAtExpression:
|
|
|
|
|
getParts(ExpressionPart|AllConditionParts|TracePointPart|CommandPart, &m_savedParameters);
|
|
|
|
|
break;
|
|
|
|
|
case BreakpointOnQmlSignalEmit:
|
|
|
|
|
getParts(FunctionPart, &m_savedParameters);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Enable and set up new state from saved values.
|
|
|
|
|
switch (newType) {
|
|
|
|
|
case UnknownBreakpointType:
|
|
|
|
|
case LastBreakpointType:
|
|
|
|
|
break;
|
|
|
|
|
case BreakpointByFileAndLine:
|
|
|
|
|
setParts(FileAndLinePart|AllConditionParts|ModulePart|TracePointPart|CommandPart, m_savedParameters);
|
|
|
|
|
setPartsEnabled(FileAndLinePart|AllConditionParts|ModulePart|TracePointPart|CommandPart);
|
|
|
|
|
clearOtherParts(FileAndLinePart|AllConditionParts|ModulePart|TracePointPart|CommandPart);
|
|
|
|
|
break;
|
|
|
|
|
case BreakpointByFunction:
|
|
|
|
|
setParts(FunctionPart|AllConditionParts|ModulePart|TracePointPart|CommandPart, m_savedParameters);
|
|
|
|
|
setPartsEnabled(FunctionPart|AllConditionParts|ModulePart|TracePointPart|CommandPart);
|
|
|
|
|
clearOtherParts(FunctionPart|AllConditionParts|ModulePart|TracePointPart|CommandPart);
|
|
|
|
|
break;
|
|
|
|
|
case BreakpointAtThrow:
|
|
|
|
|
case BreakpointAtCatch:
|
|
|
|
|
case BreakpointAtFork:
|
|
|
|
|
case BreakpointAtExec:
|
|
|
|
|
//case BreakpointAtVFork:
|
|
|
|
|
case BreakpointAtSysCall:
|
|
|
|
|
clearOtherParts(AllConditionParts|ModulePart|TracePointPart|CommandPart);
|
|
|
|
|
setPartsEnabled(AllConditionParts|TracePointPart|CommandPart);
|
|
|
|
|
break;
|
|
|
|
|
case BreakpointAtJavaScriptThrow:
|
|
|
|
|
clearOtherParts(AllParts);
|
|
|
|
|
setPartsEnabled(0);
|
|
|
|
|
break;
|
|
|
|
|
case BreakpointAtMain:
|
|
|
|
|
m_lineEditFunction->setText("main"); // Just for display
|
|
|
|
|
clearOtherParts(0);
|
|
|
|
|
setPartsEnabled(0);
|
|
|
|
|
break;
|
|
|
|
|
case BreakpointByAddress:
|
|
|
|
|
case WatchpointAtAddress:
|
|
|
|
|
setParts(AddressPart|AllConditionParts|TracePointPart|CommandPart, m_savedParameters);
|
|
|
|
|
setPartsEnabled(AddressPart|AllConditionParts|TracePointPart|CommandPart);
|
|
|
|
|
clearOtherParts(AddressPart|AllConditionParts|TracePointPart|CommandPart);
|
|
|
|
|
break;
|
|
|
|
|
case WatchpointAtExpression:
|
|
|
|
|
setParts(ExpressionPart|AllConditionParts|TracePointPart|CommandPart, m_savedParameters);
|
|
|
|
|
setPartsEnabled(ExpressionPart|AllConditionParts|TracePointPart|CommandPart);
|
|
|
|
|
clearOtherParts(ExpressionPart|AllConditionParts|TracePointPart|CommandPart);
|
|
|
|
|
break;
|
|
|
|
|
case BreakpointOnQmlSignalEmit:
|
|
|
|
|
setParts(FunctionPart, m_savedParameters);
|
|
|
|
|
setPartsEnabled(FunctionPart);
|
|
|
|
|
clearOtherParts(FunctionPart);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BreakpointDialog::showDialog(BreakpointParameters *data,
|
|
|
|
|
BreakpointParts *parts)
|
|
|
|
|
{
|
|
|
|
|
setParameters(*data);
|
|
|
|
|
if (exec() != QDialog::Accepted)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// Check if changed.
|
|
|
|
|
const BreakpointParameters newParameters = parameters();
|
|
|
|
|
*parts = data->differencesTo(newParameters);
|
|
|
|
|
if (!*parts)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
*data = newParameters;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Dialog allowing changing properties of multiple breakpoints at a time.
|
|
|
|
|
class MultiBreakPointsDialog : public QDialog
|
|
|
|
|
{
|
|
|
|
|
Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::BreakHandler)
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
MultiBreakPointsDialog(QWidget *parent = 0);
|
|
|
|
|
|
|
|
|
|
QString condition() const { return m_lineEditCondition->text(); }
|
|
|
|
|
int ignoreCount() const { return m_spinBoxIgnoreCount->value(); }
|
|
|
|
|
int threadSpec() const
|
|
|
|
|
{ return BreakHandler::threadSpecFromDisplay(m_lineEditThreadSpec->text()); }
|
|
|
|
|
|
|
|
|
|
void setCondition(const QString &c) { m_lineEditCondition->setText(c); }
|
|
|
|
|
void setIgnoreCount(int i) { m_spinBoxIgnoreCount->setValue(i); }
|
|
|
|
|
void setThreadSpec(int t)
|
|
|
|
|
{ return m_lineEditThreadSpec->setText(BreakHandler::displayFromThreadSpec(t)); }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
QLineEdit *m_lineEditCondition;
|
|
|
|
|
QSpinBox *m_spinBoxIgnoreCount;
|
|
|
|
|
QLineEdit *m_lineEditThreadSpec;
|
|
|
|
|
QDialogButtonBox *m_buttonBox;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
MultiBreakPointsDialog::MultiBreakPointsDialog(QWidget *parent) :
|
|
|
|
|
QDialog(parent)
|
|
|
|
|
{
|
|
|
|
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
|
|
|
|
setWindowTitle(tr("Edit Breakpoint Properties"));
|
|
|
|
|
|
|
|
|
|
m_lineEditCondition = new QLineEdit(this);
|
|
|
|
|
m_spinBoxIgnoreCount = new QSpinBox(this);
|
|
|
|
|
m_spinBoxIgnoreCount->setMinimum(0);
|
|
|
|
|
m_spinBoxIgnoreCount->setMaximum(2147483647);
|
|
|
|
|
m_lineEditThreadSpec = new QLineEdit(this);
|
|
|
|
|
|
|
|
|
|
m_buttonBox = new QDialogButtonBox(this);
|
|
|
|
|
m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
|
|
|
|
|
|
|
|
|
|
auto formLayout = new QFormLayout;
|
|
|
|
|
if (currentEngine()->hasCapability(BreakConditionCapability))
|
|
|
|
|
formLayout->addRow(tr("&Condition:"), m_lineEditCondition);
|
|
|
|
|
formLayout->addRow(tr("&Ignore count:"), m_spinBoxIgnoreCount);
|
|
|
|
|
formLayout->addRow(tr("&Thread specification:"), m_lineEditThreadSpec);
|
|
|
|
|
|
|
|
|
|
auto verticalLayout = new QVBoxLayout(this);
|
|
|
|
|
verticalLayout->addLayout(formLayout);
|
|
|
|
|
verticalLayout->addWidget(m_buttonBox);
|
|
|
|
|
|
|
|
|
|
connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
|
|
|
|
connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-04 09:54:23 +01:00
|
|
|
BreakHandler::BreakHandler()
|
2010-11-18 14:57:00 +01:00
|
|
|
: m_syncTimerId(-1)
|
2011-06-15 14:02:26 +02:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
qRegisterMetaType<BreakpointModelId>();
|
2015-04-17 12:46:28 +02:00
|
|
|
TextEditor::TextMark::setCategoryColor(Constants::TEXT_MARK_CATEGORY_BREAKPOINT,
|
2016-07-18 12:36:31 +02:00
|
|
|
Theme::Debugger_Breakpoint_TextMarkColor);
|
2016-08-16 14:17:48 +02:00
|
|
|
TextEditor::TextMark::setDefaultToolTip(Constants::TEXT_MARK_CATEGORY_BREAKPOINT,
|
|
|
|
|
tr("Breakpoint"));
|
2015-01-10 01:07:01 +01:00
|
|
|
|
2011-06-15 14:02:26 +02:00
|
|
|
#if USE_BREAK_MODEL_TEST
|
|
|
|
|
new ModelTest(this, 0);
|
|
|
|
|
#endif
|
2015-01-16 15:24:53 +01:00
|
|
|
setHeader(QStringList()
|
2015-01-09 10:49:18 +01:00
|
|
|
<< tr("Number") << tr("Function") << tr("File") << tr("Line")
|
|
|
|
|
<< tr("Address") << tr("Condition") << tr("Ignore") << tr("Threads"));
|
2014-11-21 11:36:45 +02:00
|
|
|
}
|
2008-12-04 11:37:43 +01:00
|
|
|
|
2010-11-10 16:33:11 +01:00
|
|
|
static inline bool fileNameMatch(const QString &f1, const QString &f2)
|
2010-03-26 08:52:49 +01:00
|
|
|
{
|
2015-02-03 23:58:49 +02:00
|
|
|
if (HostOsInfo::fileNameCaseSensitivity() == Qt::CaseInsensitive)
|
2012-08-23 15:53:58 +02:00
|
|
|
return f1.compare(f2, Qt::CaseInsensitive) == 0;
|
2010-11-10 16:33:11 +01:00
|
|
|
return f1 == f2;
|
2010-03-26 08:52:49 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-09 10:49:18 +01:00
|
|
|
static bool isSimilarTo(const BreakpointParameters ¶ms, const BreakpointResponse &needle)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-11-10 16:33:11 +01:00
|
|
|
// Clear miss.
|
2015-01-09 10:49:18 +01:00
|
|
|
if (needle.type != UnknownBreakpointType && params.type != UnknownBreakpointType
|
|
|
|
|
&& params.type != needle.type)
|
2010-11-10 16:33:11 +01:00
|
|
|
return false;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-11-10 16:33:11 +01:00
|
|
|
// Clear hit.
|
2015-01-09 10:49:18 +01:00
|
|
|
if (params.address && params.address == needle.address)
|
2010-11-10 16:33:11 +01:00
|
|
|
return true;
|
|
|
|
|
|
2014-11-06 14:30:52 +01:00
|
|
|
// Clear hit.
|
2015-01-09 10:49:18 +01:00
|
|
|
if (params == needle)
|
2014-11-06 14:30:52 +01:00
|
|
|
return true;
|
|
|
|
|
|
2010-11-10 16:33:11 +01:00
|
|
|
// At least at a position we were looking for.
|
|
|
|
|
// FIXME: breaks multiple breakpoints at the same location
|
2015-01-09 10:49:18 +01:00
|
|
|
if (!params.fileName.isEmpty()
|
|
|
|
|
&& fileNameMatch(params.fileName, needle.fileName)
|
|
|
|
|
&& params.lineNumber == needle.lineNumber)
|
2010-11-10 16:33:11 +01:00
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
// At least at a position we were looking for.
|
|
|
|
|
// FIXME: breaks multiple breakpoints at the same location
|
2015-01-09 10:49:18 +01:00
|
|
|
if (!params.fileName.isEmpty()
|
|
|
|
|
&& fileNameMatch(params.fileName, needle.fileName)
|
|
|
|
|
&& params.lineNumber == needle.lineNumber)
|
2010-11-10 16:33:11 +01:00
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoint BreakHandler::findSimilarBreakpoint(const BreakpointResponse &needle) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-02-11 17:29:10 +01:00
|
|
|
// Search a breakpoint we might refer to.
|
2016-06-24 09:36:42 +02:00
|
|
|
return Breakpoint(findItemAtLevel<1>([needle](BreakpointItem *b) {
|
2015-01-10 01:07:01 +01:00
|
|
|
if (b->m_response.id.isValid() && b->m_response.id.majorPart() == needle.id.majorPart())
|
2016-06-10 17:03:21 +02:00
|
|
|
return true;
|
|
|
|
|
return isSimilarTo(b->m_params, needle);
|
|
|
|
|
}));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoint BreakHandler::findBreakpointByResponseId(const BreakpointResponseId &id) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2016-06-24 09:36:42 +02:00
|
|
|
return Breakpoint(findItemAtLevel<1>([id](BreakpointItem *b) {
|
2016-06-10 17:03:21 +02:00
|
|
|
return b->m_response.id.majorPart() == id.majorPart();
|
|
|
|
|
}));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoint BreakHandler::findBreakpointByFunction(const QString &functionName) const
|
2010-05-19 17:34:47 +02:00
|
|
|
{
|
2016-06-24 09:36:42 +02:00
|
|
|
return Breakpoint(findItemAtLevel<1>([functionName](BreakpointItem *b) {
|
2016-06-10 17:03:21 +02:00
|
|
|
return b->m_params.functionName == functionName;
|
|
|
|
|
}));
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoint BreakHandler::findBreakpointByAddress(quint64 address) const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2016-06-24 09:36:42 +02:00
|
|
|
return Breakpoint(findItemAtLevel<1>([address](BreakpointItem *b) {
|
2016-06-10 17:03:21 +02:00
|
|
|
return b->m_params.address == address || b->m_params.address == address;
|
|
|
|
|
}));
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoint BreakHandler::findBreakpointByFileAndLine(const QString &fileName,
|
2010-11-10 16:33:11 +01:00
|
|
|
int lineNumber, bool useMarkerPosition)
|
|
|
|
|
{
|
2016-06-24 09:36:42 +02:00
|
|
|
return Breakpoint(findItemAtLevel<1>([=](BreakpointItem *b) {
|
2016-06-10 17:03:21 +02:00
|
|
|
return b->isLocatedAt(fileName, lineNumber, useMarkerPosition);
|
|
|
|
|
}));
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoint BreakHandler::breakpointById(BreakpointModelId id) const
|
2015-01-09 10:49:18 +01:00
|
|
|
{
|
2016-06-24 09:36:42 +02:00
|
|
|
return Breakpoint(findItemAtLevel<1>([id](BreakpointItem *b) { return b->m_id == id; }));
|
2016-07-18 12:36:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVariant BreakHandler::data(const QModelIndex &idx, int role) const
|
|
|
|
|
{
|
|
|
|
|
if (role == BaseTreeView::ItemDelegateRole)
|
|
|
|
|
return QVariant::fromValue(new LeftElideDelegate);
|
|
|
|
|
|
|
|
|
|
return BreakModel::data(idx, role);
|
2015-01-09 10:49:18 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void BreakHandler::deletionHelper(BreakpointModelId id)
|
2010-11-15 15:24:27 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoint b = breakpointById(id);
|
|
|
|
|
QTC_ASSERT(b, return);
|
2016-07-04 15:53:53 +02:00
|
|
|
destroyItem(b.b);
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoint BreakHandler::findWatchpoint(const BreakpointParameters ¶ms) const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2016-06-24 09:36:42 +02:00
|
|
|
return Breakpoint(findItemAtLevel<1>([params](BreakpointItem *b) {
|
2016-06-10 17:03:21 +02:00
|
|
|
return b->m_params.isWatchpoint()
|
2015-01-10 01:07:01 +01:00
|
|
|
&& b->m_params.address == params.address
|
|
|
|
|
&& b->m_params.size == params.size
|
|
|
|
|
&& b->m_params.expression == params.expression
|
2016-06-10 17:03:21 +02:00
|
|
|
&& b->m_params.bitpos == params.bitpos;
|
|
|
|
|
}));
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void BreakHandler::saveBreakpoints()
|
|
|
|
|
{
|
|
|
|
|
QList<QVariant> list;
|
2016-06-24 09:36:42 +02:00
|
|
|
forItemsAtLevel<1>([&list](BreakpointItem *b) {
|
2015-01-10 01:07:01 +01:00
|
|
|
const BreakpointParameters ¶ms = b->m_params;
|
2008-12-02 12:01:29 +01:00
|
|
|
QMap<QString, QVariant> map;
|
2015-01-09 10:49:18 +01:00
|
|
|
if (params.type != BreakpointByFileAndLine)
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("type", params.type);
|
2015-01-09 10:49:18 +01:00
|
|
|
if (!params.fileName.isEmpty())
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("filename", params.fileName);
|
2015-01-09 10:49:18 +01:00
|
|
|
if (params.lineNumber)
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("linenumber", params.lineNumber);
|
2015-01-09 10:49:18 +01:00
|
|
|
if (!params.functionName.isEmpty())
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("funcname", params.functionName);
|
2015-01-09 10:49:18 +01:00
|
|
|
if (params.address)
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("address", params.address);
|
2015-01-09 10:49:18 +01:00
|
|
|
if (!params.condition.isEmpty())
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("condition", params.condition);
|
2015-01-09 10:49:18 +01:00
|
|
|
if (params.ignoreCount)
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("ignorecount", params.ignoreCount);
|
2015-01-09 10:49:18 +01:00
|
|
|
if (params.threadSpec >= 0)
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("threadspec", params.threadSpec);
|
2015-01-09 10:49:18 +01:00
|
|
|
if (!params.enabled)
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("disabled", "1");
|
2015-01-09 10:49:18 +01:00
|
|
|
if (params.oneShot)
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("oneshot", "1");
|
2015-01-09 10:49:18 +01:00
|
|
|
if (params.pathUsage != BreakpointPathUsageEngineDefault)
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("usefullpath", QString::number(params.pathUsage));
|
2015-01-09 10:49:18 +01:00
|
|
|
if (params.tracepoint)
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("tracepoint", "1");
|
2015-01-09 10:49:18 +01:00
|
|
|
if (!params.module.isEmpty())
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("module", params.module);
|
2015-01-09 10:49:18 +01:00
|
|
|
if (!params.command.isEmpty())
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("command", params.command);
|
2015-01-09 10:49:18 +01:00
|
|
|
if (!params.expression.isEmpty())
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("expression", params.expression);
|
2015-01-09 10:49:18 +01:00
|
|
|
if (!params.message.isEmpty())
|
2016-06-07 17:04:53 +02:00
|
|
|
map.insert("message", params.message);
|
2008-12-02 12:01:29 +01:00
|
|
|
list.append(map);
|
2016-06-10 17:03:21 +02:00
|
|
|
});
|
2014-07-28 14:23:52 +02:00
|
|
|
setSessionValue("Breakpoints", list);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::loadBreakpoints()
|
|
|
|
|
{
|
2014-07-28 14:23:52 +02:00
|
|
|
QVariant value = sessionValue("Breakpoints");
|
2008-12-02 12:01:29 +01:00
|
|
|
QList<QVariant> list = value.toList();
|
|
|
|
|
foreach (const QVariant &var, list) {
|
|
|
|
|
const QMap<QString, QVariant> map = var.toMap();
|
2015-01-09 10:49:18 +01:00
|
|
|
BreakpointParameters params(BreakpointByFileAndLine);
|
2016-06-07 17:04:53 +02:00
|
|
|
QVariant v = map.value("filename");
|
2009-06-30 15:50:56 +02:00
|
|
|
if (v.isValid())
|
2015-01-09 10:49:18 +01:00
|
|
|
params.fileName = v.toString();
|
2016-06-07 17:04:53 +02:00
|
|
|
v = map.value("linenumber");
|
2009-06-30 15:50:56 +02:00
|
|
|
if (v.isValid())
|
2015-01-09 10:49:18 +01:00
|
|
|
params.lineNumber = v.toString().toInt();
|
2016-06-07 17:04:53 +02:00
|
|
|
v = map.value("condition");
|
2009-06-30 15:50:56 +02:00
|
|
|
if (v.isValid())
|
2016-06-07 17:04:53 +02:00
|
|
|
params.condition = v.toString();
|
|
|
|
|
v = map.value("address");
|
2010-05-07 15:16:31 +02:00
|
|
|
if (v.isValid())
|
2015-01-09 10:49:18 +01:00
|
|
|
params.address = v.toString().toULongLong();
|
2016-06-07 17:04:53 +02:00
|
|
|
v = map.value("ignorecount");
|
2009-06-30 15:50:56 +02:00
|
|
|
if (v.isValid())
|
2015-01-09 10:49:18 +01:00
|
|
|
params.ignoreCount = v.toString().toInt();
|
2016-06-07 17:04:53 +02:00
|
|
|
v = map.value("threadspec");
|
2010-04-29 18:36:18 +02:00
|
|
|
if (v.isValid())
|
2015-01-09 10:49:18 +01:00
|
|
|
params.threadSpec = v.toString().toInt();
|
2016-06-07 17:04:53 +02:00
|
|
|
v = map.value("funcname");
|
2009-06-30 15:50:56 +02:00
|
|
|
if (v.isValid())
|
2015-01-09 10:49:18 +01:00
|
|
|
params.functionName = v.toString();
|
2016-06-07 17:04:53 +02:00
|
|
|
v = map.value("disabled");
|
2009-06-30 15:50:56 +02:00
|
|
|
if (v.isValid())
|
2015-01-09 10:49:18 +01:00
|
|
|
params.enabled = !v.toInt();
|
2016-06-07 17:04:53 +02:00
|
|
|
v = map.value("oneshot");
|
2012-08-21 14:16:07 +02:00
|
|
|
if (v.isValid())
|
2015-01-09 10:49:18 +01:00
|
|
|
params.oneShot = v.toInt();
|
2016-06-07 17:04:53 +02:00
|
|
|
v = map.value("usefullpath");
|
2009-06-30 15:50:56 +02:00
|
|
|
if (v.isValid())
|
2015-01-09 10:49:18 +01:00
|
|
|
params.pathUsage = static_cast<BreakpointPathUsage>(v.toInt());
|
2016-06-07 17:04:53 +02:00
|
|
|
v = map.value("tracepoint");
|
2010-12-16 17:58:43 +01:00
|
|
|
if (v.isValid())
|
2015-01-09 10:49:18 +01:00
|
|
|
params.tracepoint = bool(v.toInt());
|
2016-06-07 17:04:53 +02:00
|
|
|
v = map.value("type");
|
2013-04-09 10:59:36 +02:00
|
|
|
if (v.isValid() && v.toInt() != UnknownBreakpointType)
|
2015-01-09 10:49:18 +01:00
|
|
|
params.type = BreakpointType(v.toInt());
|
2016-06-07 17:04:53 +02:00
|
|
|
v = map.value("module");
|
2011-02-02 14:41:14 +01:00
|
|
|
if (v.isValid())
|
2015-01-09 10:49:18 +01:00
|
|
|
params.module = v.toString();
|
2016-06-07 17:04:53 +02:00
|
|
|
v = map.value("command");
|
2011-02-04 11:33:45 +01:00
|
|
|
if (v.isValid())
|
2015-01-09 10:49:18 +01:00
|
|
|
params.command = v.toString();
|
2016-06-07 17:04:53 +02:00
|
|
|
v = map.value("expression");
|
2011-05-11 15:24:50 +02:00
|
|
|
if (v.isValid())
|
2015-01-09 10:49:18 +01:00
|
|
|
params.expression = v.toString();
|
2016-06-07 17:04:53 +02:00
|
|
|
v = map.value("message");
|
2011-06-27 10:37:57 +02:00
|
|
|
if (v.isValid())
|
2015-01-09 10:49:18 +01:00
|
|
|
params.message = v.toString();
|
|
|
|
|
if (params.isValid())
|
|
|
|
|
appendBreakpointInternal(params);
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
else
|
2015-01-09 10:49:18 +01:00
|
|
|
qWarning("Not restoring invalid breakpoint: %s", qPrintable(params.toString()));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::updateMarkers()
|
|
|
|
|
{
|
2016-06-24 09:36:42 +02:00
|
|
|
forItemsAtLevel<1>([](BreakpointItem *b) { b->updateMarker(); });
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoint BreakHandler::findBreakpointByIndex(const QModelIndex &index) const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2016-06-24 09:36:42 +02:00
|
|
|
return Breakpoint(itemForIndexAtLevel<1>(index));
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoints BreakHandler::findBreakpointsByIndex(const QList<QModelIndex> &list) const
|
2010-11-15 15:30:39 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
QSet<Breakpoint> ids;
|
|
|
|
|
foreach (const QModelIndex &index, list) {
|
|
|
|
|
if (Breakpoint b = findBreakpointByIndex(index))
|
2016-06-10 17:03:21 +02:00
|
|
|
ids.insert(b);
|
2015-01-10 01:07:01 +01:00
|
|
|
}
|
2010-11-24 11:44:43 +01:00
|
|
|
return ids.toList();
|
2010-11-15 15:30:39 +01:00
|
|
|
}
|
|
|
|
|
|
2010-12-14 13:00:02 +01:00
|
|
|
QString BreakHandler::displayFromThreadSpec(int spec)
|
2010-11-30 13:39:01 +01:00
|
|
|
{
|
2010-12-14 13:00:02 +01:00
|
|
|
return spec == -1 ? BreakHandler::tr("(all)") : QString::number(spec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int BreakHandler::threadSpecFromDisplay(const QString &str)
|
|
|
|
|
{
|
|
|
|
|
bool ok = false;
|
|
|
|
|
int result = str.toInt(&ok);
|
|
|
|
|
return ok ? result : -1;
|
2010-11-30 13:39:01 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-09 10:49:18 +01:00
|
|
|
const QString empty(QLatin1Char('-'));
|
2011-05-11 16:24:04 +02:00
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
QVariant BreakpointItem::data(int column, int role) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-11-25 15:01:51 +01:00
|
|
|
bool orig = false;
|
2015-01-10 01:07:01 +01:00
|
|
|
switch (m_state) {
|
2010-11-25 15:01:51 +01:00
|
|
|
case BreakpointInsertRequested:
|
|
|
|
|
case BreakpointInsertProceeding:
|
|
|
|
|
case BreakpointChangeRequested:
|
|
|
|
|
case BreakpointChangeProceeding:
|
|
|
|
|
case BreakpointInserted:
|
|
|
|
|
case BreakpointRemoveRequested:
|
|
|
|
|
case BreakpointRemoveProceeding:
|
|
|
|
|
break;
|
|
|
|
|
case BreakpointNew:
|
|
|
|
|
case BreakpointDead:
|
|
|
|
|
orig = true;
|
|
|
|
|
break;
|
|
|
|
|
};
|
|
|
|
|
|
2015-02-02 09:29:58 +01:00
|
|
|
if (role == Qt::ForegroundRole) {
|
|
|
|
|
static const QVariant gray(QColor(140, 140, 140));
|
|
|
|
|
switch (m_state) {
|
|
|
|
|
case BreakpointInsertRequested:
|
|
|
|
|
case BreakpointInsertProceeding:
|
|
|
|
|
case BreakpointChangeRequested:
|
|
|
|
|
case BreakpointChangeProceeding:
|
|
|
|
|
case BreakpointRemoveRequested:
|
|
|
|
|
case BreakpointRemoveProceeding:
|
|
|
|
|
return gray;
|
|
|
|
|
case BreakpointInserted:
|
|
|
|
|
case BreakpointNew:
|
|
|
|
|
case BreakpointDead:
|
|
|
|
|
break;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-09 10:49:18 +01:00
|
|
|
switch (column) {
|
2016-06-03 12:04:14 +02:00
|
|
|
case BreakpointNumberColumn:
|
2011-06-21 16:45:23 +02:00
|
|
|
if (role == Qt::DisplayRole)
|
2015-01-10 01:07:01 +01:00
|
|
|
return m_id.toString();
|
2010-11-18 14:57:00 +01:00
|
|
|
if (role == Qt::DecorationRole)
|
2015-01-09 10:49:18 +01:00
|
|
|
return icon();
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
2016-06-03 12:04:14 +02:00
|
|
|
case BreakpointFunctionColumn:
|
2008-12-02 12:01:29 +01:00
|
|
|
if (role == Qt::DisplayRole) {
|
2015-01-10 01:07:01 +01:00
|
|
|
if (!m_response.functionName.isEmpty())
|
|
|
|
|
return simplifyType(m_response.functionName);
|
|
|
|
|
if (!m_params.functionName.isEmpty())
|
|
|
|
|
return m_params.functionName;
|
|
|
|
|
if (m_params.type == BreakpointAtMain
|
|
|
|
|
|| m_params.type == BreakpointAtThrow
|
|
|
|
|
|| m_params.type == BreakpointAtCatch
|
|
|
|
|
|| m_params.type == BreakpointAtFork
|
|
|
|
|
|| m_params.type == BreakpointAtExec
|
|
|
|
|
//|| m_params.type == BreakpointAtVFork
|
|
|
|
|
|| m_params.type == BreakpointAtSysCall)
|
|
|
|
|
return typeToString(m_params.type);
|
|
|
|
|
if (m_params.type == WatchpointAtAddress) {
|
|
|
|
|
quint64 address = m_response.address ? m_response.address : m_params.address;
|
|
|
|
|
return BreakHandler::tr("Data at 0x%1").arg(address, 0, 16);
|
2012-03-19 14:12:29 +01:00
|
|
|
}
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.type == WatchpointAtExpression) {
|
|
|
|
|
QString expression = !m_response.expression.isEmpty()
|
|
|
|
|
? m_response.expression : m_params.expression;
|
|
|
|
|
return BreakHandler::tr("Data at %1").arg(expression);
|
2012-03-19 14:12:29 +01:00
|
|
|
}
|
2010-11-18 14:57:00 +01:00
|
|
|
return empty;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
break;
|
2016-06-03 12:04:14 +02:00
|
|
|
case BreakpointFileColumn:
|
2008-12-02 12:01:29 +01:00
|
|
|
if (role == Qt::DisplayRole) {
|
2010-11-18 14:57:00 +01:00
|
|
|
QString str;
|
2015-01-10 01:07:01 +01:00
|
|
|
if (!m_response.fileName.isEmpty())
|
|
|
|
|
str = m_response.fileName;
|
|
|
|
|
if (str.isEmpty() && !m_params.fileName.isEmpty())
|
|
|
|
|
str = m_params.fileName;
|
2010-11-18 14:57:00 +01:00
|
|
|
if (str.isEmpty()) {
|
2015-02-03 23:58:49 +02:00
|
|
|
QString s = FileName::fromString(str).fileName();
|
2010-11-18 14:57:00 +01:00
|
|
|
if (!s.isEmpty())
|
|
|
|
|
str = s;
|
|
|
|
|
}
|
2010-02-10 11:45:40 +01:00
|
|
|
// FIXME: better?
|
2015-01-09 10:49:18 +01:00
|
|
|
//if (params.multiple && str.isEmpty() && !response.fileName.isEmpty())
|
2010-11-18 13:38:58 +01:00
|
|
|
// str = response.fileName;
|
2010-11-18 14:57:00 +01:00
|
|
|
if (!str.isEmpty())
|
2010-12-14 09:57:14 +01:00
|
|
|
return QDir::toNativeSeparators(str);
|
2010-11-18 14:57:00 +01:00
|
|
|
return empty;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
break;
|
2016-06-03 12:04:14 +02:00
|
|
|
case BreakpointLineColumn:
|
2008-12-02 12:01:29 +01:00
|
|
|
if (role == Qt::DisplayRole) {
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_response.lineNumber > 0)
|
|
|
|
|
return m_response.lineNumber;
|
|
|
|
|
if (m_params.lineNumber > 0)
|
|
|
|
|
return m_params.lineNumber;
|
2010-11-18 14:57:00 +01:00
|
|
|
return empty;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2010-04-29 18:36:18 +02:00
|
|
|
if (role == Qt::UserRole + 1)
|
2015-01-10 01:07:01 +01:00
|
|
|
return m_params.lineNumber;
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
2016-06-03 12:04:14 +02:00
|
|
|
case BreakpointAddressColumn:
|
2010-11-26 12:30:05 +01:00
|
|
|
if (role == Qt::DisplayRole) {
|
2015-01-10 01:07:01 +01:00
|
|
|
const quint64 address = orig ? m_params.address : m_response.address;
|
2010-11-26 12:30:05 +01:00
|
|
|
if (address)
|
2016-07-18 12:36:31 +02:00
|
|
|
return QString("0x%1").arg(address, 0, 16);
|
2011-06-21 16:45:23 +02:00
|
|
|
return QVariant();
|
2010-11-26 12:30:05 +01:00
|
|
|
}
|
|
|
|
|
break;
|
2016-06-03 12:04:14 +02:00
|
|
|
case BreakpointConditionColumn:
|
2008-12-02 12:01:29 +01:00
|
|
|
if (role == Qt::DisplayRole)
|
2015-01-10 01:07:01 +01:00
|
|
|
return orig ? m_params.condition : m_response.condition;
|
2008-12-02 12:01:29 +01:00
|
|
|
if (role == Qt::ToolTipRole)
|
2015-01-10 01:07:01 +01:00
|
|
|
return BreakHandler::tr("Breakpoint will only be hit if this condition is met.");
|
2010-04-29 18:36:18 +02:00
|
|
|
if (role == Qt::UserRole + 1)
|
2015-01-10 01:07:01 +01:00
|
|
|
return m_params.condition;
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
2016-06-03 12:04:14 +02:00
|
|
|
case BreakpointIgnoreColumn:
|
2010-09-21 14:26:45 +02:00
|
|
|
if (role == Qt::DisplayRole) {
|
2010-11-10 16:33:11 +01:00
|
|
|
const int ignoreCount =
|
2015-01-10 01:07:01 +01:00
|
|
|
orig ? m_params.ignoreCount : m_response.ignoreCount;
|
2010-09-21 14:26:45 +02:00
|
|
|
return ignoreCount ? QVariant(ignoreCount) : QVariant(QString());
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
if (role == Qt::ToolTipRole)
|
2015-01-10 01:07:01 +01:00
|
|
|
return BreakHandler::tr("Breakpoint will only be hit after being ignored so many times.");
|
2010-04-29 18:36:18 +02:00
|
|
|
if (role == Qt::UserRole + 1)
|
2015-01-10 01:07:01 +01:00
|
|
|
return m_params.ignoreCount;
|
2010-06-11 13:39:47 +10:00
|
|
|
break;
|
2016-06-03 12:04:14 +02:00
|
|
|
case BreakpointThreadsColumn:
|
2010-11-30 13:39:01 +01:00
|
|
|
if (role == Qt::DisplayRole)
|
2015-01-10 01:07:01 +01:00
|
|
|
return BreakHandler::displayFromThreadSpec(orig ? m_params.threadSpec : m_response.threadSpec);
|
2010-04-29 18:36:18 +02:00
|
|
|
if (role == Qt::ToolTipRole)
|
2015-01-10 01:07:01 +01:00
|
|
|
return BreakHandler::tr("Breakpoint will only be hit in the specified thread(s).");
|
2010-04-29 18:36:18 +02:00
|
|
|
if (role == Qt::UserRole + 1)
|
2015-01-10 01:07:01 +01:00
|
|
|
return BreakHandler::displayFromThreadSpec(m_params.threadSpec);
|
2010-06-11 13:39:47 +10:00
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2015-01-09 10:49:18 +01:00
|
|
|
|
|
|
|
|
if (role == Qt::ToolTipRole && boolSetting(UseToolTipsInBreakpointsView))
|
|
|
|
|
return toToolTip();
|
|
|
|
|
|
|
|
|
|
return QVariant();
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
#define PROPERTY(type, getter, setter) \
|
|
|
|
|
\
|
|
|
|
|
type Breakpoint::getter() const \
|
2010-11-10 16:33:11 +01:00
|
|
|
{ \
|
2015-01-10 01:07:01 +01:00
|
|
|
return parameters().getter; \
|
|
|
|
|
} \
|
|
|
|
|
\
|
|
|
|
|
void Breakpoint::setter(const type &value) \
|
2010-11-10 16:33:11 +01:00
|
|
|
{ \
|
2015-01-10 01:07:01 +01:00
|
|
|
QTC_ASSERT(b, return); \
|
|
|
|
|
if (b->m_params.getter == value) \
|
2010-11-15 16:22:51 +01:00
|
|
|
return; \
|
2015-01-10 01:07:01 +01:00
|
|
|
b->m_params.getter = value; \
|
|
|
|
|
if (b->m_state != BreakpointNew) { \
|
|
|
|
|
b->m_state = BreakpointChangeRequested; \
|
|
|
|
|
b->scheduleSynchronization(); \
|
2010-12-14 13:35:42 +01:00
|
|
|
} \
|
2010-09-28 13:14:14 +02:00
|
|
|
}
|
|
|
|
|
|
2011-02-17 13:00:11 +01:00
|
|
|
PROPERTY(BreakpointPathUsage, pathUsage, setPathUsage)
|
2010-11-10 16:33:11 +01:00
|
|
|
PROPERTY(QString, fileName, setFileName)
|
|
|
|
|
PROPERTY(QString, functionName, setFunctionName)
|
|
|
|
|
PROPERTY(BreakpointType, type, setType)
|
2010-11-30 13:39:01 +01:00
|
|
|
PROPERTY(int, threadSpec, setThreadSpec)
|
2016-06-07 17:04:53 +02:00
|
|
|
PROPERTY(QString, condition, setCondition)
|
2016-04-13 18:19:45 +02:00
|
|
|
PROPERTY(QString, command, setCommand)
|
2010-11-10 16:33:11 +01:00
|
|
|
PROPERTY(quint64, address, setAddress)
|
2011-05-10 15:57:33 +02:00
|
|
|
PROPERTY(QString, expression, setExpression)
|
2011-06-27 10:37:57 +02:00
|
|
|
PROPERTY(QString, message, setMessage)
|
2010-11-15 12:32:51 +01:00
|
|
|
PROPERTY(int, ignoreCount, setIgnoreCount)
|
2010-11-10 16:33:11 +01:00
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void BreakpointItem::scheduleSynchronization()
|
2010-11-15 15:05:39 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
m_handler->scheduleSynchronization();
|
2010-11-15 15:05:39 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
const BreakpointParameters &Breakpoint::parameters() const
|
2010-11-15 15:05:39 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
static BreakpointParameters p;
|
|
|
|
|
QTC_ASSERT(b, return p);
|
|
|
|
|
return b->m_params;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-04 16:27:46 +01:00
|
|
|
void Breakpoint::addToCommand(DebuggerCommand *cmd) const
|
|
|
|
|
{
|
2016-06-07 17:04:53 +02:00
|
|
|
cmd->arg("modelid", id().toString());
|
2015-10-08 16:19:57 +02:00
|
|
|
cmd->arg("id", int(response().id.majorPart()));
|
2015-02-04 16:27:46 +01:00
|
|
|
cmd->arg("type", type());
|
|
|
|
|
cmd->arg("ignorecount", ignoreCount());
|
2016-06-07 17:04:53 +02:00
|
|
|
cmd->arg("condition", toHex(condition()));
|
|
|
|
|
cmd->arg("command", toHex(command()));
|
|
|
|
|
cmd->arg("function", functionName());
|
2015-02-04 16:27:46 +01:00
|
|
|
cmd->arg("oneshot", isOneShot());
|
|
|
|
|
cmd->arg("enabled", isEnabled());
|
2016-06-07 17:04:53 +02:00
|
|
|
cmd->arg("file", fileName());
|
2015-10-08 16:19:57 +02:00
|
|
|
cmd->arg("line", lineNumber());
|
2015-02-04 16:27:46 +01:00
|
|
|
cmd->arg("address", address());
|
|
|
|
|
cmd->arg("expression", expression());
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
BreakpointState Breakpoint::state() const
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(b, return BreakpointState());
|
|
|
|
|
return b->m_state;
|
2010-11-15 15:05:39 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
int Breakpoint::lineNumber() const { return parameters().lineNumber; }
|
|
|
|
|
|
|
|
|
|
bool Breakpoint::isEnabled() const { return parameters().enabled; }
|
|
|
|
|
|
|
|
|
|
bool Breakpoint::isWatchpoint() const { return parameters().isWatchpoint(); }
|
|
|
|
|
|
|
|
|
|
bool Breakpoint::isTracepoint() const { return parameters().isTracepoint(); }
|
|
|
|
|
|
|
|
|
|
QIcon Breakpoint::icon() const { return b ? b->icon() : QIcon(); }
|
|
|
|
|
|
|
|
|
|
DebuggerEngine *Breakpoint::engine() const
|
2011-05-09 08:35:58 +02:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
return b ? b->m_engine : 0;
|
2011-05-09 08:35:58 +02:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
const BreakpointResponse &Breakpoint::response() const
|
2010-12-16 17:58:43 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
static BreakpointResponse r;
|
|
|
|
|
return b ? b->m_response : r;
|
2010-12-16 17:58:43 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
bool Breakpoint::isOneShot() const { return parameters().oneShot; }
|
|
|
|
|
|
|
|
|
|
void Breakpoint::removeAlienBreakpoint()
|
2012-08-21 14:16:07 +02:00
|
|
|
{
|
2015-07-16 08:49:43 +02:00
|
|
|
b->m_state = BreakpointRemoveProceeding;
|
2015-01-10 01:07:01 +01:00
|
|
|
b->deleteThis();
|
2012-08-21 14:16:07 +02:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::removeBreakpoint() const
|
2011-06-24 19:02:12 +02:00
|
|
|
{
|
2015-08-31 16:35:24 +02:00
|
|
|
if (b)
|
|
|
|
|
b->removeBreakpoint();
|
2011-06-24 19:02:12 +02:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoint::Breakpoint(BreakpointItem *b)
|
|
|
|
|
: b(b)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
void Breakpoint::setEnabled(bool on) const
|
2010-12-16 17:58:43 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
QTC_ASSERT(b, return);
|
|
|
|
|
if (b->m_params.enabled == on)
|
2010-12-16 17:58:43 +01:00
|
|
|
return;
|
2015-01-10 01:07:01 +01:00
|
|
|
b->m_params.enabled = on;
|
2015-01-09 10:49:18 +01:00
|
|
|
b->updateMarkerIcon();
|
2016-04-22 07:36:06 +02:00
|
|
|
b->update();
|
2015-01-10 01:07:01 +01:00
|
|
|
if (b->m_engine) {
|
|
|
|
|
b->m_state = BreakpointChangeRequested;
|
|
|
|
|
b->scheduleSynchronization();
|
2011-02-17 13:49:47 +01:00
|
|
|
}
|
2010-12-16 17:58:43 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::setMarkerFileAndLine(const QString &fileName, int lineNumber)
|
2010-11-15 19:05:31 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
if (b)
|
|
|
|
|
b->setMarkerFileAndLine(fileName, lineNumber);
|
2010-11-15 19:05:31 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::setTracepoint(bool on)
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
if (b->m_params.tracepoint == on)
|
|
|
|
|
return;
|
|
|
|
|
b->m_params.tracepoint = on;
|
|
|
|
|
b->updateMarkerIcon();
|
|
|
|
|
|
|
|
|
|
if (b->m_engine) {
|
|
|
|
|
b->m_state = BreakpointChangeRequested;
|
|
|
|
|
b->scheduleSynchronization();
|
|
|
|
|
}
|
2010-11-16 13:52:21 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void BreakpointItem::setMarkerFileAndLine(const QString &fileName, int lineNumber)
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_response.fileName == fileName && m_response.lineNumber == lineNumber)
|
|
|
|
|
return;
|
|
|
|
|
m_response.fileName = fileName;
|
|
|
|
|
m_response.lineNumber = lineNumber;
|
|
|
|
|
destroyMarker();
|
|
|
|
|
updateMarker();
|
|
|
|
|
update();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Breakpoint::setEngine(DebuggerEngine *value)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(b->m_state == BreakpointNew, qDebug() << "STATE: " << b->m_state << b->m_id);
|
|
|
|
|
QTC_ASSERT(!b->m_engine, qDebug() << "NO ENGINE" << b->m_id; return);
|
|
|
|
|
b->m_engine = value;
|
|
|
|
|
b->m_state = BreakpointInsertRequested;
|
|
|
|
|
b->m_response = BreakpointResponse();
|
2015-01-09 10:49:18 +01:00
|
|
|
b->updateMarker();
|
2015-01-10 01:07:01 +01:00
|
|
|
//b->scheduleSynchronization();
|
2010-11-16 13:52:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool isAllowedTransition(BreakpointState from, BreakpointState to)
|
|
|
|
|
{
|
|
|
|
|
switch (from) {
|
|
|
|
|
case BreakpointNew:
|
2015-01-10 01:07:01 +01:00
|
|
|
return to == BreakpointInsertRequested
|
|
|
|
|
|| to == BreakpointDead;
|
2010-11-16 13:52:21 +01:00
|
|
|
case BreakpointInsertRequested:
|
|
|
|
|
return to == BreakpointInsertProceeding;
|
|
|
|
|
case BreakpointInsertProceeding:
|
|
|
|
|
return to == BreakpointInserted
|
2010-11-18 12:30:56 +01:00
|
|
|
|| to == BreakpointDead
|
2011-10-01 16:21:59 +02:00
|
|
|
|| to == BreakpointChangeRequested
|
|
|
|
|
|| to == BreakpointRemoveRequested;
|
2010-11-16 13:52:21 +01:00
|
|
|
case BreakpointChangeRequested:
|
|
|
|
|
return to == BreakpointChangeProceeding;
|
|
|
|
|
case BreakpointChangeProceeding:
|
|
|
|
|
return to == BreakpointInserted
|
|
|
|
|
|| to == BreakpointDead;
|
|
|
|
|
case BreakpointInserted:
|
2010-11-16 16:10:55 +01:00
|
|
|
return to == BreakpointChangeRequested
|
|
|
|
|
|| to == BreakpointRemoveRequested;
|
2010-11-16 13:52:21 +01:00
|
|
|
case BreakpointRemoveRequested:
|
2010-11-16 16:10:55 +01:00
|
|
|
return to == BreakpointRemoveProceeding;
|
2010-11-16 13:52:21 +01:00
|
|
|
case BreakpointRemoveProceeding:
|
2010-11-16 16:10:55 +01:00
|
|
|
return to == BreakpointDead;
|
2010-11-16 13:52:21 +01:00
|
|
|
case BreakpointDead:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
qDebug() << "UNKNOWN BREAKPOINT STATE:" << from;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
bool BreakpointItem::isEngineRunning() const
|
2011-05-11 12:18:32 +02:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
if (!m_engine)
|
|
|
|
|
return false;
|
|
|
|
|
const DebuggerState state = m_engine->state();
|
|
|
|
|
return state != DebuggerFinished && state != DebuggerNotReady;
|
2011-05-11 12:18:32 +02:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void BreakpointItem::setState(BreakpointState state)
|
2010-11-15 14:12:05 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
//qDebug() << "BREAKPOINT STATE TRANSITION, ID: " << m_id
|
|
|
|
|
// << " FROM: " << state << " TO: " << state;
|
|
|
|
|
if (!isAllowedTransition(m_state, state)) {
|
|
|
|
|
qDebug() << "UNEXPECTED BREAKPOINT STATE TRANSITION" << m_state << state;
|
|
|
|
|
QTC_CHECK(false);
|
|
|
|
|
}
|
2010-11-16 13:52:21 +01:00
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_state == state) {
|
|
|
|
|
qDebug() << "STATE UNCHANGED: " << m_id << m_state;
|
2010-11-15 16:58:23 +01:00
|
|
|
return;
|
|
|
|
|
}
|
2010-11-16 13:52:21 +01:00
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
m_state = state;
|
2011-06-24 19:36:13 +02:00
|
|
|
|
|
|
|
|
// FIXME: updateMarker() should recognize the need for icon changes.
|
|
|
|
|
if (state == BreakpointInserted) {
|
2015-01-10 01:07:01 +01:00
|
|
|
destroyMarker();
|
|
|
|
|
updateMarker();
|
2011-06-24 19:36:13 +02:00
|
|
|
}
|
2015-01-10 01:07:01 +01:00
|
|
|
update();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakpointItem::deleteThis()
|
|
|
|
|
{
|
|
|
|
|
setState(BreakpointDead);
|
|
|
|
|
destroyMarker();
|
|
|
|
|
|
|
|
|
|
// This is called from b directly. So delay deletion of b.
|
|
|
|
|
ExtensionSystem::InvokerBase invoker;
|
|
|
|
|
invoker.addArgument(m_id);
|
|
|
|
|
invoker.setConnectionType(Qt::QueuedConnection);
|
|
|
|
|
invoker.invoke(m_handler, "deletionHelper");
|
|
|
|
|
QTC_CHECK(invoker.wasSuccessful());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Breakpoint::gotoState(BreakpointState target, BreakpointState assumedCurrent)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(b, return);
|
|
|
|
|
QTC_ASSERT(b->m_state == assumedCurrent, qDebug() << b->m_state);
|
|
|
|
|
b->setState(target);
|
2010-11-15 14:12:05 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::notifyBreakpointChangeAfterInsertNeeded()
|
2010-11-30 12:47:53 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
gotoState(BreakpointChangeRequested, BreakpointInsertProceeding);
|
2010-11-30 12:47:53 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::notifyBreakpointInsertProceeding()
|
2009-04-28 15:08:52 +02:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
gotoState(BreakpointInsertProceeding, BreakpointInsertRequested);
|
2009-04-28 15:08:52 +02:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::notifyBreakpointInsertOk()
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
gotoState(BreakpointInserted, BreakpointInsertProceeding);
|
2015-08-31 16:35:24 +02:00
|
|
|
if (b->m_engine)
|
|
|
|
|
b->m_engine->updateBreakpointMarker(*this);
|
2010-11-16 13:52:21 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::notifyBreakpointInsertFailed()
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
gotoState(BreakpointDead, BreakpointInsertProceeding);
|
2010-11-16 13:52:21 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::notifyBreakpointRemoveProceeding()
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
gotoState(BreakpointRemoveProceeding, BreakpointRemoveRequested);
|
2010-11-16 13:52:21 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::notifyBreakpointRemoveOk()
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
QTC_ASSERT(b, return);
|
|
|
|
|
QTC_ASSERT(b->m_state == BreakpointRemoveProceeding, qDebug() << b->m_state);
|
2015-08-31 16:35:24 +02:00
|
|
|
if (b->m_engine)
|
|
|
|
|
b->m_engine->removeBreakpointMarker(*this);
|
2015-01-10 01:07:01 +01:00
|
|
|
b->deleteThis();
|
2010-11-16 13:52:21 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::notifyBreakpointRemoveFailed()
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
QTC_ASSERT(b, return);
|
|
|
|
|
QTC_ASSERT(b->m_state == BreakpointRemoveProceeding, qDebug() << b->m_state);
|
2015-08-31 16:35:24 +02:00
|
|
|
if (b->m_engine)
|
|
|
|
|
b->m_engine->removeBreakpointMarker(*this);
|
2015-01-10 01:07:01 +01:00
|
|
|
b->deleteThis();
|
2010-11-16 13:52:21 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::notifyBreakpointChangeProceeding()
|
2010-11-18 16:16:23 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
gotoState(BreakpointChangeProceeding, BreakpointChangeRequested);
|
2010-11-18 16:16:23 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::notifyBreakpointChangeOk()
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
gotoState(BreakpointInserted, BreakpointChangeProceeding);
|
2010-11-16 13:52:21 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::notifyBreakpointChangeFailed()
|
2009-04-28 15:08:52 +02:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
gotoState(BreakpointDead, BreakpointChangeProceeding);
|
2010-11-16 13:52:21 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::notifyBreakpointReleased()
|
2010-11-16 13:52:21 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
QTC_ASSERT(b, return);
|
2015-01-14 09:09:15 +01:00
|
|
|
b->removeChildren();
|
2015-01-10 01:07:01 +01:00
|
|
|
//QTC_ASSERT(b->m_state == BreakpointChangeProceeding, qDebug() << b->m_state);
|
|
|
|
|
b->m_state = BreakpointNew;
|
|
|
|
|
b->m_engine = 0;
|
|
|
|
|
b->m_response = BreakpointResponse();
|
2015-01-09 10:49:18 +01:00
|
|
|
b->destroyMarker();
|
|
|
|
|
b->updateMarker();
|
2015-01-10 01:07:01 +01:00
|
|
|
if (b->m_params.type == WatchpointAtAddress
|
|
|
|
|
|| b->m_params.type == WatchpointAtExpression
|
|
|
|
|
|| b->m_params.type == BreakpointByAddress)
|
|
|
|
|
b->m_params.enabled = false;
|
2013-09-19 14:15:58 +02:00
|
|
|
else
|
2015-01-10 01:07:01 +01:00
|
|
|
b->m_params.address = 0;
|
|
|
|
|
b->update();
|
2009-04-28 15:08:52 +02:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::notifyBreakpointAdjusted(const BreakpointParameters ¶ms)
|
2010-11-16 18:20:52 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
QTC_ASSERT(b, return);
|
|
|
|
|
QTC_ASSERT(b->m_state == BreakpointInserted, qDebug() << b->m_state);
|
|
|
|
|
b->m_params = params;
|
2015-01-09 10:49:18 +01:00
|
|
|
//if (b->needsChange())
|
2015-01-10 01:07:01 +01:00
|
|
|
// b->setState(BreakpointChangeRequested);
|
2010-11-16 18:20:52 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::notifyBreakpointNeedsReinsertion()
|
2010-11-30 12:47:53 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
QTC_ASSERT(b, return);
|
|
|
|
|
QTC_ASSERT(b->m_state == BreakpointChangeProceeding, qDebug() << b->m_state);
|
|
|
|
|
b->m_state = BreakpointInsertRequested;
|
2010-11-30 12:47:53 +01:00
|
|
|
}
|
2010-11-16 18:20:52 +01:00
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void BreakpointItem::removeBreakpoint()
|
2009-04-28 15:08:52 +02:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
switch (m_state) {
|
2011-10-28 12:26:00 +02:00
|
|
|
case BreakpointRemoveRequested:
|
|
|
|
|
break;
|
2011-02-17 13:49:47 +01:00
|
|
|
case BreakpointInserted:
|
2011-10-01 16:21:59 +02:00
|
|
|
case BreakpointInsertProceeding:
|
2015-01-10 01:07:01 +01:00
|
|
|
setState(BreakpointRemoveRequested);
|
2010-11-18 14:57:00 +01:00
|
|
|
scheduleSynchronization();
|
2011-02-17 13:49:47 +01:00
|
|
|
break;
|
|
|
|
|
case BreakpointNew:
|
2015-01-10 01:07:01 +01:00
|
|
|
deleteThis();
|
2011-02-17 13:49:47 +01:00
|
|
|
break;
|
|
|
|
|
default:
|
2011-06-15 14:02:26 +02:00
|
|
|
qWarning("Warning: Cannot remove breakpoint %s in state '%s'.",
|
2015-01-10 01:07:01 +01:00
|
|
|
qPrintable(m_id.toString()), qPrintable(stateToString(m_state)));
|
|
|
|
|
m_state = BreakpointRemoveRequested;
|
2011-02-17 13:49:47 +01:00
|
|
|
break;
|
2009-04-28 15:08:52 +02:00
|
|
|
}
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-01-09 10:49:18 +01:00
|
|
|
void BreakHandler::appendBreakpoint(const BreakpointParameters ¶ms)
|
2014-12-05 12:08:41 +01:00
|
|
|
{
|
2015-01-09 10:49:18 +01:00
|
|
|
appendBreakpointInternal(params);
|
2014-12-05 12:08:41 +01:00
|
|
|
scheduleSynchronization();
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-09 10:49:18 +01:00
|
|
|
void BreakHandler::appendBreakpointInternal(const BreakpointParameters ¶ms)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2015-01-09 10:49:18 +01:00
|
|
|
if (!params.isValid()) {
|
|
|
|
|
qWarning("Not adding invalid breakpoint: %s", qPrintable(params.toString()));
|
2011-10-20 10:45:59 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
BreakpointItem *b = new BreakpointItem(this);
|
|
|
|
|
b->m_params = params;
|
2015-01-09 10:49:18 +01:00
|
|
|
b->updateMarker();
|
2015-01-14 09:09:15 +01:00
|
|
|
rootItem()->appendChild(b);
|
2011-06-15 14:02:26 +02:00
|
|
|
}
|
2011-02-04 09:11:24 +01:00
|
|
|
|
2012-03-19 14:12:29 +01:00
|
|
|
void BreakHandler::handleAlienBreakpoint(const BreakpointResponse &response, DebuggerEngine *engine)
|
2011-06-24 14:17:16 +02:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoint b = findSimilarBreakpoint(response);
|
|
|
|
|
if (b) {
|
2012-03-19 14:12:29 +01:00
|
|
|
if (response.id.isMinor())
|
2015-01-10 01:07:01 +01:00
|
|
|
b.insertSubBreakpoint(response);
|
2012-03-19 14:12:29 +01:00
|
|
|
else
|
2015-01-10 01:07:01 +01:00
|
|
|
b.setResponse(response);
|
2011-06-24 14:17:16 +02:00
|
|
|
} else {
|
2015-01-10 01:07:01 +01:00
|
|
|
auto b = new BreakpointItem(this);
|
|
|
|
|
b->m_params = response;
|
|
|
|
|
b->m_response = response;
|
|
|
|
|
b->m_state = BreakpointInserted;
|
|
|
|
|
b->m_engine = engine;
|
2015-01-09 10:49:18 +01:00
|
|
|
b->updateMarker();
|
2015-01-14 09:09:15 +01:00
|
|
|
rootItem()->appendChild(b);
|
2011-06-24 14:17:16 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::insertSubBreakpoint(const BreakpointResponse ¶ms)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(b, return);
|
|
|
|
|
b->insertSubBreakpoint(params);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakpointItem::insertSubBreakpoint(const BreakpointResponse ¶ms)
|
2011-06-15 14:02:26 +02:00
|
|
|
{
|
2015-01-09 10:49:18 +01:00
|
|
|
QTC_ASSERT(params.id.isMinor(), return);
|
2011-06-24 14:17:16 +02:00
|
|
|
|
2015-01-09 10:49:18 +01:00
|
|
|
int minorPart = params.id.minorPart();
|
|
|
|
|
|
2016-06-10 17:03:21 +02:00
|
|
|
LocationItem *l = findFirstLevelChild([minorPart](LocationItem *l) {
|
|
|
|
|
return l->params.id.minorPart() == minorPart;
|
|
|
|
|
});
|
|
|
|
|
if (l) {
|
|
|
|
|
// This modifies an existing sub-breakpoint.
|
|
|
|
|
l->params = params;
|
|
|
|
|
l->update();
|
|
|
|
|
} else {
|
|
|
|
|
// This is a new sub-breakpoint.
|
|
|
|
|
l = new LocationItem;
|
|
|
|
|
l->params = params;
|
|
|
|
|
appendChild(l);
|
|
|
|
|
expand();
|
2011-06-21 16:45:23 +02:00
|
|
|
}
|
2010-06-25 16:06:48 +02:00
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void BreakHandler::saveSessionData()
|
|
|
|
|
{
|
|
|
|
|
saveBreakpoints();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::loadSessionData()
|
2010-11-25 16:32:07 +01:00
|
|
|
{
|
2015-04-22 14:49:14 +02:00
|
|
|
clear();
|
2013-05-07 15:29:53 +02:00
|
|
|
loadBreakpoints();
|
2010-11-25 16:32:07 +01:00
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void BreakHandler::breakByFunction(const QString &functionName)
|
|
|
|
|
{
|
2010-03-26 08:52:49 +01:00
|
|
|
// One breakpoint per function is enough for now. This does not handle
|
|
|
|
|
// combinations of multiple conditions and ignore counts, though.
|
2016-06-24 09:36:42 +02:00
|
|
|
bool found = findItemAtLevel<1>([functionName](BreakpointItem *b) {
|
2015-01-10 01:07:01 +01:00
|
|
|
const BreakpointParameters ¶ms = b->m_params;
|
2016-06-10 17:03:21 +02:00
|
|
|
return params.functionName == functionName
|
2015-01-09 10:49:18 +01:00
|
|
|
&& params.condition.isEmpty()
|
2016-06-10 17:03:21 +02:00
|
|
|
&& params.ignoreCount == 0;
|
|
|
|
|
});
|
|
|
|
|
if (found)
|
|
|
|
|
return;
|
|
|
|
|
|
2015-01-09 10:49:18 +01:00
|
|
|
BreakpointParameters params(BreakpointByFunction);
|
|
|
|
|
params.functionName = functionName;
|
|
|
|
|
appendBreakpoint(params);
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::scheduleSynchronization()
|
|
|
|
|
{
|
|
|
|
|
if (m_syncTimerId == -1)
|
|
|
|
|
m_syncTimerId = startTimer(10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::timerEvent(QTimerEvent *event)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(event->timerId() == m_syncTimerId, return);
|
|
|
|
|
killTimer(m_syncTimerId);
|
|
|
|
|
m_syncTimerId = -1;
|
|
|
|
|
saveBreakpoints(); // FIXME: remove?
|
2014-10-22 13:04:47 +02:00
|
|
|
Internal::synchronizeBreakpoints();
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::gotoLocation() const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
if (DebuggerEngine *engine = currentEngine()) {
|
2015-04-17 11:19:58 +02:00
|
|
|
if (b->m_params.type == BreakpointByAddress) {
|
2015-01-10 01:07:01 +01:00
|
|
|
engine->gotoLocation(b->m_params.address);
|
2015-04-17 11:19:58 +02:00
|
|
|
} else {
|
2015-05-18 11:09:17 +02:00
|
|
|
// Don't use gotoLocation unconditionally as this ends up in
|
|
|
|
|
// disassembly if OperateByInstruction is on. But fallback
|
|
|
|
|
// to disassembly if we can't open the file.
|
2015-04-17 11:19:58 +02:00
|
|
|
const QString file = QDir::cleanPath(b->markerFileName());
|
2015-05-18 11:09:17 +02:00
|
|
|
if (IEditor *editor = EditorManager::openEditor(file))
|
|
|
|
|
editor->gotoLine(b->markerLineNumber(), 0);
|
|
|
|
|
else
|
|
|
|
|
engine->openDisassemblerView(Location(b->m_response.address));
|
2015-04-17 11:19:58 +02:00
|
|
|
}
|
2010-11-24 11:44:43 +01:00
|
|
|
}
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void BreakpointItem::updateFileNameFromMarker(const QString &fileName)
|
2012-03-12 16:56:25 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
m_params.fileName = fileName;
|
|
|
|
|
update();
|
2012-03-12 16:56:25 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void BreakpointItem::updateLineNumberFromMarker(int lineNumber)
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
|
|
|
|
// Ignore updates to the "real" line number while the debugger is
|
|
|
|
|
// running, as this can be triggered by moving the breakpoint to
|
|
|
|
|
// the next line that generated code.
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.lineNumber == lineNumber)
|
2011-06-07 17:21:45 +02:00
|
|
|
; // Nothing
|
2015-01-10 01:07:01 +01:00
|
|
|
else if (isEngineRunning())
|
|
|
|
|
m_params.lineNumber += lineNumber - m_response.lineNumber;
|
2011-06-01 13:24:29 +02:00
|
|
|
else
|
2015-01-10 01:07:01 +01:00
|
|
|
m_params.lineNumber = lineNumber;
|
|
|
|
|
updateMarker();
|
|
|
|
|
update();
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void BreakpointItem::changeLineNumberFromMarker(int lineNumber)
|
2012-10-09 22:34:36 +02:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
m_params.lineNumber = lineNumber;
|
|
|
|
|
|
2012-10-09 22:34:36 +02:00
|
|
|
// We need to delay this as it is called from a marker which will be destroyed.
|
|
|
|
|
ExtensionSystem::InvokerBase invoker;
|
2015-01-10 01:07:01 +01:00
|
|
|
invoker.addArgument(m_id);
|
2012-10-09 22:34:36 +02:00
|
|
|
invoker.setConnectionType(Qt::QueuedConnection);
|
2015-01-10 01:07:01 +01:00
|
|
|
invoker.invoke(m_handler, "changeLineNumberFromMarkerHelper");
|
2012-10-09 22:34:36 +02:00
|
|
|
QTC_CHECK(invoker.wasSuccessful());
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void BreakHandler::changeLineNumberFromMarkerHelper(BreakpointModelId id)
|
2012-10-09 22:34:36 +02:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoint b = breakpointById(id);
|
|
|
|
|
QTC_ASSERT(b, return);
|
|
|
|
|
BreakpointParameters params = b.parameters();
|
2016-07-04 15:53:53 +02:00
|
|
|
destroyItem(b.b);
|
2015-01-09 10:49:18 +01:00
|
|
|
appendBreakpoint(params);
|
2012-10-09 22:34:36 +02:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoints BreakHandler::allBreakpoints() const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoints items;
|
2016-06-24 09:36:42 +02:00
|
|
|
forItemsAtLevel<1>([&items](BreakpointItem *b) { items.append(Breakpoint(b)); });
|
2015-01-10 01:07:01 +01:00
|
|
|
return items;
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoints BreakHandler::unclaimedBreakpoints() const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
return engineBreakpoints(0);
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoints BreakHandler::engineBreakpoints(DebuggerEngine *engine) const
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
Breakpoints items;
|
2016-06-24 09:36:42 +02:00
|
|
|
forItemsAtLevel<1>([&items, engine](BreakpointItem *b) {
|
2015-01-10 01:07:01 +01:00
|
|
|
if (b->m_engine == engine)
|
|
|
|
|
items.append(Breakpoint(b));
|
2016-06-10 17:03:21 +02:00
|
|
|
});
|
2015-01-10 01:07:01 +01:00
|
|
|
return items;
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
|
|
|
|
|
2011-09-29 14:46:59 +02:00
|
|
|
QStringList BreakHandler::engineBreakpointPaths(DebuggerEngine *engine) const
|
|
|
|
|
{
|
|
|
|
|
QSet<QString> set;
|
2016-06-24 09:36:42 +02:00
|
|
|
forItemsAtLevel<1>([&set, engine](BreakpointItem *b) {
|
2015-01-10 01:07:01 +01:00
|
|
|
if (b->m_engine == engine) {
|
|
|
|
|
if (b->m_params.type == BreakpointByFileAndLine)
|
|
|
|
|
set.insert(QFileInfo(b->m_params.fileName).dir().path());
|
2011-09-29 14:46:59 +02:00
|
|
|
}
|
2016-06-10 17:03:21 +02:00
|
|
|
});
|
2011-09-29 14:46:59 +02:00
|
|
|
return set.toList();
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void Breakpoint::setResponse(const BreakpointResponse &response)
|
2010-11-10 16:33:11 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
QTC_ASSERT(b, return);
|
|
|
|
|
b->m_response = response;
|
2015-01-09 10:49:18 +01:00
|
|
|
b->destroyMarker();
|
|
|
|
|
b->updateMarker();
|
2011-03-04 19:26:11 +01:00
|
|
|
// Take over corrected values from response.
|
2015-01-10 01:07:01 +01:00
|
|
|
if ((b->m_params.type == BreakpointByFileAndLine
|
|
|
|
|
|| b->m_params.type == BreakpointByFunction)
|
2011-05-11 15:24:50 +02:00
|
|
|
&& !response.module.isEmpty())
|
2015-01-10 01:07:01 +01:00
|
|
|
b->m_params.module = response.module;
|
2010-11-10 16:33:11 +01:00
|
|
|
}
|
2010-11-04 09:54:23 +01:00
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
bool Internal::Breakpoint::needsChange() const
|
2010-11-16 10:50:11 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
return b && b->needsChange();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Breakpoint::changeBreakpointData(const BreakpointParameters ¶ms)
|
|
|
|
|
{
|
|
|
|
|
if (!b)
|
2010-11-16 10:50:11 +01:00
|
|
|
return;
|
2015-01-10 01:07:01 +01:00
|
|
|
if (params == b->m_params)
|
|
|
|
|
return;
|
|
|
|
|
b->m_params = params;
|
2015-08-31 16:35:24 +02:00
|
|
|
if (b->m_engine)
|
|
|
|
|
b->m_engine->updateBreakpointMarker(*this);
|
2015-01-09 10:49:18 +01:00
|
|
|
b->destroyMarker();
|
|
|
|
|
b->updateMarker();
|
2015-01-10 01:07:01 +01:00
|
|
|
b->update();
|
|
|
|
|
if (b->needsChange() && b->m_engine && b->m_state != BreakpointNew) {
|
|
|
|
|
b->setState(BreakpointChangeRequested);
|
|
|
|
|
b->m_handler->scheduleSynchronization();
|
2010-11-30 12:47:53 +01:00
|
|
|
}
|
2010-11-16 10:50:11 +01:00
|
|
|
}
|
2010-11-15 19:05:31 +01:00
|
|
|
|
2016-07-18 12:36:31 +02:00
|
|
|
bool BreakHandler::setData(const QModelIndex &idx, const QVariant &value, int role)
|
|
|
|
|
{
|
|
|
|
|
if (role == BaseTreeView::ItemActivatedRole) {
|
|
|
|
|
if (Breakpoint bp = findBreakpointByIndex(idx))
|
|
|
|
|
bp.gotoLocation();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (role == BaseTreeView::ItemViewEventRole) {
|
|
|
|
|
ItemViewEvent ev = value.value<ItemViewEvent>();
|
|
|
|
|
|
|
|
|
|
if (ev.as<QContextMenuEvent>())
|
|
|
|
|
return contextMenuEvent(ev);
|
|
|
|
|
|
|
|
|
|
if (auto kev = ev.as<QKeyEvent>(QEvent::KeyPress)) {
|
|
|
|
|
if (kev->key() == Qt::Key_Delete) {
|
|
|
|
|
QModelIndexList si = ev.currentOrSelectedRows();
|
|
|
|
|
const Breakpoints ids = findBreakpointsByIndex(si);
|
|
|
|
|
// int row = qMin(rowCount() - ids.size() - 1, idx.row());
|
|
|
|
|
deleteBreakpoints(ids);
|
|
|
|
|
// setCurrentIndex(index(row, 0)); FIXME
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (kev->key() == Qt::Key_Space) {
|
|
|
|
|
const QModelIndexList selectedIds = ev.selectedRows();
|
|
|
|
|
if (!selectedIds.isEmpty()) {
|
|
|
|
|
const Breakpoints items = findBreakpointsByIndex(selectedIds);
|
|
|
|
|
const bool isEnabled = items.isEmpty() || items.at(0).isEnabled();
|
|
|
|
|
setBreakpointsEnabled(items, !isEnabled);
|
|
|
|
|
// FIXME
|
|
|
|
|
// foreach (const QModelIndex &id, selectedIds)
|
|
|
|
|
// update(id);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ev.as<QMouseEvent>(QEvent::MouseButtonDblClick)) {
|
|
|
|
|
if (Breakpoint b = findBreakpointByIndex(idx)) {
|
|
|
|
|
if (idx.column() >= BreakpointAddressColumn)
|
|
|
|
|
editBreakpoints({ b }, ev.view());
|
2016-09-14 14:28:53 +02:00
|
|
|
else
|
|
|
|
|
b.gotoLocation();
|
2016-07-18 12:36:31 +02:00
|
|
|
} else {
|
|
|
|
|
addBreakpoint();
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BreakHandler::contextMenuEvent(const ItemViewEvent &ev)
|
|
|
|
|
{
|
|
|
|
|
const QModelIndexList selectedIndices = ev.selectedRows();
|
|
|
|
|
const Breakpoints selectedItems = findBreakpointsByIndex(selectedIndices);
|
|
|
|
|
const bool enabled = selectedItems.isEmpty() || selectedItems.at(0).isEnabled();
|
|
|
|
|
|
|
|
|
|
auto menu = new QMenu;
|
|
|
|
|
|
|
|
|
|
addAction(menu, tr("Add Breakpoint..."), true, [this] { addBreakpoint(); });
|
|
|
|
|
|
|
|
|
|
addAction(menu, tr("Delete Selected Breakpoints"),
|
|
|
|
|
!selectedItems.isEmpty(),
|
|
|
|
|
[this, selectedItems] { deleteBreakpoints(selectedItems); });
|
|
|
|
|
|
|
|
|
|
addAction(menu, tr("Edit Selected Breakpoints..."),
|
|
|
|
|
!selectedItems.isEmpty(),
|
|
|
|
|
[this, selectedItems, ev] { editBreakpoints(selectedItems, ev.view()); });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// FIXME BP: m_engine->threadsHandler()->currentThreadId();
|
|
|
|
|
int threadId = 0;
|
|
|
|
|
addAction(menu,
|
|
|
|
|
threadId == -1 ? tr("Associate Breakpoint With All Threads")
|
|
|
|
|
: tr("Associate Breakpoint With Thread %1").arg(threadId),
|
|
|
|
|
!selectedItems.isEmpty(),
|
|
|
|
|
[this, selectedItems, threadId] {
|
|
|
|
|
for (Breakpoint bp : selectedItems)
|
|
|
|
|
bp.setThreadSpec(threadId);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
addAction(menu,
|
|
|
|
|
selectedItems.size() > 1
|
|
|
|
|
? enabled ? tr("Disable Selected Breakpoints") : tr("Enable Selected Breakpoints")
|
|
|
|
|
: enabled ? tr("Disable Breakpoint") : tr("Enable Breakpoint"),
|
|
|
|
|
!selectedItems.isEmpty(),
|
|
|
|
|
[this, selectedItems, enabled] { setBreakpointsEnabled(selectedItems, !enabled); });
|
|
|
|
|
|
|
|
|
|
menu->addSeparator();
|
|
|
|
|
|
|
|
|
|
addAction(menu, tr("Delete All Breakpoints"),
|
|
|
|
|
rowCount() > 0,
|
|
|
|
|
[this] { deleteAllBreakpoints(); });
|
|
|
|
|
|
|
|
|
|
// Delete by file: Find indices of breakpoints of the same file.
|
2016-06-24 09:36:42 +02:00
|
|
|
BreakpointItem *item = itemForIndexAtLevel<1>(ev.index());
|
2016-07-18 12:36:31 +02:00
|
|
|
Breakpoints breakpointsInFile;
|
|
|
|
|
QString file;
|
|
|
|
|
if (item) {
|
|
|
|
|
const QModelIndex index = ev.index().sibling(ev.index().row(), BreakpointFileColumn);
|
|
|
|
|
if (!file.isEmpty()) {
|
|
|
|
|
for (int i = 0; i != rowCount(); ++i)
|
|
|
|
|
if (index.data().toString() == file)
|
|
|
|
|
breakpointsInFile.append(findBreakpointByIndex(index));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
addAction(menu, tr("Delete Breakpoints of \"%1\"").arg(file),
|
|
|
|
|
tr("Delete Breakpoints of File"),
|
|
|
|
|
breakpointsInFile.size() > 1,
|
|
|
|
|
[this, breakpointsInFile] { deleteBreakpoints(breakpointsInFile); });
|
|
|
|
|
|
|
|
|
|
menu->addSeparator();
|
|
|
|
|
|
|
|
|
|
addAction(menu, tr("Synchronize Breakpoints"),
|
|
|
|
|
Internal::hasSnapshots(),
|
|
|
|
|
[this] { Internal::synchronizeBreakpoints(); });
|
|
|
|
|
|
|
|
|
|
menu->addSeparator();
|
|
|
|
|
menu->addAction(action(UseToolTipsInBreakpointsView));
|
|
|
|
|
if (currentEngine()->hasCapability(MemoryAddressCapability))
|
|
|
|
|
menu->addAction(action(UseAddressInBreakpointsView));
|
|
|
|
|
menu->addSeparator();
|
|
|
|
|
menu->addAction(action(SettingsDialog));
|
|
|
|
|
|
|
|
|
|
menu->popup(ev.globalPos());
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::setBreakpointsEnabled(const Breakpoints &bps, bool enabled)
|
|
|
|
|
{
|
|
|
|
|
foreach (Breakpoint b, bps)
|
|
|
|
|
b.setEnabled(enabled);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::deleteAllBreakpoints()
|
|
|
|
|
{
|
|
|
|
|
QDialogButtonBox::StandardButton pressed =
|
|
|
|
|
CheckableMessageBox::doNotAskAgainQuestion(ICore::dialogParent(),
|
|
|
|
|
tr("Remove All Breakpoints"),
|
|
|
|
|
tr("Are you sure you want to remove all breakpoints "
|
|
|
|
|
"from all files in the current session?"),
|
|
|
|
|
ICore::settings(),
|
|
|
|
|
"RemoveAllBreakpoints");
|
|
|
|
|
if (pressed == QDialogButtonBox::Yes)
|
|
|
|
|
deleteBreakpoints(breakHandler()->allBreakpoints());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::deleteBreakpoints(const Breakpoints &bps)
|
|
|
|
|
{
|
|
|
|
|
foreach (Breakpoint bp, bps)
|
|
|
|
|
bp.removeBreakpoint();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::editBreakpoint(Breakpoint bp, QWidget *parent)
|
|
|
|
|
{
|
|
|
|
|
BreakpointParameters data = bp.parameters();
|
|
|
|
|
BreakpointParts parts = NoParts;
|
|
|
|
|
|
|
|
|
|
BreakpointDialog dialog(bp, parent);
|
|
|
|
|
if (!dialog.showDialog(&data, &parts))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
bp.changeBreakpointData(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::addBreakpoint()
|
|
|
|
|
{
|
|
|
|
|
BreakpointParameters data(BreakpointByFileAndLine);
|
|
|
|
|
BreakpointParts parts = NoParts;
|
|
|
|
|
BreakpointDialog dialog(Breakpoint(), ICore::dialogParent());
|
|
|
|
|
dialog.setWindowTitle(tr("Add Breakpoint"));
|
|
|
|
|
if (dialog.showDialog(&data, &parts))
|
|
|
|
|
appendBreakpoint(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::editBreakpoints(const Breakpoints &bps, QWidget *parent)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(!bps.isEmpty(), return);
|
|
|
|
|
|
|
|
|
|
const Breakpoint bp = bps.at(0);
|
|
|
|
|
|
|
|
|
|
if (bps.size() == 1) {
|
|
|
|
|
editBreakpoint(bp, parent);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This allows to change properties of multiple breakpoints at a time.
|
|
|
|
|
if (!bp)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
MultiBreakPointsDialog dialog;
|
|
|
|
|
dialog.setCondition(bp.condition());
|
|
|
|
|
dialog.setIgnoreCount(bp.ignoreCount());
|
|
|
|
|
dialog.setThreadSpec(bp.threadSpec());
|
|
|
|
|
|
|
|
|
|
if (dialog.exec() == QDialog::Rejected)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const QString newCondition = dialog.condition();
|
|
|
|
|
const int newIgnoreCount = dialog.ignoreCount();
|
|
|
|
|
const int newThreadSpec = dialog.threadSpec();
|
|
|
|
|
|
|
|
|
|
foreach (Breakpoint bp, bps) {
|
|
|
|
|
if (bp) {
|
|
|
|
|
bp.setCondition(newCondition);
|
|
|
|
|
bp.setIgnoreCount(newIgnoreCount);
|
|
|
|
|
bp.setThreadSpec(newThreadSpec);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-15 19:05:31 +01:00
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// Storage
|
|
|
|
|
//
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
// Ok to be not thread-safe. The order does not matter and only the gui
|
|
|
|
|
// produces authoritative ids.
|
|
|
|
|
static int currentId = 0;
|
|
|
|
|
|
|
|
|
|
BreakpointItem::BreakpointItem(BreakHandler *handler)
|
|
|
|
|
: m_handler(handler), m_id(++currentId), m_state(BreakpointNew), m_engine(0), m_marker(0)
|
2010-11-15 19:05:31 +01:00
|
|
|
{}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
BreakpointItem::~BreakpointItem()
|
2015-01-09 10:49:18 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
delete m_marker;
|
2015-01-09 10:49:18 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void BreakpointItem::destroyMarker()
|
2010-11-15 13:12:13 +01:00
|
|
|
{
|
2015-05-21 13:17:23 +02:00
|
|
|
if (m_marker) {
|
|
|
|
|
BreakpointMarker *m = m_marker;
|
|
|
|
|
m->m_bp = 0;
|
|
|
|
|
m_marker = 0;
|
|
|
|
|
delete m;
|
|
|
|
|
}
|
2010-11-15 14:27:06 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
QString BreakpointItem::markerFileName() const
|
2010-11-18 13:38:58 +01:00
|
|
|
{
|
2010-11-18 16:00:56 +01:00
|
|
|
// Some heuristics to find a "good" file name.
|
2015-01-10 01:07:01 +01:00
|
|
|
if (!m_params.fileName.isEmpty()) {
|
|
|
|
|
QFileInfo fi(m_params.fileName);
|
2010-11-18 16:00:56 +01:00
|
|
|
if (fi.exists())
|
|
|
|
|
return fi.absoluteFilePath();
|
|
|
|
|
}
|
2015-01-10 01:07:01 +01:00
|
|
|
if (!m_response.fileName.isEmpty()) {
|
|
|
|
|
QFileInfo fi(m_response.fileName);
|
2010-11-18 16:00:56 +01:00
|
|
|
if (fi.exists())
|
|
|
|
|
return fi.absoluteFilePath();
|
|
|
|
|
}
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_response.fileName.endsWith(m_params.fileName))
|
|
|
|
|
return m_response.fileName;
|
|
|
|
|
if (m_params.fileName.endsWith(m_response.fileName))
|
|
|
|
|
return m_params.fileName;
|
|
|
|
|
return m_response.fileName.size() > m_params.fileName.size()
|
|
|
|
|
? m_response.fileName : m_params.fileName;
|
2010-11-18 13:38:58 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
int BreakpointItem::markerLineNumber() const
|
2010-11-18 13:38:58 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
return m_response.lineNumber ? m_response.lineNumber : m_params.lineNumber;
|
2010-11-18 13:38:58 +01:00
|
|
|
}
|
|
|
|
|
|
2010-11-15 14:27:06 +01:00
|
|
|
static void formatAddress(QTextStream &str, quint64 address)
|
|
|
|
|
{
|
|
|
|
|
if (address) {
|
|
|
|
|
str << "0x";
|
|
|
|
|
str.setIntegerBase(16);
|
|
|
|
|
str << address;
|
|
|
|
|
str.setIntegerBase(10);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
bool BreakpointItem::needsChange() const
|
2010-11-16 18:14:00 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
if (!m_params.conditionsMatch(m_response.condition))
|
2010-11-16 18:14:00 +01:00
|
|
|
return true;
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.ignoreCount != m_response.ignoreCount)
|
2010-11-16 18:14:00 +01:00
|
|
|
return true;
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.enabled != m_response.enabled)
|
2010-11-16 18:14:00 +01:00
|
|
|
return true;
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.threadSpec != m_response.threadSpec)
|
2010-11-30 12:47:53 +01:00
|
|
|
return true;
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.command != m_response.command)
|
2011-02-04 11:33:45 +01:00
|
|
|
return true;
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.type == BreakpointByFileAndLine && m_params.lineNumber != m_response.lineNumber)
|
2011-11-04 14:03:48 +01:00
|
|
|
return true;
|
2013-01-31 11:39:11 +01:00
|
|
|
// FIXME: Too strict, functions may have parameter lists, or not.
|
2015-01-10 01:07:01 +01:00
|
|
|
// if (m_params.type == BreakpointByFunction && m_params.functionName != m_response.functionName)
|
2013-01-31 11:39:11 +01:00
|
|
|
// return true;
|
2015-01-10 01:07:01 +01:00
|
|
|
// if (m_params.type == BreakpointByAddress && m_params.address != m_response.address)
|
2013-01-31 11:39:11 +01:00
|
|
|
// return true;
|
2010-11-16 18:14:00 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
bool BreakpointItem::isLocatedAt
|
2010-11-15 19:05:31 +01:00
|
|
|
(const QString &fileName, int lineNumber, bool useMarkerPosition) const
|
|
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
int line = useMarkerPosition ? m_response.lineNumber : m_params.lineNumber;
|
2010-11-18 16:31:18 +01:00
|
|
|
return lineNumber == line
|
2015-01-10 01:07:01 +01:00
|
|
|
&& (fileNameMatch(fileName, m_response.fileName)
|
2010-11-18 16:31:18 +01:00
|
|
|
|| fileNameMatch(fileName, markerFileName()));
|
2010-11-15 19:05:31 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void BreakpointItem::updateMarkerIcon()
|
2012-03-08 14:00:26 +01:00
|
|
|
{
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_marker) {
|
|
|
|
|
m_marker->setIcon(icon());
|
|
|
|
|
m_marker->updateMarker();
|
2012-04-26 19:21:28 +02:00
|
|
|
}
|
2012-03-08 14:00:26 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
void BreakpointItem::updateMarker()
|
2011-06-24 19:44:49 +02:00
|
|
|
{
|
|
|
|
|
QString file = markerFileName();
|
|
|
|
|
int line = markerLineNumber();
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_marker && (file != m_marker->fileName() || line != m_marker->lineNumber()))
|
2011-06-24 19:44:49 +02:00
|
|
|
destroyMarker();
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
if (!m_marker && !file.isEmpty() && line > 0)
|
|
|
|
|
m_marker = new BreakpointMarker(this, file, line);
|
2016-08-31 15:42:29 +02:00
|
|
|
|
|
|
|
|
if (m_marker) {
|
|
|
|
|
QString toolTip;
|
|
|
|
|
auto addToToolTipText = [&toolTip](const QString &info, const QString &label) {
|
|
|
|
|
if (info.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
if (!toolTip.isEmpty())
|
|
|
|
|
toolTip += ' ';
|
|
|
|
|
toolTip += label + ": '" + info + '\'';
|
|
|
|
|
};
|
|
|
|
|
addToToolTipText(m_params.condition, tr("Breakpoint Condition"));
|
|
|
|
|
addToToolTipText(m_params.command, tr("Debugger Command"));
|
|
|
|
|
m_marker->setToolTip(toolTip);
|
|
|
|
|
}
|
2011-06-24 19:44:49 +02:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
QIcon BreakpointItem::icon() const
|
2010-11-18 14:57:00 +01:00
|
|
|
{
|
|
|
|
|
// FIXME: This seems to be called on each cursor blink as soon as the
|
|
|
|
|
// cursor is near a line with a breakpoint marker (+/- 2 lines or so).
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.isTracepoint())
|
2016-06-27 14:38:36 +02:00
|
|
|
return Icons::TRACEPOINT.icon();
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.type == WatchpointAtAddress)
|
2016-06-27 14:38:36 +02:00
|
|
|
return Icons::WATCHPOINT.icon();
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.type == WatchpointAtExpression)
|
2016-06-27 14:38:36 +02:00
|
|
|
return Icons::WATCHPOINT.icon();
|
2015-01-10 01:07:01 +01:00
|
|
|
if (!m_params.enabled)
|
2016-06-27 14:38:36 +02:00
|
|
|
return Icons::BREAKPOINT_DISABLED.icon();
|
2015-08-12 13:49:35 +02:00
|
|
|
if (m_state == BreakpointInserted && !m_response.pending)
|
2016-06-27 14:38:36 +02:00
|
|
|
return Icons::BREAKPOINT.icon();
|
|
|
|
|
return Icons::BREAKPOINT_PENDING.icon();
|
2010-11-18 14:57:00 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
QString BreakpointItem::toToolTip() const
|
2010-11-15 14:27:06 +01:00
|
|
|
{
|
|
|
|
|
QString rc;
|
|
|
|
|
QTextStream str(&rc);
|
|
|
|
|
str << "<html><body><table>"
|
2011-09-26 16:48:54 +02:00
|
|
|
//<< "<tr><td>" << tr("ID:") << "</td><td>" << m_id << "</td></tr>"
|
2010-11-15 14:27:06 +01:00
|
|
|
<< "<tr><td>" << tr("State:")
|
2015-01-10 01:07:01 +01:00
|
|
|
<< "</td><td>" << (m_params.enabled ? tr("Enabled") : tr("Disabled"));
|
|
|
|
|
if (m_response.pending)
|
2011-02-03 16:26:23 +01:00
|
|
|
str << tr(", pending");
|
2015-01-10 01:07:01 +01:00
|
|
|
str << ", " << m_state << " (" << stateToString(m_state) << ")</td></tr>";
|
|
|
|
|
if (m_engine) {
|
2011-02-03 16:26:23 +01:00
|
|
|
str << "<tr><td>" << tr("Engine:")
|
2015-01-10 01:07:01 +01:00
|
|
|
<< "</td><td>" << m_engine->objectName() << "</td></tr>";
|
2011-02-03 16:26:23 +01:00
|
|
|
}
|
2015-01-10 01:07:01 +01:00
|
|
|
if (!m_response.pending) {
|
2011-02-03 16:26:23 +01:00
|
|
|
str << "<tr><td>" << tr("Breakpoint Number:")
|
2015-01-10 01:07:01 +01:00
|
|
|
<< "</td><td>" << m_response.id.toString() << "</td></tr>";
|
2011-02-03 16:26:23 +01:00
|
|
|
}
|
|
|
|
|
str << "<tr><td>" << tr("Breakpoint Type:")
|
2015-01-10 01:07:01 +01:00
|
|
|
<< "</td><td>" << typeToString(m_params.type) << "</td></tr>"
|
2011-06-24 16:25:30 +02:00
|
|
|
<< "<tr><td>" << tr("Marker File:")
|
2011-02-03 16:26:23 +01:00
|
|
|
<< "</td><td>" << QDir::toNativeSeparators(markerFileName()) << "</td></tr>"
|
2010-11-18 16:00:56 +01:00
|
|
|
<< "<tr><td>" << tr("Marker Line:")
|
|
|
|
|
<< "</td><td>" << markerLineNumber() << "</td></tr>"
|
2015-10-14 13:26:22 +02:00
|
|
|
<< "<tr><td>" << tr("Hit Count:")
|
|
|
|
|
<< "</td><td>" << m_response.hitCount << "</td></tr>"
|
2010-11-15 14:27:06 +01:00
|
|
|
<< "</table><br><hr><table>"
|
|
|
|
|
<< "<tr><th>" << tr("Property")
|
|
|
|
|
<< "</th><th>" << tr("Requested")
|
|
|
|
|
<< "</th><th>" << tr("Obtained") << "</th></tr>"
|
|
|
|
|
<< "<tr><td>" << tr("Internal Number:")
|
2015-01-10 01:07:01 +01:00
|
|
|
<< "</td><td>—</td><td>" << m_response.id.toString() << "</td></tr>";
|
|
|
|
|
if (m_params.type == BreakpointByFunction) {
|
2011-02-02 14:41:14 +01:00
|
|
|
str << "<tr><td>" << tr("Function Name:")
|
2015-01-10 01:07:01 +01:00
|
|
|
<< "</td><td>" << m_params.functionName
|
|
|
|
|
<< "</td><td>" << m_response.functionName
|
2011-02-02 14:41:14 +01:00
|
|
|
<< "</td></tr>";
|
|
|
|
|
}
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.type == BreakpointByFileAndLine) {
|
2011-02-02 14:41:14 +01:00
|
|
|
str << "<tr><td>" << tr("File Name:")
|
2015-01-10 01:07:01 +01:00
|
|
|
<< "</td><td>" << QDir::toNativeSeparators(m_params.fileName)
|
|
|
|
|
<< "</td><td>" << QDir::toNativeSeparators(m_response.fileName)
|
2010-11-15 14:27:06 +01:00
|
|
|
<< "</td></tr>"
|
2010-11-18 13:38:58 +01:00
|
|
|
<< "<tr><td>" << tr("Line Number:")
|
2015-01-10 01:07:01 +01:00
|
|
|
<< "</td><td>" << m_params.lineNumber
|
|
|
|
|
<< "</td><td>" << m_response.lineNumber << "</td></tr>"
|
2011-01-05 19:30:24 +01:00
|
|
|
<< "<tr><td>" << tr("Corrected Line Number:")
|
|
|
|
|
<< "</td><td>-"
|
2015-01-10 01:07:01 +01:00
|
|
|
<< "</td><td>" << m_response.correctedLineNumber << "</td></tr>";
|
2011-02-02 14:41:14 +01:00
|
|
|
}
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.type == BreakpointByFunction || m_params.type == BreakpointByFileAndLine) {
|
2011-02-02 14:41:14 +01:00
|
|
|
str << "<tr><td>" << tr("Module:")
|
2015-01-10 01:07:01 +01:00
|
|
|
<< "</td><td>" << m_params.module
|
|
|
|
|
<< "</td><td>" << m_response.module
|
2011-02-02 14:41:14 +01:00
|
|
|
<< "</td></tr>";
|
|
|
|
|
}
|
|
|
|
|
str << "<tr><td>" << tr("Breakpoint Address:")
|
2010-11-15 14:27:06 +01:00
|
|
|
<< "</td><td>";
|
2015-01-10 01:07:01 +01:00
|
|
|
formatAddress(str, m_params.address);
|
2010-11-15 14:27:06 +01:00
|
|
|
str << "</td><td>";
|
2015-01-10 01:07:01 +01:00
|
|
|
formatAddress(str, m_response.address);
|
2011-03-02 13:37:29 +01:00
|
|
|
str << "</td></tr>";
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_response.multiple) {
|
2011-03-02 13:37:29 +01:00
|
|
|
str << "<tr><td>" << tr("Multiple Addresses:")
|
2011-06-21 16:45:23 +02:00
|
|
|
<< "</td><td>"
|
|
|
|
|
<< "</td></tr>";
|
2011-03-02 13:37:29 +01:00
|
|
|
}
|
2015-01-10 01:07:01 +01:00
|
|
|
if (!m_params.command.isEmpty() || !m_response.command.isEmpty()) {
|
2011-03-02 13:37:29 +01:00
|
|
|
str << "<tr><td>" << tr("Command:")
|
2015-01-10 01:07:01 +01:00
|
|
|
<< "</td><td>" << m_params.command
|
|
|
|
|
<< "</td><td>" << m_response.command
|
2011-03-02 13:37:29 +01:00
|
|
|
<< "</td></tr>";
|
2011-02-04 11:33:45 +01:00
|
|
|
}
|
2015-01-10 01:07:01 +01:00
|
|
|
if (!m_params.message.isEmpty() || !m_response.message.isEmpty()) {
|
2011-06-27 10:37:57 +02:00
|
|
|
str << "<tr><td>" << tr("Message:")
|
2015-01-10 01:07:01 +01:00
|
|
|
<< "</td><td>" << m_params.message
|
|
|
|
|
<< "</td><td>" << m_response.message
|
2011-06-27 10:37:57 +02:00
|
|
|
<< "</td></tr>";
|
|
|
|
|
}
|
2015-01-10 01:07:01 +01:00
|
|
|
if (!m_params.condition.isEmpty() || !m_response.condition.isEmpty()) {
|
2011-03-02 13:37:29 +01:00
|
|
|
str << "<tr><td>" << tr("Condition:")
|
2015-01-10 01:07:01 +01:00
|
|
|
<< "</td><td>" << m_params.condition
|
|
|
|
|
<< "</td><td>" << m_response.condition
|
2011-03-02 13:37:29 +01:00
|
|
|
<< "</td></tr>";
|
2011-02-03 16:26:23 +01:00
|
|
|
}
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.ignoreCount || m_response.ignoreCount) {
|
2011-02-03 16:26:23 +01:00
|
|
|
str << "<tr><td>" << tr("Ignore Count:") << "</td><td>";
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.ignoreCount)
|
|
|
|
|
str << m_params.ignoreCount;
|
2011-02-03 16:26:23 +01:00
|
|
|
str << "</td><td>";
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_response.ignoreCount)
|
|
|
|
|
str << m_response.ignoreCount;
|
2011-03-02 13:37:29 +01:00
|
|
|
str << "</td></tr>";
|
2011-02-03 16:26:23 +01:00
|
|
|
}
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.threadSpec >= 0 || m_response.threadSpec >= 0) {
|
2011-03-02 13:37:29 +01:00
|
|
|
str << "<tr><td>" << tr("Thread Specification:")
|
2011-02-03 16:26:23 +01:00
|
|
|
<< "</td><td>";
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_params.threadSpec >= 0)
|
|
|
|
|
str << m_params.threadSpec;
|
2011-02-03 16:26:23 +01:00
|
|
|
str << "</td><td>";
|
2015-01-10 01:07:01 +01:00
|
|
|
if (m_response.threadSpec >= 0)
|
|
|
|
|
str << m_response.threadSpec;
|
2011-02-03 16:26:23 +01:00
|
|
|
str << "</td></tr>";
|
|
|
|
|
}
|
|
|
|
|
str << "</table></body></html>";
|
2010-11-15 14:27:06 +01:00
|
|
|
return rc;
|
2010-11-15 13:12:13 +01:00
|
|
|
}
|
|
|
|
|
|
2012-06-03 21:59:21 +02:00
|
|
|
void BreakHandler::setWatchpointAtAddress(quint64 address, unsigned size)
|
|
|
|
|
{
|
2015-01-09 10:49:18 +01:00
|
|
|
BreakpointParameters params(WatchpointAtAddress);
|
|
|
|
|
params.address = address;
|
|
|
|
|
params.size = size;
|
2015-01-10 01:07:01 +01:00
|
|
|
if (findWatchpoint(params)) {
|
2012-06-03 21:59:21 +02:00
|
|
|
qDebug() << "WATCHPOINT EXISTS";
|
|
|
|
|
// removeBreakpoint(index);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-01-09 10:49:18 +01:00
|
|
|
appendBreakpoint(params);
|
2012-06-03 21:59:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BreakHandler::setWatchpointAtExpression(const QString &exp)
|
|
|
|
|
{
|
2015-01-09 10:49:18 +01:00
|
|
|
BreakpointParameters params(WatchpointAtExpression);
|
|
|
|
|
params.expression = exp;
|
2015-01-10 01:07:01 +01:00
|
|
|
if (findWatchpoint(params)) {
|
2012-06-03 21:59:21 +02:00
|
|
|
qDebug() << "WATCHPOINT EXISTS";
|
|
|
|
|
// removeBreakpoint(index);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-01-09 10:49:18 +01:00
|
|
|
appendBreakpoint(params);
|
2012-06-03 21:59:21 +02:00
|
|
|
}
|
|
|
|
|
|
2015-01-10 01:07:01 +01:00
|
|
|
bool Breakpoint::isValid() const
|
|
|
|
|
{
|
|
|
|
|
return b && b->m_id.isValid();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint Breakpoint::hash() const
|
|
|
|
|
{
|
|
|
|
|
return b ? 0 : qHash(b->m_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BreakpointModelId Breakpoint::id() const
|
|
|
|
|
{
|
|
|
|
|
return b ? b->m_id : BreakpointModelId();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Breakpoint::msgWatchpointByExpressionTriggered(const int number, const QString &expr) const
|
|
|
|
|
{
|
|
|
|
|
return id()
|
|
|
|
|
? tr("Data breakpoint %1 (%2) at %3 triggered.")
|
|
|
|
|
.arg(id().toString()).arg(number).arg(expr)
|
|
|
|
|
: tr("Internal data breakpoint %1 at %2 triggered.")
|
|
|
|
|
.arg(number).arg(expr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Breakpoint::msgWatchpointByExpressionTriggered(const int number, const QString &expr,
|
|
|
|
|
const QString &threadId) const
|
|
|
|
|
{
|
|
|
|
|
return id()
|
|
|
|
|
? tr("Data breakpoint %1 (%2) at %3 in thread %4 triggered.")
|
|
|
|
|
.arg(id().toString()).arg(number).arg(expr).arg(threadId)
|
|
|
|
|
: tr("Internal data breakpoint %1 at %2 in thread %3 triggered.")
|
|
|
|
|
.arg(number).arg(expr).arg(threadId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Breakpoint::msgWatchpointByAddressTriggered(const int number, quint64 address) const
|
|
|
|
|
{
|
|
|
|
|
return id()
|
|
|
|
|
? tr("Data breakpoint %1 (%2) at 0x%3 triggered.")
|
|
|
|
|
.arg(id().toString()).arg(number).arg(address, 0, 16)
|
|
|
|
|
: tr("Internal data breakpoint %1 at 0x%2 triggered.")
|
|
|
|
|
.arg(number).arg(address, 0, 16);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Breakpoint::msgWatchpointByAddressTriggered(
|
|
|
|
|
const int number, quint64 address, const QString &threadId) const
|
|
|
|
|
{
|
|
|
|
|
return id()
|
|
|
|
|
? tr("Data breakpoint %1 (%2) at 0x%3 in thread %4 triggered.")
|
|
|
|
|
.arg(id().toString()).arg(number).arg(address, 0, 16).arg(threadId)
|
|
|
|
|
: tr("Internal data breakpoint %1 at 0x%2 in thread %3 triggered.")
|
|
|
|
|
.arg(id().toString()).arg(number).arg(address, 0, 16).arg(threadId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Breakpoint::msgBreakpointTriggered(const int number, const QString &threadId) const
|
|
|
|
|
{
|
|
|
|
|
return id()
|
|
|
|
|
? tr("Stopped at breakpoint %1 (%2) in thread %3.")
|
|
|
|
|
.arg(id().toString()).arg(number).arg(threadId)
|
|
|
|
|
: tr("Stopped at internal breakpoint %1 in thread %2.")
|
|
|
|
|
.arg(number).arg(threadId);
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-16 11:08:54 +02:00
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace Debugger
|