forked from qt-creator/qt-creator
Merge branch '1.3' of git@scm.dev.nokia.troll.no:creator/mainline into 1.3
This commit is contained in:
@@ -1701,36 +1701,12 @@ ULONG CdbDebugEnginePrivate::updateThreadList()
|
||||
if (debugCDB)
|
||||
qDebug() << Q_FUNC_INFO << m_hDebuggeeProcess;
|
||||
|
||||
ThreadsHandler* th = manager()->threadsHandler();
|
||||
QList<ThreadData> threads;
|
||||
bool success = false;
|
||||
ULONG currentThreadId;
|
||||
QString errorMessage;
|
||||
ULONG currentThreadId = 0;
|
||||
do {
|
||||
ULONG threadCount;
|
||||
HRESULT hr= m_cif.debugSystemObjects->GetNumberThreads(&threadCount);
|
||||
if (FAILED(hr)) {
|
||||
errorMessage= msgComFailed("GetNumberThreads", hr);
|
||||
break;
|
||||
}
|
||||
// Get ids and index of current
|
||||
if (threadCount) {
|
||||
m_cif.debugSystemObjects->GetCurrentThreadId(¤tThreadId);
|
||||
QVector<ULONG> threadIds(threadCount);
|
||||
hr = m_cif.debugSystemObjects->GetThreadIdsByIndex(0, threadCount, &(*threadIds.begin()), 0);
|
||||
if (FAILED(hr)) {
|
||||
errorMessage= msgComFailed("GetThreadIdsByIndex", hr);
|
||||
break;
|
||||
}
|
||||
for (ULONG i = 0; i < threadCount; i++)
|
||||
threads.push_back(ThreadData(threadIds.at(i)));
|
||||
}
|
||||
|
||||
th->setThreads(threads);
|
||||
success = true;
|
||||
} while (false);
|
||||
if (!success)
|
||||
m_engine->warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage));
|
||||
if (!CdbStackTraceContext::getThreads(m_cif, true, &threads, ¤tThreadId, &errorMessage))
|
||||
m_engine->warning(errorMessage);
|
||||
manager()->threadsHandler()->setThreads(threads);
|
||||
return currentThreadId;
|
||||
}
|
||||
|
||||
|
||||
@@ -219,5 +219,105 @@ void CdbStackTraceContext::format(QTextStream &str) const
|
||||
}
|
||||
}
|
||||
|
||||
// Thread state helper
|
||||
|
||||
static inline QString msgGetThreadStateFailed(unsigned long threadId, const QString &why)
|
||||
{
|
||||
return QString::fromLatin1("Unable to determine the state of thread %1: %2").arg(threadId).arg(why);
|
||||
}
|
||||
|
||||
static inline bool getStoppedThreadState(const CdbComInterfaces &cif,
|
||||
ThreadData *t,
|
||||
QString *errorMessage)
|
||||
{
|
||||
ULONG currentThread;
|
||||
HRESULT hr = cif.debugSystemObjects->GetCurrentThreadId(¤tThread);
|
||||
if (FAILED(hr)) {
|
||||
*errorMessage = msgGetThreadStateFailed(t->id, msgComFailed("GetCurrentThreadId", hr));
|
||||
return false;
|
||||
}
|
||||
if (currentThread != t->id) {
|
||||
hr = cif.debugSystemObjects->SetCurrentThreadId(t->id);
|
||||
if (FAILED(hr)) {
|
||||
*errorMessage = msgGetThreadStateFailed(t->id, msgComFailed("SetCurrentThreadId", hr));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ULONG frameCount;
|
||||
DEBUG_STACK_FRAME topFrame[1];
|
||||
hr = cif.debugControl->GetStackTrace(0, 0, 0, topFrame, 1, &frameCount);
|
||||
if (FAILED(hr)) {
|
||||
*errorMessage = msgGetThreadStateFailed(t->id, msgComFailed("GetStackTrace", hr));
|
||||
return false;
|
||||
}
|
||||
|
||||
t->address = topFrame[0].InstructionOffset;
|
||||
WCHAR wszBuf[MAX_PATH];
|
||||
|
||||
cif.debugSymbols->GetNameByOffsetWide(topFrame[0].InstructionOffset, wszBuf, MAX_PATH, 0, 0);
|
||||
t->function = QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf));
|
||||
ULONG ulLine;
|
||||
hr = cif.debugSymbols->GetLineByOffsetWide(topFrame[0].InstructionOffset, &ulLine, wszBuf, MAX_PATH, 0, 0);
|
||||
if (SUCCEEDED(hr)) {
|
||||
t->line = ulLine;
|
||||
// Just display base name
|
||||
t->file = QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf));
|
||||
if (!t->file.isEmpty()) {
|
||||
const int slashPos = t->file.lastIndexOf(QLatin1Char('\\'));
|
||||
if (slashPos != -1)
|
||||
t->file.remove(0, slashPos + 1);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline QString msgGetThreadsFailed(const QString &why)
|
||||
{
|
||||
return QString::fromLatin1("Unable to determine the thread information: %1").arg(why);
|
||||
}
|
||||
|
||||
bool CdbStackTraceContext::getThreads(const CdbComInterfaces &cif,
|
||||
bool isStopped,
|
||||
QList<ThreadData> *threads,
|
||||
ULONG *currentThreadId,
|
||||
QString *errorMessage)
|
||||
{
|
||||
threads->clear();
|
||||
ULONG threadCount;
|
||||
*currentThreadId = 0;
|
||||
HRESULT hr= cif.debugSystemObjects->GetNumberThreads(&threadCount);
|
||||
if (FAILED(hr)) {
|
||||
*errorMessage= msgGetThreadsFailed(msgComFailed("GetNumberThreads", hr));
|
||||
return false;
|
||||
}
|
||||
// Get ids and index of current
|
||||
if (!threadCount)
|
||||
return true;
|
||||
hr = cif.debugSystemObjects->GetCurrentThreadId(currentThreadId);
|
||||
if (FAILED(hr)) {
|
||||
*errorMessage= msgGetThreadsFailed(msgComFailed("GetCurrentThreadId", hr));
|
||||
return false;
|
||||
}
|
||||
|
||||
QVector<ULONG> threadIds(threadCount);
|
||||
hr = cif.debugSystemObjects->GetThreadIdsByIndex(0, threadCount, &(*threadIds.begin()), 0);
|
||||
if (FAILED(hr)) {
|
||||
*errorMessage= msgGetThreadsFailed(msgComFailed("GetThreadIdsByIndex", hr));
|
||||
return false;
|
||||
}
|
||||
for (ULONG i = 0; i < threadCount; i++) {
|
||||
ThreadData threadData(threadIds.at(i));
|
||||
if (isStopped) {
|
||||
if (!getStoppedThreadState(cif, &threadData, errorMessage)) {
|
||||
qWarning("%s\n", qPrintable(*errorMessage));
|
||||
errorMessage->clear();
|
||||
}
|
||||
}
|
||||
threads->push_back(threadData);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
@@ -49,6 +49,7 @@ struct CdbComInterfaces;
|
||||
class CdbSymbolGroupContext;
|
||||
class CdbStackFrameContext;
|
||||
class CdbDumperHelper;
|
||||
struct ThreadData;
|
||||
|
||||
/* Context representing a break point stack consisting of several frames.
|
||||
* Maintains an on-demand constructed list of CdbStackFrameContext
|
||||
@@ -81,6 +82,14 @@ public:
|
||||
void format(QTextStream &str) const;
|
||||
QString toString() const;
|
||||
|
||||
// Retrieve information about threads. When stopped, add
|
||||
// current stack frame.
|
||||
static bool getThreads(const CdbComInterfaces &cif,
|
||||
bool isStopped,
|
||||
QList<ThreadData> *threads,
|
||||
ULONG *currentThreadId,
|
||||
QString *errorMessage);
|
||||
|
||||
private:
|
||||
bool init(unsigned long frameCount, QString *errorMessage);
|
||||
CIDebugSymbolGroup *createSymbolGroup(int index, QString *errorMessage);
|
||||
|
||||
@@ -1654,6 +1654,8 @@ void DebuggerManager::setState(DebuggerState state)
|
||||
|| state == InferiorUnrunnable;
|
||||
|
||||
const bool running = state == InferiorRunning;
|
||||
if (running)
|
||||
threadsHandler()->notifyRunning();
|
||||
const bool stopped = state == InferiorStopped;
|
||||
|
||||
if (stopped)
|
||||
|
||||
@@ -238,11 +238,28 @@ bool StackHandler::isDebuggingDebuggingHelpers() const
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ThreadsHandler::ThreadsHandler(QObject *parent)
|
||||
: QAbstractTableModel(parent), m_currentIndex(0)
|
||||
ThreadData::ThreadData(int threadId) :
|
||||
id(threadId),
|
||||
line(-1)
|
||||
{
|
||||
}
|
||||
|
||||
void ThreadData::notifyRunning()
|
||||
{
|
||||
address = 0;
|
||||
function.clear();
|
||||
file.clear();
|
||||
line = -1;
|
||||
}
|
||||
|
||||
enum { IdColumn, AddressColumn, FunctionColumn, FileColumn, LineColumn, ColumnCount };
|
||||
|
||||
ThreadsHandler::ThreadsHandler(QObject *parent) :
|
||||
QAbstractTableModel(parent),
|
||||
m_currentIndex(0),
|
||||
m_positionIcon(QLatin1String(":/debugger/images/location.svg")),
|
||||
m_emptyIcon(QLatin1String(":/debugger/images/empty.svg"))
|
||||
{
|
||||
m_emptyIcon = QIcon(":/debugger/images/empty.svg");
|
||||
m_positionIcon = QIcon(":/debugger/images/location.svg");
|
||||
}
|
||||
|
||||
int ThreadsHandler::rowCount(const QModelIndex &parent) const
|
||||
@@ -253,23 +270,39 @@ int ThreadsHandler::rowCount(const QModelIndex &parent) const
|
||||
|
||||
int ThreadsHandler::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return parent.isValid() ? 0 : 1;
|
||||
return parent.isValid() ? 0 : int(ColumnCount);
|
||||
}
|
||||
|
||||
QVariant ThreadsHandler::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid() || index.row() >= m_threads.size())
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
const int row = index.row();
|
||||
if (row >= m_threads.size())
|
||||
return QVariant();
|
||||
const ThreadData &thread = m_threads.at(row);
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (index.column()) {
|
||||
case 0: // Thread ID
|
||||
return m_threads.at(index.row()).id;
|
||||
case 1: // Function name
|
||||
return "???";
|
||||
case IdColumn:
|
||||
return thread.id;
|
||||
case FunctionColumn:
|
||||
return thread.function;
|
||||
case FileColumn:
|
||||
return thread.file;
|
||||
case LineColumn:
|
||||
return thread.line >= 0 ? QString::number(thread.line) : QString();
|
||||
case AddressColumn:
|
||||
return thread.address > 0 ? QLatin1String("0x") + QString::number(thread.address, 16) : QString();
|
||||
}
|
||||
} else if (role == Qt::ToolTipRole) {
|
||||
return tr("Thread: %1").arg(m_threads.at(index.row()).id);
|
||||
if (thread.address == 0)
|
||||
return tr("Thread: %1").arg(thread.id);
|
||||
// Stopped
|
||||
if (thread.file.isEmpty())
|
||||
return tr("Thread: %1 at %2 (0x%3)").arg(thread.id).arg(thread.function).arg(thread.address, 0, 16);
|
||||
return tr("Thread: %1 at %2, %3:%4 (0x%5)").
|
||||
arg(thread.id).arg(thread.function, thread.file).arg(thread.line).arg(thread.address, 0, 16);
|
||||
} 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;
|
||||
@@ -280,9 +313,19 @@ QVariant ThreadsHandler::data(const QModelIndex &index, int role) const
|
||||
|
||||
QVariant ThreadsHandler::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||
if (section < 1)
|
||||
return tr("Thread ID");
|
||||
if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
switch (section) {
|
||||
case IdColumn:
|
||||
return tr("Thread ID");
|
||||
case FunctionColumn:
|
||||
return tr("Function");
|
||||
case FileColumn:
|
||||
return tr("File");
|
||||
case LineColumn:
|
||||
return tr("Line");
|
||||
case AddressColumn:
|
||||
return tr("Address");
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
@@ -322,3 +365,16 @@ void ThreadsHandler::removeAll()
|
||||
m_currentIndex = 0;
|
||||
reset();
|
||||
}
|
||||
|
||||
void ThreadsHandler::notifyRunning()
|
||||
{
|
||||
// Threads stopped (that is, address != 0 showing)?
|
||||
if (m_threads.empty())
|
||||
return;
|
||||
if (m_threads.front().address == 0)
|
||||
return;
|
||||
const QList<ThreadData>::iterator end = m_threads.end();
|
||||
for (QList<ThreadData>::iterator it = m_threads.begin(); it != end; ++it)
|
||||
it->notifyRunning();
|
||||
emit dataChanged(index(0, 1), index(m_threads.size()- 1, ColumnCount - 1));
|
||||
}
|
||||
|
||||
@@ -100,8 +100,15 @@ private:
|
||||
|
||||
struct ThreadData
|
||||
{
|
||||
ThreadData(int threadId = 0) : id(threadId) {}
|
||||
ThreadData(int threadId = 0);
|
||||
void notifyRunning(); // Clear state information
|
||||
|
||||
int id;
|
||||
// State information when stopped
|
||||
quint64 address;
|
||||
QString function;
|
||||
QString file;
|
||||
int line;
|
||||
};
|
||||
|
||||
/*! A model to represent the running threads in a QTreeView or ComboBox */
|
||||
@@ -119,6 +126,9 @@ public:
|
||||
QList<ThreadData> threads() const;
|
||||
QAbstractItemModel *threadsModel() { return this; }
|
||||
|
||||
// Clear out all frame information
|
||||
void notifyRunning();
|
||||
|
||||
private:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
@@ -126,11 +136,10 @@ private:
|
||||
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;
|
||||
const QIcon m_positionIcon;
|
||||
const QIcon m_emptyIcon;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ BuildStepsPage::BuildStepsPage(Project *project, bool clean) :
|
||||
{
|
||||
m_vbox = new QVBoxLayout(this);
|
||||
m_vbox->setContentsMargins(0, 0, 0, 0);
|
||||
m_vbox->setSpacing(0);
|
||||
const QList<BuildStep *> &steps = m_clean ? m_pro->cleanSteps() : m_pro->buildSteps();
|
||||
foreach (BuildStep *bs, steps) {
|
||||
addBuildStepWidget(-1, bs);
|
||||
@@ -163,8 +164,12 @@ void BuildStepsPage::addBuildStepWidget(int pos, BuildStep *step)
|
||||
|
||||
s.upButton = new QToolButton(this);
|
||||
s.upButton->setArrowType(Qt::UpArrow);
|
||||
s.upButton->setMaximumHeight(22);
|
||||
s.upButton->setMaximumWidth(22);
|
||||
s.downButton = new QToolButton(this);
|
||||
s.downButton->setArrowType(Qt::DownArrow);
|
||||
s.downButton->setMaximumHeight(22);
|
||||
s.downButton->setMaximumWidth(22);
|
||||
#ifdef Q_OS_MAC
|
||||
s.upButton->setIconSize(QSize(10, 10));
|
||||
s.downButton->setIconSize(QSize(10, 10));
|
||||
@@ -174,6 +179,7 @@ void BuildStepsPage::addBuildStepWidget(int pos, BuildStep *step)
|
||||
toolWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
s.hbox = new QHBoxLayout(toolWidget);
|
||||
s.hbox->setMargin(0);
|
||||
s.hbox->setSpacing(0);
|
||||
s.hbox->addWidget(s.upButton);
|
||||
s.hbox->addWidget(s.downButton);
|
||||
s.detailsWidget->setToolWidget(toolWidget);
|
||||
|
||||
@@ -104,7 +104,7 @@ void PanelsWidget::addWidget(QWidget *widget)
|
||||
p.panelWidget = widget;
|
||||
|
||||
p.marginLayout = 0;
|
||||
m_layout->insertWidget(m_layout->count() -1, widget);
|
||||
m_layout->insertWidget(m_layout->count() - 1, widget);
|
||||
m_panels.append(p);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
|
||||
Reference in New Issue
Block a user