Initial import
13
src/plugins/debugger/Debugger.pluginspec
Normal file
@@ -0,0 +1,13 @@
|
||||
<plugin name="Debugger" version="0.9.1" compatVersion="0.9.1">
|
||||
<vendor>Nokia Corporation</vendor>
|
||||
<copyright>(C) 2008 Nokia Corporation</copyright>
|
||||
<license>Nokia Technology Preview License Agreement</license>
|
||||
<description>Debugger integration.</description>
|
||||
<url>http://www.trolltech.com/</url>
|
||||
<dependencyList>
|
||||
<dependency name="CppEditor" version="0.9.1"/><!-- Debugger plugin adds items to the editor's context menu -->
|
||||
<dependency name="ProjectExplorer" version="0.9.1"/>
|
||||
<dependency name="Core" version="0.9.1"/>
|
||||
<dependency name="Find" version="0.9.1"/>
|
||||
</dependencyList>
|
||||
</plugin>
|
||||
45
src/plugins/debugger/assert.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_QWB_ASSERT_H
|
||||
#define DEBUGGER_QWB_ASSERT_H
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
#define QWB_ASSERT(cond, action) \
|
||||
if(cond){}else{qDebug()<<"ASSERTION"<<#cond<<"FAILED"<<__FILE__<<__LINE__;action;}
|
||||
#else
|
||||
#define QWB_ASSERT(cond, action) \
|
||||
if(cond){}else{qDebug()<<"ASSERTION"<<#cond<<"FAILED";action;}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
344
src/plugins/debugger/attachexternaldialog.cpp
Normal file
@@ -0,0 +1,344 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "attachexternaldialog.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QPushButton>
|
||||
#include <QStandardItemModel>
|
||||
#include <QHeaderView>
|
||||
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
AttachExternalDialog::AttachExternalDialog(QWidget *parent, const QString &pid)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
|
||||
m_defaultPID = pid;
|
||||
m_model = new QStandardItemModel(this);
|
||||
|
||||
procView->setSortingEnabled(true);
|
||||
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
|
||||
connect(procView, SIGNAL(activated(const QModelIndex &)),
|
||||
this, SLOT(procSelected(const QModelIndex &)));
|
||||
|
||||
|
||||
pidLineEdit->setText(m_defaultPID);
|
||||
rebuildProcessList();
|
||||
}
|
||||
|
||||
static bool isProcessName(const QString &procname)
|
||||
{
|
||||
for (int i = 0; i != procname.size(); ++i)
|
||||
if (!procname.at(i).isDigit())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct ProcData {
|
||||
QString ppid;
|
||||
QString name;
|
||||
QString state;
|
||||
};
|
||||
|
||||
static void insertItem(QStandardItem *root, const QString &pid,
|
||||
const QMap<QString, ProcData> &procs, QMap<QString, QStandardItem *> &known)
|
||||
{
|
||||
//qDebug() << "HANDLING " << pid;
|
||||
QStandardItem *parent = 0;
|
||||
const ProcData &proc = procs[pid];
|
||||
if (1 || pid == "0") {
|
||||
parent = root;
|
||||
} else {
|
||||
if (!known.contains(proc.ppid))
|
||||
insertItem(root, proc.ppid, procs, known);
|
||||
parent = known[proc.ppid];
|
||||
}
|
||||
QList<QStandardItem *> row;
|
||||
row.append(new QStandardItem(pid));
|
||||
row.append(new QStandardItem(proc.name));
|
||||
//row.append(new QStandardItem(proc.ppid));
|
||||
row.append(new QStandardItem(proc.state));
|
||||
parent->appendRow(row);
|
||||
known[pid] = row[0];
|
||||
}
|
||||
|
||||
void AttachExternalDialog::rebuildProcessList()
|
||||
{
|
||||
QStringList procnames = QDir("/proc/").entryList();
|
||||
if (procnames.isEmpty()) {
|
||||
procView->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
typedef QMap<QString, ProcData> Procs;
|
||||
Procs procs;
|
||||
|
||||
foreach (const QString &procname, procnames) {
|
||||
if (!isProcessName(procname))
|
||||
continue;
|
||||
QString filename = "/proc/" + procname + "/stat";
|
||||
QFile file(filename);
|
||||
file.open(QIODevice::ReadOnly);
|
||||
QStringList data = QString::fromLocal8Bit(file.readAll()).split(' ');
|
||||
//qDebug() << filename << data;
|
||||
ProcData proc;
|
||||
proc.name = data.at(1);
|
||||
if (proc.name.startsWith('(') && proc.name.endsWith(')'))
|
||||
proc.name = proc.name.mid(1, proc.name.size() - 2);
|
||||
proc.state = data.at(2);
|
||||
proc.ppid = data.at(3);
|
||||
procs[procname] = proc;
|
||||
}
|
||||
|
||||
m_model->clear();
|
||||
QMap<QString, QStandardItem *> known;
|
||||
for (Procs::const_iterator it = procs.begin(); it != procs.end(); ++it)
|
||||
insertItem(m_model->invisibleRootItem(), it.key(), procs, known);
|
||||
m_model->setHeaderData(0, Qt::Horizontal, "Process ID", Qt::DisplayRole);
|
||||
m_model->setHeaderData(1, Qt::Horizontal, "Name", Qt::DisplayRole);
|
||||
//model->setHeaderData(2, Qt::Horizontal, "Parent", Qt::DisplayRole);
|
||||
m_model->setHeaderData(2, Qt::Horizontal, "State", Qt::DisplayRole);
|
||||
|
||||
procView->setModel(m_model);
|
||||
procView->expandAll();
|
||||
procView->resizeColumnToContents(0);
|
||||
procView->resizeColumnToContents(1);
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
|
||||
#include <windows.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <tchar.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Forward declarations:
|
||||
BOOL GetProcessList( );
|
||||
BOOL ListProcessModules( DWORD dwPID );
|
||||
BOOL ListProcessThreads( DWORD dwOwnerPID );
|
||||
void printError( TCHAR* msg );
|
||||
|
||||
BOOL GetProcessList( )
|
||||
{
|
||||
HANDLE hProcessSnap;
|
||||
HANDLE hProcess;
|
||||
PROCESSENTRY32 pe32;
|
||||
DWORD dwPriorityClass;
|
||||
|
||||
// Take a snapshot of all processes in the system.
|
||||
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
|
||||
if( hProcessSnap == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
printError( TEXT("CreateToolhelp32Snapshot (of processes)") );
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Set the size of the structure before using it.
|
||||
pe32.dwSize = sizeof( PROCESSENTRY32 );
|
||||
|
||||
// Retrieve information about the first process,
|
||||
// and exit if unsuccessful
|
||||
if( !Process32First( hProcessSnap, &pe32 ) )
|
||||
{
|
||||
printError( TEXT("Process32First") ); // show cause of failure
|
||||
CloseHandle( hProcessSnap ); // clean the snapshot object
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Now walk the snapshot of processes, and
|
||||
// display information about each process in turn
|
||||
do
|
||||
{
|
||||
printf( "\n\n=====================================================" );
|
||||
_tprintf( TEXT("\nPROCESS NAME: %s"), pe32.szExeFile );
|
||||
printf( "\n-----------------------------------------------------" );
|
||||
|
||||
// Retrieve the priority class.
|
||||
dwPriorityClass = 0;
|
||||
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
|
||||
if( hProcess == NULL )
|
||||
printError( TEXT("OpenProcess") );
|
||||
else
|
||||
{
|
||||
dwPriorityClass = GetPriorityClass( hProcess );
|
||||
if( !dwPriorityClass )
|
||||
printError( TEXT("GetPriorityClass") );
|
||||
CloseHandle( hProcess );
|
||||
}
|
||||
|
||||
printf( "\n Process ID = 0x%08X", pe32.th32ProcessID );
|
||||
printf( "\n Thread count = %d", pe32.cntThreads );
|
||||
printf( "\n Parent process ID = 0x%08X", pe32.th32ParentProcessID );
|
||||
printf( "\n Priority base = %d", pe32.pcPriClassBase );
|
||||
if( dwPriorityClass )
|
||||
printf( "\n Priority class = %d", dwPriorityClass );
|
||||
|
||||
// List the modules and threads associated with this process
|
||||
ListProcessModules( pe32.th32ProcessID );
|
||||
ListProcessThreads( pe32.th32ProcessID );
|
||||
|
||||
} while( Process32Next( hProcessSnap, &pe32 ) );
|
||||
|
||||
CloseHandle( hProcessSnap );
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
|
||||
BOOL ListProcessModules( DWORD dwPID )
|
||||
{
|
||||
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
|
||||
MODULEENTRY32 me32;
|
||||
|
||||
// Take a snapshot of all modules in the specified process.
|
||||
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
|
||||
if( hModuleSnap == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
printError( TEXT("CreateToolhelp32Snapshot (of modules)") );
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Set the size of the structure before using it.
|
||||
me32.dwSize = sizeof( MODULEENTRY32 );
|
||||
|
||||
// Retrieve information about the first module,
|
||||
// and exit if unsuccessful
|
||||
if( !Module32First( hModuleSnap, &me32 ) )
|
||||
{
|
||||
printError( TEXT("Module32First") ); // show cause of failure
|
||||
CloseHandle( hModuleSnap ); // clean the snapshot object
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Now walk the module list of the process,
|
||||
// and display information about each module
|
||||
do
|
||||
{
|
||||
_tprintf( TEXT("\n\n MODULE NAME: %s"), me32.szModule );
|
||||
_tprintf( TEXT("\n Executable = %s"), me32.szExePath );
|
||||
printf( "\n Process ID = 0x%08X", me32.th32ProcessID );
|
||||
printf( "\n Ref count (g) = 0x%04X", me32.GlblcntUsage );
|
||||
printf( "\n Ref count (p) = 0x%04X", me32.ProccntUsage );
|
||||
printf( "\n Base address = 0x%08X", (DWORD) me32.modBaseAddr );
|
||||
printf( "\n Base size = %d", me32.modBaseSize );
|
||||
|
||||
} while( Module32Next( hModuleSnap, &me32 ) );
|
||||
|
||||
CloseHandle( hModuleSnap );
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
BOOL ListProcessThreads( DWORD dwOwnerPID )
|
||||
{
|
||||
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
|
||||
THREADENTRY32 te32;
|
||||
|
||||
// Take a snapshot of all running threads
|
||||
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
|
||||
if( hThreadSnap == INVALID_HANDLE_VALUE )
|
||||
return( FALSE );
|
||||
|
||||
// Fill in the size of the structure before using it.
|
||||
te32.dwSize = sizeof(THREADENTRY32 );
|
||||
|
||||
// Retrieve information about the first thread,
|
||||
// and exit if unsuccessful
|
||||
if( !Thread32First( hThreadSnap, &te32 ) )
|
||||
{
|
||||
printError( TEXT("Thread32First") ); // show cause of failure
|
||||
CloseHandle( hThreadSnap ); // clean the snapshot object
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Now walk the thread list of the system,
|
||||
// and display information about each thread
|
||||
// associated with the specified process
|
||||
do
|
||||
{
|
||||
if( te32.th32OwnerProcessID == dwOwnerPID )
|
||||
{
|
||||
printf( "\n\n THREAD ID = 0x%08X", te32.th32ThreadID );
|
||||
printf( "\n Base priority = %d", te32.tpBasePri );
|
||||
printf( "\n Delta priority = %d", te32.tpDeltaPri );
|
||||
}
|
||||
} while( Thread32Next(hThreadSnap, &te32 ) );
|
||||
|
||||
CloseHandle( hThreadSnap );
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
void printError( TCHAR* msg )
|
||||
{
|
||||
DWORD eNum;
|
||||
TCHAR sysMsg[256];
|
||||
TCHAR* p;
|
||||
|
||||
eNum = GetLastError( );
|
||||
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, eNum,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
sysMsg, 256, NULL );
|
||||
|
||||
// Trim the end of the line and terminate it with a null
|
||||
p = sysMsg;
|
||||
while( ( *p > 31 ) || ( *p == 9 ) )
|
||||
++p;
|
||||
do { *p-- = 0; } while( ( p >= sysMsg ) &&
|
||||
( ( *p == '.' ) || ( *p < 33 ) ) );
|
||||
|
||||
// Display the message
|
||||
_tprintf( TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void AttachExternalDialog::procSelected(const QModelIndex &index0)
|
||||
{
|
||||
QModelIndex index = index0.sibling(index0.row(), 0);
|
||||
QStandardItem *item = m_model->itemFromIndex(index);
|
||||
if (!item)
|
||||
return;
|
||||
pidLineEdit->setText(item->text());
|
||||
accept();
|
||||
}
|
||||
|
||||
int AttachExternalDialog::attachPID() const
|
||||
{
|
||||
return pidLineEdit->text().toInt();
|
||||
}
|
||||
65
src/plugins/debugger/attachexternaldialog.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef ATTACHEXTERNALDIALOG_H
|
||||
#define ATTACHEXTERNALDIALOG_H
|
||||
|
||||
#include "ui_attachexternaldialog.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QStandardItemModel;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class AttachExternalDialog : public QDialog, Ui::AttachExternalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AttachExternalDialog(QWidget *parent, const QString &pid);
|
||||
int attachPID() const;
|
||||
|
||||
private slots:
|
||||
void rebuildProcessList();
|
||||
void procSelected(const QModelIndex &);
|
||||
|
||||
private:
|
||||
QString m_defaultPID;
|
||||
QStandardItemModel *m_model;
|
||||
};
|
||||
|
||||
} // namespace Debugger
|
||||
} // namespace Internal
|
||||
|
||||
#endif // ATTACHEEXTERNALDIALOG_H
|
||||
64
src/plugins/debugger/attachexternaldialog.ui
Normal file
@@ -0,0 +1,64 @@
|
||||
<ui version="4.0" >
|
||||
<class>AttachExternalDialog</class>
|
||||
<widget class="QDialog" name="AttachExternalDialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>561</width>
|
||||
<height>866</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Start Debugger</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="pidLabel" >
|
||||
<property name="text" >
|
||||
<string>Attach to Process ID:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="pidLineEdit" />
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="procView" >
|
||||
<property name="editTriggers" >
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
344
src/plugins/debugger/attachremotedialog.cpp
Normal file
@@ -0,0 +1,344 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "attachremotedialog.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QPushButton>
|
||||
#include <QStandardItemModel>
|
||||
#include <QHeaderView>
|
||||
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
AttachRemoteDialog::AttachRemoteDialog(QWidget *parent, const QString &pid)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
|
||||
m_defaultPID = pid;
|
||||
m_model = new QStandardItemModel(this);
|
||||
|
||||
procView->setSortingEnabled(true);
|
||||
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
|
||||
connect(procView, SIGNAL(activated(const QModelIndex &)),
|
||||
this, SLOT(procSelected(const QModelIndex &)));
|
||||
|
||||
|
||||
pidLineEdit->setText(m_defaultPID);
|
||||
rebuildProcessList();
|
||||
}
|
||||
|
||||
static bool isProcessName(const QString &procname)
|
||||
{
|
||||
for (int i = 0; i != procname.size(); ++i)
|
||||
if (!procname.at(i).isDigit())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct ProcData {
|
||||
QString ppid;
|
||||
QString name;
|
||||
QString state;
|
||||
};
|
||||
|
||||
static void insertItem(QStandardItem *root, const QString &pid,
|
||||
const QMap<QString, ProcData> &procs, QMap<QString, QStandardItem *> &known)
|
||||
{
|
||||
//qDebug() << "HANDLING " << pid;
|
||||
QStandardItem *parent = 0;
|
||||
const ProcData &proc = procs[pid];
|
||||
if (1 || pid == "0") {
|
||||
parent = root;
|
||||
} else {
|
||||
if (!known.contains(proc.ppid))
|
||||
insertItem(root, proc.ppid, procs, known);
|
||||
parent = known[proc.ppid];
|
||||
}
|
||||
QList<QStandardItem *> row;
|
||||
row.append(new QStandardItem(pid));
|
||||
row.append(new QStandardItem(proc.name));
|
||||
//row.append(new QStandardItem(proc.ppid));
|
||||
row.append(new QStandardItem(proc.state));
|
||||
parent->appendRow(row);
|
||||
known[pid] = row[0];
|
||||
}
|
||||
|
||||
void AttachRemoteDialog::rebuildProcessList()
|
||||
{
|
||||
QStringList procnames = QDir("/proc/").entryList();
|
||||
if (procnames.isEmpty()) {
|
||||
procView->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
typedef QMap<QString, ProcData> Procs;
|
||||
Procs procs;
|
||||
|
||||
foreach (const QString &procname, procnames) {
|
||||
if (!isProcessName(procname))
|
||||
continue;
|
||||
QString filename = "/proc/" + procname + "/stat";
|
||||
QFile file(filename);
|
||||
file.open(QIODevice::ReadOnly);
|
||||
QStringList data = QString::fromLocal8Bit(file.readAll()).split(' ');
|
||||
//qDebug() << filename << data;
|
||||
ProcData proc;
|
||||
proc.name = data.at(1);
|
||||
if (proc.name.startsWith('(') && proc.name.endsWith(')'))
|
||||
proc.name = proc.name.mid(1, proc.name.size() - 2);
|
||||
proc.state = data.at(2);
|
||||
proc.ppid = data.at(3);
|
||||
procs[procname] = proc;
|
||||
}
|
||||
|
||||
m_model->clear();
|
||||
QMap<QString, QStandardItem *> known;
|
||||
for (Procs::const_iterator it = procs.begin(); it != procs.end(); ++it)
|
||||
insertItem(m_model->invisibleRootItem(), it.key(), procs, known);
|
||||
m_model->setHeaderData(0, Qt::Horizontal, "Process ID", Qt::DisplayRole);
|
||||
m_model->setHeaderData(1, Qt::Horizontal, "Name", Qt::DisplayRole);
|
||||
//model->setHeaderData(2, Qt::Horizontal, "Parent", Qt::DisplayRole);
|
||||
m_model->setHeaderData(2, Qt::Horizontal, "State", Qt::DisplayRole);
|
||||
|
||||
procView->setModel(m_model);
|
||||
procView->expandAll();
|
||||
procView->resizeColumnToContents(0);
|
||||
procView->resizeColumnToContents(1);
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
|
||||
#include <windows.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <tchar.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Forward declarations:
|
||||
BOOL GetProcessList( );
|
||||
BOOL ListProcessModules( DWORD dwPID );
|
||||
BOOL ListProcessThreads( DWORD dwOwnerPID );
|
||||
void printError( TCHAR* msg );
|
||||
|
||||
BOOL GetProcessList( )
|
||||
{
|
||||
HANDLE hProcessSnap;
|
||||
HANDLE hProcess;
|
||||
PROCESSENTRY32 pe32;
|
||||
DWORD dwPriorityClass;
|
||||
|
||||
// Take a snapshot of all processes in the system.
|
||||
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
|
||||
if( hProcessSnap == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
printError( TEXT("CreateToolhelp32Snapshot (of processes)") );
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Set the size of the structure before using it.
|
||||
pe32.dwSize = sizeof( PROCESSENTRY32 );
|
||||
|
||||
// Retrieve information about the first process,
|
||||
// and exit if unsuccessful
|
||||
if( !Process32First( hProcessSnap, &pe32 ) )
|
||||
{
|
||||
printError( TEXT("Process32First") ); // show cause of failure
|
||||
CloseHandle( hProcessSnap ); // clean the snapshot object
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Now walk the snapshot of processes, and
|
||||
// display information about each process in turn
|
||||
do
|
||||
{
|
||||
printf( "\n\n=====================================================" );
|
||||
_tprintf( TEXT("\nPROCESS NAME: %s"), pe32.szExeFile );
|
||||
printf( "\n-----------------------------------------------------" );
|
||||
|
||||
// Retrieve the priority class.
|
||||
dwPriorityClass = 0;
|
||||
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
|
||||
if( hProcess == NULL )
|
||||
printError( TEXT("OpenProcess") );
|
||||
else
|
||||
{
|
||||
dwPriorityClass = GetPriorityClass( hProcess );
|
||||
if( !dwPriorityClass )
|
||||
printError( TEXT("GetPriorityClass") );
|
||||
CloseHandle( hProcess );
|
||||
}
|
||||
|
||||
printf( "\n Process ID = 0x%08X", pe32.th32ProcessID );
|
||||
printf( "\n Thread count = %d", pe32.cntThreads );
|
||||
printf( "\n Parent process ID = 0x%08X", pe32.th32ParentProcessID );
|
||||
printf( "\n Priority base = %d", pe32.pcPriClassBase );
|
||||
if( dwPriorityClass )
|
||||
printf( "\n Priority class = %d", dwPriorityClass );
|
||||
|
||||
// List the modules and threads associated with this process
|
||||
ListProcessModules( pe32.th32ProcessID );
|
||||
ListProcessThreads( pe32.th32ProcessID );
|
||||
|
||||
} while( Process32Next( hProcessSnap, &pe32 ) );
|
||||
|
||||
CloseHandle( hProcessSnap );
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
|
||||
BOOL ListProcessModules( DWORD dwPID )
|
||||
{
|
||||
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
|
||||
MODULEENTRY32 me32;
|
||||
|
||||
// Take a snapshot of all modules in the specified process.
|
||||
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
|
||||
if( hModuleSnap == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
printError( TEXT("CreateToolhelp32Snapshot (of modules)") );
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Set the size of the structure before using it.
|
||||
me32.dwSize = sizeof( MODULEENTRY32 );
|
||||
|
||||
// Retrieve information about the first module,
|
||||
// and exit if unsuccessful
|
||||
if( !Module32First( hModuleSnap, &me32 ) )
|
||||
{
|
||||
printError( TEXT("Module32First") ); // show cause of failure
|
||||
CloseHandle( hModuleSnap ); // clean the snapshot object
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Now walk the module list of the process,
|
||||
// and display information about each module
|
||||
do
|
||||
{
|
||||
_tprintf( TEXT("\n\n MODULE NAME: %s"), me32.szModule );
|
||||
_tprintf( TEXT("\n Executable = %s"), me32.szExePath );
|
||||
printf( "\n Process ID = 0x%08X", me32.th32ProcessID );
|
||||
printf( "\n Ref count (g) = 0x%04X", me32.GlblcntUsage );
|
||||
printf( "\n Ref count (p) = 0x%04X", me32.ProccntUsage );
|
||||
printf( "\n Base address = 0x%08X", (DWORD) me32.modBaseAddr );
|
||||
printf( "\n Base size = %d", me32.modBaseSize );
|
||||
|
||||
} while( Module32Next( hModuleSnap, &me32 ) );
|
||||
|
||||
CloseHandle( hModuleSnap );
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
BOOL ListProcessThreads( DWORD dwOwnerPID )
|
||||
{
|
||||
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
|
||||
THREADENTRY32 te32;
|
||||
|
||||
// Take a snapshot of all running threads
|
||||
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
|
||||
if( hThreadSnap == INVALID_HANDLE_VALUE )
|
||||
return( FALSE );
|
||||
|
||||
// Fill in the size of the structure before using it.
|
||||
te32.dwSize = sizeof(THREADENTRY32 );
|
||||
|
||||
// Retrieve information about the first thread,
|
||||
// and exit if unsuccessful
|
||||
if( !Thread32First( hThreadSnap, &te32 ) )
|
||||
{
|
||||
printError( TEXT("Thread32First") ); // show cause of failure
|
||||
CloseHandle( hThreadSnap ); // clean the snapshot object
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Now walk the thread list of the system,
|
||||
// and display information about each thread
|
||||
// associated with the specified process
|
||||
do
|
||||
{
|
||||
if( te32.th32OwnerProcessID == dwOwnerPID )
|
||||
{
|
||||
printf( "\n\n THREAD ID = 0x%08X", te32.th32ThreadID );
|
||||
printf( "\n Base priority = %d", te32.tpBasePri );
|
||||
printf( "\n Delta priority = %d", te32.tpDeltaPri );
|
||||
}
|
||||
} while( Thread32Next(hThreadSnap, &te32 ) );
|
||||
|
||||
CloseHandle( hThreadSnap );
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
void printError( TCHAR* msg )
|
||||
{
|
||||
DWORD eNum;
|
||||
TCHAR sysMsg[256];
|
||||
TCHAR* p;
|
||||
|
||||
eNum = GetLastError( );
|
||||
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, eNum,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
sysMsg, 256, NULL );
|
||||
|
||||
// Trim the end of the line and terminate it with a null
|
||||
p = sysMsg;
|
||||
while( ( *p > 31 ) || ( *p == 9 ) )
|
||||
++p;
|
||||
do { *p-- = 0; } while( ( p >= sysMsg ) &&
|
||||
( ( *p == '.' ) || ( *p < 33 ) ) );
|
||||
|
||||
// Display the message
|
||||
_tprintf( TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void AttachRemoteDialog::procSelected(const QModelIndex &index0)
|
||||
{
|
||||
QModelIndex index = index0.sibling(index0.row(), 0);
|
||||
QStandardItem *item = m_model->itemFromIndex(index);
|
||||
if (!item)
|
||||
return;
|
||||
pidLineEdit->setText(item->text());
|
||||
accept();
|
||||
}
|
||||
|
||||
int AttachRemoteDialog::attachPID() const
|
||||
{
|
||||
return pidLineEdit->text().toInt();
|
||||
}
|
||||
65
src/plugins/debugger/attachremotedialog.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef ATTACHREMOTE_DIALOG_H
|
||||
#define ATTACHREMOTE_DIALOG_H
|
||||
|
||||
#include "ui_attachremotedialog.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QStandardItemModel;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class AttachRemoteDialog : public QDialog, Ui::AttachRemoteDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AttachRemoteDialog(QWidget *parent, const QString &pid);
|
||||
int attachPID() const;
|
||||
|
||||
private slots:
|
||||
void rebuildProcessList();
|
||||
void procSelected(const QModelIndex &);
|
||||
|
||||
private:
|
||||
QString m_defaultPID;
|
||||
QStandardItemModel *m_model;
|
||||
};
|
||||
|
||||
} // namespace Debugger
|
||||
} // namespace Internal
|
||||
|
||||
#endif // ATTACHREMOTEDIALOG_H
|
||||
64
src/plugins/debugger/attachremotedialog.ui
Normal file
@@ -0,0 +1,64 @@
|
||||
<ui version="4.0" >
|
||||
<class>AttachRemoteDialog</class>
|
||||
<widget class="QDialog" name="AttachRemoteDialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>561</width>
|
||||
<height>866</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Start Debugger</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="pidLabel" >
|
||||
<property name="text" >
|
||||
<string>Attach to Process ID:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="pidLineEdit" />
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="procView" >
|
||||
<property name="editTriggers" >
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
58
src/plugins/debugger/breakbyfunction.ui
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BreakByFunctionDialog</class>
|
||||
<widget class="QDialog" name="BreakByFunctionDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>337</width>
|
||||
<height>101</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Start Debugger</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="functionLabel">
|
||||
<property name="text">
|
||||
<string>Function to break on:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="functionLineEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
95
src/plugins/debugger/breakcondition.ui
Normal file
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>BreakCondition</class>
|
||||
<widget class="QDialog" name="BreakCondition">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>435</width>
|
||||
<height>142</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelCondition">
|
||||
<property name="text">
|
||||
<string>Condition:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEditCondition"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelIgnoreCount">
|
||||
<property name="text">
|
||||
<string>Ignore count:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxIgnoreCount">
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>BreakCondition</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>BreakCondition</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
559
src/plugins/debugger/breakhandler.cpp
Normal file
@@ -0,0 +1,559 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "breakhandler.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "imports.h" // TextEditor::BaseTextMark
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QFileInfo>
|
||||
|
||||
using namespace Debugger;
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BreakpointMarker
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
|
||||
// The red blob on the left side in the cpp editor.
|
||||
class BreakpointMarker : public TextEditor::BaseTextMark
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BreakpointMarker(BreakpointData *data, const QString &fileName, int lineNumber)
|
||||
: BaseTextMark(fileName, lineNumber), m_data(data), m_pending(true)
|
||||
{
|
||||
//qDebug() << "CREATE MARKER " << fileName << lineNumber;
|
||||
}
|
||||
|
||||
~BreakpointMarker()
|
||||
{
|
||||
//qDebug() << "REMOVE MARKER ";
|
||||
m_data = 0;
|
||||
}
|
||||
|
||||
QIcon icon() const
|
||||
{
|
||||
static const QIcon icon(":/gdbdebugger/images/breakpoint.svg");
|
||||
static const QIcon icon2(":/gdbdebugger/images/breakpoint_pending.svg");
|
||||
return m_pending ? icon2 : icon;
|
||||
}
|
||||
|
||||
void setPending(bool pending)
|
||||
{
|
||||
if (pending == m_pending)
|
||||
return;
|
||||
m_pending = pending;
|
||||
updateMarker();
|
||||
}
|
||||
|
||||
void updateBlock(const QTextBlock &)
|
||||
{
|
||||
//qDebug() << "BREAKPOINT MARKER UPDATE BLOCK";
|
||||
}
|
||||
|
||||
void removedFromEditor()
|
||||
{
|
||||
if (!m_data)
|
||||
return;
|
||||
|
||||
BreakHandler *handler = m_data->handler();
|
||||
handler->removeBreakpoint(handler->indexOf(m_data));
|
||||
handler->saveBreakpoints();
|
||||
handler->updateMarkers();
|
||||
}
|
||||
|
||||
void updateLineNumber(int lineNumber)
|
||||
{
|
||||
if (!m_data)
|
||||
return;
|
||||
//if (m_data->markerLineNumber == lineNumber)
|
||||
// return;
|
||||
if (m_data->markerLineNumber != lineNumber) {
|
||||
m_data->markerLineNumber = lineNumber;
|
||||
// FIXME: should we tell gdb about the change?
|
||||
// Ignore it for now, as we would require re-compilation
|
||||
// and debugger re-start anyway.
|
||||
if (0 && !m_data->bpLineNumber.isEmpty()) {
|
||||
if (!m_data->bpNumber.trimmed().isEmpty()) {
|
||||
m_data->pending = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_data->lineNumber = QString::number(lineNumber);
|
||||
m_data->handler()->updateMarkers();
|
||||
}
|
||||
|
||||
private:
|
||||
BreakpointData *m_data;
|
||||
bool m_pending;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BreakpointData
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
BreakpointData::BreakpointData(BreakHandler *handler)
|
||||
{
|
||||
//qDebug() << "CREATE BREAKPOINTDATA" << this;
|
||||
m_handler = handler;
|
||||
pending = true;
|
||||
marker = 0;
|
||||
markerLineNumber = 0;
|
||||
bpMultiple = false;
|
||||
}
|
||||
|
||||
BreakpointData::~BreakpointData()
|
||||
{
|
||||
removeMarker();
|
||||
//qDebug() << "DESTROY BREAKPOINTDATA" << this;
|
||||
}
|
||||
|
||||
void BreakpointData::removeMarker()
|
||||
{
|
||||
BreakpointMarker *m = marker;
|
||||
marker = 0;
|
||||
delete m;
|
||||
}
|
||||
|
||||
void BreakpointData::updateMarker()
|
||||
{
|
||||
if (marker && (markerFileName != marker->fileName()
|
||||
|| markerLineNumber != marker->lineNumber()))
|
||||
removeMarker();
|
||||
|
||||
if (!marker && !markerFileName.isEmpty() && markerLineNumber > 0)
|
||||
marker = new BreakpointMarker(this, markerFileName, markerLineNumber);
|
||||
|
||||
if (marker)
|
||||
marker->setPending(pending);
|
||||
}
|
||||
|
||||
QString BreakpointData::toToolTip() const
|
||||
{
|
||||
QString str;
|
||||
str += "<table>";
|
||||
str += "<tr><td>Marker File:</td><td>" + markerFileName + "</td></tr>";
|
||||
str += "<tr><td>Marker Line:</td><td>" + QString::number(markerLineNumber) + "</td></tr>";
|
||||
str += "<tr><td>BP Number:</td><td>" + bpNumber + "</td></tr>";
|
||||
str += "<tr><td>BP Address:</td><td>" + bpAddress + "</td></tr>";
|
||||
str += "<tr><td>----------</td><td></td><td></td></tr>";
|
||||
str += "<tr><td>Property:</td><td>Wanted:</td><td>Actual:</td></tr>";
|
||||
str += "<tr><td></td><td></td><td></td></tr>";
|
||||
str += "<tr><td>Internal Number:</td><td>-</td><td>" + bpNumber + "</td></tr>";
|
||||
str += "<tr><td>File Name:</td><td>" + fileName + "</td><td>" + bpFileName + "</td></tr>";
|
||||
str += "<tr><td>Function Name:</td><td>" + funcName + "</td><td>" + bpFuncName + "</td></tr>";
|
||||
str += "<tr><td>Line Number:</td><td>" + lineNumber + "</td><td>" + bpLineNumber + "</td></tr>";
|
||||
str += "<tr><td>Condition:</td><td>" + condition + "</td><td>" + bpCondition + "</td></tr>";
|
||||
str += "<tr><td>Ignore count:</td><td>" + ignoreCount + "</td><td>" + bpIgnoreCount + "</td></tr>";
|
||||
str += "</table>";
|
||||
return str;
|
||||
}
|
||||
|
||||
bool BreakpointData::isLocatedAt(const QString &fileName_, int lineNumber_) const
|
||||
{
|
||||
/*
|
||||
if (lineNumber != QString::number(lineNumber_))
|
||||
return false;
|
||||
if (fileName == fileName_)
|
||||
return true;
|
||||
if (fileName_.endsWith(fileName))
|
||||
return true;
|
||||
return false;
|
||||
*/
|
||||
return lineNumber_ == markerLineNumber && fileName_ == markerFileName;
|
||||
}
|
||||
|
||||
bool BreakpointData::conditionsMatch() const
|
||||
{
|
||||
// same versions of gdb "beautify" the passed condition
|
||||
QString s1 = condition;
|
||||
s1.remove(QChar(' '));
|
||||
QString s2 = bpCondition;
|
||||
s2.remove(QChar(' '));
|
||||
return s1 == s2;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BreakHandler
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
BreakHandler::BreakHandler(QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
int BreakHandler::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : 6;
|
||||
}
|
||||
|
||||
int BreakHandler::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : size();
|
||||
}
|
||||
|
||||
void BreakHandler::removeAt(int index)
|
||||
{
|
||||
BreakpointData *data = at(index);
|
||||
m_bp.removeAt(index);
|
||||
delete data;
|
||||
}
|
||||
|
||||
void BreakHandler::clear()
|
||||
{
|
||||
for (int index = size(); --index >= 0; )
|
||||
removeAt(index);
|
||||
}
|
||||
|
||||
int BreakHandler::findBreakpoint(const BreakpointData &needle)
|
||||
{
|
||||
// looks for a breakpoint we might refer to
|
||||
for (int index = 0; index != size(); ++index) {
|
||||
const BreakpointData *data = at(index);
|
||||
// clear hit.
|
||||
if (data->bpNumber == needle.bpNumber)
|
||||
return index;
|
||||
// at least at a position we were looking for
|
||||
// FIXME: breaks multiple breakpoints at the same location
|
||||
if (data->fileName == needle.bpFileName
|
||||
&& data->lineNumber == needle.bpLineNumber)
|
||||
return index;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BreakHandler::findBreakpoint(int bpNumber)
|
||||
{
|
||||
for (int index = 0; index != size(); ++index)
|
||||
if (at(index)->bpNumber == QString::number(bpNumber))
|
||||
return index;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void BreakHandler::saveBreakpoints()
|
||||
{
|
||||
QList<QVariant> list;
|
||||
for (int index = 0; index != size(); ++index) {
|
||||
const BreakpointData *data = at(index);
|
||||
QMap<QString, QVariant> map;
|
||||
if (!data->fileName.isEmpty())
|
||||
map["filename"] = data->fileName;
|
||||
if (!data->lineNumber.isEmpty())
|
||||
map["linenumber"] = data->lineNumber;
|
||||
if (!data->funcName.isEmpty())
|
||||
map["funcname"] = data->funcName;
|
||||
if (!data->condition.isEmpty())
|
||||
map["condition"] = data->condition;
|
||||
if (!data->ignoreCount.isEmpty())
|
||||
map["ignorecount"] = data->ignoreCount;
|
||||
list.append(map);
|
||||
}
|
||||
setSessionValueRequested("Breakpoints", list);
|
||||
}
|
||||
|
||||
void BreakHandler::loadBreakpoints()
|
||||
{
|
||||
QVariant value;
|
||||
sessionValueRequested("Breakpoints", &value);
|
||||
QList<QVariant> list = value.toList();
|
||||
|
||||
clear();
|
||||
foreach (const QVariant &var, list) {
|
||||
const QMap<QString, QVariant> map = var.toMap();
|
||||
BreakpointData *data = new BreakpointData(this);
|
||||
data->fileName = map["filename"].toString();
|
||||
data->lineNumber = map["linenumber"].toString();
|
||||
data->condition = map["condition"].toString();
|
||||
data->ignoreCount = map["ignorecount"].toString();
|
||||
data->funcName = map["funcname"].toString();
|
||||
data->markerFileName = data->fileName;
|
||||
data->markerLineNumber = data->lineNumber.toInt();
|
||||
append(data);
|
||||
}
|
||||
}
|
||||
|
||||
void BreakHandler::resetBreakpoints()
|
||||
{
|
||||
for (int index = size(); --index >= 0;) {
|
||||
BreakpointData *data = at(index);
|
||||
data->pending = true;
|
||||
data->bpNumber.clear();
|
||||
data->bpFuncName.clear();
|
||||
data->bpFileName.clear();
|
||||
data->bpLineNumber.clear();
|
||||
data->bpCondition.clear();
|
||||
data->bpIgnoreCount.clear();
|
||||
// keep marker data if it was primary
|
||||
if (data->markerFileName != data->fileName)
|
||||
data->markerFileName.clear();
|
||||
if (data->markerLineNumber != data->lineNumber.toInt())
|
||||
data->markerLineNumber = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BreakHandler::updateMarkers()
|
||||
{
|
||||
for (int index = 0; index != size(); ++index)
|
||||
at(index)->updateMarker();
|
||||
emit layoutChanged();
|
||||
}
|
||||
|
||||
QVariant BreakHandler::headerData(int section,
|
||||
Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||
static QString headers[] = {
|
||||
tr("Number"), tr("Function"), tr("File"), tr("Line"),
|
||||
tr("Condition"), tr("Ignore")
|
||||
};
|
||||
return headers[section];
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant BreakHandler::data(const QModelIndex &mi, int role) const
|
||||
{
|
||||
static const QIcon icon(":/gdbdebugger/images/breakpoint.svg");
|
||||
static const QIcon icon2(":/gdbdebugger/images/breakpoint_pending.svg");
|
||||
static const QString empty = QString(QLatin1Char('-'));
|
||||
|
||||
QWB_ASSERT(mi.isValid(), return QVariant());
|
||||
|
||||
if (mi.row() >= size())
|
||||
return QVariant();
|
||||
|
||||
const BreakpointData *data = at(mi.row());
|
||||
switch (mi.column()) {
|
||||
case 0:
|
||||
if (role == Qt::DisplayRole) {
|
||||
QString str = data->bpNumber;
|
||||
return str.isEmpty() ? empty : str;
|
||||
}
|
||||
if (role == Qt::DecorationRole)
|
||||
return data->pending ? icon2 : icon;
|
||||
break;
|
||||
case 1:
|
||||
if (role == Qt::DisplayRole) {
|
||||
QString str = data->pending ? data->funcName : data->bpFuncName;
|
||||
return str.isEmpty() ? empty : str;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (role == Qt::DisplayRole) {
|
||||
QString str = data->pending ? data->fileName : data->bpFileName;
|
||||
str = QFileInfo(str).fileName();
|
||||
//if (data->bpMultiple && str.isEmpty() && !data->markerFileName.isEmpty())
|
||||
// str = data->markerFileName;
|
||||
return str.isEmpty() ? empty : str;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (role == Qt::DisplayRole) {
|
||||
QString str = data->pending ? data->lineNumber : data->bpLineNumber;
|
||||
//if (data->bpMultiple && str.isEmpty() && !data->markerFileName.isEmpty())
|
||||
// str = data->markerLineNumber;
|
||||
return str.isEmpty() ? empty : str;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (role == Qt::DisplayRole)
|
||||
return data->pending ? data->condition : data->bpCondition;
|
||||
if (role == Qt::ToolTipRole)
|
||||
return tr("Breakpoint will only be hit if this condition is met.");
|
||||
break;
|
||||
case 5:
|
||||
if (role == Qt::DisplayRole)
|
||||
return data->pending ? data->ignoreCount : data->bpIgnoreCount;
|
||||
if (role == Qt::ToolTipRole)
|
||||
return tr("Breakpoint will only be hit after being ignored so many times.");
|
||||
break;
|
||||
}
|
||||
if (role == Qt::ToolTipRole)
|
||||
return data->toToolTip();
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool BreakHandler::setData(const QModelIndex &mi, const QVariant &value, int role)
|
||||
{
|
||||
if (role != Qt::EditRole)
|
||||
return false;
|
||||
|
||||
BreakpointData *data = at(mi.row());
|
||||
switch (mi.column()) {
|
||||
case 4: {
|
||||
QString val = value.toString();
|
||||
if (val != data->condition) {
|
||||
data->condition = val;
|
||||
dataChanged(mi, mi);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case 5: {
|
||||
QString val = value.toString();
|
||||
if (val != data->ignoreCount) {
|
||||
data->ignoreCount = val;
|
||||
dataChanged(mi, mi);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<BreakpointData *> BreakHandler::takeRemovedBreakpoints()
|
||||
{
|
||||
QList<BreakpointData *> result = m_removed;
|
||||
m_removed.clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
void BreakHandler::removeBreakpointHelper(int index)
|
||||
{
|
||||
BreakpointData *data = m_bp.at(index);
|
||||
m_bp.removeAt(index);
|
||||
data->removeMarker();
|
||||
m_removed.append(data);
|
||||
}
|
||||
|
||||
|
||||
void BreakHandler::removeBreakpoint(int index)
|
||||
{
|
||||
if (index < 0 || index >= size())
|
||||
return;
|
||||
BreakHandler::removeBreakpointHelper(index);
|
||||
emit layoutChanged();
|
||||
saveBreakpoints();
|
||||
}
|
||||
|
||||
|
||||
int BreakHandler::indexOf(const QString &fileName, int lineNumber)
|
||||
{
|
||||
for (int index = 0; index != size(); ++index)
|
||||
if (at(index)->isLocatedAt(fileName, lineNumber))
|
||||
return index;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void BreakHandler::setBreakpoint(const QString &fileName, int lineNumber)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
|
||||
BreakpointData *data = new BreakpointData(this);
|
||||
data->fileName = fileName;
|
||||
data->lineNumber = QString::number(lineNumber);
|
||||
data->pending = true;
|
||||
data->markerFileName = fileName;
|
||||
data->markerLineNumber = lineNumber;
|
||||
append(data);
|
||||
emit layoutChanged();
|
||||
saveBreakpoints();
|
||||
updateMarkers();
|
||||
}
|
||||
|
||||
void BreakHandler::removeAllBreakpoints()
|
||||
{
|
||||
for (int index = size(); --index >= 0;)
|
||||
removeBreakpointHelper(index);
|
||||
emit layoutChanged();
|
||||
saveBreakpoints();
|
||||
updateMarkers();
|
||||
}
|
||||
|
||||
void BreakHandler::setAllPending()
|
||||
{
|
||||
loadBreakpoints();
|
||||
for (int index = size(); --index >= 0;)
|
||||
at(index)->pending = true;
|
||||
saveBreakpoints();
|
||||
updateMarkers();
|
||||
}
|
||||
|
||||
void BreakHandler::saveSessionData()
|
||||
{
|
||||
saveBreakpoints();
|
||||
updateMarkers();
|
||||
}
|
||||
|
||||
void BreakHandler::loadSessionData()
|
||||
{
|
||||
//resetBreakpoints();
|
||||
loadBreakpoints();
|
||||
updateMarkers();
|
||||
}
|
||||
|
||||
void BreakHandler::activateBreakPoint(int index)
|
||||
{
|
||||
const BreakpointData *data = at(index);
|
||||
//qDebug() << "BREAKPOINT ACTIVATED: " << data->fileName;
|
||||
if (!data->markerFileName.isEmpty())
|
||||
emit gotoLocation(data->markerFileName, data->markerLineNumber, false);
|
||||
}
|
||||
|
||||
void BreakHandler::breakByFunction(const QString &functionName)
|
||||
{
|
||||
// One per function is enough for now
|
||||
for (int index = size(); --index >= 0;) {
|
||||
const BreakpointData *data = at(index);
|
||||
QWB_ASSERT(data, break);
|
||||
if (data->funcName == functionName && data->condition.isEmpty()
|
||||
&& data->ignoreCount.isEmpty())
|
||||
return;
|
||||
}
|
||||
BreakpointData *data = new BreakpointData(this);
|
||||
data->funcName = functionName;
|
||||
append(data);
|
||||
saveBreakpoints();
|
||||
updateMarkers();
|
||||
}
|
||||
|
||||
#include "breakhandler.moc"
|
||||
174
src/plugins/debugger/breakhandler.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_BREAKHANDLER_H
|
||||
#define DEBUGGER_BREAKHANDLER_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QAbstractItemModel>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class BreakpointMarker;
|
||||
class BreakHandler;
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BreakpointData
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
class BreakpointData
|
||||
{
|
||||
public:
|
||||
explicit BreakpointData(BreakHandler *handler);
|
||||
~BreakpointData();
|
||||
|
||||
void removeMarker();
|
||||
void updateMarker();
|
||||
QString toToolTip() const;
|
||||
BreakHandler *handler() { return m_handler; }
|
||||
|
||||
bool isLocatedAt(const QString &fileName, int lineNumber) const;
|
||||
bool conditionsMatch() const;
|
||||
|
||||
private:
|
||||
// Intentionally unimplemented.
|
||||
// Making it copiable is tricky because of the markers.
|
||||
void operator=(const BreakpointData &);
|
||||
BreakpointData(const BreakpointData &);
|
||||
|
||||
// Our owner
|
||||
BreakHandler *m_handler; // not owned.
|
||||
|
||||
public:
|
||||
bool pending; // does the debugger engine know about us already?
|
||||
|
||||
// this "user requested information". will get stored in the session
|
||||
QString fileName; // short name of source file
|
||||
QString condition; // condition associated with breakpoint
|
||||
QString ignoreCount; // ignore count associated with breakpoint
|
||||
QString lineNumber; // line in source file
|
||||
QString funcName; // name of containing function
|
||||
|
||||
// this is what gdb produced in response
|
||||
QString bpNumber; // breakpoint number assigned by the debugger engine
|
||||
QString bpCondition; // condition acknowledged by the debugger engine
|
||||
QString bpIgnoreCount; // ignore count acknowledged by the debugger engine
|
||||
QString bpFileName; // file name acknowledged by the debugger engine
|
||||
QString bpLineNumber; // line number acknowledged by the debugger engine
|
||||
QString bpFuncName; // function name acknowledged by the debugger engine
|
||||
QString bpAddress; // address acknowledged by the debugger engine
|
||||
bool bpMultiple; // happens in constructors/gdb
|
||||
|
||||
// taken from either user input or gdb responses
|
||||
QString markerFileName; // used to locate the marker
|
||||
int markerLineNumber;
|
||||
|
||||
// our red blob in the editor
|
||||
BreakpointMarker *marker;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BreakHandler
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
class BreakHandler : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BreakHandler(QObject *parent = 0);
|
||||
|
||||
void removeAllBreakpoints();
|
||||
void setAllPending();
|
||||
void loadSessionData();
|
||||
void saveSessionData();
|
||||
|
||||
QAbstractItemModel *model() { return this; }
|
||||
|
||||
BreakpointData *at(int index) const { return index < size() ? m_bp.at(index) : 0; }
|
||||
int size() const { return m_bp.size(); }
|
||||
void append(BreakpointData *data) { m_bp.append(data); }
|
||||
void removeAt(int index); // also deletes the marker
|
||||
void clear(); // also deletes all the marker
|
||||
int indexOf(BreakpointData *data) { return m_bp.indexOf(data); }
|
||||
int indexOf(const QString &fileName, int lineNumber);
|
||||
int findBreakpoint(const BreakpointData &data); // returns index
|
||||
int findBreakpoint(int bpNumber); // returns index
|
||||
void updateMarkers();
|
||||
|
||||
QList<BreakpointData *> takeRemovedBreakpoints();
|
||||
|
||||
public slots:
|
||||
void setBreakpoint(const QString &fileName, int lineNumber);
|
||||
void breakByFunction(const QString &functionName);
|
||||
void activateBreakPoint(int index);
|
||||
void removeBreakpoint(int index);
|
||||
|
||||
signals:
|
||||
void gotoLocation(const QString &fileName, int lineNumber, bool setMarker);
|
||||
|
||||
void sessionValueRequested(const QString &name, QVariant *value);
|
||||
void setSessionValueRequested(const QString &name, const QVariant &value);
|
||||
|
||||
private:
|
||||
friend class BreakpointMarker;
|
||||
|
||||
// QAbstractItemModel
|
||||
int columnCount(const QModelIndex &parent) const;
|
||||
int rowCount(const QModelIndex &parent) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &, int role);
|
||||
QModelIndex parent(const QModelIndex &) const { return QModelIndex(); }
|
||||
QModelIndex index(int row, int column, const QModelIndex &) const
|
||||
{ return createIndex(row, column); }
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
|
||||
void markerUpdated(BreakpointMarker *, int lineNumber);
|
||||
void loadBreakpoints();
|
||||
void saveBreakpoints();
|
||||
void resetBreakpoints();
|
||||
void removeBreakpointHelper(int index);
|
||||
|
||||
QList<BreakpointData *> m_bp;
|
||||
QList<BreakpointData *> m_removed;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_BREAKHANDLER_H
|
||||
164
src/plugins/debugger/breakwindow.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "breakwindow.h"
|
||||
|
||||
#include "ui_breakcondition.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QFileInfoList>
|
||||
#include <QHeaderView>
|
||||
#include <QKeyEvent>
|
||||
#include <QMenu>
|
||||
#include <QResizeEvent>
|
||||
#include <QToolButton>
|
||||
#include <QTreeView>
|
||||
|
||||
using Debugger::Internal::BreakWindow;
|
||||
|
||||
|
||||
BreakWindow::BreakWindow(QWidget *parent)
|
||||
: QTreeView(parent), m_alwaysResizeColumnsToContents(false)
|
||||
{
|
||||
setWindowTitle(tr("Breakpoints"));
|
||||
setWindowIcon(QIcon(":/gdbdebugger/images/debugger_breakpoints.png"));
|
||||
setAlternatingRowColors(true);
|
||||
setRootIsDecorated(false);
|
||||
setIconSize(QSize(10, 10));
|
||||
|
||||
connect(this, SIGNAL(activated(QModelIndex)),
|
||||
this, SLOT(rowActivated(QModelIndex)));
|
||||
}
|
||||
|
||||
void BreakWindow::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Delete)
|
||||
deleteBreakpoint(currentIndex());
|
||||
QTreeView::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void BreakWindow::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QHeaderView *hv = header();
|
||||
int totalSize = event->size().width() - 180;
|
||||
hv->resizeSection(0, 60);
|
||||
hv->resizeSection(1, (totalSize * 30) / 100);
|
||||
hv->resizeSection(2, (totalSize * 30) / 100);
|
||||
hv->resizeSection(3, (totalSize * 30) / 100);
|
||||
hv->resizeSection(4, 70);
|
||||
hv->resizeSection(5, 50);
|
||||
QTreeView::resizeEvent(event);
|
||||
}
|
||||
|
||||
void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
{
|
||||
QMenu menu;
|
||||
QModelIndex index = indexAt(ev->pos());
|
||||
QAction *act0 = new QAction("Delete breakpoint", &menu);
|
||||
QAction *act1 = new QAction("Adjust column widths to contents", &menu);
|
||||
QAction *act2 = new QAction("Always adjust column widths to contents", &menu);
|
||||
QAction *act3 = new QAction("Edit condition...", &menu);
|
||||
act2->setCheckable(true);
|
||||
act2->setChecked(m_alwaysResizeColumnsToContents);
|
||||
if (index.isValid()) {
|
||||
menu.addAction(act0);
|
||||
menu.addAction(act3);
|
||||
menu.addSeparator();
|
||||
}
|
||||
menu.addAction(act1);
|
||||
menu.addAction(act2);
|
||||
|
||||
QAction *act = menu.exec(ev->globalPos());
|
||||
|
||||
if (act == act0)
|
||||
deleteBreakpoint(index);
|
||||
else if (act == act1)
|
||||
resizeColumnsToContents();
|
||||
else if (act == act2)
|
||||
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
|
||||
else if (act == act3)
|
||||
editCondition(index);
|
||||
}
|
||||
|
||||
void BreakWindow::deleteBreakpoint(const QModelIndex &idx)
|
||||
{
|
||||
int row = idx.row();
|
||||
if (row == model()->rowCount() - 1)
|
||||
--row;
|
||||
setCurrentIndex(idx.sibling(row, 0));
|
||||
emit breakPointDeleted(idx.row());
|
||||
}
|
||||
|
||||
void BreakWindow::editCondition(const QModelIndex &idx)
|
||||
{
|
||||
QDialog dlg(this);
|
||||
Ui::BreakCondition ui;
|
||||
ui.setupUi(&dlg);
|
||||
|
||||
int row = idx.row();
|
||||
dlg.setWindowTitle(tr("Conditions on Breakpoint %1").arg(row));
|
||||
ui.lineEditCondition->setText(model()->data(idx.sibling(row, 4)).toString());
|
||||
ui.spinBoxIgnoreCount->setValue(model()->data(idx.sibling(row, 5)).toInt());
|
||||
|
||||
if (dlg.exec() == QDialog::Rejected)
|
||||
return;
|
||||
|
||||
model()->setData(idx.sibling(row, 4), ui.lineEditCondition->text());
|
||||
model()->setData(idx.sibling(row, 5), ui.spinBoxIgnoreCount->value());
|
||||
}
|
||||
|
||||
void BreakWindow::resizeColumnsToContents()
|
||||
{
|
||||
resizeColumnToContents(0);
|
||||
resizeColumnToContents(1);
|
||||
resizeColumnToContents(2);
|
||||
resizeColumnToContents(3);
|
||||
}
|
||||
|
||||
void BreakWindow::setAlwaysResizeColumnsToContents(bool on)
|
||||
{
|
||||
m_alwaysResizeColumnsToContents = on;
|
||||
QHeaderView::ResizeMode mode = on
|
||||
? QHeaderView::ResizeToContents : QHeaderView::Interactive;
|
||||
header()->setResizeMode(0, mode);
|
||||
header()->setResizeMode(1, mode);
|
||||
header()->setResizeMode(2, mode);
|
||||
header()->setResizeMode(3, mode);
|
||||
}
|
||||
|
||||
void BreakWindow::rowActivated(const QModelIndex &index)
|
||||
{
|
||||
emit breakPointActivated(index.row());
|
||||
}
|
||||
|
||||
76
src/plugins/debugger/breakwindow.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_BREAKWINDOW_H
|
||||
#define DEBUGGER_BREAKWINDOW_H
|
||||
|
||||
#include <QTreeView>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class BreakWindow : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BreakWindow(QWidget *parent = 0);
|
||||
|
||||
public slots:
|
||||
void resizeColumnsToContents();
|
||||
void setAlwaysResizeColumnsToContents(bool on);
|
||||
|
||||
signals:
|
||||
void breakPointDeleted(int index);
|
||||
void breakPointActivated(int index);
|
||||
|
||||
private slots:
|
||||
void rowActivated(const QModelIndex &index);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *ev);
|
||||
void contextMenuEvent(QContextMenuEvent *ev);
|
||||
void keyPressEvent(QKeyEvent *ev);
|
||||
|
||||
private:
|
||||
void deleteBreakpoint(const QModelIndex &idx);
|
||||
void editCondition(const QModelIndex &idx);
|
||||
|
||||
bool m_alwaysResizeColumnsToContents;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_BREAKWINDOW
|
||||
|
||||
92
src/plugins/debugger/debugger.pro
Normal file
@@ -0,0 +1,92 @@
|
||||
TEMPLATE = lib
|
||||
TARGET = Debugger
|
||||
|
||||
# CONFIG += single
|
||||
include(../../qworkbenchplugin.pri)
|
||||
include(../../plugins/projectexplorer/projectexplorer.pri)
|
||||
include(../../plugins/find/find.pri)
|
||||
include(../../plugins/coreplugin/coreplugin.pri)
|
||||
include(../../plugins/texteditor/texteditor.pri)
|
||||
include(../../plugins/cpptools/cpptools.pri)
|
||||
include(../../libs/cplusplus/cplusplus.pri)
|
||||
|
||||
# DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII
|
||||
QT += gui network script
|
||||
|
||||
HEADERS += assert.h \
|
||||
attachexternaldialog.h \
|
||||
attachremotedialog.h \
|
||||
breakhandler.h \
|
||||
breakwindow.h \
|
||||
debuggerconstants.h \
|
||||
debuggermanager.h \
|
||||
debuggeroutputwindow.h \
|
||||
debuggerplugin.h \
|
||||
debuggerrunner.h \
|
||||
mode.h \
|
||||
disassemblerhandler.h \
|
||||
disassemblerwindow.h \
|
||||
gdbengine.h \
|
||||
gdbmi.h \
|
||||
gdboptionpage.h \
|
||||
idebuggerengine.h \
|
||||
imports.h \
|
||||
moduleshandler.h \
|
||||
moduleswindow.h \
|
||||
procinterrupt.h \
|
||||
registerhandler.h \
|
||||
registerwindow.h \
|
||||
scriptengine.h \
|
||||
stackhandler.h \
|
||||
stackwindow.h \
|
||||
startexternaldialog.h \
|
||||
threadswindow.h \
|
||||
watchhandler.h \
|
||||
watchwindow.h
|
||||
|
||||
SOURCES += attachexternaldialog.cpp \
|
||||
attachremotedialog.cpp \
|
||||
breakhandler.cpp \
|
||||
breakwindow.cpp \
|
||||
breakwindow.h \
|
||||
debuggermanager.cpp \
|
||||
debuggeroutputwindow.cpp \
|
||||
debuggerplugin.cpp \
|
||||
debuggerrunner.cpp \
|
||||
mode.cpp \
|
||||
disassemblerhandler.cpp \
|
||||
disassemblerwindow.cpp \
|
||||
gdbengine.cpp \
|
||||
gdbmi.cpp \
|
||||
gdboptionpage.cpp \
|
||||
gdbtypemacros.cpp \
|
||||
gdbengine.h \
|
||||
moduleshandler.cpp \
|
||||
moduleswindow.cpp \
|
||||
procinterrupt.cpp \
|
||||
registerhandler.cpp \
|
||||
registerwindow.cpp \
|
||||
scriptengine.cpp \
|
||||
stackhandler.cpp \
|
||||
stackwindow.cpp \
|
||||
startexternaldialog.cpp \
|
||||
threadswindow.cpp \
|
||||
watchhandler.cpp \
|
||||
watchwindow.cpp
|
||||
|
||||
FORMS += attachexternaldialog.ui \
|
||||
attachremotedialog.ui \
|
||||
breakbyfunction.ui \
|
||||
breakcondition.ui \
|
||||
mode.ui \
|
||||
gdboptionpage.ui \
|
||||
gdbtypemacros.ui \
|
||||
startexternaldialog.ui \
|
||||
|
||||
RESOURCES += debugger.qrc
|
||||
|
||||
false {
|
||||
SOURCES += $$PWD/modeltest.cpp
|
||||
HEADERS += $$PWD/modeltest.h
|
||||
DEFINES += USE_MODEL_TEST=1
|
||||
}
|
||||
24
src/plugins/debugger/debugger.qrc
Normal file
@@ -0,0 +1,24 @@
|
||||
<RCC>
|
||||
<qresource prefix="/gdbdebugger" >
|
||||
<file>images/breakpoint.svg</file>
|
||||
<file>images/breakpoint_pending.svg</file>
|
||||
<file>images/debugger_breakpoints.png</file>
|
||||
<file>images/debugger_continue_small.png</file>
|
||||
<file>images/debugger_interrupt_small.png</file>
|
||||
<file>images/debugger_start.png</file>
|
||||
<file>images/debugger_start_small.png</file>
|
||||
<file>images/debugger_stepinto_small.png</file>
|
||||
<file>images/debugger_stepout_small.png</file>
|
||||
<file>images/debugger_stepover_small.png</file>
|
||||
<file>images/debugger_steponeproc_small.png</file>
|
||||
<file>images/debugger_stepoverproc_small.png</file>
|
||||
<file>images/debugger_stop_small.png</file>
|
||||
<file>images/delete.png</file>
|
||||
<file>images/done.png</file>
|
||||
<file>images/empty.svg</file>
|
||||
<file>images/error.png</file>
|
||||
<file>images/location.svg</file>
|
||||
<file>images/newitem.png</file>
|
||||
<file>images/running.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
65
src/plugins/debugger/debuggerconstants.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGERCONSTANTS_H
|
||||
#define DEBUGGERCONSTANTS_H
|
||||
|
||||
namespace Debugger {
|
||||
namespace Constants {
|
||||
|
||||
// modes and their priorities
|
||||
const char * const MODE_DEBUG = "Debugger.Mode.Debug";
|
||||
const int P_MODE_DEBUG = 85;
|
||||
|
||||
// common actions
|
||||
const char * const INTERRUPT = "Debugger.Interrupt";
|
||||
const char * const RESET = "Debugger.Reset";
|
||||
const char * const STEP = "Debugger.StepLine";
|
||||
const char * const STEPOUT = "Debugger.StepOut";
|
||||
const char * const NEXT = "Debugger.NextLine";
|
||||
const char * const STEPI = "Debugger.StepInstruction";
|
||||
const char * const NEXTI = "Debugger.NextInstruction";
|
||||
|
||||
const char * const M_VIEW_DEBUG = "Debugger.Menu.View.Debug";
|
||||
const char * const G_DEBUG = "Debugger.Group.Debug";
|
||||
const char * const G_VIEW_DEBUG = "Debugger.Group.View.Debug";
|
||||
|
||||
const char * const C_GDBDEBUGGER = "Gdb Debugger";
|
||||
const char * const GDBRUNNING = "Gdb.Running";
|
||||
|
||||
const char * const PROPERTY_REGISTER_FORMAT = "Debugger.Property.RegisterFormat";
|
||||
|
||||
} // namespace Constants
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGERCONSTANTS_H
|
||||
|
||||
1298
src/plugins/debugger/debuggermanager.cpp
Normal file
451
src/plugins/debugger/debuggermanager.h
Normal file
@@ -0,0 +1,451 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_DEBUGGERMANAGER_H
|
||||
#define DEBUGGER_DEBUGGERMANAGER_H
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QPoint>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAction;
|
||||
class QAbstractItemModel;
|
||||
class QDockWidget;
|
||||
class QMainWindow;
|
||||
class QModelIndex;
|
||||
class QSplitter;
|
||||
class QWidget;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class DebuggerOutputWindow;
|
||||
class DebuggerPlugin;
|
||||
class DebugMode;
|
||||
|
||||
class BreakHandler;
|
||||
class DisassemblerHandler;
|
||||
class ModulesHandler;
|
||||
class RegisterHandler;
|
||||
class StackHandler;
|
||||
class ThreadsHandler;
|
||||
class WatchHandler;
|
||||
class WatchData;
|
||||
class BreakpointData;
|
||||
|
||||
|
||||
// Note: the Debugger process itself is referred to as 'Debugger',
|
||||
// whereas the debugged process is referred to as 'Inferior' or 'Debuggee'.
|
||||
|
||||
// DebuggerProcessNotReady
|
||||
// |
|
||||
// DebuggerProcessStartingUp
|
||||
// |
|
||||
// DebuggerReady [R] [N]
|
||||
// | <-------------------------------------.
|
||||
// DebuggerInferiorRunningRequested |
|
||||
// | |
|
||||
// DebuggerInferiorRunning |
|
||||
// | |
|
||||
// DebuggerInferiorStopRequested |
|
||||
// | |
|
||||
// DebuggerInferiorStopped |
|
||||
// | |
|
||||
// DebuggerInferiorUpdating |
|
||||
// | |
|
||||
// DebuggerInferiorUpdateFinishing |
|
||||
// | |
|
||||
// DebuggerInferiorReady [C] [N] |
|
||||
// | |
|
||||
// `---------------------------------------'
|
||||
//
|
||||
// Allowed actions:
|
||||
// [R] : Run
|
||||
// [C] : Continue
|
||||
// [N] : Step, Next
|
||||
|
||||
|
||||
|
||||
enum DebuggerStatus
|
||||
{
|
||||
DebuggerProcessNotReady, // Debugger not started
|
||||
DebuggerProcessStartingUp, // Debugger starting up
|
||||
DebuggerProcessReady, // Debugger started, Inferior not yet
|
||||
// running or already finished
|
||||
|
||||
DebuggerInferiorRunningRequested, // Debuggee requested to run
|
||||
DebuggerInferiorRunning, // Debuggee running
|
||||
DebuggerInferiorStopRequested, // Debuggee running, stop requested
|
||||
DebuggerInferiorStopped, // Debuggee stopped
|
||||
|
||||
DebuggerInferiorUpdating, // Debuggee updating data views
|
||||
DebuggerInferiorUpdateFinishing, // Debuggee updating data views aborting
|
||||
DebuggerInferiorReady,
|
||||
};
|
||||
|
||||
|
||||
class IDebuggerEngine;
|
||||
class GdbEngine;
|
||||
class ScriptEngine;
|
||||
class WinEngine;
|
||||
|
||||
// The construct below is not nice but enforces a bit of order. The
|
||||
// DebuggerManager interfaces a lots of thing: The DebuggerPlugin,
|
||||
// the DebuggerEngines, the RunMode, the handlers and views.
|
||||
// Instead of making the whole interface public, we split in into
|
||||
// smaller parts and grant friend access only to the classes that
|
||||
// need it.
|
||||
|
||||
|
||||
//
|
||||
// IDebuggerManagerAccessForEngines
|
||||
//
|
||||
|
||||
class IDebuggerManagerAccessForEngines
|
||||
{
|
||||
public:
|
||||
virtual ~IDebuggerManagerAccessForEngines() {}
|
||||
|
||||
private:
|
||||
// This is the part of the interface that's exclusively seen by the
|
||||
// debugger engines.
|
||||
friend class GdbEngine;
|
||||
friend class ScriptEngine;
|
||||
friend class WinEngine;
|
||||
|
||||
// called from the engines after successful startup
|
||||
virtual void notifyStartupFinished() = 0;
|
||||
virtual void notifyInferiorStopped() = 0;
|
||||
virtual void notifyInferiorUpdateFinished() = 0;
|
||||
virtual void notifyInferiorRunningRequested() = 0;
|
||||
virtual void notifyInferiorRunning() = 0;
|
||||
virtual void notifyInferiorExited() = 0;
|
||||
virtual void notifyInferiorPidChanged(int) = 0;
|
||||
|
||||
virtual DisassemblerHandler *disassemblerHandler() = 0;
|
||||
virtual ModulesHandler *modulesHandler() = 0;
|
||||
virtual BreakHandler *breakHandler() = 0;
|
||||
virtual RegisterHandler *registerHandler() = 0;
|
||||
virtual StackHandler *stackHandler() = 0;
|
||||
virtual ThreadsHandler *threadsHandler() = 0;
|
||||
virtual WatchHandler *watchHandler() = 0;
|
||||
|
||||
virtual void showApplicationOutput(const QString &prefix, const QString &data) = 0;
|
||||
virtual QAction *useCustomDumpersAction() const = 0;
|
||||
virtual QAction *debugDumpersAction() const = 0;
|
||||
virtual bool skipKnownFrames() const = 0;
|
||||
virtual bool debugDumpers() const = 0;
|
||||
virtual bool useCustomDumpers() const = 0;
|
||||
virtual bool useFastStart() const = 0;
|
||||
|
||||
virtual void reloadDisassembler() = 0;
|
||||
virtual void reloadModules() = 0;
|
||||
virtual void reloadRegisters() = 0;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// IDebuggerManagerAccessForDebugMode
|
||||
//
|
||||
|
||||
class IDebuggerManagerAccessForDebugMode
|
||||
{
|
||||
public:
|
||||
virtual ~IDebuggerManagerAccessForDebugMode() {}
|
||||
|
||||
private:
|
||||
friend class DebugMode;
|
||||
|
||||
virtual QWidget *threadsWindow() = 0;
|
||||
virtual QList<QDockWidget*> dockWidgets() const = 0;
|
||||
virtual void createDockWidgets() = 0;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// DebuggerManager
|
||||
//
|
||||
|
||||
class DebuggerManager : public QObject,
|
||||
public IDebuggerManagerAccessForEngines,
|
||||
public IDebuggerManagerAccessForDebugMode
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DebuggerManager();
|
||||
~DebuggerManager();
|
||||
|
||||
IDebuggerManagerAccessForEngines *engineInterface();
|
||||
IDebuggerManagerAccessForDebugMode *debugModeInterface();
|
||||
QMainWindow *mainWindow() const { return m_mainWindow; }
|
||||
|
||||
enum StartMode { startInternal, startExternal, attachExternal };
|
||||
enum DebuggerType { GdbDebugger, ScriptDebugger, WinDebugger };
|
||||
|
||||
public slots:
|
||||
bool startNewDebugger(StartMode mode);
|
||||
void exitDebugger();
|
||||
|
||||
void setSimpleDockWidgetArrangement();
|
||||
void setLocked(bool locked);
|
||||
void dockToggled(bool on);
|
||||
|
||||
void setBusyCursor(bool on);
|
||||
void queryCurrentTextEditor(QString *fileName, int *lineNumber, QObject **ed);
|
||||
void querySessionValue(const QString &name, QVariant *value);
|
||||
void setSessionValue(const QString &name, const QVariant &value);
|
||||
QVariant configValue(const QString &name);
|
||||
void queryConfigValue(const QString &name, QVariant *value);
|
||||
void setConfigValue(const QString &name, const QVariant &value);
|
||||
QVariant sessionValue(const QString &name);
|
||||
|
||||
void gotoLocation(const QString &file, int line, bool setLocationMarker);
|
||||
void resetLocation();
|
||||
|
||||
void interruptDebuggingRequest();
|
||||
void startExternalApplication();
|
||||
void attachExternalApplication();
|
||||
|
||||
void jumpToLineExec();
|
||||
void runToLineExec();
|
||||
void runToFunctionExec();
|
||||
void toggleBreakpoint();
|
||||
void breakByFunction();
|
||||
void breakByFunction(const QString &functionName);
|
||||
void setBreakpoint(const QString &fileName, int lineNumber);
|
||||
void watchExpression(const QString &expression);
|
||||
void breakAtMain();
|
||||
void activateFrame(int index);
|
||||
void selectThread(int index);
|
||||
|
||||
void stepExec();
|
||||
void stepOutExec();
|
||||
void nextExec();
|
||||
void stepIExec();
|
||||
void nextIExec();
|
||||
void continueExec();
|
||||
|
||||
void addToWatchWindow();
|
||||
void updateWatchModel();
|
||||
void removeWatchExpression(const QString &iname);
|
||||
void expandChildren(const QModelIndex &idx);
|
||||
void collapseChildren(const QModelIndex &idx);
|
||||
|
||||
void sessionLoaded();
|
||||
void aboutToSaveSession();
|
||||
|
||||
void assignValueInDebugger(const QString &expr, const QString &value);
|
||||
void executeDebuggerCommand(const QString &command);
|
||||
|
||||
void showStatusMessage(const QString &msg, int timeout); // -1 forever
|
||||
|
||||
private slots:
|
||||
void showDebuggerOutput(const QString &prefix, const QString &msg);
|
||||
void showDebuggerInput(const QString &prefix, const QString &msg);
|
||||
void showApplicationOutput(const QString &prefix, const QString &msg);
|
||||
|
||||
void reloadDisassembler();
|
||||
void disassemblerDockToggled(bool on);
|
||||
|
||||
void reloadModules();
|
||||
void modulesDockToggled(bool on);
|
||||
void loadSymbols(const QString &moduleName);
|
||||
void loadAllSymbols();
|
||||
|
||||
void reloadRegisters();
|
||||
void registerDockToggled(bool on);
|
||||
void setStatus(int status);
|
||||
|
||||
private:
|
||||
//
|
||||
// Implementation of IDebuggerManagerAccessForEngines
|
||||
//
|
||||
DisassemblerHandler *disassemblerHandler() { return m_disassemblerHandler; }
|
||||
ModulesHandler *modulesHandler() { return m_modulesHandler; }
|
||||
BreakHandler *breakHandler() { return m_breakHandler; }
|
||||
RegisterHandler *registerHandler() { return m_registerHandler; }
|
||||
StackHandler *stackHandler() { return m_stackHandler; }
|
||||
ThreadsHandler *threadsHandler() { return m_threadsHandler; }
|
||||
WatchHandler *watchHandler() { return m_watchHandler; }
|
||||
QAction *useCustomDumpersAction() const { return m_useCustomDumpersAction; }
|
||||
QAction *debugDumpersAction() const { return m_debugDumpersAction; }
|
||||
bool skipKnownFrames() const;
|
||||
bool debugDumpers() const;
|
||||
bool useCustomDumpers() const;
|
||||
bool useFastStart() const;
|
||||
|
||||
void notifyStartupFinished();
|
||||
void notifyInferiorStopped();
|
||||
void notifyInferiorUpdateFinished();
|
||||
void notifyInferiorRunningRequested();
|
||||
void notifyInferiorRunning();
|
||||
void notifyInferiorExited();
|
||||
void notifyInferiorPidChanged(int);
|
||||
|
||||
void cleanupViews();
|
||||
|
||||
//
|
||||
// Implementation of IDebuggerManagerAccessForDebugMode
|
||||
//
|
||||
QWidget *threadsWindow() { return m_threadsWindow; }
|
||||
QList<QDockWidget*> dockWidgets() const { return m_dockWidgets; }
|
||||
void createDockWidgets();
|
||||
|
||||
//
|
||||
// internal implementation
|
||||
//
|
||||
Q_SLOT void loadSessionData();
|
||||
Q_SLOT void saveSessionData();
|
||||
Q_SLOT void dumpLog();
|
||||
|
||||
public:
|
||||
// stuff in this block should be made private by moving it to
|
||||
// one of the interfaces
|
||||
QAbstractItemModel *threadsModel();
|
||||
int status() const { return m_status; }
|
||||
StartMode startMode() const { return m_startMode; }
|
||||
|
||||
signals:
|
||||
void debuggingFinished();
|
||||
void inferiorPidChanged(qint64 pid);
|
||||
void statusChanged(int newstatus);
|
||||
void debugModeRequested();
|
||||
void previousModeRequested();
|
||||
void statusMessageRequested(const QString &msg, int timeout); // -1 for 'forever'
|
||||
void gotoLocationRequested(const QString &file, int line, bool setLocationMarker);
|
||||
void resetLocationRequested();
|
||||
void currentTextEditorRequested(QString *fileName, int *lineNumber, QObject **ob);
|
||||
void currentMainWindowRequested(QWidget **);
|
||||
void sessionValueRequested(const QString &name, QVariant *value);
|
||||
void setSessionValueRequested(const QString &name, const QVariant &value);
|
||||
void configValueRequested(const QString &name, QVariant *value);
|
||||
void setConfigValueRequested(const QString &name, const QVariant &value);
|
||||
void applicationOutputAvailable(const QString &prefix, const QString &msg);
|
||||
|
||||
|
||||
public:
|
||||
// FIXME: make private
|
||||
QString m_executable;
|
||||
QStringList m_environment;
|
||||
QString m_workingDir;
|
||||
QString m_buildDir;
|
||||
QStringList m_processArgs;
|
||||
int m_attachedPID;
|
||||
|
||||
private:
|
||||
void init();
|
||||
void setDebuggerType(DebuggerType type);
|
||||
QDockWidget *createDockForWidget(QWidget *widget);
|
||||
|
||||
void shutdown();
|
||||
|
||||
void toggleBreakpoint(const QString &fileName, int lineNumber);
|
||||
void setToolTipExpression(const QPoint &pos, const QString &exp0);
|
||||
|
||||
StartMode m_startMode;
|
||||
DebuggerType m_debuggerType;
|
||||
|
||||
/// Views
|
||||
QMainWindow *m_mainWindow;
|
||||
QDockWidget *m_breakDock;
|
||||
QDockWidget *m_disassemblerDock;
|
||||
QDockWidget *m_modulesDock;
|
||||
QDockWidget *m_outputDock;
|
||||
QDockWidget *m_registerDock;
|
||||
QDockWidget *m_stackDock;
|
||||
QDockWidget *m_threadsDock;
|
||||
QDockWidget *m_watchDock;
|
||||
QList<QDockWidget*> m_dockWidgets;
|
||||
|
||||
BreakHandler *m_breakHandler;
|
||||
DisassemblerHandler *m_disassemblerHandler;
|
||||
ModulesHandler *m_modulesHandler;
|
||||
RegisterHandler *m_registerHandler;
|
||||
StackHandler *m_stackHandler;
|
||||
ThreadsHandler *m_threadsHandler;
|
||||
WatchHandler *m_watchHandler;
|
||||
|
||||
/// Actions
|
||||
friend class DebuggerPlugin;
|
||||
QAction *m_startExternalAction;
|
||||
QAction *m_attachExternalAction;
|
||||
QAction *m_continueAction;
|
||||
QAction *m_stopAction;
|
||||
QAction *m_resetAction; // FIXME: Should not be needed in a stable release
|
||||
QAction *m_stepAction;
|
||||
QAction *m_stepOutAction;
|
||||
QAction *m_runToLineAction;
|
||||
QAction *m_runToFunctionAction;
|
||||
QAction *m_jumpToLineAction;
|
||||
QAction *m_nextAction;
|
||||
QAction *m_watchAction;
|
||||
QAction *m_breakAction;
|
||||
QAction *m_breakByFunctionAction;
|
||||
QAction *m_breakAtMainAction;
|
||||
QAction *m_sepAction;
|
||||
QAction *m_stepIAction;
|
||||
QAction *m_nextIAction;
|
||||
QAction *m_skipKnownFramesAction;
|
||||
|
||||
QAction *m_debugDumpersAction;
|
||||
QAction *m_useCustomDumpersAction;
|
||||
QAction *m_useFastStartAction;
|
||||
QAction *m_dumpLogAction;
|
||||
|
||||
QWidget *m_breakWindow;
|
||||
QWidget *m_disassemblerWindow;
|
||||
QWidget *m_localsWindow;
|
||||
QWidget *m_registerWindow;
|
||||
QWidget *m_modulesWindow;
|
||||
QWidget *m_tooltipWindow;
|
||||
QWidget *m_stackWindow;
|
||||
QWidget *m_threadsWindow;
|
||||
QWidget *m_watchersWindow;
|
||||
DebuggerOutputWindow *m_outputWindow;
|
||||
|
||||
int m_status;
|
||||
bool m_busy;
|
||||
|
||||
IDebuggerEngine *engine();
|
||||
IDebuggerEngine *m_engine;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_DEBUGGERMANAGER_H
|
||||
318
src/plugins/debugger/debuggeroutputwindow.cpp
Normal file
@@ -0,0 +1,318 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "debuggeroutputwindow.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <QtGui/QAction>
|
||||
#include <QtGui/QHBoxLayout>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QKeyEvent>
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QLineEdit>
|
||||
#include <QtGui/QMenu>
|
||||
#include <QtGui/QSpacerItem>
|
||||
#include <QtGui/QSplitter>
|
||||
#include <QtGui/QTextBlock>
|
||||
|
||||
#ifndef GDBDEBUGGERLEAN
|
||||
|
||||
#include <aggregation/aggregate.h>
|
||||
#include <find/basetextfind.h>
|
||||
|
||||
using namespace Find;
|
||||
|
||||
#endif // GDBDEBUGGERLEAN
|
||||
|
||||
using Debugger::Internal::DebuggerOutputWindow;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// InputPane
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
class DebuggerPane : public QTextEdit
|
||||
{
|
||||
public:
|
||||
DebuggerPane(QWidget *parent)
|
||||
: QTextEdit(parent)
|
||||
{
|
||||
m_clearContentsAction = new QAction(this);
|
||||
m_clearContentsAction->setText("Clear contents");
|
||||
m_clearContentsAction->setEnabled(true);
|
||||
m_clearContentsAction->setShortcut(Qt::ControlModifier + Qt::Key_R);
|
||||
connect(m_clearContentsAction, SIGNAL(triggered(bool)),
|
||||
parent, SLOT(clearContents()));
|
||||
|
||||
m_saveContentsAction = new QAction(this);
|
||||
m_saveContentsAction->setText("Save contents");
|
||||
m_saveContentsAction->setEnabled(true);
|
||||
}
|
||||
|
||||
void contextMenuEvent(QContextMenuEvent *ev)
|
||||
{
|
||||
QMenu *menu = createStandardContextMenu();
|
||||
menu->addAction(m_clearContentsAction);
|
||||
//menu->addAction(m_saveContentsAction);
|
||||
addContextActions(menu);
|
||||
menu->exec(ev->globalPos());
|
||||
delete menu;
|
||||
}
|
||||
|
||||
virtual void addContextActions(QMenu *) {}
|
||||
|
||||
public:
|
||||
QAction *m_clearContentsAction;
|
||||
QAction *m_saveContentsAction;
|
||||
};
|
||||
|
||||
class InputPane : public DebuggerPane
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
InputPane(QWidget *parent) : DebuggerPane(parent)
|
||||
{
|
||||
m_commandExecutionAction = new QAction(this);
|
||||
m_commandExecutionAction->setText("Execute line");
|
||||
m_commandExecutionAction->setEnabled(true);
|
||||
//m_commandExecutionAction->setShortcut
|
||||
// (Qt::ControlModifier + Qt::Key_Return);
|
||||
|
||||
connect(m_commandExecutionAction, SIGNAL(triggered(bool)),
|
||||
this, SLOT(executeCommand()));
|
||||
}
|
||||
|
||||
signals:
|
||||
void commandExecutionRequested(const QString &);
|
||||
void clearContentsRequested();
|
||||
void statusMessageRequested(const QString &, int);
|
||||
void commandSelected(int);
|
||||
|
||||
private slots:
|
||||
void executeCommand()
|
||||
{
|
||||
emit commandExecutionRequested(textCursor().block().text());
|
||||
}
|
||||
|
||||
private:
|
||||
void keyPressEvent(QKeyEvent *ev)
|
||||
{
|
||||
if (ev->modifiers() == Qt::ControlModifier && ev->key() == Qt::Key_Return)
|
||||
emit commandExecutionRequested(textCursor().block().text());
|
||||
else if (ev->modifiers() == Qt::ControlModifier && ev->key() == Qt::Key_R)
|
||||
emit clearContentsRequested();
|
||||
else
|
||||
QTextEdit::keyPressEvent(ev);
|
||||
}
|
||||
|
||||
void mouseDoubleClickEvent(QMouseEvent *ev)
|
||||
{
|
||||
QString line = cursorForPosition(ev->pos()).block().text();
|
||||
int n = 0;
|
||||
|
||||
// cut time string
|
||||
if (line.size() > 18 && line.at(0) == '[')
|
||||
line = line.mid(18);
|
||||
//qDebug() << line;
|
||||
|
||||
for (int i = 0; i != line.size(); ++i) {
|
||||
QChar c = line.at(i);
|
||||
if (!c.isDigit())
|
||||
break;
|
||||
n = 10 * n + c.unicode() - '0';
|
||||
}
|
||||
emit commandSelected(n);
|
||||
}
|
||||
|
||||
void addContextActions(QMenu *menu)
|
||||
{
|
||||
menu->addAction(m_commandExecutionAction);
|
||||
}
|
||||
|
||||
void focusInEvent(QFocusEvent *ev)
|
||||
{
|
||||
emit statusMessageRequested("Type Ctrl-<Return> to execute a line.", -1);
|
||||
QTextEdit::focusInEvent(ev);
|
||||
}
|
||||
|
||||
void focusOutEvent(QFocusEvent *ev)
|
||||
{
|
||||
emit statusMessageRequested(QString(), -1);
|
||||
QTextEdit::focusOutEvent(ev);
|
||||
}
|
||||
|
||||
QAction *m_commandExecutionAction;
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CombinedPane
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CombinedPane : public DebuggerPane
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CombinedPane(QWidget *parent)
|
||||
: DebuggerPane(parent)
|
||||
{}
|
||||
|
||||
public slots:
|
||||
void gotoResult(int i)
|
||||
{
|
||||
QString needle = QString::number(i) + '^';
|
||||
QString needle2 = "stdout:" + needle;
|
||||
QTextCursor cursor(document());
|
||||
do {
|
||||
const QString line = cursor.block().text();
|
||||
if (line.startsWith(needle) || line.startsWith(needle2)) {
|
||||
setFocus();
|
||||
setTextCursor(cursor);
|
||||
ensureCursorVisible();
|
||||
cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor);
|
||||
setTextCursor(cursor);
|
||||
break;
|
||||
}
|
||||
} while (cursor.movePosition(QTextCursor::Down));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DebuggerOutputWindow
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
DebuggerOutputWindow::DebuggerOutputWindow(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
setWindowTitle(tr("Gdb"));
|
||||
|
||||
QSplitter *m_splitter = new QSplitter(Qt::Horizontal, this);
|
||||
// mixed input/output
|
||||
m_combinedText = new CombinedPane(this);
|
||||
m_combinedText->setReadOnly(true);
|
||||
m_combinedText->setReadOnly(false);
|
||||
m_combinedText->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
|
||||
// input only
|
||||
m_inputText = new InputPane(this);
|
||||
m_inputText->setReadOnly(false);
|
||||
m_inputText->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
|
||||
m_splitter->addWidget(m_inputText);
|
||||
m_splitter->addWidget(m_combinedText);
|
||||
|
||||
QGridLayout *layout = new QGridLayout(this);
|
||||
layout->setMargin(0);
|
||||
layout->addWidget(m_splitter);
|
||||
setLayout(layout);
|
||||
|
||||
#ifndef GDBDEBUGGERLEAN
|
||||
Aggregation::Aggregate *aggregate = new Aggregation::Aggregate;
|
||||
aggregate->add(m_combinedText);
|
||||
aggregate->add(new BaseTextFind(m_combinedText));
|
||||
|
||||
aggregate = new Aggregation::Aggregate;
|
||||
aggregate->add(m_inputText);
|
||||
aggregate->add(new BaseTextFind(m_inputText));
|
||||
#endif
|
||||
|
||||
connect(m_inputText, SIGNAL(commandExecutionRequested(QString)),
|
||||
this, SIGNAL(commandExecutionRequested(QString)));
|
||||
connect(m_inputText, SIGNAL(statusMessageRequested(QString,int)),
|
||||
this, SIGNAL(statusMessageRequested(QString,int)));
|
||||
connect(m_inputText, SIGNAL(commandSelected(int)),
|
||||
m_combinedText, SLOT(gotoResult(int)));
|
||||
};
|
||||
|
||||
void DebuggerOutputWindow::onReturnPressed()
|
||||
{
|
||||
emit commandExecutionRequested(m_commandEdit->text());
|
||||
}
|
||||
|
||||
void DebuggerOutputWindow::showOutput(const QString &prefix, const QString &output)
|
||||
{
|
||||
if (output.isEmpty())
|
||||
return;
|
||||
foreach (QString line, output.split("\n")) {
|
||||
// FIXME: QTextEdit asserts on really long lines...
|
||||
const int n = 3000;
|
||||
if (line.size() > n)
|
||||
line = line.left(n) + " [...] <cut off>";
|
||||
m_combinedText->append(prefix + line);
|
||||
}
|
||||
QTextCursor cursor = m_combinedText->textCursor();
|
||||
cursor.movePosition(QTextCursor::End);
|
||||
m_combinedText->setTextCursor(cursor);
|
||||
m_combinedText->ensureCursorVisible();
|
||||
}
|
||||
|
||||
void DebuggerOutputWindow::showInput(const QString &prefix, const QString &input)
|
||||
{
|
||||
m_inputText->append(input);
|
||||
QTextCursor cursor = m_inputText->textCursor();
|
||||
cursor.movePosition(QTextCursor::End);
|
||||
m_inputText->setTextCursor(cursor);
|
||||
m_inputText->ensureCursorVisible();
|
||||
showOutput("input:", input);
|
||||
}
|
||||
|
||||
void DebuggerOutputWindow::clearContents()
|
||||
{
|
||||
m_combinedText->clear();
|
||||
m_inputText->clear();
|
||||
}
|
||||
|
||||
void DebuggerOutputWindow::setCursor(const QCursor &cursor)
|
||||
{
|
||||
m_combinedText->setCursor(cursor);
|
||||
m_inputText->setCursor(cursor);
|
||||
QWidget::setCursor(cursor);
|
||||
}
|
||||
|
||||
QString DebuggerOutputWindow::combinedContents() const
|
||||
{
|
||||
return m_combinedText->toPlainText();
|
||||
}
|
||||
|
||||
QString DebuggerOutputWindow::inputContents() const
|
||||
{
|
||||
return m_inputText->toPlainText();
|
||||
}
|
||||
|
||||
#include "debuggeroutputwindow.moc"
|
||||
87
src/plugins/debugger/debuggeroutputwindow.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_OUTPUTWINDOW_H
|
||||
#define DEBUGGER_OUTPUTWINDOW_H
|
||||
|
||||
#include <QtGui/QLineEdit>
|
||||
#include <QtGui/QSplitter>
|
||||
#include <QtGui/QTextEdit>
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class DebuggerOutputWindow : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DebuggerOutputWindow(QWidget *parent = 0);
|
||||
|
||||
QWidget *outputWidget(QWidget *) { return this; }
|
||||
QList<QWidget*> toolBarWidgets(void) const { return QList<QWidget *>(); }
|
||||
|
||||
QString name() const { return windowTitle(); }
|
||||
void visibilityChanged(bool /*visible*/) {}
|
||||
|
||||
void bringPaneToForeground() { emit showPage(); }
|
||||
void setCursor(const QCursor &cursor);
|
||||
|
||||
QString combinedContents() const;
|
||||
QString inputContents() const;
|
||||
|
||||
public slots:
|
||||
void clearContents();
|
||||
void showOutput(const QString &prefix, const QString &output);
|
||||
void showInput(const QString &prefix, const QString &input);
|
||||
|
||||
signals:
|
||||
void showPage();
|
||||
void statusMessageRequested(const QString &msg, int);
|
||||
void commandExecutionRequested(const QString &cmd);
|
||||
|
||||
private slots:
|
||||
void onReturnPressed();
|
||||
|
||||
private:
|
||||
QTextEdit *m_combinedText; // combined input/output
|
||||
QTextEdit *m_inputText; // scriptable input alone
|
||||
QLineEdit *m_commandEdit;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_OUTPUTWINDOW_H
|
||||
|
||||
610
src/plugins/debugger/debuggerplugin.cpp
Normal file
@@ -0,0 +1,610 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "debuggerplugin.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "debuggerconstants.h"
|
||||
#include "debuggermanager.h"
|
||||
#include "debuggerrunner.h"
|
||||
#include "gdboptionpage.h"
|
||||
#include "gdbengine.h"
|
||||
#include "mode.h"
|
||||
|
||||
#include <coreplugin/actionmanager/actionmanagerinterface.h>
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/messagemanager.h>
|
||||
#include <coreplugin/modemanager.h>
|
||||
#include <coreplugin/uniqueidmanager.h>
|
||||
#include <cplusplus/ExpressionUnderCursor.h>
|
||||
#include <cppeditor/cppeditorconstants.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <texteditor/basetextmark.h>
|
||||
#include <texteditor/itexteditor.h>
|
||||
#include <texteditor/texteditorconstants.h>
|
||||
#include <texteditor/basetexteditor.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/qplugin.h>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QPoint>
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtGui/QPlainTextEdit>
|
||||
#include <QtGui/QTextBlock>
|
||||
#include <QtGui/QTextCursor>
|
||||
|
||||
|
||||
using namespace Debugger::Internal;
|
||||
using namespace Debugger::Constants;
|
||||
using namespace TextEditor;
|
||||
using namespace Core;
|
||||
using namespace ProjectExplorer;
|
||||
using namespace CPlusPlus;
|
||||
|
||||
|
||||
namespace Debugger {
|
||||
namespace Constants {
|
||||
|
||||
const char * const STARTEXTERNAL = "Debugger.StartExternal";
|
||||
const char * const ATTACHEXTERNAL = "Debugger.AttachExternal";
|
||||
|
||||
const char * const RUN_TO_LINE = "Debugger.RunToLine";
|
||||
const char * const RUN_TO_FUNCTION = "Debugger.RunToFunction";
|
||||
const char * const JUMP_TO_LINE = "Debugger.JumpToLine";
|
||||
const char * const TOGGLE_BREAK = "Debugger.ToggleBreak";
|
||||
const char * const BREAK_BY_FUNCTION = "Debugger.BreakByFunction";
|
||||
const char * const BREAK_AT_MAIN = "Debugger.BreakAtMain";
|
||||
const char * const DEBUG_DUMPERS = "Debugger.DebugDumpers";
|
||||
const char * const ADD_TO_WATCH = "Debugger.AddToWatch";
|
||||
const char * const USE_CUSTOM_DUMPERS = "Debugger.UseCustomDumpers";
|
||||
const char * const USE_FAST_START = "Debugger.UseFastStart";
|
||||
const char * const SKIP_KNOWN_FRAMES = "Debugger.SkipKnownFrames";
|
||||
const char * const DUMP_LOG = "Debugger.DumpLog";
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
const char * const INTERRUPT_KEY = "Shift+F5";
|
||||
const char * const RESET_KEY = "Ctrl+Shift+F5";
|
||||
const char * const STEP_KEY = "F7";
|
||||
const char * const STEPOUT_KEY = "Shift+F7";
|
||||
const char * const NEXT_KEY = "F6";
|
||||
const char * const STEPI_KEY = "Shift+F9";
|
||||
const char * const NEXTI_KEY = "Shift+F6";
|
||||
const char * const RUN_TO_LINE_KEY = "Shift+F8";
|
||||
const char * const RUN_TO_FUNCTION_KEY = "Ctrl+F6";
|
||||
const char * const JUMP_TO_LINE_KEY = "Alt+D,Alt+L";
|
||||
const char * const TOGGLE_BREAK_KEY = "F8";
|
||||
const char * const BREAK_BY_FUNCTION_KEY = "Alt+D,Alt+F";
|
||||
const char * const BREAK_AT_MAIN_KEY = "Alt+D,Alt+M";
|
||||
const char * const ADD_TO_WATCH_KEY = "Alt+D,Alt+W";
|
||||
#else
|
||||
const char * const INTERRUPT_KEY = "Shift+F5";
|
||||
const char * const RESET_KEY = "Ctrl+Shift+F5";
|
||||
const char * const STEP_KEY = "F11";
|
||||
const char * const STEPOUT_KEY = "Shift+F11";
|
||||
const char * const NEXT_KEY = "F10";
|
||||
const char * const STEPI_KEY = "";
|
||||
const char * const NEXTI_KEY = "";
|
||||
const char * const RUN_TO_LINE_KEY = "";
|
||||
const char * const RUN_TO_FUNCTION_KEY = "";
|
||||
const char * const JUMP_TO_LINE_KEY = "";
|
||||
const char * const TOGGLE_BREAK_KEY = "F9";
|
||||
const char * const BREAK_BY_FUNCTION_KEY = "";
|
||||
const char * const BREAK_AT_MAIN_KEY = "";
|
||||
const char * const ADD_TO_WATCH_KEY = "Ctrl+Alt+Q";
|
||||
#endif
|
||||
|
||||
} // namespace Constants
|
||||
} // namespace Debugger
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// LocationMark
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Debugger::Internal::LocationMark
|
||||
: public TextEditor::BaseTextMark
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LocationMark(const QString &fileName, int linenumber)
|
||||
: BaseTextMark(fileName, linenumber)
|
||||
{
|
||||
}
|
||||
~LocationMark();
|
||||
|
||||
QIcon icon() const;
|
||||
void updateLineNumber(int /*lineNumber*/) {}
|
||||
void updateBlock(const QTextBlock & /*block*/) {}
|
||||
void removedFromEditor() { deleteLater(); }
|
||||
private:
|
||||
};
|
||||
|
||||
LocationMark::~LocationMark()
|
||||
{
|
||||
//qDebug() << "LOCATIONMARK DESTRUCTOR" << m_editor;
|
||||
}
|
||||
|
||||
QIcon LocationMark::icon() const
|
||||
{
|
||||
static const QIcon icon(":/gdbdebugger/images/location.svg");
|
||||
return icon;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DebuggerPlugin
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
DebuggerPlugin::DebuggerPlugin()
|
||||
{
|
||||
m_pm = 0;
|
||||
m_generalOptionPage = 0;
|
||||
m_typeMacroPage = 0;
|
||||
m_locationMark = 0;
|
||||
m_manager = 0;
|
||||
}
|
||||
|
||||
DebuggerPlugin::~DebuggerPlugin()
|
||||
{}
|
||||
|
||||
void DebuggerPlugin::shutdown()
|
||||
{
|
||||
if (m_debugMode)
|
||||
m_debugMode->shutdown(); // saves state including manager information
|
||||
QWB_ASSERT(m_manager, /**/);
|
||||
if (m_manager)
|
||||
m_manager->shutdown();
|
||||
|
||||
//qDebug() << "DebuggerPlugin::~DebuggerPlugin";
|
||||
removeObject(m_debugMode);
|
||||
removeObject(m_generalOptionPage);
|
||||
removeObject(m_typeMacroPage);
|
||||
|
||||
// FIXME: when using the line below, BreakWindow etc gets deleted twice.
|
||||
// so better leak for now...
|
||||
delete m_debugMode;
|
||||
m_debugMode = 0;
|
||||
|
||||
delete m_generalOptionPage;
|
||||
m_generalOptionPage = 0;
|
||||
|
||||
delete m_typeMacroPage;
|
||||
m_typeMacroPage = 0;
|
||||
|
||||
delete m_locationMark;
|
||||
m_locationMark = 0;
|
||||
|
||||
delete m_manager;
|
||||
m_manager = 0;
|
||||
}
|
||||
|
||||
bool DebuggerPlugin::initialize(const QStringList &arguments, QString *error_message)
|
||||
{
|
||||
Q_UNUSED(arguments);
|
||||
Q_UNUSED(error_message);
|
||||
|
||||
m_manager = new DebuggerManager;
|
||||
|
||||
m_pm = ExtensionSystem::PluginManager::instance();
|
||||
|
||||
ICore *core = m_pm->getObject<Core::ICore>();
|
||||
QWB_ASSERT(core, return false);
|
||||
|
||||
Core::ActionManagerInterface *actionManager = core->actionManager();
|
||||
QWB_ASSERT(actionManager, return false);
|
||||
|
||||
Core::UniqueIDManager *uidm = core->uniqueIDManager();
|
||||
QWB_ASSERT(uidm, return false);
|
||||
|
||||
QList<int> globalcontext;
|
||||
globalcontext << Core::Constants::C_GLOBAL_ID;
|
||||
|
||||
QList<int> cppcontext;
|
||||
cppcontext << uidm->uniqueIdentifier(ProjectExplorer::Constants::LANG_CXX);
|
||||
|
||||
QList<int> debuggercontext;
|
||||
debuggercontext << uidm->uniqueIdentifier(C_GDBDEBUGGER);
|
||||
|
||||
QList<int> cppeditorcontext;
|
||||
cppeditorcontext << uidm->uniqueIdentifier(CppEditor::Constants::C_CPPEDITOR);
|
||||
|
||||
QList<int> texteditorcontext;
|
||||
texteditorcontext << uidm->uniqueIdentifier(TextEditor::Constants::C_TEXTEDITOR);
|
||||
|
||||
m_gdbRunningContext = uidm->uniqueIdentifier(Constants::GDBRUNNING);
|
||||
|
||||
//Core::IActionContainer *mcppcontext =
|
||||
// actionManager->actionContainer(CppEditor::Constants::M_CONTEXT);
|
||||
|
||||
Core::IActionContainer *mdebug =
|
||||
actionManager->actionContainer(ProjectExplorer::Constants::M_DEBUG);
|
||||
|
||||
Core::ICommand *cmd = 0;
|
||||
cmd = actionManager->registerAction(m_manager->m_startExternalAction,
|
||||
Constants::STARTEXTERNAL, globalcontext);
|
||||
mdebug->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
cmd = actionManager->registerAction(m_manager->m_attachExternalAction,
|
||||
Constants::ATTACHEXTERNAL, globalcontext);
|
||||
mdebug->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
|
||||
#endif
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_continueAction,
|
||||
ProjectExplorer::Constants::DEBUG, QList<int>()<< m_gdbRunningContext);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_stopAction,
|
||||
Constants::INTERRUPT, globalcontext);
|
||||
cmd->setAttribute(Core::ICommand::CA_UpdateText);
|
||||
cmd->setAttribute(Core::ICommand::CA_UpdateIcon);
|
||||
cmd->setDefaultKeySequence(QKeySequence(Constants::INTERRUPT_KEY));
|
||||
cmd->setDefaultText(tr("Stop Debugger/Interrupt Debugger"));
|
||||
mdebug->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_resetAction,
|
||||
Constants::RESET, globalcontext);
|
||||
cmd->setAttribute(Core::ICommand::CA_UpdateText);
|
||||
cmd->setDefaultKeySequence(QKeySequence(Constants::RESET_KEY));
|
||||
cmd->setDefaultText(tr("Reset Debugger"));
|
||||
//disabled mdebug->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
|
||||
|
||||
QAction *sep = new QAction(this);
|
||||
sep->setSeparator(true);
|
||||
cmd = actionManager->registerAction(sep,
|
||||
QLatin1String("GdbDebugger.Sep1"), globalcontext);
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_nextAction,
|
||||
Constants::NEXT, debuggercontext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(Constants::NEXT_KEY));
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_stepAction,
|
||||
Constants::STEP, debuggercontext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(Constants::STEP_KEY));
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_stepOutAction,
|
||||
Constants::STEPOUT, debuggercontext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(Constants::STEPOUT_KEY));
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_nextIAction,
|
||||
Constants::NEXTI, debuggercontext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(Constants::NEXTI_KEY));
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_stepIAction,
|
||||
Constants::STEPI, debuggercontext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(Constants::STEPI_KEY));
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_runToLineAction,
|
||||
Constants::RUN_TO_LINE, debuggercontext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(Constants::RUN_TO_LINE_KEY));
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_runToFunctionAction,
|
||||
Constants::RUN_TO_FUNCTION, debuggercontext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(Constants::RUN_TO_FUNCTION_KEY));
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_jumpToLineAction,
|
||||
Constants::JUMP_TO_LINE, debuggercontext);
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
sep = new QAction(this);
|
||||
sep->setSeparator(true);
|
||||
cmd = actionManager->registerAction(sep,
|
||||
QLatin1String("GdbDebugger.Sep3"), globalcontext);
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_breakAction,
|
||||
Constants::TOGGLE_BREAK, cppeditorcontext);
|
||||
cmd->setDefaultKeySequence(QKeySequence(Constants::TOGGLE_BREAK_KEY));
|
||||
mdebug->addAction(cmd);
|
||||
//mcppcontext->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_breakByFunctionAction,
|
||||
Constants::BREAK_BY_FUNCTION, globalcontext);
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_breakAtMainAction,
|
||||
Constants::BREAK_AT_MAIN, globalcontext);
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
sep = new QAction(this);
|
||||
sep->setSeparator(true);
|
||||
cmd = actionManager->registerAction(sep,
|
||||
QLatin1String("GdbDebugger.Sep2"), globalcontext);
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_skipKnownFramesAction,
|
||||
Constants::SKIP_KNOWN_FRAMES, globalcontext);
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_useCustomDumpersAction,
|
||||
Constants::USE_CUSTOM_DUMPERS, globalcontext);
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_useFastStartAction,
|
||||
Constants::USE_FAST_START, globalcontext);
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_dumpLogAction,
|
||||
Constants::DUMP_LOG, globalcontext);
|
||||
//cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+D,Ctrl+L")));
|
||||
cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+F11")));
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
cmd = actionManager->registerAction(m_manager->m_debugDumpersAction,
|
||||
Constants::DEBUG_DUMPERS, debuggercontext);
|
||||
mdebug->addAction(cmd);
|
||||
#endif
|
||||
|
||||
sep = new QAction(this);
|
||||
sep->setSeparator(true);
|
||||
cmd = actionManager->registerAction(sep,
|
||||
QLatin1String("GdbDebugger.Sep4"), globalcontext);
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
cmd = actionManager->registerAction(m_manager->m_watchAction,
|
||||
Constants::ADD_TO_WATCH, cppeditorcontext);
|
||||
//cmd->setDefaultKeySequence(QKeySequence(tr("ALT+D,ALT+W")));
|
||||
mdebug->addAction(cmd);
|
||||
|
||||
m_generalOptionPage = 0;
|
||||
m_typeMacroPage = 0;
|
||||
|
||||
// FIXME:
|
||||
m_generalOptionPage = new GdbOptionPage(&theGdbSettings());
|
||||
addObject(m_generalOptionPage);
|
||||
m_typeMacroPage = new TypeMacroPage(&theGdbSettings());
|
||||
addObject(m_typeMacroPage);
|
||||
|
||||
m_locationMark = 0;
|
||||
|
||||
m_debugMode = new DebugMode(m_manager, this);
|
||||
//addAutoReleasedObject(m_debugMode);
|
||||
addObject(m_debugMode);
|
||||
|
||||
addAutoReleasedObject(new DebuggerRunner(m_manager));
|
||||
|
||||
// ProjectExplorer
|
||||
connect(projectExplorer()->session(), SIGNAL(sessionLoaded()),
|
||||
m_manager, SLOT(sessionLoaded()));
|
||||
connect(projectExplorer()->session(), SIGNAL(aboutToSaveSession()),
|
||||
m_manager, SLOT(aboutToSaveSession()));
|
||||
|
||||
// EditorManager
|
||||
QObject *editorManager = core->editorManager();
|
||||
connect(editorManager, SIGNAL(editorAboutToClose(Core::IEditor*)),
|
||||
this, SLOT(editorAboutToClose(Core::IEditor*)));
|
||||
connect(editorManager, SIGNAL(editorOpened(Core::IEditor*)),
|
||||
this, SLOT(editorOpened(Core::IEditor*)));
|
||||
|
||||
// Application interaction
|
||||
connect(m_manager, SIGNAL(currentTextEditorRequested(QString*,int*,QObject**)),
|
||||
this, SLOT(queryCurrentTextEditor(QString*,int*,QObject**)));
|
||||
|
||||
connect(m_manager, SIGNAL(setSessionValueRequested(QString,QVariant)),
|
||||
this, SLOT(setSessionValue(QString,QVariant)));
|
||||
connect(m_manager, SIGNAL(sessionValueRequested(QString,QVariant*)),
|
||||
this, SLOT(querySessionValue(QString,QVariant*)));
|
||||
connect(m_manager, SIGNAL(setConfigValueRequested(QString,QVariant)),
|
||||
this, SLOT(setConfigValue(QString,QVariant)));
|
||||
connect(m_manager, SIGNAL(configValueRequested(QString,QVariant*)),
|
||||
this, SLOT(queryConfigValue(QString,QVariant*)));
|
||||
|
||||
connect(m_manager, SIGNAL(resetLocationRequested()),
|
||||
this, SLOT(resetLocation()));
|
||||
connect(m_manager, SIGNAL(gotoLocationRequested(QString,int,bool)),
|
||||
this, SLOT(gotoLocation(QString,int,bool)));
|
||||
connect(m_manager, SIGNAL(statusChanged(int)),
|
||||
this, SLOT(changeStatus(int)));
|
||||
connect(m_manager, SIGNAL(previousModeRequested()),
|
||||
this, SLOT(activatePreviousMode()));
|
||||
connect(m_manager, SIGNAL(debugModeRequested()),
|
||||
this, SLOT(activateDebugMode()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DebuggerPlugin::extensionsInitialized()
|
||||
{
|
||||
}
|
||||
|
||||
ProjectExplorer::ProjectExplorerPlugin *DebuggerPlugin::projectExplorer() const
|
||||
{
|
||||
return m_pm->getObject<ProjectExplorer::ProjectExplorerPlugin>();
|
||||
}
|
||||
|
||||
/*! Activates the previous mode when the current mode is the debug mode. */
|
||||
void DebuggerPlugin::activatePreviousMode()
|
||||
{
|
||||
ICore *core = m_pm->getObject<Core::ICore>();
|
||||
Core::ModeManager *const modeManager = core->modeManager();
|
||||
|
||||
if (modeManager->currentMode() == modeManager->mode(Constants::MODE_DEBUG)
|
||||
&& !m_previousMode.isEmpty()) {
|
||||
modeManager->activateMode(m_previousMode);
|
||||
m_previousMode.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerPlugin::activateDebugMode()
|
||||
{
|
||||
ICore *core = m_pm->getObject<Core::ICore>();
|
||||
Core::ModeManager *modeManager = core->modeManager();
|
||||
m_previousMode = QLatin1String(modeManager->currentMode()->uniqueModeName());
|
||||
modeManager->activateMode(QLatin1String(MODE_DEBUG));
|
||||
}
|
||||
|
||||
void DebuggerPlugin::queryCurrentTextEditor(QString *fileName, int *lineNumber, QObject **object)
|
||||
{
|
||||
ICore *core = m_pm->getObject<Core::ICore>();
|
||||
if (!core || !core->editorManager())
|
||||
return;
|
||||
Core::IEditor *editor = core->editorManager()->currentEditor();
|
||||
ITextEditor *textEditor = qobject_cast<ITextEditor*>(editor);
|
||||
if (!textEditor)
|
||||
return;
|
||||
if (fileName)
|
||||
*fileName = textEditor->file()->fileName();
|
||||
if (lineNumber)
|
||||
*lineNumber = textEditor->currentLine();
|
||||
if (object)
|
||||
*object = textEditor->widget();
|
||||
}
|
||||
|
||||
void DebuggerPlugin::editorOpened(Core::IEditor *editor)
|
||||
{
|
||||
if (ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor)) {
|
||||
connect(textEditor, SIGNAL(markRequested(TextEditor::ITextEditor*,int)),
|
||||
this, SLOT(requestMark(TextEditor::ITextEditor*,int)));
|
||||
connect(editor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*,QPoint,int)),
|
||||
this, SLOT(showToolTip(TextEditor::ITextEditor*,QPoint,int)));
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerPlugin::editorAboutToClose(Core::IEditor *editor)
|
||||
{
|
||||
if (ITextEditor *textEditor = qobject_cast<ITextEditor *>(editor)) {
|
||||
disconnect(textEditor, SIGNAL(markRequested(TextEditor::ITextEditor*,int)),
|
||||
this, SLOT(requestMark(TextEditor::ITextEditor*,int)));
|
||||
disconnect(editor, SIGNAL(tooltipRequested(TextEditor::ITextEditor*,QPoint,int)),
|
||||
this, SLOT(showToolTip(TextEditor::ITextEditor*,QPoint,int)));
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerPlugin::requestMark(TextEditor::ITextEditor *editor, int lineNumber)
|
||||
{
|
||||
m_manager->toggleBreakpoint(editor->file()->fileName(), lineNumber);
|
||||
}
|
||||
|
||||
void DebuggerPlugin::showToolTip(TextEditor::ITextEditor *editor,
|
||||
const QPoint &point, int pos)
|
||||
{
|
||||
QPlainTextEdit *plaintext = qobject_cast<QPlainTextEdit*>(editor->widget());
|
||||
if (!plaintext)
|
||||
return;
|
||||
|
||||
QString expr = plaintext->textCursor().selectedText();
|
||||
if (expr.isEmpty()) {
|
||||
QTextCursor tc(plaintext->document());
|
||||
tc.setPosition(pos);
|
||||
|
||||
const QChar ch = editor->characterAt(pos);
|
||||
if (ch.isLetterOrNumber() || ch == QLatin1Char('_'))
|
||||
tc.movePosition(QTextCursor::EndOfWord);
|
||||
|
||||
// Fetch the expression's code.
|
||||
ExpressionUnderCursor expressionUnderCursor;
|
||||
expr = expressionUnderCursor(tc);
|
||||
}
|
||||
//qDebug() << " TOOLTIP EXPR " << expr;
|
||||
m_manager->setToolTipExpression(point, expr);
|
||||
}
|
||||
|
||||
void DebuggerPlugin::setSessionValue(const QString &name, const QVariant &value)
|
||||
{
|
||||
//qDebug() << "SET SESSION VALUE" << name << value;
|
||||
ProjectExplorerPlugin *pe = projectExplorer();
|
||||
if (pe->session())
|
||||
pe->session()->setValue(name, value);
|
||||
else
|
||||
qDebug() << "FIXME: Session does not exist yet";
|
||||
}
|
||||
|
||||
void DebuggerPlugin::querySessionValue(const QString &name, QVariant *value)
|
||||
{
|
||||
ProjectExplorerPlugin *pe = projectExplorer();
|
||||
*value = pe->session()->value(name);
|
||||
//qDebug() << "GET SESSION VALUE: " << name << value;
|
||||
}
|
||||
|
||||
|
||||
void DebuggerPlugin::setConfigValue(const QString &name, const QVariant &value)
|
||||
{
|
||||
QWB_ASSERT(m_debugMode, return);
|
||||
m_debugMode->settings()->setValue(name, value);
|
||||
}
|
||||
|
||||
void DebuggerPlugin::queryConfigValue(const QString &name, QVariant *value)
|
||||
{
|
||||
QWB_ASSERT(m_debugMode, return);
|
||||
*value = m_debugMode->settings()->value(name);
|
||||
}
|
||||
|
||||
void DebuggerPlugin::resetLocation()
|
||||
{
|
||||
//qDebug() << "RESET_LOCATION: current:" << currentTextEditor();
|
||||
//qDebug() << "RESET_LOCATION: locations:" << m_locationMark;
|
||||
//qDebug() << "RESET_LOCATION: stored:" << m_locationMark->editor();
|
||||
delete m_locationMark;
|
||||
m_locationMark = 0;
|
||||
}
|
||||
|
||||
void DebuggerPlugin::gotoLocation(const QString &fileName, int lineNumber,
|
||||
bool setMarker)
|
||||
{
|
||||
TextEditor::BaseTextEditor::openEditorAt(fileName, lineNumber);
|
||||
if (setMarker) {
|
||||
resetLocation();
|
||||
m_locationMark = new LocationMark(fileName, lineNumber);
|
||||
}
|
||||
}
|
||||
|
||||
void DebuggerPlugin::changeStatus(int status)
|
||||
{
|
||||
bool startIsContinue = (status == DebuggerInferiorStopped);
|
||||
ICore *core = m_pm->getObject<Core::ICore>();
|
||||
if (startIsContinue) {
|
||||
core->addAdditionalContext(m_gdbRunningContext);
|
||||
core->updateContext();
|
||||
} else {
|
||||
core->removeAdditionalContext(m_gdbRunningContext);
|
||||
core->updateContext();
|
||||
}
|
||||
}
|
||||
|
||||
#include "debuggerplugin.moc"
|
||||
|
||||
Q_EXPORT_PLUGIN(DebuggerPlugin)
|
||||
111
src/plugins/debugger/debuggerplugin.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGERPLUGIN_H
|
||||
#define DEBUGGERPLUGIN_H
|
||||
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <extensionsystem/iplugin.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAction;
|
||||
class QCursor;
|
||||
class QAbstractItemView;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Core { class IEditor; }
|
||||
namespace TextEditor { class ITextEditor; }
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class DebuggerManager;
|
||||
class DebugMode;
|
||||
class GdbOptionPage;
|
||||
class TypeMacroPage;
|
||||
class LocationMark;
|
||||
|
||||
class DebuggerPlugin : public ExtensionSystem::IPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DebuggerPlugin();
|
||||
~DebuggerPlugin();
|
||||
|
||||
private:
|
||||
bool initialize(const QStringList &arguments, QString *error_message);
|
||||
void shutdown();
|
||||
void extensionsInitialized();
|
||||
|
||||
private slots:
|
||||
void activatePreviousMode();
|
||||
void activateDebugMode();
|
||||
void queryCurrentTextEditor(QString *fileName, int *line, QObject **object);
|
||||
void editorOpened(Core::IEditor *);
|
||||
void editorAboutToClose(Core::IEditor *);
|
||||
void changeStatus(int status);
|
||||
void requestMark(TextEditor::ITextEditor *editor, int lineNumber);
|
||||
void showToolTip(TextEditor::ITextEditor *editor, const QPoint &pnt, int pos);
|
||||
|
||||
void querySessionValue(const QString &name, QVariant *value);
|
||||
void setSessionValue(const QString &name, const QVariant &value);
|
||||
void queryConfigValue(const QString &name, QVariant *value);
|
||||
void setConfigValue(const QString &name, const QVariant &value);
|
||||
|
||||
void resetLocation();
|
||||
void gotoLocation(const QString &fileName, int line, bool setMarker);
|
||||
|
||||
private:
|
||||
friend class DebuggerManager;
|
||||
friend class DebugMode; // FIXME: Just a hack now so that it can access the views
|
||||
|
||||
ProjectExplorer::ProjectExplorerPlugin *projectExplorer() const;
|
||||
|
||||
DebuggerManager *m_manager;
|
||||
DebugMode *m_debugMode;
|
||||
|
||||
ExtensionSystem::PluginManager *m_pm;
|
||||
GdbOptionPage *m_generalOptionPage;
|
||||
TypeMacroPage *m_typeMacroPage;
|
||||
|
||||
QString m_previousMode;
|
||||
LocationMark *m_locationMark;
|
||||
int m_gdbRunningContext;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGERPLUGIN_H
|
||||
161
src/plugins/debugger/debuggerrunner.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "debuggerrunner.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "debuggermanager.h"
|
||||
|
||||
#include <projectexplorer/applicationrunconfiguration.h>
|
||||
#include <projectexplorer/environment.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QFileInfo>
|
||||
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
using ProjectExplorer::RunConfiguration;
|
||||
using ProjectExplorer::RunControl;
|
||||
using ProjectExplorer::ApplicationRunConfiguration;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DebuggerRunner
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DebuggerRunner::DebuggerRunner(DebuggerManager *manager)
|
||||
: m_manager(manager)
|
||||
{}
|
||||
|
||||
bool DebuggerRunner::canRun(RunConfigurationPtr runConfiguration, const QString &mode)
|
||||
{
|
||||
return mode == ProjectExplorer::Constants::DEBUGMODE
|
||||
&& !qSharedPointerCast<ApplicationRunConfiguration>(runConfiguration).isNull();
|
||||
}
|
||||
|
||||
QString DebuggerRunner::displayName() const
|
||||
{
|
||||
return QObject::tr("Debug");
|
||||
}
|
||||
|
||||
RunControl* DebuggerRunner::run(RunConfigurationPtr runConfiguration, const QString &mode)
|
||||
{
|
||||
Q_UNUSED(mode);
|
||||
Q_ASSERT(mode == ProjectExplorer::Constants::DEBUGMODE);
|
||||
ApplicationRunConfigurationPtr rc =
|
||||
qSharedPointerCast<ApplicationRunConfiguration>(runConfiguration);
|
||||
Q_ASSERT(rc);
|
||||
//qDebug() << "***** Debugging" << rc->name() << rc->executable();
|
||||
return new DebuggerRunControl(m_manager, rc);
|
||||
}
|
||||
|
||||
QWidget *DebuggerRunner::configurationWidget(RunConfigurationPtr runConfiguration)
|
||||
{
|
||||
// NBS TODO: Add GDB-specific configuration widget
|
||||
Q_UNUSED(runConfiguration);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DebuggerRunControl
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
DebuggerRunControl::DebuggerRunControl(DebuggerManager *manager,
|
||||
QSharedPointer<ApplicationRunConfiguration> runConfiguration)
|
||||
: RunControl(runConfiguration), m_manager(manager), m_running(false)
|
||||
{
|
||||
connect(m_manager, SIGNAL(debuggingFinished()),
|
||||
this, SLOT(debuggingFinished()));
|
||||
connect(m_manager, SIGNAL(applicationOutputAvailable(QString, QString)),
|
||||
this, SLOT(slotAddToOutputWindow(QString, QString)));
|
||||
connect(m_manager, SIGNAL(inferiorPidChanged(qint64)),
|
||||
this, SLOT(bringApplicationToForeground(qint64)));
|
||||
}
|
||||
|
||||
void DebuggerRunControl::start()
|
||||
{
|
||||
m_running = true;
|
||||
ApplicationRunConfigurationPtr rc =
|
||||
qSharedPointerCast<ApplicationRunConfiguration>(runConfiguration());
|
||||
QWB_ASSERT(rc, return);
|
||||
ProjectExplorer::Project *project = rc->project();
|
||||
QWB_ASSERT(project, return);
|
||||
|
||||
m_manager->m_executable = rc->executable();
|
||||
m_manager->m_environment = rc->environment().toStringList();
|
||||
m_manager->m_workingDir = rc->workingDirectory();
|
||||
m_manager->m_processArgs = rc->commandLineArguments();
|
||||
m_manager->m_buildDir =
|
||||
project->buildDirectory(project->activeBuildConfiguration());
|
||||
//<daniel> andre: + "\qtc-gdbmacros\"
|
||||
|
||||
//emit addToOutputWindow(this, tr("Debugging %1").arg(m_executable));
|
||||
if (m_manager->startNewDebugger(DebuggerManager::startInternal))
|
||||
emit started();
|
||||
else
|
||||
debuggingFinished();
|
||||
}
|
||||
|
||||
void DebuggerRunControl::slotAddToOutputWindow(const QString &prefix, const QString &line)
|
||||
{
|
||||
Q_UNUSED(prefix);
|
||||
foreach (const QString &l, line.split('\n'))
|
||||
emit addToOutputWindow(this, prefix + l);
|
||||
//emit addToOutputWindow(this, prefix + line);
|
||||
}
|
||||
|
||||
void DebuggerRunControl::stop()
|
||||
{
|
||||
m_manager->exitDebugger();
|
||||
}
|
||||
|
||||
void DebuggerRunControl::debuggingFinished()
|
||||
{
|
||||
m_running = false;
|
||||
//emit addToOutputWindow(this, tr("Debugging %1 finished").arg(m_executable));
|
||||
emit finished();
|
||||
}
|
||||
|
||||
bool DebuggerRunControl::isRunning() const
|
||||
{
|
||||
return m_running;
|
||||
}
|
||||
96
src/plugins/debugger/debuggerrunner.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGERRUNNER_H
|
||||
#define DEBUGGERRUNNER_H
|
||||
|
||||
#include <projectexplorer/runconfiguration.h>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class ApplicationRunConfiguration;
|
||||
}
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class DebuggerManager;
|
||||
class StartData;
|
||||
|
||||
typedef QSharedPointer<ProjectExplorer::RunConfiguration>
|
||||
RunConfigurationPtr;
|
||||
|
||||
typedef QSharedPointer<ProjectExplorer::ApplicationRunConfiguration>
|
||||
ApplicationRunConfigurationPtr;
|
||||
|
||||
class DebuggerRunner : public ProjectExplorer::IRunConfigurationRunner
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DebuggerRunner(DebuggerManager *manager);
|
||||
|
||||
virtual bool canRun(RunConfigurationPtr runConfiguration, const QString &mode);
|
||||
virtual QString displayName() const;
|
||||
virtual ProjectExplorer::RunControl *run(RunConfigurationPtr runConfiguration,
|
||||
const QString &mode);
|
||||
virtual QWidget *configurationWidget(RunConfigurationPtr runConfiguration);
|
||||
|
||||
private:
|
||||
DebuggerManager *m_manager;
|
||||
};
|
||||
|
||||
|
||||
class DebuggerRunControl : public ProjectExplorer::RunControl
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DebuggerRunControl(DebuggerManager *manager,
|
||||
ApplicationRunConfigurationPtr runConfiguration);
|
||||
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual bool isRunning() const;
|
||||
|
||||
private slots:
|
||||
void debuggingFinished();
|
||||
void slotAddToOutputWindow(const QString &prefix, const QString &line);
|
||||
|
||||
private:
|
||||
DebuggerManager *m_manager;
|
||||
bool m_running;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGERRUNNER_H
|
||||
187
src/plugins/debugger/disassemblerhandler.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "disassemblerhandler.h"
|
||||
|
||||
#include "assert.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QAbstractTableModel>
|
||||
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
using namespace Debugger;
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DisassemblerModel
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
/*! A model to represent the stack in a QTreeView. */
|
||||
class Debugger::Internal::DisassemblerModel : public QAbstractTableModel
|
||||
{
|
||||
public:
|
||||
DisassemblerModel(QObject *parent);
|
||||
|
||||
// ItemModel
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
|
||||
// Properties
|
||||
void setLines(const QList<DisassemblerLine> &lines);
|
||||
QList<DisassemblerLine> lines() const;
|
||||
void setCurrentLine(int line) { m_currentLine = line; }
|
||||
|
||||
private:
|
||||
friend class DisassemblerHandler;
|
||||
QList<DisassemblerLine> m_lines;
|
||||
int m_currentLine;
|
||||
QIcon m_positionIcon;
|
||||
QIcon m_emptyIcon;
|
||||
};
|
||||
|
||||
DisassemblerModel::DisassemblerModel(QObject *parent)
|
||||
: QAbstractTableModel(parent), m_currentLine(0)
|
||||
{
|
||||
m_emptyIcon = QIcon(":/gdbdebugger/images/empty.svg");
|
||||
m_positionIcon = QIcon(":/gdbdebugger/images/location.svg");
|
||||
}
|
||||
|
||||
int DisassemblerModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return m_lines.size();
|
||||
}
|
||||
|
||||
int DisassemblerModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return 3;
|
||||
}
|
||||
|
||||
QVariant DisassemblerModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() >= m_lines.size())
|
||||
return QVariant();
|
||||
|
||||
const DisassemblerLine &line = m_lines.at(index.row());
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (index.column()) {
|
||||
case 0:
|
||||
return line.addressDisplay;
|
||||
case 1:
|
||||
return line.symbolDisplay;
|
||||
case 2:
|
||||
return line.mnemonic;
|
||||
}
|
||||
} else if (role == Qt::ToolTipRole) {
|
||||
return QString();
|
||||
} else if (role == Qt::DecorationRole && index.column() == 0) {
|
||||
// Return icon that indicates whether this is the active stack frame
|
||||
return (index.row() == m_currentLine) ? m_positionIcon : m_emptyIcon;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant DisassemblerModel::headerData(int section, Qt::Orientation orientation,
|
||||
int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||
static const char * const headers[] = {
|
||||
QT_TR_NOOP("Address"),
|
||||
QT_TR_NOOP("Symbol"),
|
||||
QT_TR_NOOP("Mnemonic"),
|
||||
};
|
||||
if (section < 3)
|
||||
return tr(headers[section]);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void DisassemblerModel::setLines(const QList<DisassemblerLine> &lines)
|
||||
{
|
||||
m_lines = lines;
|
||||
if (m_currentLine >= m_lines.size())
|
||||
m_currentLine = m_lines.size() - 1;
|
||||
reset();
|
||||
}
|
||||
|
||||
QList<DisassemblerLine> DisassemblerModel::lines() const
|
||||
{
|
||||
return m_lines;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DisassemblerHandler
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
DisassemblerHandler::DisassemblerHandler()
|
||||
{
|
||||
m_model = new DisassemblerModel(this);
|
||||
}
|
||||
|
||||
void DisassemblerHandler::removeAll()
|
||||
{
|
||||
m_model->m_lines.clear();
|
||||
}
|
||||
|
||||
QAbstractItemModel *DisassemblerHandler::model() const
|
||||
{
|
||||
return m_model;
|
||||
}
|
||||
|
||||
void DisassemblerHandler::setLines(const QList<DisassemblerLine> &lines)
|
||||
{
|
||||
m_model->setLines(lines);
|
||||
}
|
||||
|
||||
QList<DisassemblerLine> DisassemblerHandler::lines() const
|
||||
{
|
||||
return m_model->lines();
|
||||
}
|
||||
|
||||
void DisassemblerHandler::setCurrentLine(int line)
|
||||
{
|
||||
m_model->setCurrentLine(line);
|
||||
}
|
||||
78
src/plugins/debugger/disassemblerhandler.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DISASSEMBLERHANDLER_H
|
||||
#define DISASSEMBLERHANDLER_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QAbstractItemModel>
|
||||
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class DisassemblerLine
|
||||
{
|
||||
public:
|
||||
QString address;
|
||||
QString symbol;
|
||||
QString addressDisplay;
|
||||
QString symbolDisplay;
|
||||
QString mnemonic;
|
||||
};
|
||||
|
||||
class DisassemblerModel;
|
||||
|
||||
class DisassemblerHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DisassemblerHandler();
|
||||
QAbstractItemModel *model() const;
|
||||
|
||||
public slots:
|
||||
void removeAll();
|
||||
|
||||
void setLines(const QList<DisassemblerLine> &lines);
|
||||
QList<DisassemblerLine> lines() const;
|
||||
void setCurrentLine(int line);
|
||||
|
||||
private:
|
||||
DisassemblerModel *m_model;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DISASSEMBLERHANDLER_H
|
||||
140
src/plugins/debugger/disassemblerwindow.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "disassemblerwindow.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
#include <QResizeEvent>
|
||||
|
||||
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
DisassemblerWindow::DisassemblerWindow()
|
||||
: m_alwaysResizeColumnsToContents(true), m_alwaysReloadContents(false)
|
||||
{
|
||||
setWindowTitle(tr("Disassembler"));
|
||||
setSortingEnabled(false);
|
||||
setAlternatingRowColors(true);
|
||||
setRootIsDecorated(false);
|
||||
header()->hide();
|
||||
//setIconSize(QSize(10, 10));
|
||||
//setWindowIcon(QIcon(":/gdbdebugger/images/debugger_breakpoints.png"));
|
||||
//QHeaderView *hv = header();
|
||||
//hv->setDefaultAlignment(Qt::AlignLeft);
|
||||
//hv->setClickable(true);
|
||||
//hv->setSortIndicatorShown(true);
|
||||
}
|
||||
|
||||
void DisassemblerWindow::resizeEvent(QResizeEvent *ev)
|
||||
{
|
||||
//QHeaderView *hv = header();
|
||||
//int totalSize = ev->size().width() - 110;
|
||||
//hv->resizeSection(0, 60);
|
||||
//hv->resizeSection(1, (totalSize * 50) / 100);
|
||||
//hv->resizeSection(2, (totalSize * 50) / 100);
|
||||
//hv->resizeSection(3, 50);
|
||||
QTreeView::resizeEvent(ev);
|
||||
}
|
||||
|
||||
void DisassemblerWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
{
|
||||
QMenu menu;
|
||||
//QTreeWidgetItem *item = itemAt(ev->pos());
|
||||
QAction *act1 = new QAction("Adjust column widths to contents", &menu);
|
||||
QAction *act2 = new QAction("Always adjust column widths to contents", &menu);
|
||||
act2->setCheckable(true);
|
||||
act2->setChecked(m_alwaysResizeColumnsToContents);
|
||||
QAction *act3 = new QAction("Reload disassembler listing", &menu);
|
||||
QAction *act4 = new QAction("Always reload disassembler listing", &menu);
|
||||
act4->setCheckable(true);
|
||||
act4->setChecked(m_alwaysReloadContents);
|
||||
//if (item) {
|
||||
// menu.addAction(act0);
|
||||
// menu.addSeparator();
|
||||
//}
|
||||
menu.addAction(act3);
|
||||
//menu.addAction(act4);
|
||||
menu.addSeparator();
|
||||
menu.addAction(act1);
|
||||
menu.addAction(act2);
|
||||
|
||||
QAction *act = menu.exec(ev->globalPos());
|
||||
|
||||
if (act == act1)
|
||||
resizeColumnsToContents();
|
||||
else if (act == act2)
|
||||
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
|
||||
else if (act == act3)
|
||||
reloadContents();
|
||||
else if (act == act2)
|
||||
setAlwaysReloadContents(!m_alwaysReloadContents);
|
||||
}
|
||||
|
||||
void DisassemblerWindow::resizeColumnsToContents()
|
||||
{
|
||||
resizeColumnToContents(0);
|
||||
resizeColumnToContents(1);
|
||||
resizeColumnToContents(2);
|
||||
}
|
||||
|
||||
void DisassemblerWindow::setAlwaysResizeColumnsToContents(bool on)
|
||||
{
|
||||
m_alwaysResizeColumnsToContents = on;
|
||||
QHeaderView::ResizeMode mode = on
|
||||
? QHeaderView::ResizeToContents : QHeaderView::Interactive;
|
||||
header()->setResizeMode(0, mode);
|
||||
header()->setResizeMode(1, mode);
|
||||
header()->setResizeMode(2, mode);
|
||||
}
|
||||
|
||||
void DisassemblerWindow::setAlwaysReloadContents(bool on)
|
||||
{
|
||||
m_alwaysReloadContents = on;
|
||||
if (m_alwaysReloadContents)
|
||||
reloadContents();
|
||||
}
|
||||
|
||||
void DisassemblerWindow::reloadContents()
|
||||
{
|
||||
emit reloadDisassemblerRequested();
|
||||
}
|
||||
|
||||
|
||||
void DisassemblerWindow::setModel(QAbstractItemModel *model)
|
||||
{
|
||||
QTreeView::setModel(model);
|
||||
setAlwaysResizeColumnsToContents(true);
|
||||
}
|
||||
|
||||
71
src/plugins/debugger/disassemblerwindow.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_DISASSEMBLERWINDOW_H
|
||||
#define DEBUGGER_DISASSEMBLERWINDOW_H
|
||||
|
||||
#include <QTreeView>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class DisassemblerWindow : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DisassemblerWindow();
|
||||
void setModel(QAbstractItemModel *model);
|
||||
|
||||
signals:
|
||||
void reloadDisassemblerRequested();
|
||||
|
||||
public slots:
|
||||
void resizeColumnsToContents();
|
||||
void setAlwaysResizeColumnsToContents(bool on);
|
||||
void reloadContents();
|
||||
void setAlwaysReloadContents(bool on);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *ev);
|
||||
void contextMenuEvent(QContextMenuEvent *ev);
|
||||
|
||||
private:
|
||||
bool m_alwaysResizeColumnsToContents;
|
||||
bool m_alwaysReloadContents;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_DISASSEMBLERWINDOW_H
|
||||
|
||||
4035
src/plugins/debugger/gdbengine.cpp
Normal file
351
src/plugins/debugger/gdbengine.h
Normal file
@@ -0,0 +1,351 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_GDBENGINE_H
|
||||
#define DEBUGGER_GDBENGINE_H
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QPoint>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAction;
|
||||
class QAbstractItemModel;
|
||||
class QWidget;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "idebuggerengine.h"
|
||||
#include "gdbmi.h"
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class DebuggerManager;
|
||||
class IDebuggerManagerAccessForEngines;
|
||||
class GdbResultRecord;
|
||||
class GdbMi;
|
||||
|
||||
class WatchData;
|
||||
class BreakpointData;
|
||||
|
||||
struct GdbCookie
|
||||
{
|
||||
GdbCookie() : type(0), synchronized(false) {}
|
||||
|
||||
QString command;
|
||||
int type;
|
||||
bool synchronized;
|
||||
QVariant cookie;
|
||||
};
|
||||
|
||||
enum DataDumperState
|
||||
{
|
||||
DataDumperUninitialized,
|
||||
DataDumperLoadTried,
|
||||
DataDumperAvailable,
|
||||
DataDumperUnavailable,
|
||||
};
|
||||
|
||||
// FIXME: Move to extra file?
|
||||
class GdbSettings
|
||||
{
|
||||
public:
|
||||
GdbSettings() { m_autoRun = m_autoQuit = false; }
|
||||
|
||||
public:
|
||||
QString m_gdbCmd;
|
||||
QString m_gdbEnv;
|
||||
bool m_autoRun;
|
||||
bool m_autoQuit;
|
||||
|
||||
QString m_scriptFile;
|
||||
QMap<QString, QVariant> m_typeMacros;
|
||||
};
|
||||
|
||||
GdbSettings &theGdbSettings();
|
||||
|
||||
class GdbEngine : public IDebuggerEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GdbEngine(DebuggerManager *parent);
|
||||
~GdbEngine();
|
||||
|
||||
signals:
|
||||
void gdbResponseAvailable();
|
||||
void gdbInputAvailable(const QString &prefix, const QString &msg);
|
||||
void gdbOutputAvailable(const QString &prefix, const QString &msg);
|
||||
void applicationOutputAvailable(const QString &prefix, const QString &msg);
|
||||
|
||||
private:
|
||||
//
|
||||
// IDebuggerEngine implementation
|
||||
//
|
||||
void stepExec();
|
||||
void stepOutExec();
|
||||
void nextExec();
|
||||
void stepIExec();
|
||||
void nextIExec();
|
||||
|
||||
void shutdown();
|
||||
void setToolTipExpression(const QPoint &pos, const QString &exp);
|
||||
bool startDebugger();
|
||||
void exitDebugger();
|
||||
|
||||
void continueInferior();
|
||||
void runInferior();
|
||||
void interruptInferior();
|
||||
|
||||
void runToLineExec(const QString &fileName, int lineNumber);
|
||||
void runToFunctionExec(const QString &functionName);
|
||||
void jumpToLineExec(const QString &fileName, int lineNumber);
|
||||
|
||||
void activateFrame(int index);
|
||||
void selectThread(int index);
|
||||
|
||||
Q_SLOT void attemptBreakpointSynchronization();
|
||||
|
||||
void loadSessionData() {}
|
||||
void saveSessionData() {}
|
||||
|
||||
void assignValueInDebugger(const QString &expr, const QString &value);
|
||||
void executeDebuggerCommand(const QString & command);
|
||||
|
||||
void loadSymbols(const QString &moduleName);
|
||||
void loadAllSymbols();
|
||||
|
||||
//
|
||||
// Own stuff
|
||||
//
|
||||
int currentFrame() const;
|
||||
QString currentWorkingDirectory() const { return m_pwd; }
|
||||
|
||||
bool supportsThreads() const;
|
||||
|
||||
void init(); // called by destructor
|
||||
void queryFullName(const QString &fileName, QString *fullName);
|
||||
QString fullName(const QString &fileName);
|
||||
QString shortName(const QString &fullName);
|
||||
// get one usable name out of these, try full names first
|
||||
QString fullName(const QStringList &candidates);
|
||||
|
||||
void handleResult(const GdbResultRecord &, int type, const QVariant &);
|
||||
|
||||
// type and cookie are sender-internal data, opaque for the "event
|
||||
// queue". resultNeeded == true increments m_pendingResults on
|
||||
// send and decrements on receipt, effectively preventing
|
||||
// watch model updates before everything is finished.
|
||||
void sendCommand(const QString & command,
|
||||
int type = 0, const QVariant &cookie = QVariant(),
|
||||
bool needStop = false, bool synchronized = false);
|
||||
void sendSynchronizedCommand(const QString & command,
|
||||
int type = 0, const QVariant &cookie = QVariant(),
|
||||
bool needStop = false);
|
||||
|
||||
void setTokenBarrier();
|
||||
|
||||
void updateLocals();
|
||||
|
||||
private slots:
|
||||
void setDebugDumpers(bool on);
|
||||
void setCustomDumpersWanted(bool on);
|
||||
|
||||
void handleResponse();
|
||||
|
||||
void gdbProcError(QProcess::ProcessError error);
|
||||
void readGdbStandardOutput();
|
||||
void readGdbStandardError();
|
||||
|
||||
private:
|
||||
int terminationIndex(const QByteArray &buffer, int &length);
|
||||
void handleStreamOutput(const QString &output, char code);
|
||||
void handleAsyncOutput2(const GdbMi &data);
|
||||
void handleAsyncOutput(const GdbMi &data);
|
||||
void handleResultRecord(const GdbResultRecord &response);
|
||||
void handleFileExecAndSymbols(const GdbResultRecord &response);
|
||||
void handleExecRun(const GdbResultRecord &response);
|
||||
void handleExecJumpToLine(const GdbResultRecord &response);
|
||||
void handleExecRunToFunction(const GdbResultRecord &response);
|
||||
void handleInfoShared(const GdbResultRecord &response);
|
||||
void handleInfoProc(const GdbResultRecord &response);
|
||||
void handleShowVersion(const GdbResultRecord &response);
|
||||
void handleQueryPwd(const GdbResultRecord &response);
|
||||
void handleQuerySources(const GdbResultRecord &response);
|
||||
void handleQuerySources2(const GdbResultRecord &response,
|
||||
const QVariant &);
|
||||
|
||||
QByteArray m_inbuffer;
|
||||
|
||||
QProcess m_gdbProc;
|
||||
|
||||
QHash<int, GdbCookie> m_cookieForToken;
|
||||
QHash<int, QByteArray> m_customOutputForToken;
|
||||
|
||||
QByteArray m_pendingConsoleStreamOutput;
|
||||
QByteArray m_pendingTargetStreamOutput;
|
||||
QByteArray m_pendingLogStreamOutput;
|
||||
//QByteArray m_pendingCustomValueContents;
|
||||
QString m_pwd;
|
||||
|
||||
// contains the first token number for the current round
|
||||
// of evaluation. Responses with older tokens are considers
|
||||
// out of date and discarded.
|
||||
int m_oldestAcceptableToken;
|
||||
|
||||
int m_gdbVersion; // 6.8.0 is 680
|
||||
int m_shared;
|
||||
|
||||
// awful hack to keep track of used files
|
||||
QHash<QString, QString> m_shortToFullName;
|
||||
QHash<QString, QString> m_fullToShortName;
|
||||
|
||||
//
|
||||
// Breakpoint specific stuff
|
||||
//
|
||||
void handleBreakList(const GdbResultRecord &record);
|
||||
void handleBreakList(const GdbMi &table);
|
||||
void handleBreakIgnore(const GdbResultRecord &record, int index);
|
||||
void handleBreakInsert(const GdbResultRecord &record, int index);
|
||||
void handleBreakInsert1(const GdbResultRecord &record, int index);
|
||||
void handleBreakCondition(const GdbResultRecord &record, int index);
|
||||
void handleBreakInfo(const GdbResultRecord &record, int index);
|
||||
void extractDataFromInfoBreak(const QString &output, BreakpointData *data);
|
||||
void breakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt);
|
||||
void sendInsertBreakpoint(int index);
|
||||
|
||||
|
||||
//
|
||||
// Disassembler specific stuff
|
||||
//
|
||||
void handleDisassemblerList(const GdbResultRecord &record,
|
||||
const QString &cookie);
|
||||
void reloadDisassembler();
|
||||
QString m_address;
|
||||
|
||||
|
||||
//
|
||||
// Modules specific stuff
|
||||
//
|
||||
void reloadModules();
|
||||
void handleModulesList(const GdbResultRecord &record);
|
||||
|
||||
|
||||
//
|
||||
// Register specific stuff
|
||||
//
|
||||
void reloadRegisters();
|
||||
void handleRegisterListNames(const GdbResultRecord &record);
|
||||
void handleRegisterListValues(const GdbResultRecord &record);
|
||||
|
||||
|
||||
//
|
||||
// Stack specific stuff
|
||||
//
|
||||
void handleStackListFrames(const GdbResultRecord &record);
|
||||
void handleStackSelectThread(const GdbResultRecord &record, int cookie);
|
||||
void handleStackListThreads(const GdbResultRecord &record, int cookie);
|
||||
|
||||
|
||||
//
|
||||
// Tooltip specific stuff
|
||||
//
|
||||
void sendToolTipCommand(const QString &command, const QString &cookie);
|
||||
|
||||
|
||||
//
|
||||
// Watch specific stuff
|
||||
//
|
||||
// FIXME: BaseClass. called to improve situation for a watch item
|
||||
void updateSubItem(const WatchData &data);
|
||||
|
||||
void updateWatchModel();
|
||||
Q_SLOT void updateWatchModel2();
|
||||
|
||||
void insertData(const WatchData &data);
|
||||
void sendWatchParameters(const QByteArray ¶ms0);
|
||||
void createGdbVariable(const WatchData &data);
|
||||
|
||||
void handleTypeContents(const QString &output);
|
||||
void maybeHandleInferiorPidChanged(const QString &pid);
|
||||
|
||||
void tryLoadCustomDumpers();
|
||||
void runCustomDumper(const WatchData &data, bool dumpChildren);
|
||||
bool isCustomValueDumperAvailable(const QString &type) const;
|
||||
|
||||
void handleVarListChildren(const GdbResultRecord &record,
|
||||
const WatchData &cookie);
|
||||
void handleVarCreate(const GdbResultRecord &record,
|
||||
const WatchData &cookie);
|
||||
void handleVarAssign();
|
||||
void handleEvaluateExpression(const GdbResultRecord &record,
|
||||
const WatchData &cookie);
|
||||
void handleToolTip(const GdbResultRecord &record,
|
||||
const QString &cookie);
|
||||
void handleDumpCustomValue1(const GdbResultRecord &record,
|
||||
const WatchData &cookie);
|
||||
void handleQueryDataDumper1(const GdbResultRecord &record);
|
||||
void handleQueryDataDumper2(const GdbResultRecord &record);
|
||||
void handleDumpCustomValue2(const GdbResultRecord &record,
|
||||
const WatchData &cookie);
|
||||
void handleDumpCustomEditValue(const GdbResultRecord &record);
|
||||
void handleDumpCustomSetup(const GdbResultRecord &record);
|
||||
void handleStackListLocals(const GdbResultRecord &record);
|
||||
void handleStackListArguments(const GdbResultRecord &record);
|
||||
void handleVarListChildrenHelper(const GdbMi &child,
|
||||
const WatchData &parent);
|
||||
void setWatchDataType(WatchData &data, const GdbMi &mi);
|
||||
|
||||
QString m_editedData;
|
||||
int m_pendingRequests;
|
||||
int m_inferiorPid;
|
||||
|
||||
QStringList m_availableSimpleDumpers;
|
||||
QString m_namespace; // namespace used in "namespaced Qt";
|
||||
|
||||
DataDumperState m_dataDumperState; // state of qt creator dumpers
|
||||
QList<GdbMi> m_currentFunctionArgs;
|
||||
QString m_currentFrame;
|
||||
QMap<QString, QString> m_varToType;
|
||||
|
||||
DebuggerManager *q;
|
||||
IDebuggerManagerAccessForEngines *qq;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_GDBENGINE_H
|
||||
473
src/plugins/debugger/gdbmi.cpp
Normal file
@@ -0,0 +1,473 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "gdbmi.h"
|
||||
#include "assert.h"
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QTextStream>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
QTextStream & operator<<(QTextStream & os, const GdbMi & mi)
|
||||
{
|
||||
return os << mi.toString();
|
||||
}
|
||||
|
||||
//static void skipSpaces(const GdbMi::Char *&from, const GdbMi::Char *to)
|
||||
//{
|
||||
// while (from != to && QChar(*from).isSpace())
|
||||
// ++from;
|
||||
//}
|
||||
|
||||
|
||||
void GdbMi::parseResultOrValue(const Char *&from, const Char *to)
|
||||
{
|
||||
//skipSpaces(from, to);
|
||||
while (from != to && QChar(*from).isSpace())
|
||||
++from;
|
||||
|
||||
//qDebug() << "parseResultOrValue: " << QByteArray::fromLatin1(from, to - from);
|
||||
parseValue(from, to);
|
||||
if (isValid()) {
|
||||
//qDebug() << "no valid result in " << QByteArray::fromLatin1(from, to - from);
|
||||
return;
|
||||
}
|
||||
if (from == to || *from == '(')
|
||||
return;
|
||||
const Char *ptr = from;
|
||||
while (ptr < to && *ptr != '=') {
|
||||
//qDebug() << "adding" << QChar(*ptr) << "to name";
|
||||
++ptr;
|
||||
}
|
||||
m_name = QByteArray(from, ptr - from);
|
||||
from = ptr;
|
||||
if (from < to && *from == '=') {
|
||||
++from;
|
||||
parseValue(from, to);
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray GdbMi::parseCString(const Char *&from, const Char *to)
|
||||
{
|
||||
QByteArray result;
|
||||
//qDebug() << "parseCString: " << QByteArray::fromUtf16(from, to - from);
|
||||
if (*from != '"') {
|
||||
qDebug() << "MI Parse Error, double quote expected";
|
||||
return QByteArray();
|
||||
}
|
||||
const Char *ptr = from;
|
||||
++ptr;
|
||||
while (ptr < to) {
|
||||
if (*ptr == '"') {
|
||||
++ptr;
|
||||
result = QByteArray(from + 1, ptr - from - 2);
|
||||
break;
|
||||
}
|
||||
if (*ptr == '\\' && ptr < to - 1)
|
||||
++ptr;
|
||||
++ptr;
|
||||
}
|
||||
|
||||
if (result.contains('\\')) {
|
||||
if (result.contains("\\032\\032"))
|
||||
result.clear();
|
||||
else {
|
||||
result = result.replace("\\n", "\n");
|
||||
result = result.replace("\\t", "\t");
|
||||
result = result.replace("\\\"", "\"");
|
||||
}
|
||||
}
|
||||
|
||||
from = ptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
void GdbMi::parseValue(const Char *&from, const Char *to)
|
||||
{
|
||||
//qDebug() << "parseValue: " << QByteArray::fromUtf16(from, to - from);
|
||||
switch (*from) {
|
||||
case '{':
|
||||
parseTuple(from, to);
|
||||
break;
|
||||
case '[':
|
||||
parseList(from, to);
|
||||
break;
|
||||
case '"':
|
||||
m_type = Const;
|
||||
m_data = parseCString(from, to);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GdbMi::parseTuple(const Char *&from, const Char *to)
|
||||
{
|
||||
//qDebug() << "parseTuple: " << QByteArray::fromUtf16(from, to - from);
|
||||
QWB_ASSERT(*from == '{', /**/);
|
||||
++from;
|
||||
parseTuple_helper(from, to);
|
||||
}
|
||||
|
||||
void GdbMi::parseTuple_helper(const Char *&from, const Char *to)
|
||||
{
|
||||
//qDebug() << "parseTuple_helper: " << QByteArray::fromUtf16(from, to - from);
|
||||
m_type = Tuple;
|
||||
while (from < to) {
|
||||
if (*from == '}') {
|
||||
++from;
|
||||
break;
|
||||
}
|
||||
GdbMi child;
|
||||
child.parseResultOrValue(from, to);
|
||||
//qDebug() << "\n=======\n" << qPrintable(child.toString()) << "\n========\n";
|
||||
if (!child.isValid())
|
||||
return;
|
||||
m_children += child;
|
||||
if (*from == ',')
|
||||
++from;
|
||||
}
|
||||
}
|
||||
|
||||
void GdbMi::parseList(const Char *&from, const Char *to)
|
||||
{
|
||||
//qDebug() << "parseList: " << QByteArray::fromUtf16(from, to - from);
|
||||
QWB_ASSERT(*from == '[', /**/);
|
||||
++from;
|
||||
m_type = List;
|
||||
while (from < to) {
|
||||
if (*from == ']') {
|
||||
++from;
|
||||
break;
|
||||
}
|
||||
GdbMi child;
|
||||
child.parseResultOrValue(from, to);
|
||||
if (child.isValid())
|
||||
m_children += child;
|
||||
if (*from == ',')
|
||||
++from;
|
||||
}
|
||||
}
|
||||
|
||||
void GdbMi::setStreamOutput(const QByteArray &name, const QByteArray &content)
|
||||
{
|
||||
if (content.isEmpty())
|
||||
return;
|
||||
GdbMi child;
|
||||
child.m_type = Const;
|
||||
child.m_name = name;
|
||||
child.m_data = content;
|
||||
m_children += child;
|
||||
if (m_type == Invalid)
|
||||
m_type = Tuple;
|
||||
}
|
||||
|
||||
static QByteArray ind(int indent)
|
||||
{
|
||||
return QByteArray(2 * indent, ' ');
|
||||
}
|
||||
|
||||
void GdbMi::dumpChildren(QByteArray * str, bool multiline, int indent) const
|
||||
{
|
||||
for (int i = 0; i < m_children.size(); ++i) {
|
||||
if (i != 0) {
|
||||
*str += ',';
|
||||
if (multiline)
|
||||
*str += '\n';
|
||||
}
|
||||
if (multiline)
|
||||
*str += ind(indent);
|
||||
*str += m_children.at(i).toString(multiline, indent);
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray GdbMi::toString(bool multiline, int indent) const
|
||||
{
|
||||
QByteArray result;
|
||||
switch (m_type) {
|
||||
case Invalid:
|
||||
if (multiline) {
|
||||
result += ind(indent) + "Invalid\n";
|
||||
} else {
|
||||
result += "Invalid";
|
||||
}
|
||||
break;
|
||||
case Const:
|
||||
if (!m_name.isEmpty())
|
||||
result += m_name + "=";
|
||||
if (multiline) {
|
||||
result += "\"" + m_data + "\"";
|
||||
} else {
|
||||
result += "\"" + m_data + "\"";
|
||||
}
|
||||
break;
|
||||
case Tuple:
|
||||
if (!m_name.isEmpty())
|
||||
result += m_name + "=";
|
||||
if (multiline) {
|
||||
result += "{\n";
|
||||
dumpChildren(&result, multiline, indent + 1);
|
||||
result += '\n' + ind(indent) + "}";
|
||||
} else {
|
||||
result += "{";
|
||||
dumpChildren(&result, multiline, indent + 1);
|
||||
result += "}";
|
||||
}
|
||||
break;
|
||||
case List:
|
||||
if (!m_name.isEmpty())
|
||||
result += m_name + "=";
|
||||
if (multiline) {
|
||||
result += "[\n";
|
||||
dumpChildren(&result, multiline, indent + 1);
|
||||
result += "]";
|
||||
} else {
|
||||
result += "[";
|
||||
dumpChildren(&result, multiline, indent + 1);
|
||||
result += '\n' + ind(indent) + "]";
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void GdbMi::fromString(const QByteArray &ba)
|
||||
{
|
||||
const Char *from = ba.constBegin();
|
||||
const Char *to = ba.constEnd();
|
||||
parseResultOrValue(from, to);
|
||||
}
|
||||
|
||||
GdbMi GdbMi::findChild(const QByteArray &name) const
|
||||
{
|
||||
for (int i = 0; i < m_children.size(); ++i)
|
||||
if (m_children.at(i).m_name == name)
|
||||
return m_children.at(i);
|
||||
return GdbMi();
|
||||
}
|
||||
|
||||
|
||||
GdbMi GdbMi::findChild(const QByteArray &name, const QByteArray &defaultData) const
|
||||
{
|
||||
for (int i = 0; i < m_children.size(); ++i)
|
||||
if (m_children.at(i).m_name == name)
|
||||
return m_children.at(i);
|
||||
GdbMi result;
|
||||
result.m_data = defaultData;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// GdbResultRecord
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QByteArray stringFromResultClass(GdbResultClass resultClass)
|
||||
{
|
||||
switch (resultClass) {
|
||||
case GdbResultDone: return "done";
|
||||
case GdbResultRunning: return "running";
|
||||
case GdbResultConnected: return "connected";
|
||||
case GdbResultError: return "error";
|
||||
case GdbResultExit: return "exit";
|
||||
default: return "unknown";
|
||||
}
|
||||
};
|
||||
|
||||
QByteArray GdbResultRecord::toString() const
|
||||
{
|
||||
QByteArray result;
|
||||
if (token != -1)
|
||||
result = QByteArray::number(token);
|
||||
result += '^';
|
||||
result += stringFromResultClass(resultClass);
|
||||
if (data.isValid())
|
||||
result += ',' + data.toString();
|
||||
result += '\n';
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// GdbStreamOutput
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if 0
|
||||
|
||||
static const char test1[] =
|
||||
"1^done,stack=[frame={level=\"0\",addr=\"0x00000000004061ca\","
|
||||
"func=\"main\",file=\"test1.cpp\","
|
||||
"fullname=\"/home/apoenitz/work/test1/test1.cpp\",line=\"209\"}]\n"
|
||||
"(gdb)\n";
|
||||
|
||||
static const char test2[] =
|
||||
"2^done,stack=[frame={level=\"0\",addr=\"0x00002ac058675840\","
|
||||
"func=\"QApplication\",file=\"/home/apoenitz/dev/qt/src/gui/kernel/qapplication.cpp\","
|
||||
"fullname=\"/home/apoenitz/dev/qt/src/gui/kernel/qapplication.cpp\",line=\"592\"},"
|
||||
"frame={level=\"1\",addr=\"0x00000000004061e0\",func=\"main\",file=\"test1.cpp\","
|
||||
"fullname=\"/home/apoenitz/work/test1/test1.cpp\",line=\"209\"}]\n"
|
||||
"(gdb)\n";
|
||||
|
||||
static const char test3[] =
|
||||
"3^done,stack=[frame={level=\"0\",addr=\"0x00000000004061ca\","
|
||||
"func=\"main\",file=\"test1.cpp\","
|
||||
"fullname=\"/home/apoenitz/work/test1/test1.cpp\",line=\"209\"}]\n"
|
||||
"(gdb)\n";
|
||||
|
||||
static const char test4[] =
|
||||
"&\"source /home/apoenitz/dev/ide/main/bin/gdb/qt4macros\\n\"\n"
|
||||
"4^done\n"
|
||||
"(gdb)\n";
|
||||
|
||||
|
||||
static const char test5[] =
|
||||
"1*stopped,reason=\"breakpoint-hit\",bkptno=\"1\",thread-id=\"1\","
|
||||
"frame={addr=\"0x0000000000405738\",func=\"main\","
|
||||
"args=[{name=\"argc\",value=\"1\"},{name=\"argv\",value=\"0x7fff1ac78f28\"}],"
|
||||
"file=\"test1.cpp\",fullname=\"/home/apoenitz/work/test1/test1.cpp\","
|
||||
"line=\"209\"}\n"
|
||||
"(gdb)\n";
|
||||
|
||||
static const char test6[] =
|
||||
"{u = {u = 2048, v = 16788279, w = -689265400}, a = 1, b = -689265424, c = 11063, s = {static null = {<No data fields>}, static shared_null = {ref = {value = 2}, alloc = 0, size = 0, data = 0x6098da, clean = 0, simpletext = 0, righttoleft = 0, asciiCache = 0, capacity = 0, reserved = 0, array = {0}}, static shared_empty = {ref = {value = 1}, alloc = 0, size = 0, data = 0x2b37d84f8fba, clean = 0, simpletext = 0, righttoleft = 0, asciiCache = 0, capacity = 0, reserved = 0, array = {0}}, d = 0x6098c0, static codecForCStrings = 0x0}}";
|
||||
|
||||
static const char test8[] =
|
||||
"8^done,data={locals={{name=\"a\"},{name=\"w\"}}}\n"
|
||||
"(gdb)\n";
|
||||
|
||||
static const char test9[] =
|
||||
"9^done,data={locals=[name=\"baz\",name=\"urgs\",name=\"purgs\"]}\n"
|
||||
"(gdb)\n";
|
||||
|
||||
|
||||
static const char test10[] =
|
||||
"16^done,name=\"urgs\",numchild=\"1\",type=\"Urgs\"\n"
|
||||
"(gdb)\n"
|
||||
"17^done,name=\"purgs\",numchild=\"1\",type=\"Urgs *\"\n"
|
||||
"(gdb)\n"
|
||||
"18^done,name=\"bar\",numchild=\"0\",type=\"int\"\n"
|
||||
"(gdb)\n"
|
||||
"19^done,name=\"z\",numchild=\"0\",type=\"int\"\n"
|
||||
"(gdb)\n";
|
||||
|
||||
static const char test11[] =
|
||||
"[{name=\"size\",value=\"1\",type=\"size_t\",readonly=\"true\"},"
|
||||
"{name=\"0\",value=\"one\",type=\"QByteArray\"}]";
|
||||
|
||||
static const char test12[] =
|
||||
"{iname=\"local.hallo\",value=\"\\\"\\\"\",type=\"QByteArray\",numchild=\"0\"}";
|
||||
|
||||
static struct Tester {
|
||||
|
||||
Tester() {
|
||||
//test(test10);
|
||||
test2(test12);
|
||||
//test(test4);
|
||||
//apple();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void test(const char* input)
|
||||
{
|
||||
//qDebug("\n<<<<\n%s\n====\n%s\n>>>>\n", input,
|
||||
//qPrintable(GdbResponse(input).toString()));
|
||||
}
|
||||
|
||||
void test2(const char* input)
|
||||
{
|
||||
GdbMi mi(input);
|
||||
qDebug("\n<<<<\n%s\n====\n%s\n>>>>\n", input,
|
||||
qPrintable(mi.toString()));
|
||||
}
|
||||
|
||||
void apple()
|
||||
{
|
||||
QByteArray input(test9);
|
||||
/*
|
||||
qDebug() << "input: " << input;
|
||||
input = input.replace("{{","[");
|
||||
input = input.replace("},{",",");
|
||||
input = input.replace("}}","]");
|
||||
qDebug() << "input: " << input;
|
||||
GdbResponse response(input);
|
||||
qDebug() << "read: " << response.toString();
|
||||
GdbMi list = response.results[0].data.findChild("data").findChild("locals");
|
||||
QByteArrayList locals;
|
||||
foreach (const GdbMi &item, list.children())
|
||||
locals.append(item.string());
|
||||
qDebug() << "Locals (new): " << locals;
|
||||
*/
|
||||
}
|
||||
void parse(const QByteArray &str)
|
||||
{
|
||||
QByteArray result;
|
||||
result += "\n ";
|
||||
int indent = 0;
|
||||
int from = 0;
|
||||
int to = str.size();
|
||||
if (str.size() && str[0] == '{' /*'}'*/) {
|
||||
++from;
|
||||
--to;
|
||||
}
|
||||
for (int i = from; i < to; ++i) {
|
||||
if (str[i] == '{')
|
||||
result += "{\n" + QByteArray(2*++indent + 1, QChar(' '));
|
||||
else if (str[i] == '}') {
|
||||
if (!result.isEmpty() && result[result.size() - 1] != '\n')
|
||||
result += "\n";
|
||||
result += QByteArray(2*--indent + 1, QChar(' ')) + "}\n";
|
||||
}
|
||||
else if (str[i] == ',') {
|
||||
if (true || !result.isEmpty() && result[result.size() - 1] != '\n')
|
||||
result += "\n";
|
||||
result += QByteArray(2*indent, QChar(' '));
|
||||
}
|
||||
else
|
||||
result += str[i];
|
||||
}
|
||||
qDebug() << "result:\n" << result;
|
||||
}
|
||||
|
||||
} dummy;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
183
src/plugins/debugger/gdbmi.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef DEBUGGER_GDBMI_H
|
||||
#define DEBUGGER_GDBMI_H
|
||||
|
||||
#include <qglobal.h>
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QList>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
/*
|
||||
|
||||
output ==>
|
||||
( out-of-band-record )* [ result-record ] "(gdb)" nl
|
||||
result-record ==>
|
||||
[ token ] "^" result-class ( "," result )* nl
|
||||
out-of-band-record ==>
|
||||
async-record | stream-record
|
||||
async-record ==>
|
||||
exec-async-output | status-async-output | notify-async-output
|
||||
exec-async-output ==>
|
||||
[ token ] "*" async-output
|
||||
status-async-output ==>
|
||||
[ token ] "+" async-output
|
||||
notify-async-output ==>
|
||||
[ token ] "=" async-output
|
||||
async-output ==>
|
||||
async-class ( "," result )* nl
|
||||
result-class ==>
|
||||
"done" | "running" | "connected" | "error" | "exit"
|
||||
async-class ==>
|
||||
"stopped" | others (where others will be added depending on the needs--this is still in development).
|
||||
result ==>
|
||||
variable "=" value
|
||||
variable ==>
|
||||
string
|
||||
value ==>
|
||||
const | tuple | list
|
||||
const ==>
|
||||
c-string
|
||||
tuple ==>
|
||||
"{}" | "{" result ( "," result )* "}"
|
||||
list ==>
|
||||
"[]" | "[" value ( "," value )* "]" | "[" result ( "," result )* "]"
|
||||
stream-record ==>
|
||||
console-stream-output | target-stream-output | log-stream-output
|
||||
console-stream-output ==>
|
||||
"~" c-string
|
||||
target-stream-output ==>
|
||||
"@" c-string
|
||||
log-stream-output ==>
|
||||
"&" c-string
|
||||
nl ==>
|
||||
CR | CR-LF
|
||||
token ==>
|
||||
any sequence of digits.
|
||||
|
||||
*/
|
||||
|
||||
// FIXME: rename into GdbMiValue
|
||||
class GdbMi
|
||||
{
|
||||
public:
|
||||
GdbMi() : m_type(Invalid) {}
|
||||
explicit GdbMi(const QByteArray &str) { fromString(str); }
|
||||
|
||||
QByteArray m_name;
|
||||
QByteArray m_data;
|
||||
QList<GdbMi> m_children;
|
||||
|
||||
enum Type {
|
||||
Invalid,
|
||||
Const,
|
||||
Tuple,
|
||||
List,
|
||||
};
|
||||
|
||||
Type m_type;
|
||||
|
||||
inline Type type() const { return m_type; }
|
||||
inline QByteArray name() const { return m_name; }
|
||||
inline bool hasName(const char *name) const { return m_name == name; }
|
||||
|
||||
inline bool isValid() const { return m_type != Invalid; }
|
||||
inline bool isConst() const { return m_type == Const; }
|
||||
inline bool isTuple() const { return m_type == Tuple; }
|
||||
inline bool isList() const { return m_type == List; }
|
||||
|
||||
|
||||
inline QByteArray data() const { return m_data; }
|
||||
inline const QList<GdbMi> &children() const { return m_children; }
|
||||
inline int childCount() const { return m_children.size(); }
|
||||
|
||||
const GdbMi & childAt(int index) const { return m_children[index]; }
|
||||
GdbMi & childAt(int index) { return m_children[index]; }
|
||||
GdbMi findChild(const QByteArray &name) const;
|
||||
GdbMi findChild(const QByteArray &name, const QByteArray &defaultString) const;
|
||||
|
||||
QByteArray toString(bool multiline = false, int indent = 0) const;
|
||||
void fromString(const QByteArray &str);
|
||||
void setStreamOutput(const QByteArray &name, const QByteArray &content);
|
||||
|
||||
private:
|
||||
friend class GdbResultRecord;
|
||||
friend class GdbEngine;
|
||||
|
||||
//typedef ushort Char;
|
||||
typedef char Char;
|
||||
static QByteArray parseCString(const Char *&from, const Char *to);
|
||||
void parseResultOrValue(const Char *&from, const Char *to);
|
||||
void parseValue(const Char *&from, const Char *to);
|
||||
void parseTuple(const Char *&from, const Char *to);
|
||||
void parseTuple_helper(const Char *&from, const Char *to);
|
||||
void parseList(const Char *&from, const Char *to);
|
||||
|
||||
void dumpChildren(QByteArray *str, bool multiline, int indent) const;
|
||||
};
|
||||
|
||||
enum GdbResultClass
|
||||
{
|
||||
// "done" | "running" | "connected" | "error" | "exit"
|
||||
GdbResultUnknown,
|
||||
GdbResultDone,
|
||||
GdbResultCustomDone,
|
||||
GdbResultRunning,
|
||||
GdbResultConnected,
|
||||
GdbResultError,
|
||||
GdbResultExit,
|
||||
};
|
||||
|
||||
class GdbResultRecord
|
||||
{
|
||||
public:
|
||||
GdbResultRecord() : token(-1), resultClass(GdbResultUnknown) {}
|
||||
QByteArray toString() const;
|
||||
|
||||
int token;
|
||||
GdbResultClass resultClass;
|
||||
GdbMi data;
|
||||
private:
|
||||
friend class GdbMi;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
//Q_DECLARE_METATYPE(GdbDebugger::Internal::GdbMi);
|
||||
|
||||
#endif // DEBUGGER_GDBMI_H
|
||||
128
src/plugins/debugger/gdboptionpage.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "gdboptionpage.h"
|
||||
|
||||
#include "gdbengine.h"
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtGui/QLineEdit>
|
||||
#include <QtGui/QFileDialog>
|
||||
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
GdbOptionPage::GdbOptionPage(GdbSettings *settings)
|
||||
{
|
||||
m_pm = ExtensionSystem::PluginManager::instance();
|
||||
m_settings = settings;
|
||||
|
||||
Core::ICore *coreIFace = m_pm->getObject<Core::ICore>();
|
||||
if (!coreIFace || !coreIFace->settings())
|
||||
return;
|
||||
QSettings *s = coreIFace->settings();
|
||||
s->beginGroup("GdbOptions");
|
||||
QString defaultCommand("gdb");
|
||||
#if defined(Q_OS_WIN32)
|
||||
defaultCommand.append(".exe");
|
||||
#endif
|
||||
m_settings->m_gdbCmd = s->value("Location", defaultCommand).toString();
|
||||
m_settings->m_gdbEnv = s->value("Environment", "").toString();
|
||||
m_settings->m_autoRun = s->value("AutoRun", true).toBool();
|
||||
m_settings->m_autoQuit = s->value("AutoQuit", true).toBool();
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
QString GdbOptionPage::name() const
|
||||
{
|
||||
return tr("Gdb");
|
||||
}
|
||||
|
||||
QString GdbOptionPage::category() const
|
||||
{
|
||||
return "Debugger|Gdb";
|
||||
}
|
||||
|
||||
QString GdbOptionPage::trCategory() const
|
||||
{
|
||||
return tr("Debugger|Gdb");
|
||||
}
|
||||
|
||||
QWidget *GdbOptionPage::createPage(QWidget *parent)
|
||||
{
|
||||
QWidget *w = new QWidget(parent);
|
||||
m_ui.setupUi(w);
|
||||
m_ui.gdbEdit->setText(m_settings->m_gdbCmd);
|
||||
m_ui.envEdit->setText(m_settings->m_gdbEnv);
|
||||
m_ui.autoStartBox->setChecked(m_settings->m_autoRun);
|
||||
m_ui.autoQuitBox->setChecked(m_settings->m_autoQuit);
|
||||
connect(m_ui.pushButtonBrowse, SIGNAL(clicked()),
|
||||
this, SLOT(browse()));
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
void GdbOptionPage::browse()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(m_ui.pushButtonBrowse,
|
||||
"Browse for gdb executable");
|
||||
if (fileName.isEmpty())
|
||||
return;
|
||||
m_settings->m_gdbCmd = fileName;
|
||||
m_ui.gdbEdit->setText(fileName);
|
||||
}
|
||||
|
||||
void GdbOptionPage::finished(bool accepted)
|
||||
{
|
||||
if (!accepted)
|
||||
return;
|
||||
|
||||
m_settings->m_gdbCmd = m_ui.gdbEdit->text();
|
||||
m_settings->m_gdbEnv = m_ui.envEdit->text();
|
||||
m_settings->m_autoRun = m_ui.autoStartBox->isChecked();
|
||||
m_settings->m_autoQuit = m_ui.autoQuitBox->isChecked();
|
||||
|
||||
Core::ICore *coreIFace = m_pm->getObject<Core::ICore>();
|
||||
if (!coreIFace || !coreIFace->settings())
|
||||
return;
|
||||
|
||||
QSettings *s = coreIFace->settings();
|
||||
|
||||
s->beginGroup("GdbOptions");
|
||||
s->setValue("Location", m_settings->m_gdbCmd);
|
||||
s->setValue("Environment", m_settings->m_gdbEnv);
|
||||
s->setValue("AutoRun", m_settings->m_autoRun);
|
||||
s->setValue("AutoQuit", m_settings->m_autoQuit);
|
||||
s->endGroup();
|
||||
}
|
||||
106
src/plugins/debugger/gdboptionpage.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef GDBOPTIONPAGE_H
|
||||
#define GDBOPTIONPAGE_H
|
||||
|
||||
#include "ui_gdboptionpage.h"
|
||||
#include "ui_gdbtypemacros.h"
|
||||
|
||||
#include <coreplugin/dialogs/ioptionspage.h>
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
namespace ExtensionSystem { class PluginManager; }
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class GdbSettings;
|
||||
|
||||
class GdbOptionPage : public Core::IOptionsPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GdbOptionPage(GdbSettings *settings);
|
||||
|
||||
QString name() const;
|
||||
QString category() const;
|
||||
QString trCategory() const;
|
||||
|
||||
QWidget *createPage(QWidget *parent);
|
||||
void finished(bool accepted);
|
||||
|
||||
public slots:
|
||||
void browse();
|
||||
|
||||
private:
|
||||
ExtensionSystem::PluginManager *m_pm;
|
||||
Ui::GdbOptionPage m_ui;
|
||||
|
||||
GdbSettings *m_settings;
|
||||
};
|
||||
|
||||
class TypeMacroPage : public Core::IOptionsPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TypeMacroPage(GdbSettings *settings);
|
||||
|
||||
QString name() const;
|
||||
QString category() const;
|
||||
QString trCategory() const;
|
||||
|
||||
QWidget *createPage(QWidget *parent);
|
||||
void finished(bool accepted);
|
||||
|
||||
private slots:
|
||||
void onScriptButton();
|
||||
void onAddButton();
|
||||
void onDelButton();
|
||||
void currentItemChanged(QTreeWidgetItem *item);
|
||||
void updateButtonState();
|
||||
|
||||
private:
|
||||
ExtensionSystem::PluginManager *m_pm;
|
||||
Ui::TypeMacroPage m_ui;
|
||||
|
||||
GdbSettings *m_settings;
|
||||
QWidget *m_widget;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // GDBOPTIONPAGE_H
|
||||
111
src/plugins/debugger/gdboptionpage.ui
Normal file
@@ -0,0 +1,111 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GdbOptionPage</class>
|
||||
<widget class="QWidget" name="GdbOptionPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>433</width>
|
||||
<height>216</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Gdb Debug Options</string>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="gdbEdit"/>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="envEdit"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Gdb Location:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>gdbEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Environment:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>envEdit</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="pushButtonBrowse">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../coreplugin/core.qrc">
|
||||
<normaloff>:/qworkbench/images/fileopen.png</normaloff>:/qworkbench/images/fileopen.png</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="autoStartBox">
|
||||
<property name="text">
|
||||
<string>Auto run executable on debugger startup</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="autoQuitBox">
|
||||
<property name="text">
|
||||
<string>Quit debugger when the executable exits</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>415</width>
|
||||
<height>41</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../coreplugin/core.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
214
src/plugins/debugger/gdbtypemacros.cpp
Normal file
@@ -0,0 +1,214 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "gdboptionpage.h"
|
||||
#include "gdbengine.h"
|
||||
#include "imports.h"
|
||||
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtGui/QFileDialog>
|
||||
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
TypeMacroPage::TypeMacroPage(GdbSettings *settings)
|
||||
{
|
||||
m_pm = ExtensionSystem::PluginManager::instance();
|
||||
m_settings = settings;
|
||||
|
||||
Core::ICore *coreIFace = m_pm->getObject<Core::ICore>();
|
||||
if (!coreIFace || !coreIFace->settings())
|
||||
return;
|
||||
|
||||
QSettings *s = coreIFace->settings();
|
||||
s->beginGroup("GdbOptions");
|
||||
if (!s->contains("ScriptFile") && !s->contains("TypeMacros")) {
|
||||
//insert qt4 defaults
|
||||
m_settings->m_scriptFile = coreIFace->resourcePath() +
|
||||
QLatin1String("/gdb/qt4macros");
|
||||
for (int i=0; i<3; ++i) {
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
switch(i) {
|
||||
case 0:
|
||||
stream << QString("printqstring") << (int)1;
|
||||
m_settings->m_typeMacros.insert(QLatin1String("QString"), data);
|
||||
break;
|
||||
case 1:
|
||||
stream << QString("printqcolor") << (int)0;
|
||||
m_settings->m_typeMacros.insert(QLatin1String("QColor"), data);
|
||||
break;
|
||||
case 2:
|
||||
stream << QString("printqfont") << (int)1;
|
||||
m_settings->m_typeMacros.insert(QLatin1String("QFont"), data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s->setValue("ScriptFile", m_settings->m_scriptFile);
|
||||
s->setValue("TypeMacros", m_settings->m_typeMacros);
|
||||
} else {
|
||||
m_settings->m_scriptFile = s->value("ScriptFile", QString()).toString();
|
||||
m_settings->m_typeMacros = s->value("TypeMacros", QMap<QString,QVariant>()).toMap();
|
||||
}
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
QString TypeMacroPage::name() const
|
||||
{
|
||||
return tr("Type Macros");
|
||||
}
|
||||
|
||||
QString TypeMacroPage::category() const
|
||||
{
|
||||
return "Debugger|Gdb";
|
||||
}
|
||||
|
||||
QString TypeMacroPage::trCategory() const
|
||||
{
|
||||
return tr("Debugger|Gdb");
|
||||
}
|
||||
|
||||
QWidget *TypeMacroPage::createPage(QWidget *parent)
|
||||
{
|
||||
QString macro;
|
||||
int index;
|
||||
|
||||
m_widget = new QWidget(parent);
|
||||
m_ui.setupUi(m_widget);
|
||||
|
||||
connect(m_ui.addButton, SIGNAL(clicked()),
|
||||
this, SLOT(onAddButton()));
|
||||
|
||||
connect(m_ui.delButton, SIGNAL(clicked()),
|
||||
this, SLOT(onDelButton()));
|
||||
|
||||
connect(m_ui.scriptButton, SIGNAL(clicked()),
|
||||
this, SLOT(onScriptButton()));
|
||||
|
||||
connect(m_ui.treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)),
|
||||
this, SLOT(currentItemChanged(QTreeWidgetItem *)));
|
||||
|
||||
connect(m_ui.typeEdit, SIGNAL(textChanged(const QString &)),
|
||||
this, SLOT(updateButtonState()));
|
||||
|
||||
connect(m_ui.macroEdit, SIGNAL(textChanged(const QString &)),
|
||||
this, SLOT(updateButtonState()));
|
||||
|
||||
QMap<QString, QVariant>::const_iterator i = m_settings->m_typeMacros.constBegin();
|
||||
while (i != m_settings->m_typeMacros.constEnd()) {
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(m_ui.treeWidget);
|
||||
QDataStream stream(i.value().toByteArray());
|
||||
stream >> macro >> index;
|
||||
item->setText(0, i.key());
|
||||
item->setText(1, macro);
|
||||
item->setData(0, Qt::UserRole, index);
|
||||
++i;
|
||||
}
|
||||
|
||||
m_ui.scriptEdit->setText(m_settings->m_scriptFile);
|
||||
|
||||
updateButtonState();
|
||||
|
||||
return m_widget;
|
||||
}
|
||||
|
||||
void TypeMacroPage::finished(bool accepted)
|
||||
{
|
||||
if (!accepted)
|
||||
return;
|
||||
|
||||
m_settings->m_typeMacros.clear();
|
||||
m_settings->m_scriptFile = m_ui.scriptEdit->text();
|
||||
|
||||
for (int i=0; i<m_ui.treeWidget->topLevelItemCount(); ++i) {
|
||||
QTreeWidgetItem *item = m_ui.treeWidget->topLevelItem(i);
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << item->text(1) << item->data(0, Qt::UserRole).toInt();
|
||||
m_settings->m_typeMacros.insert(item->text(0), data);
|
||||
}
|
||||
|
||||
Core::ICore *coreIFace = m_pm->getObject<Core::ICore>();
|
||||
if (coreIFace && coreIFace->settings()) {
|
||||
QSettings *s = coreIFace->settings();
|
||||
s->beginGroup("GdbOptions");
|
||||
s->setValue("ScriptFile", m_settings->m_scriptFile);
|
||||
s->setValue("TypeMacros", m_settings->m_typeMacros);
|
||||
s->endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
void TypeMacroPage::onScriptButton()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(m_widget, tr("Select Gdb Script"));
|
||||
m_ui.scriptEdit->setText(fileName);
|
||||
updateButtonState();
|
||||
}
|
||||
|
||||
void TypeMacroPage::onAddButton()
|
||||
{
|
||||
if (m_ui.typeEdit->text().isEmpty() || m_ui.macroEdit->text().isEmpty())
|
||||
return;
|
||||
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(m_ui.treeWidget);
|
||||
item->setText(0, m_ui.typeEdit->text());
|
||||
item->setText(1, m_ui.macroEdit->text());
|
||||
item->setData(0, Qt::UserRole, m_ui.parseAsBox->currentIndex());
|
||||
|
||||
updateButtonState();
|
||||
}
|
||||
|
||||
void TypeMacroPage::onDelButton()
|
||||
{
|
||||
if (QTreeWidgetItem *item = m_ui.treeWidget->currentItem())
|
||||
delete item;
|
||||
updateButtonState();
|
||||
}
|
||||
|
||||
void TypeMacroPage::currentItemChanged(QTreeWidgetItem *item)
|
||||
{
|
||||
m_ui.typeEdit->setText(item ? item->text(0) : QString());
|
||||
m_ui.macroEdit->setText(item ? item->text(1) : QString());
|
||||
m_ui.parseAsBox->setCurrentIndex(item ? item->data(0, Qt::UserRole).toInt() : 0);
|
||||
updateButtonState();
|
||||
}
|
||||
|
||||
void TypeMacroPage::updateButtonState()
|
||||
{
|
||||
m_ui.delButton->setEnabled(m_ui.treeWidget->currentItem() != 0);
|
||||
m_ui.addButton->setDisabled(m_ui.typeEdit->text().isEmpty()
|
||||
|| m_ui.macroEdit->text().isEmpty());
|
||||
}
|
||||
186
src/plugins/debugger/gdbtypemacros.ui
Normal file
@@ -0,0 +1,186 @@
|
||||
<ui version="4.0" >
|
||||
<author></author>
|
||||
<comment></comment>
|
||||
<exportmacro></exportmacro>
|
||||
<class>TypeMacroPage</class>
|
||||
<widget class="QWidget" name="TypeMacroPage" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>519</width>
|
||||
<height>238</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox" >
|
||||
<property name="title" >
|
||||
<string>Script File</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="scriptEdit" />
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="scriptButton" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>21</width>
|
||||
<height>23</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2" >
|
||||
<widget class="QTreeWidget" name="treeWidget" >
|
||||
<property name="rootIsDecorated" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text" >
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text" >
|
||||
<string>Macro</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" >
|
||||
<widget class="QToolButton" name="addButton" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>21</width>
|
||||
<height>23</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>+</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="gdbdebugger.qrc" >:/gdbdebugger/images/newitem.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>Macro Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Parse as:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QLineEdit" name="macroEdit" />
|
||||
</item>
|
||||
<item row="0" column="2" >
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QToolButton" name="delButton" >
|
||||
<property name="minimumSize" >
|
||||
<size>
|
||||
<width>21</width>
|
||||
<height>23</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>-</string>
|
||||
</property>
|
||||
<property name="icon" >
|
||||
<iconset resource="gdbdebugger.qrc" >:/gdbdebugger/images/delete.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLineEdit" name="typeEdit" />
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QComboBox" name="parseAsBox" >
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>ASCII (char *)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Unicode (short)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<pixmapfunction></pixmapfunction>
|
||||
<resources>
|
||||
<include location="gdbdebugger.qrc" />
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
88
src/plugins/debugger/idebuggerengine.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_IDEBUGGERENGINE_H
|
||||
#define DEBUGGER_IDEBUGGERENGINE_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class IDebuggerEngine : public QObject
|
||||
{
|
||||
public:
|
||||
IDebuggerEngine(QObject *parent = 0) : QObject(parent) {}
|
||||
|
||||
virtual void shutdown() = 0;
|
||||
virtual void setToolTipExpression(const QPoint &pos, const QString &exp) = 0;
|
||||
virtual bool startDebugger() = 0;
|
||||
virtual void exitDebugger() = 0;
|
||||
virtual void updateWatchModel() = 0;
|
||||
|
||||
virtual void stepExec() = 0;
|
||||
virtual void stepOutExec() = 0;
|
||||
virtual void nextExec() = 0;
|
||||
virtual void stepIExec() = 0;
|
||||
virtual void nextIExec() = 0;
|
||||
|
||||
virtual void continueInferior() = 0;
|
||||
virtual void runInferior() = 0;
|
||||
virtual void interruptInferior() = 0;
|
||||
|
||||
virtual void runToLineExec(const QString &fileName, int lineNumber) = 0;
|
||||
virtual void runToFunctionExec(const QString &functionName) = 0;
|
||||
virtual void jumpToLineExec(const QString &fileName, int lineNumber) = 0;
|
||||
virtual void assignValueInDebugger(const QString &expr, const QString &value) = 0;
|
||||
virtual void executeDebuggerCommand(const QString &command) = 0;
|
||||
|
||||
virtual void activateFrame(int index) = 0;
|
||||
virtual void selectThread(int index) = 0;
|
||||
|
||||
virtual void attemptBreakpointSynchronization() = 0;
|
||||
|
||||
virtual void loadSessionData() = 0;
|
||||
virtual void saveSessionData() = 0;
|
||||
|
||||
virtual void reloadDisassembler() = 0;
|
||||
|
||||
virtual void reloadModules() = 0;
|
||||
virtual void loadSymbols(const QString &moduleName) = 0;
|
||||
virtual void loadAllSymbols() = 0;
|
||||
|
||||
virtual void reloadRegisters() = 0;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_IDEBUGGERENGINE_H
|
||||
154
src/plugins/debugger/images/breakpoint.svg
Normal file
@@ -0,0 +1,154 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="14"
|
||||
height="14"
|
||||
id="svg2270"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.45.1"
|
||||
version="1.0"
|
||||
sodipodi:docbase="D:\depot\research\main\editor\images"
|
||||
sodipodi:docname="breakpoint.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs2272">
|
||||
<linearGradient
|
||||
id="linearGradient7029">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop7031" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop7033" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient17794">
|
||||
<stop
|
||||
style="stop-color:#f18383;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop17798" />
|
||||
<stop
|
||||
id="stop8006"
|
||||
offset="0.3807947"
|
||||
style="stop-color:#ed6767;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#e62323;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop17796" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient17794"
|
||||
id="linearGradient24732"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="472.42236"
|
||||
y1="436.79602"
|
||||
x2="461.39169"
|
||||
y2="424.95065" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient17794"
|
||||
id="linearGradient2438"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="472.42236"
|
||||
y1="436.79602"
|
||||
x2="461.39169"
|
||||
y2="424.95065" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient17794"
|
||||
id="radialGradient6052"
|
||||
cx="466.73566"
|
||||
cy="431.19708"
|
||||
fx="466.73566"
|
||||
fy="431.19708"
|
||||
r="9.3095722"
|
||||
gradientTransform="matrix(1,0,0,1.0057859,0,-2.4948735)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient7029"
|
||||
id="linearGradient7035"
|
||||
x1="6.75"
|
||||
y1="0.5"
|
||||
x2="6.75"
|
||||
y2="12.5"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
gridtolerance="10000"
|
||||
guidetolerance="10"
|
||||
objecttolerance="10"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="32"
|
||||
inkscape:cx="8.6877264"
|
||||
inkscape:cy="6.3888789"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g25843"
|
||||
width="14px"
|
||||
height="14px"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="998"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
showgrid="true"
|
||||
gridspacingx="0.5px"
|
||||
gridspacingy="0.5px"
|
||||
gridempspacing="2"
|
||||
inkscape:grid-points="true" />
|
||||
<metadata
|
||||
id="metadata2275">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g25843"
|
||||
transform="matrix(0.7931251,0,0,0.7931251,-372.13374,-408.22195)">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:url(#radialGradient6052);fill-opacity:1.0;stroke:#c80000;stroke-width:1.43637741;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path22737"
|
||||
sodipodi:cx="466.73566"
|
||||
sodipodi:cy="431.19708"
|
||||
sodipodi:rx="8.5913839"
|
||||
sodipodi:ry="8.6452484"
|
||||
d="M 475.32704 431.19708 A 8.5913839 8.6452484 0 1 1 458.14427,431.19708 A 8.5913839 8.6452484 0 1 1 475.32704 431.19708 z"
|
||||
transform="matrix(0.8805346,0,0,0.8750503,66.41784,145.57686)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:1;fill:url(#linearGradient7035);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path6058"
|
||||
sodipodi:cx="6.75"
|
||||
sodipodi:cy="6.5"
|
||||
sodipodi:rx="5.75"
|
||||
sodipodi:ry="6"
|
||||
d="M 12.5 6.5 A 5.75 6 0 1 1 1,6.5 A 5.75 6 0 1 1 12.5 6.5 z"
|
||||
transform="matrix(0.9867408,0,0,0.6304178,470.73423,515.01579)" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
534
src/plugins/debugger/images/breakpoint_pending.svg
Normal file
@@ -0,0 +1,534 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="14"
|
||||
height="14"
|
||||
id="svg2270"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.45.1"
|
||||
version="1.0"
|
||||
sodipodi:docbase="c:\depot\research\main\editor\images"
|
||||
sodipodi:docname="pendingbreakpoint.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs2272">
|
||||
<linearGradient
|
||||
id="linearGradient7029">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop7031" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop7033" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient17794">
|
||||
<stop
|
||||
style="stop-color:#f18383;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop17798" />
|
||||
<stop
|
||||
id="stop8006"
|
||||
offset="0.3807947"
|
||||
style="stop-color:#ed6767;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#e62323;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop17796" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient17794"
|
||||
id="linearGradient24732"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="472.42236"
|
||||
y1="436.79602"
|
||||
x2="461.39169"
|
||||
y2="424.95065" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient17794"
|
||||
id="linearGradient2438"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="472.42236"
|
||||
y1="436.79602"
|
||||
x2="461.39169"
|
||||
y2="424.95065" />
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient17794"
|
||||
id="radialGradient6052"
|
||||
cx="466.73566"
|
||||
cy="431.19708"
|
||||
fx="466.73566"
|
||||
fy="431.19708"
|
||||
r="9.3095722"
|
||||
gradientTransform="matrix(1,0,0,1.0057859,0,-2.4948735)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient7029"
|
||||
id="linearGradient7035"
|
||||
x1="6.75"
|
||||
y1="0.5"
|
||||
x2="6.75"
|
||||
y2="12.5"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="12.5"
|
||||
x2="6.75"
|
||||
y1="0.5"
|
||||
x1="6.75"
|
||||
id="linearGradient2228"
|
||||
xlink:href="#linearGradient7029"
|
||||
inkscape:collect="always" />
|
||||
<radialGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,1.0057859,0,-2.4948735)"
|
||||
r="9.3095722"
|
||||
fy="431.19708"
|
||||
fx="466.73566"
|
||||
cy="431.19708"
|
||||
cx="466.73566"
|
||||
id="radialGradient2226"
|
||||
xlink:href="#linearGradient17794"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="424.95065"
|
||||
x2="461.39169"
|
||||
y1="436.79602"
|
||||
x1="472.42236"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient2224"
|
||||
xlink:href="#linearGradient17794"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="424.95065"
|
||||
x2="461.39169"
|
||||
y1="436.79602"
|
||||
x1="472.42236"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient2222"
|
||||
xlink:href="#linearGradient17794"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient2214">
|
||||
<stop
|
||||
id="stop2216"
|
||||
offset="0"
|
||||
style="stop-color:#f18383;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#ed6767;stop-opacity:1;"
|
||||
offset="0.3807947"
|
||||
id="stop2218" />
|
||||
<stop
|
||||
id="stop2220"
|
||||
offset="1"
|
||||
style="stop-color:#e62323;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient2208">
|
||||
<stop
|
||||
id="stop2210"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop2212"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1.2661544,0,0,1.2608351,469.23729,510.59508)"
|
||||
y2="10.60876"
|
||||
x2="10.981011"
|
||||
y1="9.9135647"
|
||||
x1="10.946278"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4173"
|
||||
xlink:href="#linearGradient4128"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1.2608351,0,0,1.2608351,475.7834,516.59183)"
|
||||
y2="9.578125"
|
||||
x2="5.859375"
|
||||
y1="6.609375"
|
||||
x1="5.953125"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4159"
|
||||
xlink:href="#linearGradient4128"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="11"
|
||||
x2="11"
|
||||
y1="10"
|
||||
x1="11"
|
||||
id="linearGradient4156"
|
||||
xlink:href="#linearGradient4128"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="521.00476"
|
||||
x2="472.35138"
|
||||
y1="519.11353"
|
||||
x1="472.35138"
|
||||
gradientTransform="matrix(1,0,0,1.0000093,10.421461,10.71221)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4138"
|
||||
xlink:href="#linearGradient4128"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1,0,0,0.9687523,10.283691,16.9106)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="521.00476"
|
||||
x2="472.35138"
|
||||
y1="519.11353"
|
||||
x1="472.35138"
|
||||
id="linearGradient4134"
|
||||
xlink:href="#linearGradient4128"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="424.95065"
|
||||
x2="461.39169"
|
||||
y1="436.79602"
|
||||
x1="472.42236"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient2293"
|
||||
xlink:href="#linearGradient17794"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="424.95065"
|
||||
x2="461.39169"
|
||||
y1="436.79602"
|
||||
x1="472.42236"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient2291"
|
||||
xlink:href="#linearGradient17794"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient2285">
|
||||
<stop
|
||||
id="stop2287"
|
||||
offset="0"
|
||||
style="stop-color:#c80000;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop2289"
|
||||
offset="1"
|
||||
style="stop-color:#ffa0a0;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="424.95065"
|
||||
x2="461.39169"
|
||||
y1="436.79602"
|
||||
x1="472.42236"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient25826"
|
||||
xlink:href="#linearGradient17794"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient4128">
|
||||
<stop
|
||||
id="stop4130"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:0.78431374;" />
|
||||
<stop
|
||||
id="stop4132"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0.23529412;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1.2661544,0,0,1.2608351,469.23729,510.59508)"
|
||||
y2="10.60876"
|
||||
x2="10.981011"
|
||||
y1="9.9135647"
|
||||
x1="10.946278"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient2378"
|
||||
xlink:href="#linearGradient4128"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="11.147234"
|
||||
x2="11.02502"
|
||||
y1="9.6892195"
|
||||
x1="10.968282"
|
||||
id="linearGradient2376"
|
||||
xlink:href="#linearGradient4128"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1.2608351,0,0,1.2608351,475.7834,516.59183)"
|
||||
y2="9.578125"
|
||||
x2="5.859375"
|
||||
y1="6.609375"
|
||||
x1="5.953125"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient2374"
|
||||
xlink:href="#linearGradient4128"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="11"
|
||||
x2="11"
|
||||
y1="10"
|
||||
x1="11"
|
||||
id="linearGradient2372"
|
||||
xlink:href="#linearGradient4128"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="521.00476"
|
||||
x2="472.35138"
|
||||
y1="519.11353"
|
||||
x1="472.35138"
|
||||
gradientTransform="matrix(1,0,0,0.6666648,10.303108,184.09099)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient2370"
|
||||
xlink:href="#linearGradient4128"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="521.00476"
|
||||
x2="472.35138"
|
||||
y1="519.11353"
|
||||
x1="472.35138"
|
||||
gradientTransform="matrix(1,0,0,0.6666648,10.342666,173.98441)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient2368"
|
||||
xlink:href="#linearGradient4128"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="521.00476"
|
||||
x2="472.35138"
|
||||
y1="519.11353"
|
||||
x1="472.35138"
|
||||
gradientTransform="matrix(1,0,0,1.0000093,10.421461,10.71221)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient2366"
|
||||
xlink:href="#linearGradient4128"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
gradientTransform="matrix(1,0,0,0.9687523,10.283691,16.9106)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="521.00476"
|
||||
x2="472.35138"
|
||||
y1="519.11353"
|
||||
x1="472.35138"
|
||||
id="linearGradient2364"
|
||||
xlink:href="#linearGradient4128"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="424.95065"
|
||||
x2="461.39169"
|
||||
y1="436.79602"
|
||||
x1="472.42236"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient2362"
|
||||
xlink:href="#linearGradient17794"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="424.95065"
|
||||
x2="461.39169"
|
||||
y1="436.79602"
|
||||
x1="472.42236"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient2360"
|
||||
xlink:href="#linearGradient17794"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient2354">
|
||||
<stop
|
||||
id="stop2356"
|
||||
offset="0"
|
||||
style="stop-color:#c80000;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop2358"
|
||||
offset="1"
|
||||
style="stop-color:#ffa0a0;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="424.95065"
|
||||
x2="461.39169"
|
||||
y1="436.79602"
|
||||
x1="472.42236"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient2352"
|
||||
xlink:href="#linearGradient17794"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient2346">
|
||||
<stop
|
||||
id="stop2348"
|
||||
offset="0"
|
||||
style="stop-color:#ffffff;stop-opacity:0.78431374;" />
|
||||
<stop
|
||||
id="stop2350"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0.23529412;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4128"
|
||||
id="linearGradient2392"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,0.6666648,10.342666,173.98441)"
|
||||
x1="472.35138"
|
||||
y1="519.11353"
|
||||
x2="472.35138"
|
||||
y2="521.00476" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4128"
|
||||
id="linearGradient2394"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,0,0,0.6666648,10.303108,184.09099)"
|
||||
x1="472.35138"
|
||||
y1="519.11353"
|
||||
x2="472.35138"
|
||||
y2="521.00476" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4128"
|
||||
id="linearGradient2396"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="10.968282"
|
||||
y1="9.6892195"
|
||||
x2="11.02502"
|
||||
y2="11.147234" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
gridtolerance="10000"
|
||||
guidetolerance="10"
|
||||
objecttolerance="10"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="45.254834"
|
||||
inkscape:cx="13.678175"
|
||||
inkscape:cy="6.8291478"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g25843"
|
||||
width="14px"
|
||||
height="14px"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="998"
|
||||
inkscape:window-x="44"
|
||||
inkscape:window-y="58"
|
||||
showgrid="true"
|
||||
gridspacingx="0.5px"
|
||||
gridspacingy="0.5px"
|
||||
gridempspacing="2"
|
||||
inkscape:grid-points="true" />
|
||||
<metadata
|
||||
id="metadata2275">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g25843"
|
||||
transform="matrix(0.7931251,0,0,0.7931251,-372.13374,-408.22195)">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:url(#radialGradient6052);fill-opacity:1.0;stroke:#c80000;stroke-width:1.43637741;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path22737"
|
||||
sodipodi:cx="466.73566"
|
||||
sodipodi:cy="431.19708"
|
||||
sodipodi:rx="8.5913839"
|
||||
sodipodi:ry="8.6452484"
|
||||
d="M 475.32704 431.19708 A 8.5913839 8.6452484 0 1 1 458.14427,431.19708 A 8.5913839 8.6452484 0 1 1 475.32704 431.19708 z"
|
||||
transform="matrix(0.8805346,0,0,0.8750503,66.41784,145.57686)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="opacity:1;fill:url(#linearGradient7035);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path6058"
|
||||
sodipodi:cx="6.75"
|
||||
sodipodi:cy="6.5"
|
||||
sodipodi:rx="5.75"
|
||||
sodipodi:ry="6"
|
||||
d="M 12.5 6.5 A 5.75 6 0 1 1 1,6.5 A 5.75 6 0 1 1 12.5 6.5 z"
|
||||
transform="matrix(0.9867408,0,0,0.6304178,470.73423,515.01579)" />
|
||||
<g
|
||||
id="g2380"
|
||||
inkscape:label="Layer 1"
|
||||
transform="matrix(1.2608365,0,0,1.2633098,469.19929,514.69071)">
|
||||
<g
|
||||
transform="matrix(0.7931251,0,0,0.7931251,-372.13374,-408.22195)"
|
||||
id="g2382">
|
||||
<path
|
||||
style="fill:#7f7f8c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 481.17723,524.15684 C 481.17723,524.15684 482.11277,524.68766 483.0584,524.68766 C 484.00403,524.68766 484.95974,524.15684 484.95974,524.15684 L 483.4493,526.03249 L 483.4493,527.83201 L 484.8944,528.56151 L 484.95974,531.09144 L 481.17723,531.09144 L 481.16963,528.69627 L 482.71594,527.80266 L 482.72456,526.04216 L 481.17723,524.15684 z "
|
||||
id="path2442"
|
||||
sodipodi:nodetypes="czcccccccccc" />
|
||||
<path
|
||||
style="opacity:0.2;fill:#7f7f7f;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 481.17723,521.00476 L 481.17723,523.52643 L 482.43807,526.0481 L 481.17723,528.56977 L 481.17723,531.72186 L 484.95974,531.72186 L 484.95974,528.56977 L 483.6989,526.0481 L 484.95974,523.52643 L 484.95974,521.00476 L 481.17723,521.00476 z "
|
||||
id="path2444"
|
||||
sodipodi:nodetypes="ccccccccccc" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccccccccccccccccccc"
|
||||
id="path2174"
|
||||
d="M 480.54682,520.37434 L 480.54681,523.52643 L 481.80765,526.0481 L 480.54681,528.56977 L 480.54682,531.72185 L 485.59016,531.72185 L 485.59015,528.56977 L 484.32932,526.0481 L 485.59015,523.52643 L 485.59016,520.37434 L 480.54682,520.37434 z M 481.80766,521.63517 L 484.32932,521.63517 L 484.32932,523.52643 L 483.46249,526.0481 L 484.32932,528.56977 L 484.32932,530.46102 L 481.80766,530.46102 L 481.80765,528.56977 L 482.72372,526.0481 L 481.80765,523.52643 L 481.80766,521.63517 z "
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<rect
|
||||
ry="1.2608351"
|
||||
y="519.7439"
|
||||
x="479.28598"
|
||||
height="2.5216701"
|
||||
width="7.565001"
|
||||
id="rect2172"
|
||||
style="opacity:1;fill:#7f2aff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
ry="1.2608351"
|
||||
y="529.83063"
|
||||
x="479.28598"
|
||||
height="2.5216701"
|
||||
width="7.565001"
|
||||
id="rect2170"
|
||||
style="opacity:1;fill:#6600ff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
ry="0.63040882"
|
||||
y="520.0589"
|
||||
x="480.17267"
|
||||
height="1.2608176"
|
||||
width="5.6737618"
|
||||
id="rect4140"
|
||||
style="opacity:1;fill:url(#linearGradient2392);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
ry="0.63040882"
|
||||
y="530.16577"
|
||||
x="480.13324"
|
||||
height="1.2608176"
|
||||
width="5.6737618"
|
||||
id="rect4144"
|
||||
style="opacity:1;fill:url(#linearGradient2394);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cssz"
|
||||
transform="matrix(1.2608351,0,0,1.2608351,469.1993,514.70058)"
|
||||
id="path4161"
|
||||
d="M 11.007811,9.9179701 C 10.386665,9.9257826 9.6414144,10.484263 9.5594939,10.992187 C 9.5017174,11.350414 12.494284,11.43273 12.441847,10.914063 C 12.40754,10.574731 11.628908,9.9101582 11.007811,9.9179701 z "
|
||||
style="fill:url(#linearGradient2396);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 18 KiB |
BIN
src/plugins/debugger/images/debugger_breakpoints.png
Normal file
|
After Width: | Height: | Size: 650 B |
BIN
src/plugins/debugger/images/debugger_continue_small.png
Normal file
|
After Width: | Height: | Size: 739 B |
BIN
src/plugins/debugger/images/debugger_interrupt_small.png
Normal file
|
After Width: | Height: | Size: 417 B |
BIN
src/plugins/debugger/images/debugger_start.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/plugins/debugger/images/debugger_start_small.png
Normal file
|
After Width: | Height: | Size: 739 B |
BIN
src/plugins/debugger/images/debugger_stepinto_small.png
Normal file
|
After Width: | Height: | Size: 420 B |
BIN
src/plugins/debugger/images/debugger_steponeproc_small.png
Normal file
|
After Width: | Height: | Size: 297 B |
BIN
src/plugins/debugger/images/debugger_stepout_small.png
Normal file
|
After Width: | Height: | Size: 382 B |
BIN
src/plugins/debugger/images/debugger_stepover_small.png
Normal file
|
After Width: | Height: | Size: 617 B |
BIN
src/plugins/debugger/images/debugger_stepoverproc_small.png
Normal file
|
After Width: | Height: | Size: 517 B |
BIN
src/plugins/debugger/images/debugger_stop_small.png
Normal file
|
After Width: | Height: | Size: 314 B |
BIN
src/plugins/debugger/images/delete.png
Normal file
|
After Width: | Height: | Size: 578 B |
BIN
src/plugins/debugger/images/done.png
Normal file
|
After Width: | Height: | Size: 235 B |
67
src/plugins/debugger/images/empty.svg
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="14"
|
||||
height="14"
|
||||
id="svg2243"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.45.1"
|
||||
version="1.0"
|
||||
sodipodi:docbase="c:\depot\research\main\editor\images"
|
||||
sodipodi:docname="location.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs2245">
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
gridtolerance="10000"
|
||||
guidetolerance="10"
|
||||
objecttolerance="10"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="64"
|
||||
inkscape:cx="8.3920091"
|
||||
inkscape:cy="7.4257237"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
width="14px"
|
||||
height="14px"
|
||||
showborder="true"
|
||||
inkscape:window-width="1600"
|
||||
inkscape:window-height="1174"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
gridempspacing="2"
|
||||
showgrid="true"
|
||||
inkscape:grid-points="true"
|
||||
gridspacingx="0.5px"
|
||||
gridspacingy="0.5px" />
|
||||
<metadata
|
||||
id="metadata2248">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
BIN
src/plugins/debugger/images/error.png
Normal file
|
After Width: | Height: | Size: 326 B |
121
src/plugins/debugger/images/location.svg
Normal file
@@ -0,0 +1,121 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="14"
|
||||
height="14"
|
||||
id="svg2243"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.45.1"
|
||||
version="1.0"
|
||||
sodipodi:docbase="c:\depot\research\main\editor\images"
|
||||
sodipodi:docname="location.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs2245">
|
||||
<linearGradient
|
||||
id="linearGradient3134">
|
||||
<stop
|
||||
style="stop-color:#dcdc23;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3136" />
|
||||
<stop
|
||||
id="stop5080"
|
||||
offset="0.64285713"
|
||||
style="stop-color:#e5d044;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#b89354;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3138" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3137">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0.86274511;"
|
||||
offset="0"
|
||||
id="stop3139" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3141" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3137"
|
||||
id="linearGradient3143"
|
||||
x1="6.5"
|
||||
y1="3"
|
||||
x2="6.515625"
|
||||
y2="12.180227"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3134"
|
||||
id="linearGradient3140"
|
||||
x1="6.5"
|
||||
y1="3.015625"
|
||||
x2="6.484375"
|
||||
y2="11.984375"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
gridtolerance="10000"
|
||||
guidetolerance="10"
|
||||
objecttolerance="10"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="64"
|
||||
inkscape:cx="8.3920091"
|
||||
inkscape:cy="7.4257237"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
width="14px"
|
||||
height="14px"
|
||||
showborder="true"
|
||||
inkscape:window-width="1600"
|
||||
inkscape:window-height="1174"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
gridempspacing="2"
|
||||
showgrid="true"
|
||||
inkscape:grid-points="true"
|
||||
gridspacingx="0.5px"
|
||||
gridspacingy="0.5px" />
|
||||
<metadata
|
||||
id="metadata2248">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:url(#linearGradient3140);fill-opacity:1.0;fill-rule:evenodd;stroke:#b18b1b;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 6.5,3 L 6.5,5.5 L 0.5,5.5 L 0.5,9.5 L 6.5,9.5 L 6.5,12 L 13.125,7.5 L 6.5,3 z "
|
||||
id="path2216"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
<path
|
||||
style="fill:url(#linearGradient3143);fill-opacity:1.0;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;opacity:1"
|
||||
d="M 6.5,3 L 6.5,5.5 L 0.5,5.5 L 0.5,7.5 C 7,6.5 7.5,9.5 13,7.5 L 6.5,3 z "
|
||||
id="path5066"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
BIN
src/plugins/debugger/images/newitem.png
Normal file
|
After Width: | Height: | Size: 239 B |
BIN
src/plugins/debugger/images/running.png
Normal file
|
After Width: | Height: | Size: 532 B |
49
src/plugins/debugger/imports.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_IMPORTS_H
|
||||
#define DEBUGGER_IMPORTS_H
|
||||
|
||||
// FIXME: Plan is to remove this file. It's needed to get "harmless"
|
||||
// replacements for GH internals in the standalone version
|
||||
|
||||
#ifndef GDBDEBUGGERLEAN
|
||||
|
||||
#include <texteditor/basetextmark.h>
|
||||
|
||||
#else
|
||||
|
||||
#include "lean.h"
|
||||
|
||||
#endif
|
||||
|
||||
#endif // DEBUGGER_IMPORTS_H
|
||||
233
src/plugins/debugger/mode.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "mode.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "debuggerconstants.h"
|
||||
#include "debuggermanager.h"
|
||||
|
||||
#include <coreplugin/coreconstants.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/modemanager.h>
|
||||
#include <coreplugin/uniqueidmanager.h>
|
||||
#include <coreplugin/actionmanager/actionmanagerinterface.h>
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <coreplugin/minisplitter.h>
|
||||
#include <coreplugin/findplaceholder.h>
|
||||
#include <coreplugin/outputpane.h>
|
||||
#include <coreplugin/navigationwidget.h>
|
||||
#include <coreplugin/rightpane.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtGui/QDockWidget>
|
||||
#include <QtGui/QLabel>
|
||||
#include <QtGui/QMainWindow>
|
||||
#include <QtGui/QVBoxLayout>
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
using namespace Core;
|
||||
using namespace ExtensionSystem;
|
||||
using namespace Debugger;
|
||||
using namespace Debugger::Internal;
|
||||
using namespace Debugger::Constants;
|
||||
|
||||
|
||||
DebugMode::DebugMode(DebuggerManager *manager, QObject *parent)
|
||||
: BaseMode(tr("Debug"), Constants::MODE_DEBUG,
|
||||
QIcon(":/fancyactionbar/images/mode_Debug.png"),
|
||||
Constants::P_MODE_DEBUG, 0, parent),
|
||||
m_manager(manager)
|
||||
{
|
||||
IDebuggerManagerAccessForDebugMode *managerAccess =
|
||||
m_manager->debugModeInterface();
|
||||
UniqueIDManager *uidm =
|
||||
PluginManager::instance()->getObject<ICore>()->uniqueIDManager();
|
||||
QList<int> context;
|
||||
context.append(uidm->uniqueIdentifier(Core::Constants::C_EDITORMANAGER));
|
||||
context.append(uidm->uniqueIdentifier(Constants::C_GDBDEBUGGER));
|
||||
context.append(uidm->uniqueIdentifier(Core::Constants::C_NAVIGATION_PANE));
|
||||
setContext(context);
|
||||
|
||||
QBoxLayout *editorHolderLayout = new QVBoxLayout;
|
||||
editorHolderLayout->setMargin(0);
|
||||
editorHolderLayout->setSpacing(0);
|
||||
editorHolderLayout->addWidget(new EditorManagerPlaceHolder(this));
|
||||
editorHolderLayout->addWidget(new FindToolBarPlaceHolder(this));
|
||||
|
||||
QWidget *editorAndFindWidget = new QWidget;
|
||||
editorAndFindWidget->setLayout(editorHolderLayout);
|
||||
|
||||
MiniSplitter *rightPaneSplitter = new MiniSplitter;
|
||||
rightPaneSplitter->addWidget(editorAndFindWidget);
|
||||
rightPaneSplitter->addWidget(new RightPanePlaceHolder(this));
|
||||
rightPaneSplitter->setStretchFactor(0, 1);
|
||||
rightPaneSplitter->setStretchFactor(1, 0);
|
||||
|
||||
QWidget *centralWidget = new QWidget;
|
||||
QBoxLayout *toolBarAddingLayout = new QVBoxLayout(centralWidget);
|
||||
toolBarAddingLayout->setMargin(0);
|
||||
toolBarAddingLayout->setSpacing(0);
|
||||
toolBarAddingLayout->addWidget(rightPaneSplitter);
|
||||
|
||||
m_manager->mainWindow()->setCentralWidget(centralWidget);
|
||||
|
||||
MiniSplitter *splitter = new MiniSplitter;
|
||||
splitter->addWidget(m_manager->mainWindow());
|
||||
splitter->addWidget(new OutputPanePlaceHolder(this));
|
||||
splitter->setStretchFactor(0, 10);
|
||||
splitter->setStretchFactor(1, 0);
|
||||
splitter->setOrientation(Qt::Vertical);
|
||||
|
||||
MiniSplitter *splitter2 = new MiniSplitter;
|
||||
splitter2 = new MiniSplitter;
|
||||
splitter2->addWidget(new NavigationWidgetPlaceHolder(this));
|
||||
splitter2->addWidget(splitter);
|
||||
splitter2->setStretchFactor(0, 0);
|
||||
splitter2->setStretchFactor(1, 1);
|
||||
|
||||
setWidget(splitter2);
|
||||
|
||||
QToolBar *toolBar = createToolBar();
|
||||
toolBarAddingLayout->addWidget(toolBar);
|
||||
|
||||
managerAccess->createDockWidgets();
|
||||
m_manager->setSimpleDockWidgetArrangement();
|
||||
readSettings();
|
||||
|
||||
connect(ModeManager::instance(), SIGNAL(currentModeChanged(Core::IMode*)),
|
||||
this, SLOT(focusCurrentEditor(Core::IMode*)));
|
||||
widget()->setFocusProxy(EditorManager::instance());
|
||||
}
|
||||
|
||||
DebugMode::~DebugMode()
|
||||
{
|
||||
// Make sure the editor manager does not get deleted
|
||||
EditorManager::instance()->setParent(0);
|
||||
}
|
||||
|
||||
void DebugMode::shutdown()
|
||||
{
|
||||
writeSettings();
|
||||
}
|
||||
|
||||
QToolBar *DebugMode::createToolBar()
|
||||
{
|
||||
IDebuggerManagerAccessForDebugMode *managerAccess =
|
||||
m_manager->debugModeInterface();
|
||||
|
||||
Core::ActionManagerInterface *am =
|
||||
ExtensionSystem::PluginManager::instance()
|
||||
->getObject<Core::ICore>()->actionManager();
|
||||
QToolBar *debugToolBar = new QToolBar;
|
||||
debugToolBar->addAction(am->command(ProjectExplorer::Constants::DEBUG)->action());
|
||||
debugToolBar->addAction(am->command(Constants::INTERRUPT)->action());
|
||||
debugToolBar->addAction(am->command(Constants::NEXT)->action());
|
||||
debugToolBar->addAction(am->command(Constants::STEP)->action());
|
||||
debugToolBar->addAction(am->command(Constants::STEPOUT)->action());
|
||||
debugToolBar->addSeparator();
|
||||
debugToolBar->addAction(am->command(Constants::STEPI)->action());
|
||||
debugToolBar->addAction(am->command(Constants::NEXTI)->action());
|
||||
debugToolBar->addSeparator();
|
||||
debugToolBar->addWidget(new QLabel(tr("Threads:")));
|
||||
|
||||
QComboBox *threadBox = new QComboBox;
|
||||
threadBox->setModel(m_manager->threadsModel());
|
||||
connect(threadBox, SIGNAL(activated(int)),
|
||||
managerAccess->threadsWindow(), SIGNAL(threadSelected(int)));
|
||||
debugToolBar->addWidget(threadBox);
|
||||
|
||||
QWidget *stretch = new QWidget;
|
||||
stretch->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
debugToolBar->addWidget(stretch);
|
||||
|
||||
QMenu *viewMenu = new QMenu(debugToolBar);
|
||||
m_toggleLockedAction = new QAction(tr("Locked"), viewMenu);
|
||||
m_toggleLockedAction->setCheckable(true);
|
||||
m_toggleLockedAction->setChecked(true);
|
||||
connect(m_toggleLockedAction, SIGNAL(toggled(bool)),
|
||||
m_manager, SLOT(setLocked(bool)));
|
||||
foreach (QDockWidget *dockWidget, managerAccess->dockWidgets())
|
||||
viewMenu->addAction(dockWidget->toggleViewAction());
|
||||
viewMenu->addSeparator();
|
||||
viewMenu->addAction(m_toggleLockedAction);
|
||||
viewMenu->addSeparator();
|
||||
|
||||
QAction *resetToSimpleAction = viewMenu->addAction(tr("Reset to default layout"));
|
||||
connect(resetToSimpleAction, SIGNAL(triggered()),
|
||||
m_manager, SLOT(setSimpleDockWidgetArrangement()));
|
||||
QToolButton *viewMenuButton = new QToolButton(debugToolBar);
|
||||
viewMenuButton->setText(tr("View "));
|
||||
viewMenuButton->setPopupMode(QToolButton::InstantPopup);
|
||||
viewMenuButton->setMenu(viewMenu);
|
||||
debugToolBar->addWidget(viewMenuButton);
|
||||
|
||||
return debugToolBar;
|
||||
}
|
||||
|
||||
void DebugMode::focusCurrentEditor(IMode *mode)
|
||||
{
|
||||
if (mode != this)
|
||||
return;
|
||||
|
||||
EditorManager *editorManager = EditorManager::instance();
|
||||
|
||||
if (editorManager->currentEditor())
|
||||
editorManager->currentEditor()->widget()->setFocus();
|
||||
}
|
||||
|
||||
void DebugMode::writeSettings() const
|
||||
{
|
||||
QSettings *s = settings();
|
||||
QWB_ASSERT(m_manager, return);
|
||||
QWB_ASSERT(m_manager->mainWindow(), return);
|
||||
s->beginGroup(QLatin1String("DebugMode"));
|
||||
s->setValue(QLatin1String("State"), m_manager->mainWindow()->saveState());
|
||||
s->setValue(QLatin1String("Locked"), m_toggleLockedAction->isChecked());
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
void DebugMode::readSettings()
|
||||
{
|
||||
QSettings *s = settings();
|
||||
s->beginGroup(QLatin1String("DebugMode"));
|
||||
m_manager->mainWindow()->restoreState(s->value(QLatin1String("State"), QByteArray()).toByteArray());
|
||||
m_toggleLockedAction->setChecked(s->value(QLatin1String("Locked"), true).toBool());
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
QSettings *DebugMode::settings()
|
||||
{
|
||||
return PluginManager::instance()->getObject<ICore>()->settings();
|
||||
}
|
||||
84
src/plugins/debugger/mode.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_DEBUGMODE_H
|
||||
#define DEBUGGER_DEBUGMODE_H
|
||||
|
||||
#include <coreplugin/basemode.h>
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QPointer>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAction;
|
||||
class QDockWidget;
|
||||
class QMainWindow;
|
||||
class QSettings;
|
||||
class QSplitter;
|
||||
class QToolBar;
|
||||
class QWidget;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class DebuggerManager;
|
||||
|
||||
class DebugMode : public Core::BaseMode
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DebugMode(DebuggerManager *manager, QObject *parent = 0);
|
||||
~DebugMode();
|
||||
|
||||
// IMode
|
||||
void activated();
|
||||
void shutdown();
|
||||
static QSettings *settings();
|
||||
|
||||
private slots:
|
||||
void focusCurrentEditor(Core::IMode *mode);
|
||||
|
||||
private:
|
||||
QToolBar *createToolBar();
|
||||
void writeSettings() const;
|
||||
void readSettings();
|
||||
|
||||
QPointer<DebuggerManager> m_manager;
|
||||
QAction *m_toggleLockedAction;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_DEBUGMODE_H
|
||||
76
src/plugins/debugger/mode.ui
Normal file
@@ -0,0 +1,76 @@
|
||||
<ui version="4.0" >
|
||||
<class>DebugMode</class>
|
||||
<widget class="QWidget" name="DebugMode" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>558</width>
|
||||
<height>353</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3" >
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSplitter" name="vSplitter" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QWidget" native="1" name="editorHolder" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
|
||||
<horstretch>10</horstretch>
|
||||
<verstretch>10</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget" >
|
||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="toolbarLayout" >
|
||||
<property name="spacing" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="hSplitter" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QTabWidget" name="bottomTabWidget" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="tabPosition" >
|
||||
<enum>QTabWidget::South</enum>
|
||||
</property>
|
||||
<property name="tabShape" >
|
||||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
172
src/plugins/debugger/moduleshandler.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "moduleshandler.h"
|
||||
|
||||
#include "assert.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QTextStream>
|
||||
|
||||
#include <QtGui/QAction>
|
||||
#include <QtGui/QMainWindow>
|
||||
#include <QtGui/QStandardItemModel>
|
||||
#include <QtGui/QSortFilterProxyModel>
|
||||
|
||||
using namespace Debugger;
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ModulesModel
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
class Debugger::Internal::ModulesModel : public QAbstractItemModel
|
||||
{
|
||||
public:
|
||||
ModulesModel(ModulesHandler *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
{}
|
||||
|
||||
// QAbstractItemModel
|
||||
int columnCount(const QModelIndex &parent) const
|
||||
{ return parent.isValid() ? 0 : 4; }
|
||||
int rowCount(const QModelIndex &parent) const
|
||||
{ return parent.isValid() ? 0 : m_modules.size(); }
|
||||
QModelIndex parent(const QModelIndex &) const { return QModelIndex(); }
|
||||
QModelIndex index(int row, int column, const QModelIndex &) const
|
||||
{ return createIndex(row, column); }
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
|
||||
void clearModel() { if (!m_modules.isEmpty()) { m_modules.clear(); update(); } }
|
||||
void update() { reset(); }
|
||||
|
||||
public:
|
||||
QList<Module> m_modules;
|
||||
};
|
||||
|
||||
QVariant ModulesModel::headerData(int section,
|
||||
Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||
static QString headers[] = {
|
||||
tr("Module name") + " ",
|
||||
tr("Symbols read") + " ",
|
||||
tr("Start address") + " ",
|
||||
tr("End addAress") + " "
|
||||
};
|
||||
return headers[section];
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant ModulesModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
//static const QIcon icon(":/gdbdebugger/images/breakpoint.svg");
|
||||
//static const QIcon icon2(":/gdbdebugger/images/breakpoint_pending.svg");
|
||||
|
||||
int row = index.row();
|
||||
if (row < 0 || row >= m_modules.size())
|
||||
return QVariant();
|
||||
|
||||
const Module &module = m_modules.at(row);
|
||||
|
||||
switch (index.column()) {
|
||||
case 0:
|
||||
if (role == Qt::DisplayRole)
|
||||
return module.moduleName;
|
||||
// FIXME: add icons
|
||||
//if (role == Qt::DecorationRole)
|
||||
// return module.symbolsRead ? icon2 : icon;
|
||||
break;
|
||||
case 1:
|
||||
if (role == Qt::DisplayRole)
|
||||
return module.symbolsRead ? "yes" : "no";
|
||||
break;
|
||||
case 2:
|
||||
if (role == Qt::DisplayRole)
|
||||
return module.startAddress;
|
||||
break;
|
||||
case 3:
|
||||
if (role == Qt::DisplayRole)
|
||||
return module.endAddress;
|
||||
break;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool ModulesModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
return QAbstractItemModel::setData(index, value, role);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ModulesHandler
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
ModulesHandler::ModulesHandler()
|
||||
{
|
||||
m_model = new ModulesModel(this);
|
||||
m_proxyModel = new QSortFilterProxyModel(this);
|
||||
m_proxyModel->setSourceModel(m_model);
|
||||
}
|
||||
|
||||
QAbstractItemModel *ModulesHandler::model() const
|
||||
{
|
||||
return m_proxyModel;
|
||||
}
|
||||
|
||||
void ModulesHandler::removeAll()
|
||||
{
|
||||
m_model->clearModel();
|
||||
}
|
||||
|
||||
|
||||
void ModulesHandler::setModules(const QList<Module> &modules)
|
||||
{
|
||||
m_model->m_modules = modules;
|
||||
m_model->update();
|
||||
}
|
||||
|
||||
QList<Module> ModulesHandler::modules() const
|
||||
{
|
||||
return m_model->m_modules;
|
||||
}
|
||||
104
src/plugins/debugger/moduleshandler.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_MODULESHANDLER_H
|
||||
#define DEBUGGER_MODULESHANDLER_H
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAbstractItemModel;
|
||||
class QSortFilterProxyModel;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class ModulesModel;
|
||||
|
||||
enum ModulesModelRoles
|
||||
{
|
||||
DisplaySourceRole = Qt::UserRole,
|
||||
LoadSymbolsRole,
|
||||
LoadAllSymbolsRole
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Module
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
class Module
|
||||
{
|
||||
public:
|
||||
Module() : symbolsRead(false) {}
|
||||
|
||||
public:
|
||||
QString moduleName;
|
||||
bool symbolsRead;
|
||||
QString startAddress;
|
||||
QString endAddress;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ModulesHandler
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
class ModulesHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ModulesHandler();
|
||||
|
||||
QAbstractItemModel *model() const;
|
||||
|
||||
void setModules(const QList<Module> &modules);
|
||||
QList<Module> modules() const;
|
||||
void removeAll();
|
||||
|
||||
private:
|
||||
ModulesModel *m_model;
|
||||
QSortFilterProxyModel *m_proxyModel;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_MODULESHANDLER_H
|
||||
136
src/plugins/debugger/moduleswindow.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "moduleswindow.h"
|
||||
#include "moduleshandler.h" // for model roles
|
||||
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
#include <QResizeEvent>
|
||||
#include <QToolButton>
|
||||
|
||||
|
||||
using Debugger::Internal::ModulesWindow;
|
||||
|
||||
ModulesWindow::ModulesWindow(QWidget *parent)
|
||||
: QTreeView(parent), m_alwaysResizeColumnsToContents(false)
|
||||
{
|
||||
setWindowTitle(tr("Modules"));
|
||||
setSortingEnabled(true);
|
||||
setAlternatingRowColors(true);
|
||||
setRootIsDecorated(false);
|
||||
setIconSize(QSize(10, 10));
|
||||
}
|
||||
|
||||
void ModulesWindow::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
//QHeaderView *hv = header();
|
||||
//int totalSize = event->size().width() - 110;
|
||||
//hv->resizeSection(0, totalSize / 4);
|
||||
//hv->resizeSection(1, totalSize / 4);
|
||||
//hv->resizeSection(2, totalSize / 4);
|
||||
//hv->resizeSection(3, totalSize / 4);
|
||||
//hv->resizeSection(0, 60);
|
||||
//hv->resizeSection(1, (totalSize * 50) / 100);
|
||||
//hv->resizeSection(2, (totalSize * 50) / 100);
|
||||
//hv->resizeSection(3, 50);
|
||||
//setColumnHidden(3, true);
|
||||
QTreeView::resizeEvent(event);
|
||||
}
|
||||
|
||||
void ModulesWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
{
|
||||
QModelIndex index = indexAt(ev->pos());
|
||||
index = index.sibling(index.row(), 0);
|
||||
QString name = model()->data(index).toString();
|
||||
|
||||
QMenu menu;
|
||||
QAction *act0 = new QAction("Update module list", &menu);
|
||||
QAction *act1 = new QAction("Adjust column widths to contents", &menu);
|
||||
QAction *act2 = new QAction("Always adjust column widths to contents", &menu);
|
||||
act2->setCheckable(true);
|
||||
act2->setChecked(m_alwaysResizeColumnsToContents);
|
||||
QAction *act3 = new QAction("Show source files for module " + name, &menu);
|
||||
QAction *act4 = new QAction("Load symbols for all modules", &menu);
|
||||
QAction *act5 = new QAction("Load symbols for module " + name, &menu);
|
||||
act5->setDisabled(name.isEmpty());
|
||||
|
||||
menu.addAction(act0);
|
||||
menu.addAction(act4);
|
||||
menu.addAction(act5);
|
||||
menu.addSeparator();
|
||||
menu.addAction(act1);
|
||||
menu.addAction(act2);
|
||||
|
||||
QAction *act = menu.exec(ev->globalPos());
|
||||
|
||||
if (act == act0)
|
||||
emit reloadModulesRequested();
|
||||
else if (act == act1)
|
||||
resizeColumnsToContents();
|
||||
else if (act == act2)
|
||||
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
|
||||
else if (act == act3)
|
||||
emit displaySourceRequested(name);
|
||||
else if (act == act4)
|
||||
emit loadAllSymbolsRequested();
|
||||
else if (act == act5)
|
||||
emit loadSymbolsRequested(name);
|
||||
}
|
||||
|
||||
void ModulesWindow::resizeColumnsToContents()
|
||||
{
|
||||
resizeColumnToContents(0);
|
||||
resizeColumnToContents(1);
|
||||
resizeColumnToContents(2);
|
||||
}
|
||||
|
||||
void ModulesWindow::setAlwaysResizeColumnsToContents(bool on)
|
||||
{
|
||||
m_alwaysResizeColumnsToContents = on;
|
||||
QHeaderView::ResizeMode mode = on
|
||||
? QHeaderView::ResizeToContents : QHeaderView::Interactive;
|
||||
header()->setResizeMode(0, mode);
|
||||
header()->setResizeMode(1, mode);
|
||||
header()->setResizeMode(2, mode);
|
||||
header()->setResizeMode(3, mode);
|
||||
//setColumnHidden(3, true);
|
||||
}
|
||||
|
||||
void ModulesWindow::setModel(QAbstractItemModel *model)
|
||||
{
|
||||
QTreeView::setModel(model);
|
||||
setAlwaysResizeColumnsToContents(true);
|
||||
}
|
||||
|
||||
71
src/plugins/debugger/moduleswindow.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_MODULESWINDOW_H
|
||||
#define DEBUGGER_MODULESWINDOW_H
|
||||
|
||||
#include <QTreeView>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class ModulesWindow : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ModulesWindow(QWidget *parent = 0);
|
||||
|
||||
signals:
|
||||
void reloadModulesRequested();
|
||||
void displaySourceRequested(const QString &modulesName);
|
||||
void loadSymbolsRequested(const QString &modulesName);
|
||||
void loadAllSymbolsRequested();
|
||||
|
||||
public slots:
|
||||
void resizeColumnsToContents();
|
||||
void setAlwaysResizeColumnsToContents(bool on);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *ev);
|
||||
void contextMenuEvent(QContextMenuEvent *ev);
|
||||
void setModel(QAbstractItemModel *model);
|
||||
|
||||
private:
|
||||
bool m_alwaysResizeColumnsToContents;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_MODULESWINDOW_H
|
||||
|
||||
182
src/plugins/debugger/procinterrupt.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "procinterrupt.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <windows.h>
|
||||
#include <Tlhelp32.h>
|
||||
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
typedef HANDLE (WINAPI *PtrCreateRemoteThread)(
|
||||
HANDLE hProcess,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
SIZE_T dwStackSize,
|
||||
LPTHREAD_START_ROUTINE lpStartAddress,
|
||||
LPVOID lpParameter,
|
||||
DWORD dwCreationFlags,
|
||||
LPDWORD lpThreadId);
|
||||
|
||||
PtrCreateRemoteThread resolveCreateRemoteThread()
|
||||
{
|
||||
HINSTANCE hLib = LoadLibraryA("Kernel32");
|
||||
return (PtrCreateRemoteThread)GetProcAddress(hLib, "CreateRemoteThread");
|
||||
}
|
||||
|
||||
DWORD findProcessId(DWORD parentId)
|
||||
{
|
||||
HANDLE hProcList = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
|
||||
PROCESSENTRY32 procEntry;
|
||||
procEntry.dwSize = sizeof(PROCESSENTRY32);
|
||||
|
||||
DWORD procId = 0;
|
||||
|
||||
BOOL moreProc = Process32First(hProcList, &procEntry);
|
||||
while (moreProc) {
|
||||
if (procEntry.th32ParentProcessID == parentId) {
|
||||
procId = procEntry.th32ProcessID;
|
||||
break;
|
||||
}
|
||||
moreProc = Process32Next(hProcList, &procEntry);
|
||||
}
|
||||
|
||||
CloseHandle(hProcList);
|
||||
return procId;
|
||||
}
|
||||
#else
|
||||
|
||||
#include <QtCore/QLatin1String>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QFileInfoList>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#define OPProcessValueUnknown UINT_MAX
|
||||
|
||||
/* Mac OS X
|
||||
int OPParentIDForProcessID(int pid)
|
||||
// Returns the parent process id for the given process id (pid)
|
||||
{
|
||||
struct kinfo_proc info;
|
||||
size_t length = sizeof(struct kinfo_proc);
|
||||
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
|
||||
if (sysctl(mib, 4, &info, &length, NULL, 0) < 0)
|
||||
return OPProcessValueUnknown;
|
||||
if (length == 0)
|
||||
return OPProcessValueUnknown;
|
||||
return info.kp_eproc.e_ppid;
|
||||
}
|
||||
*/
|
||||
|
||||
int findParentProcess(int procId)
|
||||
{
|
||||
QFile statFile(QLatin1String("/proc/") + QString::number(procId) +
|
||||
QLatin1String("/stat"));
|
||||
if (!statFile.open(QIODevice::ReadOnly))
|
||||
return -1;
|
||||
|
||||
QByteArray line = statFile.readLine();
|
||||
line = line.mid(line.indexOf(')') + 4);
|
||||
//qDebug() << "1: " << line;
|
||||
line = line.left(line.indexOf(' '));
|
||||
//qDebug() << "2: " << line;
|
||||
|
||||
return QString(line).toInt();
|
||||
}
|
||||
|
||||
int findChildProcess(int parentId)
|
||||
{
|
||||
QDir proc(QLatin1String("/proc"));
|
||||
QFileInfoList procList = proc.entryInfoList(QDir::Dirs);
|
||||
foreach (const QFileInfo &info, procList) {
|
||||
int procId = 0;
|
||||
bool ok = false;
|
||||
procId = info.baseName().toInt(&ok);
|
||||
if (!ok || !procId)
|
||||
continue;
|
||||
|
||||
if (findParentProcess(procId) == parentId)
|
||||
return procId;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool Debugger::Internal::interruptProcess(int pID)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
DWORD pid = pID;
|
||||
if (!pid)
|
||||
return false;
|
||||
|
||||
PtrCreateRemoteThread libFunc = resolveCreateRemoteThread();
|
||||
if (libFunc) {
|
||||
DWORD dwThreadId = 0;
|
||||
HANDLE hproc = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
|
||||
HANDLE hthread = libFunc(hproc, NULL, 0, (LPTHREAD_START_ROUTINE)DebugBreak, 0, 0, &dwThreadId);
|
||||
CloseHandle(hthread);
|
||||
if (dwThreadId)
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
int procId = pID;
|
||||
if (procId != -1) {
|
||||
if (kill(procId, 2) == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Debugger::Internal::interruptChildProcess(Q_PID parentPID)
|
||||
{
|
||||
#ifdef WIN32
|
||||
DWORD pid = findProcessId(parentPID->dwProcessId);
|
||||
return interruptProcess(pid);
|
||||
#else
|
||||
int procId = findChildProcess(parentPID);
|
||||
//qDebug() << "INTERRUPTING PROCESS" << procId;
|
||||
return interruptProcess(procId);
|
||||
#endif
|
||||
}
|
||||
47
src/plugins/debugger/procinterrupt.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_PROCINTERRUPT_H
|
||||
#define DEBUGGER_PROCINTERRUPT_H
|
||||
|
||||
#include <QtCore/QProcess>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
bool interruptProcess(int pID);
|
||||
bool interruptChildProcess(Q_PID parentPID);
|
||||
|
||||
} // Internal
|
||||
} // GdbDebugger
|
||||
|
||||
#endif // DEBUGGER_PROCINTERRUPT_H
|
||||
128
src/plugins/debugger/registerhandler.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "registerhandler.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "debuggerconstants.h"
|
||||
|
||||
#include <QtCore/QAbstractTableModel>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <QtGui/QColor>
|
||||
|
||||
using namespace Debugger;
|
||||
using namespace Debugger::Internal;
|
||||
using namespace Debugger::Constants;
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// RegisterHandler
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
RegisterHandler::RegisterHandler(QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
setProperty(PROPERTY_REGISTER_FORMAT, "x");
|
||||
}
|
||||
|
||||
int RegisterHandler::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return m_registers.size();
|
||||
}
|
||||
|
||||
int RegisterHandler::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
return 2;
|
||||
}
|
||||
|
||||
QVariant RegisterHandler::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
static const QVariant red = QColor(200, 0, 0);
|
||||
if (!index.isValid() || index.row() >= m_registers.size())
|
||||
return QVariant();
|
||||
|
||||
const Register ® = m_registers.at(index.row());
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (index.column()) {
|
||||
case 0:
|
||||
return reg.name;
|
||||
case 1:
|
||||
return reg.value;
|
||||
}
|
||||
}
|
||||
if (role == Qt::TextColorRole && reg.changed && index.column() == 1)
|
||||
return red;
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant RegisterHandler::headerData(int section, Qt::Orientation orientation,
|
||||
int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||
static const char * const headers[] = {
|
||||
QT_TR_NOOP("Name"),
|
||||
QT_TR_NOOP("Value"),
|
||||
};
|
||||
if (section < 2)
|
||||
return tr(headers[section]);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void RegisterHandler::removeAll()
|
||||
{
|
||||
m_registers.clear();
|
||||
reset();
|
||||
}
|
||||
|
||||
bool RegisterHandler::isEmpty() const
|
||||
{
|
||||
return m_registers.isEmpty();
|
||||
}
|
||||
|
||||
void RegisterHandler::setRegisters(const QList<Register> ®isters)
|
||||
{
|
||||
m_registers = registers;
|
||||
reset();
|
||||
}
|
||||
|
||||
QList<Register> RegisterHandler::registers() const
|
||||
{
|
||||
return m_registers;
|
||||
}
|
||||
81
src/plugins/debugger/registerhandler.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_REGISTERHANDLER_H
|
||||
#define DEBUGGER_REGISTERHANDLER_H
|
||||
|
||||
#include <QtCore/QAbstractTableModel>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class Register
|
||||
{
|
||||
public:
|
||||
Register() : changed(true) {}
|
||||
Register(QString const &name_) : name(name_), changed(true) {}
|
||||
|
||||
public:
|
||||
QString name;
|
||||
QString value;
|
||||
bool changed;
|
||||
};
|
||||
|
||||
class RegisterHandler : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RegisterHandler(QObject *parent = 0);
|
||||
|
||||
void sessionClosed();
|
||||
QAbstractItemModel *model() { return this; }
|
||||
|
||||
bool isEmpty() const; // nothing known so far?
|
||||
void setRegisters(const QList<Register> ®isters);
|
||||
QList<Register> registers() const;
|
||||
void removeAll();
|
||||
|
||||
private:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
|
||||
QList<Register> m_registers;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_REGISTERHANDLER_H
|
||||
181
src/plugins/debugger/registerwindow.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "registerwindow.h"
|
||||
|
||||
#include "debuggerconstants.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QFileInfoList>
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
#include <QResizeEvent>
|
||||
#include <QToolButton>
|
||||
|
||||
|
||||
using namespace Debugger::Internal;
|
||||
using namespace Debugger::Constants;
|
||||
|
||||
RegisterWindow::RegisterWindow()
|
||||
: m_alwaysResizeColumnsToContents(true), m_alwaysReloadContents(false)
|
||||
{
|
||||
setWindowTitle(tr("Registers"));
|
||||
setSortingEnabled(true);
|
||||
setAlternatingRowColors(true);
|
||||
setRootIsDecorated(false);
|
||||
//header()->hide();
|
||||
//setIconSize(QSize(10, 10));
|
||||
//setWindowIcon(QIcon(":/gdbdebugger/images/debugger_breakpoints.png"));
|
||||
//QHeaderView *hv = header();
|
||||
//hv->setDefaultAlignment(Qt::AlignLeft);
|
||||
//hv->setClickable(true);
|
||||
//hv->setSortIndicatorShown(true);
|
||||
}
|
||||
|
||||
void RegisterWindow::resizeEvent(QResizeEvent *ev)
|
||||
{
|
||||
//QHeaderView *hv = header();
|
||||
//int totalSize = ev->size().width() - 110;
|
||||
//hv->resizeSection(0, totalSize / 4);
|
||||
//hv->resizeSection(1, totalSize / 4);
|
||||
QTreeView::resizeEvent(ev);
|
||||
}
|
||||
|
||||
void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
{
|
||||
enum { Hex, Bin, Dec, Raw, Oct, Nat,
|
||||
Adjust, AlwaysAdjust, Reload, AlwaysReload, Count };
|
||||
|
||||
QMenu menu;
|
||||
QAction *actions[Count];
|
||||
//QTreeWidgetItem *item = itemAt(ev->pos());
|
||||
QString format = model()->property(PROPERTY_REGISTER_FORMAT).toString();
|
||||
qDebug() << "FORMAT: " << format;
|
||||
|
||||
actions[Adjust] = menu.addAction("Adjust column widths to contents");
|
||||
|
||||
actions[AlwaysAdjust] = menu.addAction("Always adjust column widths to contents");
|
||||
actions[AlwaysAdjust]->setCheckable(true);
|
||||
actions[AlwaysAdjust]->setChecked(m_alwaysResizeColumnsToContents);
|
||||
|
||||
actions[Reload] = menu.addAction("Reload register listing");
|
||||
|
||||
actions[AlwaysReload] = menu.addAction("Always reload register listing");
|
||||
actions[AlwaysReload]->setCheckable(true);
|
||||
actions[AlwaysReload]->setChecked(m_alwaysReloadContents);
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
actions[Hex] = menu.addAction("Hexadecimal");
|
||||
actions[Hex]->setCheckable(true);
|
||||
actions[Hex]->setChecked(format == "h");
|
||||
|
||||
actions[Bin] = menu.addAction("Binary");
|
||||
actions[Bin]->setCheckable(true);
|
||||
actions[Bin]->setChecked(format == "t");
|
||||
|
||||
actions[Dec] = menu.addAction("Decimal");
|
||||
actions[Dec]->setCheckable(true);
|
||||
actions[Dec]->setChecked(format == "d");
|
||||
|
||||
actions[Raw] = menu.addAction("Raw");
|
||||
actions[Raw]->setCheckable(true);
|
||||
actions[Raw]->setChecked(format == "r");
|
||||
|
||||
actions[Nat] = menu.addAction("Natural");
|
||||
actions[Nat]->setCheckable(true);
|
||||
actions[Nat]->setChecked(format == "N");
|
||||
|
||||
actions[Oct] = menu.addAction("Octal");
|
||||
actions[Oct]->setCheckable(true);
|
||||
actions[Oct]->setChecked(format == "o");
|
||||
|
||||
QAction *act = menu.exec(ev->globalPos());
|
||||
|
||||
if (act == actions[Adjust])
|
||||
resizeColumnsToContents();
|
||||
else if (act == actions[AlwaysAdjust])
|
||||
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
|
||||
else if (act == actions[Reload])
|
||||
reloadContents();
|
||||
else if (act == actions[AlwaysReload])
|
||||
setAlwaysReloadContents(!m_alwaysReloadContents);
|
||||
else if (act == actions[Hex])
|
||||
model()->setProperty(PROPERTY_REGISTER_FORMAT, "h");
|
||||
else if (act == actions[Oct])
|
||||
model()->setProperty(PROPERTY_REGISTER_FORMAT, "o");
|
||||
else if (act == actions[Bin])
|
||||
model()->setProperty(PROPERTY_REGISTER_FORMAT, "t");
|
||||
else if (act == actions[Dec])
|
||||
model()->setProperty(PROPERTY_REGISTER_FORMAT, "d");
|
||||
else if (act == actions[Nat])
|
||||
model()->setProperty(PROPERTY_REGISTER_FORMAT, "N");
|
||||
|
||||
}
|
||||
|
||||
void RegisterWindow::resizeColumnsToContents()
|
||||
{
|
||||
resizeColumnToContents(0);
|
||||
resizeColumnToContents(1);
|
||||
}
|
||||
|
||||
void RegisterWindow::setAlwaysResizeColumnsToContents(bool on)
|
||||
{
|
||||
m_alwaysResizeColumnsToContents = on;
|
||||
QHeaderView::ResizeMode mode = on
|
||||
? QHeaderView::ResizeToContents : QHeaderView::Interactive;
|
||||
header()->setResizeMode(0, mode);
|
||||
header()->setResizeMode(1, mode);
|
||||
}
|
||||
|
||||
void RegisterWindow::setAlwaysReloadContents(bool on)
|
||||
{
|
||||
m_alwaysReloadContents = on;
|
||||
if (m_alwaysReloadContents)
|
||||
reloadContents();
|
||||
}
|
||||
|
||||
void RegisterWindow::reloadContents()
|
||||
{
|
||||
emit reloadRegisterRequested();
|
||||
}
|
||||
|
||||
|
||||
void RegisterWindow::setModel(QAbstractItemModel *model)
|
||||
{
|
||||
QTreeView::setModel(model);
|
||||
setAlwaysResizeColumnsToContents(true);
|
||||
}
|
||||
|
||||
71
src/plugins/debugger/registerwindow.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_REGISTERWINDOW_H
|
||||
#define DEBUGGER_REGISTERWINDOW_H
|
||||
|
||||
#include <QTreeView>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class RegisterWindow : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RegisterWindow();
|
||||
void setModel(QAbstractItemModel *model);
|
||||
|
||||
signals:
|
||||
void reloadRegisterRequested();
|
||||
|
||||
public slots:
|
||||
void resizeColumnsToContents();
|
||||
void setAlwaysResizeColumnsToContents(bool on);
|
||||
void reloadContents();
|
||||
void setAlwaysReloadContents(bool on);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *ev);
|
||||
void contextMenuEvent(QContextMenuEvent *ev);
|
||||
|
||||
private:
|
||||
bool m_alwaysResizeColumnsToContents;
|
||||
bool m_alwaysReloadContents;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_REGISTERWINDOW_H
|
||||
|
||||
677
src/plugins/debugger/scriptengine.cpp
Normal file
@@ -0,0 +1,677 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
|
||||
#include "scriptengine.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "debuggerconstants.h"
|
||||
#include "debuggermanager.h"
|
||||
|
||||
#include "disassemblerhandler.h"
|
||||
#include "breakhandler.h"
|
||||
#include "moduleshandler.h"
|
||||
#include "registerhandler.h"
|
||||
#include "stackhandler.h"
|
||||
#include "watchhandler.h"
|
||||
|
||||
#include "startexternaldialog.h"
|
||||
#include "attachexternaldialog.h"
|
||||
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#include <QtGui/QAction>
|
||||
#include <QtGui/QToolTip>
|
||||
|
||||
#include <QtScript/QScriptContext>
|
||||
#include <QtScript/QScriptClassPropertyIterator>
|
||||
#include <QtScript/QScriptContextInfo>
|
||||
#include <QtScript/QScriptEngine>
|
||||
#include <QtScript/QScriptEngineAgent>
|
||||
#include <QtScript/QScriptValue>
|
||||
#include <QtScript/QScriptValueIterator>
|
||||
|
||||
using namespace Debugger;
|
||||
using namespace Debugger::Internal;
|
||||
using namespace Debugger::Constants;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ScriptEngine
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Debugger::Internal::ScriptAgent : public QScriptEngineAgent
|
||||
{
|
||||
public:
|
||||
ScriptAgent(ScriptEngine *debugger, QScriptEngine *script);
|
||||
~ScriptAgent() {}
|
||||
|
||||
void contextPop();
|
||||
void contextPush();
|
||||
void exceptionCatch(qint64 scriptId, const QScriptValue &exception);
|
||||
void exceptionThrow(qint64 scriptId, const QScriptValue & exception,
|
||||
bool hasHandler);
|
||||
void functionEntry(qint64 scriptId);
|
||||
void functionExit(qint64 scriptId, const QScriptValue &returnValue);
|
||||
void positionChange(qint64 scriptId, int lineNumber, int columnNumber);
|
||||
void scriptLoad(qint64 id, const QString &program, const QString &fileName,
|
||||
int baseLineNumber);
|
||||
void scriptUnload(qint64 id);
|
||||
|
||||
private:
|
||||
void maybeBreakNow(bool byFunction);
|
||||
|
||||
ScriptEngine *q;
|
||||
};
|
||||
|
||||
ScriptAgent::ScriptAgent(ScriptEngine *debugger, QScriptEngine *script)
|
||||
: QScriptEngineAgent(script), q(debugger)
|
||||
{}
|
||||
|
||||
void ScriptAgent::contextPop()
|
||||
{
|
||||
qDebug() << "ScriptAgent::contextPop: ";
|
||||
}
|
||||
|
||||
void ScriptAgent::contextPush()
|
||||
{
|
||||
qDebug() << "ScriptAgent::contextPush: ";
|
||||
}
|
||||
|
||||
void ScriptAgent::exceptionCatch(qint64 scriptId, const QScriptValue & exception)
|
||||
{
|
||||
qDebug() << "ScriptAgent::exceptionCatch: " << scriptId << &exception;
|
||||
}
|
||||
|
||||
void ScriptAgent::exceptionThrow(qint64 scriptId, const QScriptValue &exception,
|
||||
bool hasHandler)
|
||||
{
|
||||
qDebug() << "ScriptAgent::exceptionThrow: " << scriptId << &exception
|
||||
<< hasHandler;
|
||||
}
|
||||
|
||||
void ScriptAgent::functionEntry(qint64 scriptId)
|
||||
{
|
||||
Q_UNUSED(scriptId);
|
||||
q->maybeBreakNow(true);
|
||||
}
|
||||
|
||||
void ScriptAgent::functionExit(qint64 scriptId, const QScriptValue &returnValue)
|
||||
{
|
||||
qDebug() << "ScriptAgent::functionExit: " << scriptId << &returnValue;
|
||||
}
|
||||
|
||||
void ScriptAgent::positionChange(qint64 scriptId, int lineNumber, int columnNumber)
|
||||
{
|
||||
//qDebug() << "ScriptAgent::position: " << lineNumber;
|
||||
Q_UNUSED(scriptId);
|
||||
Q_UNUSED(lineNumber);
|
||||
Q_UNUSED(columnNumber);
|
||||
q->maybeBreakNow(false);
|
||||
}
|
||||
|
||||
void ScriptAgent::scriptLoad(qint64 scriptId, const QString &program,
|
||||
const QString &fileName, int baseLineNumber)
|
||||
{
|
||||
Q_UNUSED(scriptId);
|
||||
Q_UNUSED(program);
|
||||
Q_UNUSED(fileName);
|
||||
Q_UNUSED(baseLineNumber);
|
||||
//qDebug() << "ScriptAgent::scriptLoad: " << program << fileName
|
||||
// << baseLineNumber;
|
||||
}
|
||||
|
||||
void ScriptAgent::scriptUnload(qint64 scriptId)
|
||||
{
|
||||
Q_UNUSED(scriptId);
|
||||
//qDebug() << "ScriptAgent::scriptUnload: " << scriptId;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ScriptEngine
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
ScriptEngine::ScriptEngine(DebuggerManager *parent)
|
||||
{
|
||||
q = parent;
|
||||
qq = parent->engineInterface();
|
||||
m_scriptEngine = new QScriptEngine(this);
|
||||
m_scriptAgent = new ScriptAgent(this, m_scriptEngine);
|
||||
m_scriptEngine->setAgent(m_scriptAgent);
|
||||
m_scriptEngine->setProcessEventsInterval(1 /*ms*/);
|
||||
}
|
||||
|
||||
ScriptEngine::~ScriptEngine()
|
||||
{
|
||||
}
|
||||
|
||||
void ScriptEngine::executeDebuggerCommand(const QString &command)
|
||||
{
|
||||
Q_UNUSED(command);
|
||||
qDebug() << "FIXME: ScriptEngine::executeDebuggerCommand()";
|
||||
}
|
||||
|
||||
void ScriptEngine::shutdown()
|
||||
{
|
||||
exitDebugger();
|
||||
}
|
||||
|
||||
void ScriptEngine::exitDebugger()
|
||||
{
|
||||
//qDebug() << " ScriptEngine::exitDebugger()";
|
||||
m_stopped = false;
|
||||
m_stopOnNextLine = false;
|
||||
m_scriptEngine->abortEvaluation();
|
||||
qq->notifyInferiorExited();
|
||||
}
|
||||
|
||||
bool ScriptEngine::startDebugger()
|
||||
{
|
||||
m_stopped = false;
|
||||
m_stopOnNextLine = false;
|
||||
m_scriptEngine->abortEvaluation();
|
||||
QFileInfo fi(q->m_executable);
|
||||
m_scriptFileName = fi.absoluteFilePath();
|
||||
QFile scriptFile(m_scriptFileName);
|
||||
if (!scriptFile.open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
QTextStream stream(&scriptFile);
|
||||
m_scriptContents = stream.readAll();
|
||||
scriptFile.close();
|
||||
attemptBreakpointSynchronization();
|
||||
QTimer::singleShot(0, q, SLOT(notifyStartupFinished()));
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScriptEngine::continueInferior()
|
||||
{
|
||||
//qDebug() << "ScriptEngine::continueInferior()";
|
||||
m_stopped = false;
|
||||
m_stopOnNextLine = false;
|
||||
}
|
||||
|
||||
void ScriptEngine::runInferior()
|
||||
{
|
||||
//qDebug() << "ScriptEngine::runInferior()";
|
||||
QScriptValue result = m_scriptEngine->evaluate(m_scriptContents, m_scriptFileName);
|
||||
}
|
||||
|
||||
void ScriptEngine::interruptInferior()
|
||||
{
|
||||
m_stopped = false;
|
||||
m_stopOnNextLine = true;
|
||||
qDebug() << "FIXME: ScriptEngine::interruptInferior()";
|
||||
}
|
||||
|
||||
void ScriptEngine::stepExec()
|
||||
{
|
||||
//qDebug() << "FIXME: ScriptEngine::stepExec()";
|
||||
m_stopped = false;
|
||||
m_stopOnNextLine = true;
|
||||
}
|
||||
|
||||
void ScriptEngine::stepIExec()
|
||||
{
|
||||
//qDebug() << "FIXME: ScriptEngine::stepIExec()";
|
||||
m_stopped = false;
|
||||
m_stopOnNextLine = true;
|
||||
}
|
||||
|
||||
void ScriptEngine::stepOutExec()
|
||||
{
|
||||
//qDebug() << "FIXME: ScriptEngine::stepOutExec()";
|
||||
m_stopped = false;
|
||||
m_stopOnNextLine = true;
|
||||
}
|
||||
|
||||
void ScriptEngine::nextExec()
|
||||
{
|
||||
//qDebug() << "FIXME: ScriptEngine::nextExec()";
|
||||
m_stopped = false;
|
||||
m_stopOnNextLine = true;
|
||||
}
|
||||
|
||||
void ScriptEngine::nextIExec()
|
||||
{
|
||||
//qDebug() << "FIXME: ScriptEngine::nextIExec()";
|
||||
m_stopped = false;
|
||||
m_stopOnNextLine = true;
|
||||
}
|
||||
|
||||
void ScriptEngine::runToLineExec(const QString &fileName, int lineNumber)
|
||||
{
|
||||
Q_UNUSED(fileName);
|
||||
Q_UNUSED(lineNumber);
|
||||
qDebug() << "FIXME: ScriptEngine::runToLineExec()";
|
||||
}
|
||||
|
||||
void ScriptEngine::runToFunctionExec(const QString &functionName)
|
||||
{
|
||||
Q_UNUSED(functionName);
|
||||
qDebug() << "FIXME: ScriptEngine::runToFunctionExec()";
|
||||
}
|
||||
|
||||
void ScriptEngine::jumpToLineExec(const QString &fileName, int lineNumber)
|
||||
{
|
||||
Q_UNUSED(fileName);
|
||||
Q_UNUSED(lineNumber);
|
||||
qDebug() << "FIXME: ScriptEngine::jumpToLineExec()";
|
||||
}
|
||||
|
||||
void ScriptEngine::activateFrame(int index)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
}
|
||||
|
||||
void ScriptEngine::selectThread(int index)
|
||||
{
|
||||
Q_UNUSED(index);
|
||||
}
|
||||
|
||||
void ScriptEngine::attemptBreakpointSynchronization()
|
||||
{
|
||||
BreakHandler *handler = qq->breakHandler();
|
||||
bool updateNeeded = false;
|
||||
for (int index = 0; index != handler->size(); ++index) {
|
||||
BreakpointData *data = handler->at(index);
|
||||
if (data->pending) {
|
||||
data->pending = false; // FIXME
|
||||
updateNeeded = true;
|
||||
}
|
||||
if (data->bpNumber.isEmpty()) {
|
||||
data->bpNumber = QString::number(index + 1);
|
||||
updateNeeded = true;
|
||||
}
|
||||
if (!data->fileName.isEmpty() && data->markerFileName.isEmpty()) {
|
||||
data->markerFileName = data->fileName;
|
||||
data->markerLineNumber = data->lineNumber.toInt();
|
||||
updateNeeded = true;
|
||||
}
|
||||
}
|
||||
if (updateNeeded)
|
||||
handler->updateMarkers();
|
||||
}
|
||||
|
||||
void ScriptEngine::reloadDisassembler()
|
||||
{
|
||||
}
|
||||
|
||||
void ScriptEngine::loadSymbols(const QString &moduleName)
|
||||
{
|
||||
Q_UNUSED(moduleName);
|
||||
}
|
||||
|
||||
void ScriptEngine::loadAllSymbols()
|
||||
{
|
||||
}
|
||||
|
||||
void ScriptEngine::reloadModules()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Tooltip specific stuff
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
static WatchData m_toolTip;
|
||||
static QPoint m_toolTipPos;
|
||||
static QHash<QString, WatchData> m_toolTipCache;
|
||||
|
||||
static bool hasLetterOrNumber(const QString &exp)
|
||||
{
|
||||
for (int i = exp.size(); --i >= 0; )
|
||||
if (exp[i].isLetterOrNumber())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool hasSideEffects(const QString &exp)
|
||||
{
|
||||
// FIXME: complete?
|
||||
return exp.contains("-=")
|
||||
|| exp.contains("+=")
|
||||
|| exp.contains("/=")
|
||||
|| exp.contains("*=")
|
||||
|| exp.contains("&=")
|
||||
|| exp.contains("|=")
|
||||
|| exp.contains("^=")
|
||||
|| exp.contains("--")
|
||||
|| exp.contains("++");
|
||||
}
|
||||
|
||||
void ScriptEngine::setToolTipExpression(const QPoint &pos, const QString &exp0)
|
||||
{
|
||||
Q_UNUSED(pos);
|
||||
Q_UNUSED(exp0);
|
||||
|
||||
if (q->status() != DebuggerInferiorStopped) {
|
||||
//qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED";
|
||||
return;
|
||||
}
|
||||
|
||||
//m_toolTipPos = pos;
|
||||
QString exp = exp0;
|
||||
|
||||
/*
|
||||
if (m_toolTipCache.contains(exp)) {
|
||||
const WatchData & data = m_toolTipCache[exp];
|
||||
q->watchHandler()->removeChildren(data.iname);
|
||||
insertData(data);
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
QToolTip::hideText();
|
||||
if (exp.isEmpty() || exp.startsWith("#")) {
|
||||
QToolTip::hideText();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasLetterOrNumber(exp)) {
|
||||
QToolTip::showText(m_toolTipPos,
|
||||
"'" + exp + "' contains no identifier");
|
||||
return;
|
||||
}
|
||||
|
||||
if (exp.startsWith('"') && exp.endsWith('"')) {
|
||||
QToolTip::showText(m_toolTipPos, "String literal " + exp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (exp.startsWith("++") || exp.startsWith("--"))
|
||||
exp = exp.mid(2);
|
||||
|
||||
if (exp.endsWith("++") || exp.endsWith("--"))
|
||||
exp = exp.mid(2);
|
||||
|
||||
if (exp.startsWith("<") || exp.startsWith("["))
|
||||
return;
|
||||
|
||||
if (hasSideEffects(exp)) {
|
||||
QToolTip::showText(m_toolTipPos,
|
||||
"Cowardly refusing to evaluate expression '" + exp
|
||||
+ "' with potential side effects");
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
//if (m_manager->status() != DebuggerInferiorStopped)
|
||||
// return;
|
||||
|
||||
// FIXME: 'exp' can contain illegal characters
|
||||
m_toolTip = WatchData();
|
||||
m_toolTip.exp = exp;
|
||||
m_toolTip.name = exp;
|
||||
m_toolTip.iname = tooltipIName;
|
||||
insertData(m_toolTip);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Watch specific stuff
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ScriptEngine::assignValueInDebugger(const QString &expression,
|
||||
const QString &value)
|
||||
{
|
||||
Q_UNUSED(expression);
|
||||
Q_UNUSED(value);
|
||||
}
|
||||
|
||||
void ScriptEngine::maybeBreakNow(bool byFunction)
|
||||
{
|
||||
QScriptContext *context = m_scriptEngine->currentContext();
|
||||
QScriptContextInfo info(context);
|
||||
|
||||
//
|
||||
// Update breakpoints
|
||||
//
|
||||
QString functionName = info.functionName();
|
||||
QString fileName = info.fileName();
|
||||
int lineNumber = info.lineNumber();
|
||||
if (byFunction)
|
||||
lineNumber = info.functionStartLineNumber();
|
||||
|
||||
BreakHandler *handler = qq->breakHandler();
|
||||
|
||||
if (m_stopOnNextLine) {
|
||||
m_stopOnNextLine = false;
|
||||
} else {
|
||||
int index = 0;
|
||||
for (; index != handler->size(); ++index) {
|
||||
BreakpointData *data = handler->at(index);
|
||||
if (byFunction) {
|
||||
if (!functionName.isEmpty() && data->funcName == functionName)
|
||||
break;
|
||||
} else {
|
||||
if (info.lineNumber() == data->lineNumber.toInt()
|
||||
&& fileName == data->fileName)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == handler->size())
|
||||
return;
|
||||
|
||||
// we just run into a breakpoint
|
||||
//qDebug() << "RESOLVING BREAKPOINT AT " << fileName << lineNumber;
|
||||
BreakpointData *data = handler->at(index);
|
||||
data->bpLineNumber = QString::number(lineNumber);
|
||||
data->bpFileName = fileName;
|
||||
data->bpFuncName = functionName;
|
||||
data->markerLineNumber = lineNumber;
|
||||
data->markerFileName = fileName;
|
||||
data->pending = false;
|
||||
data->updateMarker();
|
||||
}
|
||||
|
||||
qq->notifyInferiorStopped();
|
||||
q->gotoLocation(fileName, lineNumber, true);
|
||||
|
||||
qq->watchHandler()->reinitializeWatchers();
|
||||
//qDebug() << "UPDATE LOCALS";
|
||||
|
||||
//
|
||||
// Build stack
|
||||
//
|
||||
QList<StackFrame> stackFrames;
|
||||
int i = 0;
|
||||
for (QScriptContext *c = context; c; c = c->parentContext(), ++i) {
|
||||
QScriptContextInfo info(c);
|
||||
StackFrame frame;
|
||||
frame.level = i;
|
||||
frame.file = info.fileName();
|
||||
frame.function = info.functionName();
|
||||
frame.from = QString::number(info.functionStartLineNumber());
|
||||
frame.to = QString::number(info.functionEndLineNumber());
|
||||
frame.line = info.lineNumber();
|
||||
|
||||
if (frame.function.isEmpty())
|
||||
frame.function = "<global scope>";
|
||||
//frame.address = ...;
|
||||
stackFrames.append(frame);
|
||||
}
|
||||
qq->stackHandler()->setFrames(stackFrames);
|
||||
|
||||
//
|
||||
// Build locals
|
||||
//
|
||||
WatchData data;
|
||||
data.iname = "local";
|
||||
data.name = "local";
|
||||
data.scriptValue = context->activationObject();
|
||||
qq->watchHandler()->insertData(data);
|
||||
updateWatchModel();
|
||||
|
||||
// FIXME: Use an extra thread. This here is evil
|
||||
m_stopped = true;
|
||||
while (m_stopped) {
|
||||
//qDebug() << "LOOPING";
|
||||
QApplication::processEvents();
|
||||
}
|
||||
//qDebug() << "RUNNING AGAIN";
|
||||
}
|
||||
|
||||
void ScriptEngine::updateWatchModel()
|
||||
{
|
||||
while (true) {
|
||||
QList<WatchData> list = qq->watchHandler()->takeCurrentIncompletes();
|
||||
if (list.isEmpty())
|
||||
break;
|
||||
foreach (const WatchData &data, list)
|
||||
updateSubItem(data);
|
||||
}
|
||||
qq->watchHandler()->rebuildModel();
|
||||
q->showStatusMessage(tr("Stopped."), 5000);
|
||||
}
|
||||
|
||||
void ScriptEngine::updateSubItem(const WatchData &data0)
|
||||
{
|
||||
WatchData data = data0;
|
||||
//qDebug() << "\nUPDATE SUBITEM: " << data.toString();
|
||||
QWB_ASSERT(data.isValid(), return);
|
||||
|
||||
if (data.isTypeNeeded() || data.isValueNeeded()) {
|
||||
QScriptValue ob = data.scriptValue;
|
||||
if (ob.isArray()) {
|
||||
data.setType("Array");
|
||||
data.setValue(" ");
|
||||
} else if (ob.isBool()) {
|
||||
data.setType("Bool");
|
||||
data.setValue(ob.toBool() ? "true" : "false");
|
||||
data.setChildCount(0);
|
||||
} else if (ob.isDate()) {
|
||||
data.setType("Date");
|
||||
data.setValue(ob.toDateTime().toString().toUtf8());
|
||||
data.setChildCount(0);
|
||||
} else if (ob.isError()) {
|
||||
data.setType("Error");
|
||||
data.setValue(" ");
|
||||
} else if (ob.isFunction()) {
|
||||
data.setType("Function");
|
||||
data.setValue(" ");
|
||||
} else if (ob.isNull()) {
|
||||
data.setType("<null>");
|
||||
data.setValue("<null>");
|
||||
} else if (ob.isNumber()) {
|
||||
data.setType("Number");
|
||||
data.setValue(QString::number(ob.toNumber()).toUtf8());
|
||||
data.setChildCount(0);
|
||||
} else if (ob.isObject()) {
|
||||
data.setType("Object");
|
||||
data.setValue(" ");
|
||||
} else if (ob.isQMetaObject()) {
|
||||
data.setType("QMetaObject");
|
||||
data.setValue(" ");
|
||||
} else if (ob.isQObject()) {
|
||||
data.setType("QObject");
|
||||
data.setValue(" ");
|
||||
} else if (ob.isRegExp()) {
|
||||
data.setType("RegExp");
|
||||
data.setValue(ob.toRegExp().pattern().toUtf8());
|
||||
} else if (ob.isString()) {
|
||||
data.setType("String");
|
||||
data.setValue(ob.toString().toUtf8());
|
||||
} else if (ob.isVariant()) {
|
||||
data.setType("Variant");
|
||||
data.setValue(" ");
|
||||
} else if (ob.isUndefined()) {
|
||||
data.setType("<undefined>");
|
||||
data.setValue("<unknown>");
|
||||
} else {
|
||||
data.setType("<unknown>");
|
||||
data.setValue("<unknown>");
|
||||
}
|
||||
qq->watchHandler()->insertData(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.isChildrenNeeded()) {
|
||||
int numChild = 0;
|
||||
QScriptValueIterator it(data.scriptValue);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
WatchData data1;
|
||||
data1.iname = data.iname + "." + it.name();
|
||||
data1.name = it.name();
|
||||
data1.scriptValue = it.value();
|
||||
if (qq->watchHandler()->isExpandedIName(data1.iname))
|
||||
data1.setChildrenNeeded();
|
||||
else
|
||||
data1.setChildrenUnneeded();
|
||||
qq->watchHandler()->insertData(data1);
|
||||
++numChild;
|
||||
}
|
||||
//qDebug() << " ... CHILDREN: " << numChild;
|
||||
data.setChildCount(numChild);
|
||||
data.setChildrenUnneeded();
|
||||
qq->watchHandler()->insertData(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.isChildCountNeeded()) {
|
||||
int numChild = 0;
|
||||
QScriptValueIterator it(data.scriptValue);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
++numChild;
|
||||
}
|
||||
data.setChildCount(numChild);
|
||||
//qDebug() << " ... CHILDCOUNT: " << numChild;
|
||||
qq->watchHandler()->insertData(data);
|
||||
return;
|
||||
}
|
||||
|
||||
QWB_ASSERT(false, return);
|
||||
}
|
||||
|
||||
IDebuggerEngine *createScriptEngine(DebuggerManager *parent)
|
||||
{
|
||||
return new ScriptEngine(parent);
|
||||
}
|
||||
|
||||
134
src/plugins/debugger/scriptengine.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_SCRIPTENGINE_H
|
||||
#define DEBUGGER_SCRIPTENGINE_H
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QPoint>
|
||||
#include <QtCore/QSet>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
#include <QtNetwork/QLocalSocket>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAction;
|
||||
class QAbstractItemModel;
|
||||
class QSplitter;
|
||||
class QToolBar;
|
||||
class QScriptEngine;
|
||||
class QScriptValue;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "idebuggerengine.h"
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class DebuggerManager;
|
||||
class IDebuggerManagerAccessForEngines;
|
||||
class ScriptAgent;
|
||||
class WatchData;
|
||||
|
||||
class ScriptEngine : public IDebuggerEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScriptEngine(DebuggerManager *parent);
|
||||
~ScriptEngine();
|
||||
|
||||
private:
|
||||
// IDebuggerEngine implementation
|
||||
void stepExec();
|
||||
void stepOutExec();
|
||||
void nextExec();
|
||||
void stepIExec();
|
||||
void nextIExec();
|
||||
|
||||
void shutdown();
|
||||
void setToolTipExpression(const QPoint &pos, const QString &exp);
|
||||
bool startDebugger();
|
||||
void exitDebugger();
|
||||
|
||||
void continueInferior();
|
||||
void runInferior();
|
||||
void interruptInferior();
|
||||
|
||||
void runToLineExec(const QString &fileName, int lineNumber);
|
||||
void runToFunctionExec(const QString &functionName);
|
||||
void jumpToLineExec(const QString &fileName, int lineNumber);
|
||||
|
||||
void activateFrame(int index);
|
||||
void selectThread(int index);
|
||||
|
||||
void attemptBreakpointSynchronization();
|
||||
|
||||
void loadSessionData() {}
|
||||
void saveSessionData() {}
|
||||
|
||||
void assignValueInDebugger(const QString &expr, const QString &value);
|
||||
void executeDebuggerCommand(const QString & command);
|
||||
|
||||
void loadSymbols(const QString &moduleName);
|
||||
void loadAllSymbols();
|
||||
void reloadDisassembler();
|
||||
void reloadModules();
|
||||
void reloadRegisters() {}
|
||||
|
||||
bool supportsThreads() const { return true; }
|
||||
void maybeBreakNow(bool byFunction);
|
||||
void updateWatchModel();
|
||||
void updateSubItem(const WatchData &data0);
|
||||
|
||||
private:
|
||||
friend class ScriptAgent;
|
||||
DebuggerManager *q;
|
||||
IDebuggerManagerAccessForEngines *qq;
|
||||
|
||||
QScriptEngine *m_scriptEngine;
|
||||
QString m_scriptContents;
|
||||
QString m_scriptFileName;
|
||||
ScriptAgent *m_scriptAgent;
|
||||
|
||||
bool m_stopped;
|
||||
bool m_stopOnNextLine;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_SCRIPTENGINE_H
|
||||
271
src/plugins/debugger/stackhandler.cpp
Normal file
@@ -0,0 +1,271 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "stackhandler.h"
|
||||
|
||||
#include "assert.h"
|
||||
|
||||
#include <QtCore/QAbstractTableModel>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QFileInfo>
|
||||
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// StackHandler
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
StackHandler::StackHandler(QObject *parent)
|
||||
: QAbstractTableModel(parent), m_currentIndex(0)
|
||||
{
|
||||
m_emptyIcon = QIcon(":/gdbdebugger/images/empty.svg");
|
||||
m_positionIcon = QIcon(":/gdbdebugger/images/location.svg");
|
||||
}
|
||||
|
||||
int StackHandler::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
// Since the stack is not a tree, row count is 0 for any valid parent
|
||||
return parent.isValid() ? 0 : m_stackFrames.size();
|
||||
}
|
||||
|
||||
int StackHandler::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : 4;
|
||||
}
|
||||
|
||||
QVariant StackHandler::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() >= m_stackFrames.size())
|
||||
return QVariant();
|
||||
|
||||
const StackFrame &frame = m_stackFrames.at(index.row());
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (index.column()) {
|
||||
case 0: // Stack frame level
|
||||
return QString::number(frame.level);
|
||||
case 1: // Function name
|
||||
return frame.function;
|
||||
case 2: // File name
|
||||
return frame.file.isEmpty() ? frame.from : QFileInfo(frame.file).fileName();
|
||||
case 3: // Line number
|
||||
return frame.line;
|
||||
case 4: // Address
|
||||
return frame.address;
|
||||
}
|
||||
} else if (role == Qt::ToolTipRole) {
|
||||
return "<table><tr><td>Address:</td><td>" + frame.address + "</td></tr>"
|
||||
+ "<tr><td>Function: </td><td>" + frame.function + "</td></tr>"
|
||||
+ "<tr><td>File: </td><td>" + frame.file + "</td></tr>"
|
||||
+ "<tr><td>Line: </td><td>" + QString::number(frame.line) + "</td></tr>"
|
||||
+ "<tr><td>From: </td><td>" + frame.from + "</td></tr></table>"
|
||||
+ "<tr><td>To: </td><td>" + frame.to + "</td></tr></table>";
|
||||
} else if (role == Qt::DecorationRole && index.column() == 0) {
|
||||
// Return icon that indicates whether this is the active stack frame
|
||||
return (index.row() == m_currentIndex) ? m_positionIcon : m_emptyIcon;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant StackHandler::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||
static const char * const headers[] = {
|
||||
QT_TR_NOOP("Level"),
|
||||
QT_TR_NOOP("Function"),
|
||||
QT_TR_NOOP("File"),
|
||||
QT_TR_NOOP("Line"),
|
||||
QT_TR_NOOP("Address")
|
||||
};
|
||||
if (section < 5)
|
||||
return tr(headers[section]);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags StackHandler::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (index.row() >= m_stackFrames.size())
|
||||
return 0;
|
||||
const StackFrame &frame = m_stackFrames.at(index.row());
|
||||
const bool isValid = !frame.file.isEmpty() && !frame.function.isEmpty();
|
||||
return isValid ? QAbstractTableModel::flags(index) : Qt::ItemFlags(0);
|
||||
}
|
||||
|
||||
StackFrame StackHandler::currentFrame() const
|
||||
{
|
||||
QWB_ASSERT(m_currentIndex >= 0, return StackFrame());
|
||||
QWB_ASSERT(m_currentIndex < m_stackFrames.size(), return StackFrame());
|
||||
return m_stackFrames.at(m_currentIndex);
|
||||
}
|
||||
|
||||
void StackHandler::setCurrentIndex(int level)
|
||||
{
|
||||
if (level == m_currentIndex)
|
||||
return;
|
||||
|
||||
// Emit changed for previous frame
|
||||
QModelIndex i = index(m_currentIndex, 0);
|
||||
emit dataChanged(i, i);
|
||||
|
||||
m_currentIndex = level;
|
||||
|
||||
// Emit changed for new frame
|
||||
i = index(m_currentIndex, 0);
|
||||
emit dataChanged(i, i);
|
||||
}
|
||||
|
||||
void StackHandler::removeAll()
|
||||
{
|
||||
m_stackFrames.clear();
|
||||
m_currentIndex = 0;
|
||||
reset();
|
||||
}
|
||||
|
||||
void StackHandler::setFrames(const QList<StackFrame> &frames)
|
||||
{
|
||||
m_stackFrames = frames;
|
||||
if (m_currentIndex >= m_stackFrames.size())
|
||||
m_currentIndex = m_stackFrames.size() - 1;
|
||||
reset();
|
||||
}
|
||||
|
||||
QList<StackFrame> StackHandler::frames() const
|
||||
{
|
||||
return m_stackFrames;
|
||||
}
|
||||
|
||||
bool StackHandler::isDebuggingDumpers() const
|
||||
{
|
||||
for (int i = m_stackFrames.size(); --i >= 0; )
|
||||
if (m_stackFrames.at(i).function.startsWith("qDumpObjectData"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ThreadsHandler
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ThreadsHandler::ThreadsHandler(QObject *parent)
|
||||
: QAbstractTableModel(parent), m_currentIndex(0)
|
||||
{
|
||||
m_emptyIcon = QIcon(":/gdbdebugger/images/empty.svg");
|
||||
m_positionIcon = QIcon(":/gdbdebugger/images/location.svg");
|
||||
}
|
||||
|
||||
int ThreadsHandler::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
// Since the stack is not a tree, row count is 0 for any valid parent
|
||||
return parent.isValid() ? 0 : m_threads.size();
|
||||
}
|
||||
|
||||
int ThreadsHandler::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : 1;
|
||||
}
|
||||
|
||||
QVariant ThreadsHandler::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() >= m_threads.size())
|
||||
return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (index.column()) {
|
||||
case 0: // Thread ID
|
||||
return m_threads.at(index.row()).id;
|
||||
case 1: // Function name
|
||||
return "???";
|
||||
}
|
||||
} else if (role == Qt::ToolTipRole) {
|
||||
return "Thread: " + QString::number(m_threads.at(index.row()).id);
|
||||
} else if (role == Qt::DecorationRole && index.column() == 0) {
|
||||
// Return icon that indicates whether this is the active stack frame
|
||||
return (index.row() == m_currentIndex) ? m_positionIcon : m_emptyIcon;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant ThreadsHandler::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||
static const char * const headers[] = {
|
||||
QT_TR_NOOP("Thread ID"),
|
||||
};
|
||||
if (section < 1)
|
||||
return tr(headers[section]);
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void ThreadsHandler::setCurrentThread(int index)
|
||||
{
|
||||
if (index == m_currentIndex)
|
||||
return;
|
||||
|
||||
// Emit changed for previous frame
|
||||
QModelIndex i = ThreadsHandler::index(m_currentIndex, 0);
|
||||
emit dataChanged(i, i);
|
||||
|
||||
m_currentIndex = index;
|
||||
|
||||
// Emit changed for new frame
|
||||
i = ThreadsHandler::index(m_currentIndex, 0);
|
||||
emit dataChanged(i, i);
|
||||
}
|
||||
|
||||
void ThreadsHandler::setThreads(const QList<ThreadData> &threads)
|
||||
{
|
||||
m_threads = threads;
|
||||
if (m_currentIndex >= m_threads.size())
|
||||
m_currentIndex = m_threads.size() - 1;
|
||||
reset();
|
||||
}
|
||||
|
||||
QList<ThreadData> ThreadsHandler::threads() const
|
||||
{
|
||||
return m_threads;
|
||||
}
|
||||
|
||||
void ThreadsHandler::removeAll()
|
||||
{
|
||||
m_threads.clear();
|
||||
m_currentIndex = 0;
|
||||
reset();
|
||||
}
|
||||
136
src/plugins/debugger/stackhandler.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_STACKHANDLER_H
|
||||
#define DEBUGGER_STACKHANDLER_H
|
||||
|
||||
#include <QtCore/QAbstractTableModel>
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// StackModel
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct StackFrame
|
||||
{
|
||||
int level;
|
||||
QString function;
|
||||
QString file; // we try to put an absolute file name in there
|
||||
QString from;
|
||||
QString to;
|
||||
int line;
|
||||
QString address;
|
||||
};
|
||||
|
||||
/*! A model to represent the stack in a QTreeView. */
|
||||
class StackHandler : public QAbstractTableModel
|
||||
{
|
||||
public:
|
||||
StackHandler(QObject *parent = 0);
|
||||
|
||||
void setFrames(const QList<StackFrame> &frames);
|
||||
QList<StackFrame> frames() const;
|
||||
void setCurrentIndex(int index);
|
||||
int currentIndex() const { return m_currentIndex; }
|
||||
StackFrame currentFrame() const;
|
||||
int stackSize() const { return m_stackFrames.size(); }
|
||||
|
||||
// Called from StackHandler after a new stack list has been received
|
||||
void removeAll();
|
||||
QAbstractItemModel *stackModel() { return this; }
|
||||
bool isDebuggingDumpers() const;
|
||||
|
||||
private:
|
||||
// QAbstractTableModel
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
|
||||
QList<StackFrame> m_stackFrames;
|
||||
int m_currentIndex;
|
||||
QIcon m_positionIcon;
|
||||
QIcon m_emptyIcon;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ThreadsHandler
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ThreadData
|
||||
{
|
||||
int id;
|
||||
};
|
||||
|
||||
/*! A model to represent the running threads in a QTreeView or ComboBox */
|
||||
class ThreadsHandler : public QAbstractTableModel
|
||||
{
|
||||
public:
|
||||
ThreadsHandler(QObject *parent = 0);
|
||||
|
||||
void setCurrentThread(int index);
|
||||
void selectThread(int index);
|
||||
void setThreads(const QList<ThreadData> &threads);
|
||||
void removeAll();
|
||||
QList<ThreadData> threads() const;
|
||||
QAbstractItemModel *threadsModel() { return this; }
|
||||
|
||||
private:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
|
||||
private:
|
||||
friend class StackHandler;
|
||||
QList<ThreadData> m_threads;
|
||||
int m_currentIndex;
|
||||
QIcon m_positionIcon;
|
||||
QIcon m_emptyIcon;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_STACKHANDLER_H
|
||||
117
src/plugins/debugger/stackwindow.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "stackwindow.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "stackhandler.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
#include <QResizeEvent>
|
||||
#include <QTreeView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
using Debugger::Internal::StackWindow;
|
||||
|
||||
StackWindow::StackWindow(QWidget *parent)
|
||||
: QTreeView(parent), m_alwaysResizeColumnsToContents(false)
|
||||
{
|
||||
setWindowTitle(tr("Stack"));
|
||||
|
||||
setAlternatingRowColors(true);
|
||||
setRootIsDecorated(false);
|
||||
setIconSize(QSize(10, 10));
|
||||
|
||||
header()->setDefaultAlignment(Qt::AlignLeft);
|
||||
|
||||
connect(this, SIGNAL(activated(QModelIndex)),
|
||||
this, SLOT(rowActivated(QModelIndex)));
|
||||
}
|
||||
|
||||
void StackWindow::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QHeaderView *hv = header();
|
||||
int totalSize = event->size().width() - 120;
|
||||
if (totalSize > 10) {
|
||||
hv->resizeSection(0, 45);
|
||||
hv->resizeSection(1, totalSize / 2);
|
||||
hv->resizeSection(2, totalSize / 2);
|
||||
hv->resizeSection(3, 55);
|
||||
}
|
||||
QTreeView::resizeEvent(event);
|
||||
}
|
||||
|
||||
void StackWindow::rowActivated(const QModelIndex &index)
|
||||
{
|
||||
//qDebug() << "ACTIVATED: " << index.row() << index.column();
|
||||
emit frameActivated(index.row());
|
||||
}
|
||||
|
||||
void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
{
|
||||
QMenu menu;
|
||||
QAction *act1 = new QAction(tr("Adjust column widths to contents"), &menu);
|
||||
QAction *act2 = new QAction(tr("Always adjust column widths to contents"), &menu);
|
||||
act2->setCheckable(true);
|
||||
act2->setChecked(m_alwaysResizeColumnsToContents);
|
||||
|
||||
menu.addAction(act1);
|
||||
menu.addAction(act2);
|
||||
|
||||
QAction *act = menu.exec(ev->globalPos());
|
||||
|
||||
if (act == act1)
|
||||
resizeColumnsToContents();
|
||||
else if (act == act2)
|
||||
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
|
||||
}
|
||||
|
||||
void StackWindow::resizeColumnsToContents()
|
||||
{
|
||||
resizeColumnToContents(0);
|
||||
resizeColumnToContents(1);
|
||||
resizeColumnToContents(2);
|
||||
}
|
||||
|
||||
void StackWindow::setAlwaysResizeColumnsToContents(bool on)
|
||||
{
|
||||
m_alwaysResizeColumnsToContents = on;
|
||||
QHeaderView::ResizeMode mode = on
|
||||
? QHeaderView::ResizeToContents : QHeaderView::Interactive;
|
||||
header()->setResizeMode(0, mode);
|
||||
header()->setResizeMode(1, mode);
|
||||
header()->setResizeMode(2, mode);
|
||||
}
|
||||
75
src/plugins/debugger/stackwindow.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_STACKWINDOW_H
|
||||
#define DEBUGGER_STACKWINDOW_H
|
||||
|
||||
#include <QtGui/QTreeView>
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QComboBox;
|
||||
class QModelIndex;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class StackWindow : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
StackWindow(QWidget *parent = 0);
|
||||
|
||||
signals:
|
||||
void frameActivated(int);
|
||||
|
||||
public slots:
|
||||
void resizeColumnsToContents();
|
||||
void setAlwaysResizeColumnsToContents(bool on);
|
||||
|
||||
private slots:
|
||||
void rowActivated(const QModelIndex &index);
|
||||
|
||||
private:
|
||||
void resizeEvent(QResizeEvent *ev);
|
||||
void contextMenuEvent(QContextMenuEvent *ev);
|
||||
|
||||
bool m_alwaysResizeColumnsToContents;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_STACKWINDOW_H
|
||||
|
||||
124
src/plugins/debugger/startexternaldialog.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "startexternaldialog.h"
|
||||
|
||||
#include <QtGui/QFileDialog>
|
||||
#include <QtGui/QPushButton>
|
||||
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
StartExternalDialog::StartExternalDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
|
||||
|
||||
//execLabel->setHidden(false);
|
||||
//execEdit->setHidden(false);
|
||||
//browseButton->setHidden(false);
|
||||
|
||||
execLabel->setText(tr("Executable:"));
|
||||
argLabel->setText(tr("Arguments:"));
|
||||
|
||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
|
||||
connect(browseButton, SIGNAL(clicked()),
|
||||
this, SLOT(onBrowseButton()));
|
||||
}
|
||||
|
||||
void StartExternalDialog::setExecutableFile(const QString &str)
|
||||
{
|
||||
execEdit->setText(str);
|
||||
}
|
||||
|
||||
void StartExternalDialog::setExecutableArguments(const QString &str)
|
||||
{
|
||||
argsEdit->setText(str);
|
||||
}
|
||||
|
||||
QString StartExternalDialog::executableFile() const
|
||||
{
|
||||
return execEdit->text();
|
||||
}
|
||||
|
||||
QString StartExternalDialog::executableArguments() const
|
||||
{
|
||||
return argsEdit->text();
|
||||
/*
|
||||
bool inQuotes = false;
|
||||
QString args = argsEdit->text();
|
||||
QChar current;
|
||||
QChar last;
|
||||
QString arg;
|
||||
|
||||
QStringList result;
|
||||
if (!args.isEmpty())
|
||||
result << QLatin1String("--args");
|
||||
result << execEdit->text();
|
||||
|
||||
for(int i=0; i<args.length(); ++i) {
|
||||
current = args.at(i);
|
||||
|
||||
if (current == QLatin1Char('\"') && last != QLatin1Char('\\')) {
|
||||
if (inQuotes && !arg.isEmpty()) {
|
||||
result << arg;
|
||||
arg.clear();
|
||||
}
|
||||
inQuotes = !inQuotes;
|
||||
} else if (!inQuotes && current == QLatin1Char(' ')) {
|
||||
arg = arg.trimmed();
|
||||
if (!arg.isEmpty()) {
|
||||
result << arg;
|
||||
arg.clear();
|
||||
}
|
||||
} else {
|
||||
arg += current;
|
||||
}
|
||||
|
||||
last = current;
|
||||
}
|
||||
|
||||
if (!arg.isEmpty())
|
||||
result << arg;
|
||||
|
||||
return result;
|
||||
*/
|
||||
}
|
||||
|
||||
void StartExternalDialog::onBrowseButton()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Select Executable"),
|
||||
execEdit->text());
|
||||
execEdit->setText(fileName);
|
||||
}
|
||||
63
src/plugins/debugger/startexternaldialog.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_STARTEXTERNALDIALOG_H
|
||||
#define DEBUGGER_STARTEXTERNALDIALOG_H
|
||||
|
||||
#include <QtGui/QDialog>
|
||||
|
||||
#include "ui_startexternaldialog.h"
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class StartExternalDialog : public QDialog, Ui::StartExternalDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
StartExternalDialog(QWidget *parent);
|
||||
|
||||
void setExecutableFile(const QString &executable);
|
||||
void setExecutableArguments(const QString &args);
|
||||
|
||||
QString executableFile() const;
|
||||
QString executableArguments() const;
|
||||
|
||||
private slots:
|
||||
void onBrowseButton();
|
||||
};
|
||||
|
||||
} // namespace Debugger
|
||||
} // namespace Internal
|
||||
|
||||
#endif // DEBUGGER_STARTEXTERNALDIALOG_H
|
||||
93
src/plugins/debugger/startexternaldialog.ui
Normal file
@@ -0,0 +1,93 @@
|
||||
<ui version="4.0" >
|
||||
<class>StartExternalDialog</class>
|
||||
<widget class="QDialog" name="StartExternalDialog" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>425</width>
|
||||
<height>127</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Start Debugger</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="1" column="1" >
|
||||
<widget class="QLineEdit" name="argsEdit" />
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QLineEdit" name="execEdit" />
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="execLabel" >
|
||||
<property name="text" >
|
||||
<string>Executable:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" >
|
||||
<widget class="QToolButton" name="browseButton" >
|
||||
<property name="text" >
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" >
|
||||
<widget class="QLabel" name="argLabel" >
|
||||
<property name="text" >
|
||||
<string>Arguments:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0" >
|
||||
<size>
|
||||
<width>407</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
112
src/plugins/debugger/threadswindow.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "threadswindow.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "stackhandler.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
#include <QHeaderView>
|
||||
#include <QMenu>
|
||||
#include <QResizeEvent>
|
||||
#include <QTreeView>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
using Debugger::Internal::ThreadsWindow;
|
||||
|
||||
ThreadsWindow::ThreadsWindow(QWidget *parent)
|
||||
: QTreeView(parent), m_alwaysResizeColumnsToContents(false)
|
||||
{
|
||||
setWindowTitle(tr("Thread"));
|
||||
|
||||
setAlternatingRowColors(true);
|
||||
setRootIsDecorated(false);
|
||||
setIconSize(QSize(10, 10));
|
||||
|
||||
header()->setDefaultAlignment(Qt::AlignLeft);
|
||||
|
||||
connect(this, SIGNAL(activated(const QModelIndex &)),
|
||||
this, SLOT(rowActivated(const QModelIndex &)));
|
||||
}
|
||||
|
||||
void ThreadsWindow::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
//QHeaderView *hv = header();
|
||||
//int totalSize = event->size().width() - 120;
|
||||
//hv->resizeSection(0, 45);
|
||||
//hv->resizeSection(1, totalSize);
|
||||
//hv->resizeSection(2, 55);
|
||||
QTreeView::resizeEvent(event);
|
||||
}
|
||||
|
||||
void ThreadsWindow::rowActivated(const QModelIndex &index)
|
||||
{
|
||||
//qDebug() << "ACTIVATED: " << index.row() << index.column();
|
||||
emit threadSelected(index.row());
|
||||
}
|
||||
|
||||
void ThreadsWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
{
|
||||
QMenu menu;
|
||||
QAction *act1 = new QAction(tr("Adjust column widths to contents"), &menu);
|
||||
QAction *act2 = new QAction(tr("Always adjust column widths to contents"), &menu);
|
||||
act2->setCheckable(true);
|
||||
act2->setChecked(m_alwaysResizeColumnsToContents);
|
||||
menu.addAction(act1);
|
||||
menu.addAction(act2);
|
||||
|
||||
QAction *act = menu.exec(ev->globalPos());
|
||||
|
||||
if (act == act1)
|
||||
resizeColumnsToContents();
|
||||
else if (act == act2)
|
||||
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
|
||||
}
|
||||
|
||||
void ThreadsWindow::resizeColumnsToContents()
|
||||
{
|
||||
resizeColumnToContents(0);
|
||||
//resizeColumnToContents(1);
|
||||
}
|
||||
|
||||
void ThreadsWindow::setAlwaysResizeColumnsToContents(bool on)
|
||||
{
|
||||
m_alwaysResizeColumnsToContents = on;
|
||||
QHeaderView::ResizeMode mode = on
|
||||
? QHeaderView::ResizeToContents : QHeaderView::Interactive;
|
||||
header()->setResizeMode(0, mode);
|
||||
//header()->setResizeMode(1, mode);
|
||||
}
|
||||
|
||||
68
src/plugins/debugger/threadswindow.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_THREADWINDOW_H
|
||||
#define DEBUGGER_THREADWINDOW_H
|
||||
|
||||
#include <QtGui/QTreeView>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class ThreadsWindow : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ThreadsWindow(QWidget *parent = 0);
|
||||
|
||||
signals:
|
||||
void threadSelected(int);
|
||||
|
||||
public slots:
|
||||
void resizeColumnsToContents();
|
||||
void setAlwaysResizeColumnsToContents(bool on);
|
||||
|
||||
private slots:
|
||||
void rowActivated(const QModelIndex &index);
|
||||
|
||||
private:
|
||||
void resizeEvent(QResizeEvent *ev);
|
||||
void contextMenuEvent(QContextMenuEvent *ev);
|
||||
|
||||
bool m_alwaysResizeColumnsToContents;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_THREADWINDOW_H
|
||||
1137
src/plugins/debugger/watchhandler.cpp
Normal file
219
src/plugins/debugger/watchhandler.h
Normal file
@@ -0,0 +1,219 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_WATCHHANDLER_H
|
||||
#define DEBUGGER_WATCHHANDLER_H
|
||||
|
||||
#include <QtCore/QPointer>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QSet>
|
||||
#include <QtGui/QStandardItem>
|
||||
#include <QtGui/QStandardItemModel>
|
||||
#include <QtGui/QTreeView>
|
||||
#include <QtScript/QScriptValue>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class WatchData
|
||||
{
|
||||
public:
|
||||
WatchData();
|
||||
|
||||
enum State
|
||||
{
|
||||
Complete = 0,
|
||||
ChildCountNeeded = 1,
|
||||
ValueNeeded = 2,
|
||||
TypeNeeded = 4,
|
||||
ChildrenNeeded = 8,
|
||||
|
||||
NeededMask = ValueNeeded
|
||||
| TypeNeeded
|
||||
| ChildrenNeeded
|
||||
| ChildCountNeeded,
|
||||
|
||||
InitialState = ValueNeeded
|
||||
| TypeNeeded
|
||||
| ChildrenNeeded
|
||||
| ChildCountNeeded
|
||||
};
|
||||
|
||||
void setValue(const QByteArray &);
|
||||
void setType(const QString &);
|
||||
void setValueToolTip(const QString &);
|
||||
void setError(const QString &);
|
||||
void setAddress(const QString &address);
|
||||
|
||||
bool isSomethingNeeded() const { return state & NeededMask; }
|
||||
void setAllNeeded() { state = NeededMask; }
|
||||
void setAllUnneeded() { state = State(0); }
|
||||
|
||||
bool isTypeNeeded() const { return state & TypeNeeded; }
|
||||
bool isTypeKnown() const { return !(state & TypeNeeded); }
|
||||
void setTypeNeeded() { state = State(state | TypeNeeded); }
|
||||
void setTypeUnneeded() { state = State(state & ~TypeNeeded); }
|
||||
|
||||
bool isValueNeeded() const { return state & ValueNeeded; }
|
||||
bool isValueKnown() const { return !(state & ValueNeeded); }
|
||||
void setValueNeeded() { state = State(state | ValueNeeded); }
|
||||
void setValueUnneeded() { state = State(state & ~ValueNeeded); }
|
||||
|
||||
bool isChildrenNeeded() const { return state & ChildrenNeeded; }
|
||||
bool isChildrenKnown() const { return !(state & ChildrenNeeded); }
|
||||
void setChildrenNeeded() { state = State(state | ChildrenNeeded); }
|
||||
void setChildrenUnneeded() { state = State(state & ~ChildrenNeeded); }
|
||||
|
||||
bool isChildCountNeeded() const { return state & ChildCountNeeded; }
|
||||
bool isChildCountKnown() const { return !(state & ChildCountNeeded); }
|
||||
void setChildCountNeeded() { state = State(state | ChildCountNeeded); }
|
||||
void setChildCountUnneeded() { state = State(state & ~ChildCountNeeded); }
|
||||
void setChildCount(int n) { childCount = n; setChildCountUnneeded();
|
||||
if (n == 0) setChildrenUnneeded(); }
|
||||
|
||||
QString toString() const;
|
||||
bool isLocal() const { return iname.startsWith(QLatin1String("local.")); }
|
||||
bool isWatcher() const { return iname.startsWith(QLatin1String("watch.")); };
|
||||
bool isValid() const { return !iname.isEmpty(); }
|
||||
|
||||
public:
|
||||
QString iname; // internal name sth like 'local.baz.public.a'
|
||||
QString exp; // the expression
|
||||
QString name; // displayed name
|
||||
QString value; // displayed value
|
||||
QByteArray editvalue; // displayed value
|
||||
QString valuetooltip; // tooltip in value column
|
||||
QString type; // displayed type
|
||||
QString variable; // name of internal Gdb variable if created
|
||||
QString addr; // displayed adress
|
||||
QString framekey; // key for type cache
|
||||
QScriptValue scriptValue; // if needed...
|
||||
int childCount;
|
||||
bool valuedisabled; // value will be greyed out
|
||||
|
||||
private:
|
||||
|
||||
public:
|
||||
int state;
|
||||
|
||||
// Model
|
||||
int parentIndex;
|
||||
int row;
|
||||
int level;
|
||||
QList<int> childIndex;
|
||||
bool changed;
|
||||
};
|
||||
|
||||
enum { INameRole = Qt::UserRole, VisualRole };
|
||||
|
||||
|
||||
class WatchHandler : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WatchHandler();
|
||||
QAbstractItemModel *model() { return this; }
|
||||
|
||||
//
|
||||
// QAbstractItemModel
|
||||
//
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
QModelIndex index(int, int, const QModelIndex &idx) const;
|
||||
QModelIndex parent(const QModelIndex &idx) const;
|
||||
int rowCount(const QModelIndex &idx) const;
|
||||
int columnCount(const QModelIndex &idx) const;
|
||||
bool hasChildren(const QModelIndex &idx) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &idx) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
bool checkIndex(int id) const;
|
||||
|
||||
//public slots:
|
||||
void cleanup();
|
||||
void watchExpression(const QString &exp);
|
||||
void removeWatchExpression(const QString &exp);
|
||||
void reinitializeWatchers();
|
||||
|
||||
void collapseChildren(const QModelIndex &idx);
|
||||
void expandChildren(const QModelIndex &idx);
|
||||
|
||||
void rebuildModel(); // unconditionally version of above
|
||||
void showEditValue(const WatchData &data);
|
||||
|
||||
bool isDisplayedIName(const QString &iname) const
|
||||
{ return m_displayedINames.contains(iname); }
|
||||
bool isExpandedIName(const QString &iname) const
|
||||
{ return m_expandedINames.contains(iname); }
|
||||
|
||||
void insertData(const WatchData &data);
|
||||
QList<WatchData> takeCurrentIncompletes();
|
||||
|
||||
bool canFetchMore(const QModelIndex &parent) const;
|
||||
void fetchMore(const QModelIndex &parent);
|
||||
|
||||
WatchData *findData(const QString &iname);
|
||||
|
||||
signals:
|
||||
void watchModelUpdateRequested();
|
||||
|
||||
private:
|
||||
WatchData takeData(const QString &iname);
|
||||
QString toString() const;
|
||||
void cleanModel();
|
||||
|
||||
bool m_expandPointers;
|
||||
bool m_inChange;
|
||||
|
||||
typedef QMap<QString, QPointer<QWidget> > EditWindows;
|
||||
EditWindows m_editWindows;
|
||||
|
||||
QList<WatchData> m_incompleteSet;
|
||||
QList<WatchData> m_completeSet;
|
||||
QList<WatchData> m_oldSet;
|
||||
QList<WatchData> m_displaySet;
|
||||
|
||||
void setDisplayedIName(const QString &iname, bool on);
|
||||
QSet<QString> m_expandedINames; // those expanded in the treeview
|
||||
QSet<QString> m_displayedINames; // those with "external" viewers
|
||||
|
||||
bool m_inFetchMore;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
Q_DECLARE_METATYPE(Debugger::Internal::WatchData);
|
||||
|
||||
#endif // DEBUGGER_WATCHHANDLER_H
|
||||
253
src/plugins/debugger/watchwindow.cpp
Normal file
@@ -0,0 +1,253 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "watchwindow.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#include <QtGui/QAction>
|
||||
#include <QtGui/QContextMenuEvent>
|
||||
#include <QtGui/QHeaderView>
|
||||
#include <QtGui/QLineEdit>
|
||||
#include <QtGui/QMenu>
|
||||
#include <QtGui/QResizeEvent>
|
||||
#include <QtGui/QSplitter>
|
||||
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
enum { INameRole = Qt::UserRole, VisualRole };
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WatchWindow
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
WatchWindow::WatchWindow(Type type, QWidget *parent)
|
||||
: QTreeView(parent), m_type(type)
|
||||
{
|
||||
m_blocked = false;
|
||||
setWindowTitle(tr("Locals and Watchers"));
|
||||
setAlternatingRowColors(true);
|
||||
setIndentation(indentation() * 9/10);
|
||||
setUniformRowHeights(true);
|
||||
|
||||
connect(itemDelegate(), SIGNAL(commitData(QWidget *)),
|
||||
this, SLOT(handleChangedItem(QWidget *)));
|
||||
connect(this, SIGNAL(expanded(QModelIndex)),
|
||||
this, SLOT(expandNode(QModelIndex)));
|
||||
connect(this, SIGNAL(collapsed(QModelIndex)),
|
||||
this, SLOT(collapseNode(QModelIndex)));
|
||||
}
|
||||
|
||||
void WatchWindow::expandNode(const QModelIndex &idx)
|
||||
{
|
||||
//QModelIndex mi0 = idx.sibling(idx.row(), 0);
|
||||
//QString iname = model()->data(mi0, INameRole).toString();
|
||||
//QString name = model()->data(mi0, Qt::DisplayRole).toString();
|
||||
//qDebug() << "\n\nEXPAND NODE " // << iname << name
|
||||
// << idx << (m_blocked ? "blocked" : "passed");
|
||||
//if (isExpanded(idx))
|
||||
// return;
|
||||
//if (m_blocked)
|
||||
// return;
|
||||
emit requestExpandChildren(idx);
|
||||
}
|
||||
|
||||
void WatchWindow::collapseNode(const QModelIndex &idx)
|
||||
{
|
||||
//QModelIndex mi0 = idx.sibling(idx.row(), 0);
|
||||
//QString iname = model()->data(mi0, INameRole).toString();
|
||||
//QString name = model()->data(mi0, Qt::DisplayRole).toString();
|
||||
//qDebug() << "COLLAPSE NODE " << idx;
|
||||
if (m_blocked)
|
||||
return;
|
||||
emit requestCollapseChildren(idx);
|
||||
}
|
||||
|
||||
void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
{
|
||||
QMenu menu;
|
||||
QAction *act1 = new QAction("Adjust column widths to contents", &menu);
|
||||
QAction *act2 = new QAction("Always adjust column widths to contents", &menu);
|
||||
act2->setCheckable(true);
|
||||
act2->setChecked(m_alwaysResizeColumnsToContents);
|
||||
|
||||
menu.addAction(act1);
|
||||
menu.addAction(act2);
|
||||
|
||||
QAction *act3 = 0;
|
||||
QAction *act4 = 0;
|
||||
QModelIndex idx = indexAt(ev->pos());
|
||||
QModelIndex mi0 = idx.sibling(idx.row(), 0);
|
||||
QString exp = model()->data(mi0).toString();
|
||||
QString iname = model()->data(mi0, INameRole).toString();
|
||||
QModelIndex mi1 = idx.sibling(idx.row(), 0);
|
||||
QString value = model()->data(mi1).toString();
|
||||
bool visual = false;
|
||||
if (idx.isValid()) {
|
||||
menu.addSeparator();
|
||||
if (m_type == LocalsType)
|
||||
act3 = new QAction("Watch expression '" + exp + "'", &menu);
|
||||
else
|
||||
act3 = new QAction("Remove expression '" + exp + "'", &menu);
|
||||
menu.addAction(act3);
|
||||
|
||||
visual = model()->data(mi0, VisualRole).toBool();
|
||||
act4 = new QAction("Watch expression '" + exp + "' in separate widget", &menu);
|
||||
act4->setCheckable(true);
|
||||
act4->setChecked(visual);
|
||||
// FIXME: menu.addAction(act4);
|
||||
}
|
||||
|
||||
QAction *act = menu.exec(ev->globalPos());
|
||||
|
||||
if (!act)
|
||||
;
|
||||
else if (act == act1)
|
||||
resizeColumnsToContents();
|
||||
else if (act == act2)
|
||||
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
|
||||
else if (act == act3)
|
||||
if (m_type == LocalsType)
|
||||
emit requestWatchExpression(exp);
|
||||
else
|
||||
emit requestRemoveWatchExpression(iname);
|
||||
else if (act == act4)
|
||||
model()->setData(mi0, !visual, VisualRole);
|
||||
}
|
||||
|
||||
void WatchWindow::resizeColumnsToContents()
|
||||
{
|
||||
resizeColumnToContents(0);
|
||||
resizeColumnToContents(1);
|
||||
}
|
||||
|
||||
void WatchWindow::setAlwaysResizeColumnsToContents(bool on)
|
||||
{
|
||||
if (!header())
|
||||
return;
|
||||
m_alwaysResizeColumnsToContents = on;
|
||||
QHeaderView::ResizeMode mode = on
|
||||
? QHeaderView::ResizeToContents : QHeaderView::Interactive;
|
||||
header()->setResizeMode(0, mode);
|
||||
header()->setResizeMode(1, mode);
|
||||
}
|
||||
|
||||
void WatchWindow::editItem(const QModelIndex &idx)
|
||||
{
|
||||
Q_UNUSED(idx); // FIXME
|
||||
}
|
||||
|
||||
void WatchWindow::reset()
|
||||
{
|
||||
int row = 0;
|
||||
if (m_type == TooltipType)
|
||||
row = 1;
|
||||
else if (m_type == WatchersType)
|
||||
row = 2;
|
||||
//qDebug() << "WATCHWINDOW::RESET" << row;
|
||||
QTreeView::reset();
|
||||
setRootIndex(model()->index(row, 0, model()->index(0, 0)));
|
||||
//setRootIndex(model()->index(0, 0));
|
||||
}
|
||||
|
||||
void WatchWindow::setModel(QAbstractItemModel *model)
|
||||
{
|
||||
QTreeView::setModel(model);
|
||||
|
||||
setRootIsDecorated(true);
|
||||
header()->setDefaultAlignment(Qt::AlignLeft);
|
||||
header()->setResizeMode(QHeaderView::ResizeToContents);
|
||||
if (m_type != LocalsType)
|
||||
header()->hide();
|
||||
|
||||
connect(model, SIGNAL(modelAboutToBeReset()),
|
||||
this, SLOT(modelAboutToBeReset()));
|
||||
connect(model, SIGNAL(modelReset()),
|
||||
this, SLOT(modelReset()));
|
||||
}
|
||||
|
||||
void WatchWindow::modelAboutToBeReset()
|
||||
{
|
||||
m_blocked = true;
|
||||
//qDebug() << "Model about to be reset";
|
||||
m_expandedItems.clear();
|
||||
m_expandedItems.insert("local");
|
||||
m_expandedItems.insert("watch");
|
||||
modelAboutToBeResetHelper(model()->index(0, 0));
|
||||
//qDebug() << " expanded: " << m_expandedItems;
|
||||
}
|
||||
|
||||
void WatchWindow::modelAboutToBeResetHelper(const QModelIndex &idx)
|
||||
{
|
||||
QString iname = model()->data(idx, INameRole).toString();
|
||||
//qDebug() << "Model about to be reset helper" << iname << idx
|
||||
// << isExpanded(idx);
|
||||
if (isExpanded(idx))
|
||||
m_expandedItems.insert(iname);
|
||||
for (int i = 0, n = model()->rowCount(idx); i != n; ++i) {
|
||||
QModelIndex idx1 = model()->index(i, 0, idx);
|
||||
modelAboutToBeResetHelper(idx1);
|
||||
}
|
||||
}
|
||||
|
||||
void WatchWindow::modelReset()
|
||||
{
|
||||
//qDebug() << "Model reset";
|
||||
expand(model()->index(0, 0));
|
||||
modelResetHelper(model()->index(0, 0));
|
||||
m_blocked = false;
|
||||
}
|
||||
|
||||
void WatchWindow::modelResetHelper(const QModelIndex &idx)
|
||||
{
|
||||
QString name = model()->data(idx, Qt::DisplayRole).toString();
|
||||
QString iname = model()->data(idx, INameRole).toString();
|
||||
//qDebug() << "Model reset helper" << iname << name;
|
||||
if (m_expandedItems.contains(iname)) {
|
||||
expand(idx);
|
||||
for (int i = 0, n = model()->rowCount(idx); i != n; ++i) {
|
||||
QModelIndex idx1 = model()->index(i, 0, idx);
|
||||
modelResetHelper(idx1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WatchWindow::handleChangedItem(QWidget *widget)
|
||||
{
|
||||
QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget);
|
||||
if (lineEdit)
|
||||
requestAssignValue("foo", lineEdit->text());
|
||||
}
|
||||
|
||||
95
src/plugins/debugger/watchwindow.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#ifndef DEBUGGER_WATCHWINDOW_H
|
||||
#define DEBUGGER_WATCHWINDOW_H
|
||||
|
||||
#include <QtGui/QTreeView>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WatchWindow
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
class WatchWindow : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Type { LocalsType, TooltipType, WatchersType };
|
||||
|
||||
WatchWindow(Type type, QWidget *parent = 0);
|
||||
void setType(Type type) { m_type = type; }
|
||||
Type type() const { return m_type; }
|
||||
|
||||
public slots:
|
||||
void resizeColumnsToContents();
|
||||
void setAlwaysResizeColumnsToContents(bool on = true);
|
||||
void setModel(QAbstractItemModel *model);
|
||||
|
||||
signals:
|
||||
void requestWatchExpression(const QString &exp);
|
||||
void requestRemoveWatchExpression(const QString &iname);
|
||||
void requestAssignValue(const QString &exp, const QString &value);
|
||||
void requestExpandChildren(const QModelIndex &idx);
|
||||
void requestCollapseChildren(const QModelIndex &idx);
|
||||
|
||||
private slots:
|
||||
void handleChangedItem(QWidget *);
|
||||
void expandNode(const QModelIndex &index);
|
||||
void collapseNode(const QModelIndex &index);
|
||||
void modelAboutToBeReset();
|
||||
void modelReset();
|
||||
|
||||
private:
|
||||
void contextMenuEvent(QContextMenuEvent *ev);
|
||||
void editItem(const QModelIndex &idx);
|
||||
void reset(); /* reimpl */
|
||||
|
||||
void modelAboutToBeResetHelper(const QModelIndex &idx);
|
||||
void modelResetHelper(const QModelIndex &idx);
|
||||
|
||||
bool m_alwaysResizeColumnsToContents;
|
||||
Type m_type;
|
||||
bool m_blocked;
|
||||
QSet<QString> m_expandedItems;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_WATCHWINDOW_H
|
||||