diff --git a/src/plugins/debugger/breakcondition.ui b/src/plugins/debugger/breakcondition.ui index f5b5b0819d3c15ece4bc8aa8e04936d8a9f1475c..73aaa8ac39198547e132f8ef691adc4099af91d4 100644 --- a/src/plugins/debugger/breakcondition.ui +++ b/src/plugins/debugger/breakcondition.ui @@ -14,32 +14,65 @@ <item> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> + <widget class="QLabel" name="labelFileName"> + <property name="text"> + <string>File name:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="lineEditFileName"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="labelLineNumber"> + <property name="text"> + <string>Line number:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="lineEditLineNumber"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="labelFunction"> + <property name="text"> + <string>Function:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="lineEditFunction"/> + </item> + <item row="3" column="0"> <widget class="QLabel" name="labelCondition"> <property name="text"> <string>Condition:</string> </property> </widget> </item> - <item row="0" column="1"> + <item row="3" column="1"> <widget class="QLineEdit" name="lineEditCondition"/> </item> - <item row="1" column="0"> + <item row="4" 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> + <item row="4" column="1"> + <widget class="QLineEdit" name="lineEditIgnoreCount"/> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="labelThreadSpec"> + <property name="text"> + <string>Thread specification:</string> </property> </widget> </item> + <item row="5" column="1"> + <widget class="QLineEdit" name="lineEditThreadSpec"/> + </item> </layout> </item> <item> diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index 6ed2830cd8cdb6b85bc67177e0c9caa724bb2c30..c41eb00c86a2824d7defa848ad294e5acac0aec5 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -247,6 +247,8 @@ QString BreakpointData::toToolTip() const << "</td><td>" << condition << "</td><td>" << bpCondition << "</td></tr>" << "<tr><td>" << BreakHandler::tr("Ignore Count:") << "</td><td>" << ignoreCount << "</td><td>" << bpIgnoreCount << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("Thread Specification:") + << "</td><td>" << threadSpec << "</td><td>" << bpThreadSpec << "</td></tr>" << "</table></body></html>"; return rc; } @@ -268,7 +270,9 @@ QString BreakpointData::toString() const << BreakHandler::tr("Condition:") << condition << " -- " << bpCondition << '\n' << BreakHandler::tr("Ignore Count:") - << ignoreCount << " -- " << bpIgnoreCount << '\n'; + << ignoreCount << " -- " << bpIgnoreCount << '\n' + << BreakHandler::tr("Thread Specification:") + << threadSpec << " -- " << bpThreadSpec << '\n'; return rc; } @@ -320,7 +324,7 @@ BreakHandler::~BreakHandler() int BreakHandler::columnCount(const QModelIndex &parent) const { - return parent.isValid() ? 0 : 7; + return parent.isValid() ? 0 : 8; } int BreakHandler::rowCount(const QModelIndex &parent) const @@ -418,6 +422,8 @@ void BreakHandler::saveBreakpoints() map.insert(QLatin1String("condition"), data->condition); if (!data->ignoreCount.isEmpty()) map.insert(QLatin1String("ignorecount"), data->ignoreCount); + if (!data->threadSpec.isEmpty()) + map.insert(QLatin1String("threadspec"), data->threadSpec); if (!data->enabled) map.insert(QLatin1String("disabled"), QLatin1String("1")); if (data->useFullPath) @@ -447,6 +453,9 @@ void BreakHandler::loadBreakpoints() v = map.value(QLatin1String("ignorecount")); if (v.isValid()) data->ignoreCount = v.toString().toLatin1(); + v = map.value(QLatin1String("threadspec")); + if (v.isValid()) + data->threadSpec = v.toString().toLatin1(); v = map.value(QLatin1String("funcname")); if (v.isValid()) data->funcName = v.toString(); @@ -476,6 +485,7 @@ void BreakHandler::resetBreakpoints() data->bpCorrectedLineNumber.clear(); data->bpCondition.clear(); data->bpIgnoreCount.clear(); + data->bpThreadSpec.clear(); data->bpAddress.clear(); // Keep marker data if it was primary. if (data->markerFileName() != data->fileName) @@ -502,7 +512,7 @@ QVariant BreakHandler::headerData(int section, if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { static QString headers[] = { tr("Number"), tr("Function"), tr("File"), tr("Line"), - tr("Condition"), tr("Ignore"), tr("Address") + tr("Condition"), tr("Ignore"), tr("Threads"), tr("Address") }; return headers[section]; } @@ -538,6 +548,8 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const const QString str = data->pending ? data->funcName : data->bpFuncName; return str.isEmpty() ? empty : str; } + if (role == Qt::UserRole + 1) + return data->funcName; break; case 2: if (role == Qt::DisplayRole) { @@ -553,6 +565,8 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const } if (role == Qt::UserRole) return data->useFullPath; + if (role == Qt::UserRole + 1) + return data->fileName; break; case 3: if (role == Qt::DisplayRole) { @@ -562,19 +576,36 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const const QString str = data->pending ? data->lineNumber : data->bpLineNumber; return str.isEmpty() ? empty : str; } + if (role == Qt::UserRole + 1) + return data->lineNumber; 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."); + if (role == Qt::UserRole + 1) + return data->condition; 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."); + if (role == Qt::UserRole + 1) + return data->ignoreCount; case 6: + if (role == Qt::DisplayRole) { + if (data->pending) + return !data->threadSpec.isEmpty() ? data->threadSpec : tr("(all)"); + else + return !data->bpThreadSpec.isEmpty() ? data->bpThreadSpec : tr("(all)"); + } + if (role == Qt::ToolTipRole) + return tr("Breakpoint will only be hit in the specified thread(s)."); + if (role == Qt::UserRole + 1) + return data->threadSpec; + case 7: if (role == Qt::DisplayRole) return data->bpAddress; break; @@ -597,38 +628,73 @@ Qt::ItemFlags BreakHandler::flags(const QModelIndex &mi) const bool BreakHandler::setData(const QModelIndex &mi, const QVariant &value, int role) { - if (role != Qt::EditRole) - return false; - BreakpointData *data = at(mi.row()); + + if (role == Qt::UserRole + 1) { + if (data->enabled != value.toBool()) { + toggleBreakpointEnabled(data); + layoutChanged(); + } + return true; + } + + if (role == Qt::UserRole + 2) { + if (data->useFullPath != value.toBool()) { + data->useFullPath = value.toBool(); + layoutChanged(); + } + return true; + } + + //if (role != Qt::EditRole) + // return false; + switch (mi.column()) { - case 0: { - if (data->enabled != value.toBool()) { - toggleBreakpointEnabled(data); - dataChanged(mi, mi); + case 1: { + QString val = value.toString(); + if (data->funcName != val) { + data->funcName = val; + layoutChanged(); } return true; } case 2: { - if (data->useFullPath != value.toBool()) { - data->useFullPath = value.toBool(); - dataChanged(mi, mi); + QString val = value.toString(); + if (data->fileName != val) { + data->fileName = val; + layoutChanged(); + } + return true; + } + case 3: { + QByteArray val = value.toString().toLatin1(); + if (data->lineNumber != val) { + data->lineNumber = val; + layoutChanged(); } return true; } case 4: { - QString val = value.toString(); + QByteArray val = value.toString().toLatin1(); if (val != data->condition) { - data->condition = val.toLatin1(); - dataChanged(mi, mi); + data->condition = val; + layoutChanged(); } return true; } case 5: { - QString val = value.toString(); + QByteArray val = value.toString().toLatin1(); if (val != data->ignoreCount) { - data->ignoreCount = val.toLatin1(); - dataChanged(mi, mi); + data->ignoreCount = val; + layoutChanged(); + } + return true; + } + case 6: { + QByteArray val = value.toString().toLatin1(); + if (val != data->threadSpec) { + data->threadSpec = val; + layoutChanged(); } return true; } diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h index c0aaadc8cb6727e82f604e8ce929433cc9b01b04..ad2c640a30f7b7441d12a111f56d2fcc11baf77c 100644 --- a/src/plugins/debugger/breakhandler.h +++ b/src/plugins/debugger/breakhandler.h @@ -80,6 +80,7 @@ public: QByteArray condition; // Condition associated with breakpoint. QByteArray ignoreCount; // Ignore count associated with breakpoint. QByteArray lineNumber; // Line in source file. + QByteArray threadSpec; // Thread specification. QString funcName; // Name of containing function. bool useFullPath; // Should we use the full path when setting the bp? @@ -91,6 +92,7 @@ public: QString bpFullName; // Full file name acknowledged by the debugger engine. QByteArray bpLineNumber; // Line number acknowledged by the debugger engine. QByteArray bpCorrectedLineNumber; // Acknowledged by the debugger engine. + QByteArray bpThreadSpec; // Thread spec acknowledged by the debugger engine. QString bpFuncName; // Function name acknowledged by the debugger engine. QByteArray bpAddress; // Address acknowledged by the debugger engine. bool bpMultiple; // Happens in constructors/gdb. diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp index 34ddcd551d59e81bf6d405c494721d03a8fd0879..99826798c01ad7f1c809acd057bd0bccb62fa00c 100644 --- a/src/plugins/debugger/breakwindow.cpp +++ b/src/plugins/debugger/breakwindow.cpp @@ -103,7 +103,7 @@ BreakWindow::BreakWindow(Debugger::DebuggerManager *manager) void BreakWindow::showAddressColumn(bool on) { - setColumnHidden(6, !on); + setColumnHidden(7, !on); } static QModelIndexList normalizeIndexes(const QModelIndexList &list) @@ -133,6 +133,13 @@ void BreakWindow::resizeEvent(QResizeEvent *ev) QTreeView::resizeEvent(ev); } +void BreakWindow::mouseDoubleClickEvent(QMouseEvent *ev) +{ + QModelIndex indexUnderMouse = indexAt(ev->pos()); + if (indexUnderMouse.isValid()) + editBreakpoint(QModelIndexList() << indexUnderMouse); +} + void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) { QMenu menu; @@ -185,9 +192,9 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) alwaysAdjustAction->setCheckable(true); alwaysAdjustAction->setChecked(m_alwaysResizeColumnsToContents); - QAction *editConditionAction = - new QAction(tr("Edit Condition..."), &menu); - editConditionAction->setEnabled(si.size() > 0); + QAction *editBreakpointAction = + new QAction(tr("Edit Breakpoint..."), &menu); + editBreakpointAction->setEnabled(si.size() > 0); QAction *synchronizeAction = new QAction(tr("Synchronize Breakpoints"), &menu); @@ -223,7 +230,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) new QAction(tr("Set Breakpoint at \"catch\""), this); menu.addAction(deleteAction); - menu.addAction(editConditionAction); + menu.addAction(editBreakpointAction); menu.addAction(toggleEnabledAction); menu.addAction(pathAction); menu.addSeparator(); @@ -261,8 +268,8 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) resizeColumnsToContents(); else if (act == alwaysAdjustAction) setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents); - else if (act == editConditionAction) - editConditions(si); + else if (act == editBreakpointAction) + editBreakpoint(si); else if (act == synchronizeAction) emit breakpointSynchronizationRequested(); else if (act == toggleEnabledAction) @@ -284,7 +291,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) void BreakWindow::setBreakpointsEnabled(const QModelIndexList &list, bool enabled) { foreach (const QModelIndex &idx, list) - model()->setData(idx, enabled); + model()->setData(idx, enabled, Qt::UserRole + 1); emit breakpointSynchronizationRequested(); } @@ -292,7 +299,7 @@ void BreakWindow::setBreakpointsFullPath(const QModelIndexList &list, bool fullp { foreach (const QModelIndex &idx, list) { QModelIndex idx2 = idx.sibling(idx.row(), 2); - model()->setData(idx2, fullpath); + model()->setData(idx2, fullpath, Qt::UserRole + 2); } emit breakpointSynchronizationRequested(); } @@ -320,7 +327,7 @@ void BreakWindow::deleteBreakpoints(QList<int> list) setCurrentIndex(model()->index(row, 0)); } -void BreakWindow::editConditions(const QModelIndexList &list) +void BreakWindow::editBreakpoint(const QModelIndexList &list) { QDialog dlg(this); Ui::BreakCondition ui; @@ -330,15 +337,36 @@ void BreakWindow::editConditions(const QModelIndexList &list) QModelIndex idx = list.front(); 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()); + int role = Qt::UserRole + 1; + ui.lineEditFunction->hide(); + ui.labelFunction->hide(); + ui.lineEditFileName->hide(); + ui.labelFileName->hide(); + ui.lineEditLineNumber->hide(); + ui.labelLineNumber->hide(); + //ui.lineEditFunction->setText( + // model()->data(idx.sibling(row, 1), role).toString()); + //ui.lineEditFileName->setText( + // model()->data(idx.sibling(row, 2), role).toString()); + //ui.lineEditLineNumber->setText( + // model()->data(idx.sibling(row, 3), role).toString()); + ui.lineEditCondition->setText( + model()->data(idx.sibling(row, 4), role).toString()); + ui.lineEditIgnoreCount->setText( + model()->data(idx.sibling(row, 5), role).toString()); + ui.lineEditThreadSpec->setText( + model()->data(idx.sibling(row, 6), role).toString()); if (dlg.exec() == QDialog::Rejected) return; foreach (const QModelIndex &idx, list) { + //model()->setData(idx.sibling(idx.row(), 1), ui.lineEditFunction->text()); + //model()->setData(idx.sibling(idx.row(), 2), ui.lineEditFileName->text()); + //model()->setData(idx.sibling(idx.row(), 3), ui.lineEditLineNumber->text()); model()->setData(idx.sibling(idx.row(), 4), ui.lineEditCondition->text()); - model()->setData(idx.sibling(idx.row(), 5), ui.spinBoxIgnoreCount->value()); + model()->setData(idx.sibling(idx.row(), 5), ui.lineEditIgnoreCount->text()); + model()->setData(idx.sibling(idx.row(), 6), ui.lineEditThreadSpec->text()); } emit breakpointSynchronizationRequested(); } diff --git a/src/plugins/debugger/breakwindow.h b/src/plugins/debugger/breakwindow.h index 3429d7a64858e5ef9731e280baf88036a3990207..be25319d2bbe8d66e617ef08b6cba43772566865 100644 --- a/src/plugins/debugger/breakwindow.h +++ b/src/plugins/debugger/breakwindow.h @@ -1,4 +1,5 @@ /************************************************************************** +QT_END_NAMESPACE ** ** This file is part of Qt Creator ** @@ -65,11 +66,12 @@ protected: void resizeEvent(QResizeEvent *ev); void contextMenuEvent(QContextMenuEvent *ev); void keyPressEvent(QKeyEvent *ev); + void mouseDoubleClickEvent(QMouseEvent *ev); private: void deleteBreakpoints(const QModelIndexList &list); void deleteBreakpoints(QList<int> rows); - void editConditions(const QModelIndexList &list); + void editBreakpoint(const QModelIndexList &list); void setBreakpointsEnabled(const QModelIndexList &list, bool enabled); void setBreakpointsFullPath(const QModelIndexList &list, bool fullpath); diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.cpp b/src/plugins/debugger/cdb/cdbbreakpoint.cpp index 79e7012aeb60106bdc53608afef948ee0bac7a31..cdd57b5544bc5097a112f475c77213be9e3418bc 100644 --- a/src/plugins/debugger/cdb/cdbbreakpoint.cpp +++ b/src/plugins/debugger/cdb/cdbbreakpoint.cpp @@ -102,6 +102,7 @@ bool synchronizeBreakPoints(CIDebugControl* debugControl, // Take over rest as is nbd->bpCondition = nbd->condition; nbd->bpIgnoreCount = nbd->ignoreCount; + nbd->bpThreadSpec = nbd->threadSpec; nbd->bpFileName = nbd->fileName; nbd->bpLineNumber = nbd->lineNumber; nbd->bpFuncName = nbd->funcName; diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 166e5de6c7b6132faad6e63bdb67830648065a00..16199e52ebb4e5feff47b61c82ff1b01860f5a75 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -443,7 +443,7 @@ void GdbEngine::handleResponse(const QByteArray &buff) int progress = m_progress->progressValue(); m_progress->setProgressValue(qMin(70, progress + 1)); QByteArray id = result.findChild("id").data(); - showStatusMessage(tr("Thread group %1 created.").arg(_(id)), 1000); + showStatusMessage(tr("Thread group %1 created").arg(_(id)), 1000); int pid = id.toInt(); if (pid != inferiorPid()) handleInferiorPidChanged(pid); @@ -789,7 +789,7 @@ void GdbEngine::postCommandHelper(const GdbCommand &cmd) } else if (state() == InferiorRunningRequested_Kill) { debugMessage(_("RUNNING REQUESTED; POSTPONING INTERRUPT (KILL PENDING)")); } else if (state() == InferiorRunning) { - showStatusMessage(tr("Stopping temporarily."), 1000); + showStatusMessage(tr("Stopping temporarily"), 1000); interruptInferiorTemporarily(); } else { qDebug() << "ATTEMPTING TO QUEUE COMMAND IN INAPPROPRIATE STATE" << state(); @@ -802,7 +802,7 @@ void GdbEngine::postCommandHelper(const GdbCommand &cmd) void GdbEngine::flushQueuedCommands() { - showStatusMessage(tr("Processing queued commands."), 1000); + showStatusMessage(tr("Processing queued commands"), 1000); while (!m_commandsToRunOnTemporaryBreak.isEmpty()) { GdbCommand cmd = m_commandsToRunOnTemporaryBreak.takeFirst(); debugMessage(_("RUNNING QUEUED COMMAND " + cmd.command + ' ' @@ -908,7 +908,7 @@ void GdbEngine::handleResultRecord(GdbResponse *response) debugMessage(_("APPLYING WORKAROUND #1")); showMessageBox(QMessageBox::Critical, tr("Executable failed"), QString::fromLocal8Bit(msg)); - showStatusMessage(tr("Process failed to start.")); + showStatusMessage(tr("Process failed to start")); shutdown(); } else if (msg == "\"finish\" not meaningful in the outermost frame.") { // Handle a case known to appear on gdb 6.4 symbianelf when @@ -1091,7 +1091,7 @@ void GdbEngine::handleExecJumpToLine(const GdbResponse &response) // ~"242\t x *= 2;" //109^done" setState(InferiorStopped); - showStatusMessage(tr("Jumped. Stopped.")); + showStatusMessage(tr("Jumped. Stopped")); QByteArray output = response.data.findChild("logstreamoutput").data(); if (output.isEmpty()) return; @@ -1117,7 +1117,7 @@ void GdbEngine::handleExecJumpToLine(const GdbResponse &response) // // file="main.cpp",fullname="/tmp/g/main.cpp",line="37"} // QTC_ASSERT(state() == InferiorStopping, qDebug() << state()) // setState(InferiorStopped); -// showStatusMessage(tr("Function reached. Stopped.")); +// showStatusMessage(tr("Function reached. Stopped")); // GdbMi frame = response.data.findChild("frame"); // StackFrame f = parseStackFrame(frame, 0); // gotoLocation(f, true); @@ -1389,7 +1389,7 @@ void GdbEngine::handleStop1(const GdbMi &data) if (reason == "breakpoint-hit") { QByteArray bpNumber = data.findChild("bkptno").data(); QByteArray threadId = data.findChild("thread-id").data(); - showStatusMessage(tr("Stopped at breakpoint %1 in thread %2.") + showStatusMessage(tr("Stopped at breakpoint %1 in thread %2") .arg(_(bpNumber), _(threadId))); } else { QString reasontr = tr("Stopped: \"%1\"").arg(_(reason)); @@ -2115,6 +2115,8 @@ void GdbEngine::breakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt if (ba.startsWith('<') && ba.endsWith('>')) ba = ba.mid(1, ba.size() - 2); data->bpFuncName = _(ba); + } else if (child.hasName("thread")) { + data->bpThreadSpec = child.data(); } } // This field is not present. Contents needs to be parsed from @@ -2145,9 +2147,8 @@ QString GdbEngine::breakLocation(const QString &file) const return where; } -QByteArray GdbEngine::breakpointLocation(int index) +QByteArray GdbEngine::breakpointLocation(const BreakpointData *data) { - const BreakpointData *data = manager()->breakHandler()->at(index); if (!data->funcName.isEmpty()) return data->funcName.toLatin1(); // In this case, data->funcName is something like '*0xdeadbeef' @@ -2162,21 +2163,28 @@ QByteArray GdbEngine::breakpointLocation(int index) void GdbEngine::sendInsertBreakpoint(int index) { + const BreakpointData *data = manager()->breakHandler()->at(index); // Set up fallback in case of pending breakpoints which aren't handled // by the MI interface. QByteArray cmd; - if (m_isMacGdb) + if (m_isMacGdb) { cmd = "-break-insert -l -1 -f "; - else if (m_gdbAdapter->isTrkAdapter()) + } else if (m_gdbAdapter->isTrkAdapter()) { cmd = "-break-insert -h -f "; - else if (m_gdbVersion >= 60800) + } else if (m_gdbVersion >= 70000) { + cmd = "-break-insert "; + if (!data->threadSpec.isEmpty()) + cmd += "-p " + data->threadSpec; + cmd += " -f "; + } else if (m_gdbVersion >= 60800) { // Probably some earlier version would work as well. cmd = "-break-insert -f "; - else + } else { cmd = "-break-insert "; + } //if (!data->condition.isEmpty()) // cmd += "-c " + data->condition + ' '; - cmd += breakpointLocation(index); + cmd += breakpointLocation(data); postCommand(cmd, NeedsStop | RebuildBreakpointModel, CB(handleBreakInsert1), index); } @@ -2184,17 +2192,16 @@ void GdbEngine::sendInsertBreakpoint(int index) void GdbEngine::handleBreakInsert1(const GdbResponse &response) { int index = response.cookie.toInt(); - BreakHandler *handler = manager()->breakHandler(); + BreakpointData *data = manager()->breakHandler()->at(index); if (response.resultClass == GdbResultDone) { // Interesting only on Mac? - BreakpointData *data = handler->at(index); GdbMi bkpt = response.data.findChild("bkpt"); breakpointDataFromOutput(data, bkpt); } else { // Some versions of gdb like "GNU gdb (GDB) SUSE (6.8.91.20090930-2.4)" // know how to do pending breakpoints using CLI but not MI. So try // again with MI. - QByteArray cmd = "break " + breakpointLocation(index); + QByteArray cmd = "break " + breakpointLocation(data); postCommand(cmd, NeedsStop | RebuildBreakpointModel, CB(handleBreakInsert2), index); } @@ -2524,7 +2531,8 @@ void GdbEngine::attemptBreakpointSynchronization() else // Because gdb won't do both changes at a time anyway. if (data->ignoreCount != data->bpIgnoreCount) { // Update ignorecount if needed. - postCommand("ignore " + data->bpNumber + ' ' + data->ignoreCount, + QByteArray ic = QByteArray::number(data->ignoreCount.toInt()); + postCommand("ignore " + data->bpNumber + ' ' + ic, NeedsStop | RebuildBreakpointModel, CB(handleBreakIgnore), data->bpNumber.toInt()); continue; @@ -2536,6 +2544,17 @@ void GdbEngine::attemptBreakpointSynchronization() data->bpEnabled = false; continue; } + if (data->threadSpec != data->bpThreadSpec && !data->bpThreadSpec.isEmpty()) { + // The only way to change this seems to be to re-set the bp completely. + //qDebug() << "FIXME: THREAD: " << data->threadSpec << data->bpThreadSpec; + //data->bpThreadSpec = data->threadSpec; + if (!data->bpNumber.isEmpty()) { + postCommand("-break-delete " + data->bpNumber, + NeedsStop | RebuildBreakpointModel); + sendInsertBreakpoint(index); + } + continue; + } if (data->bpAddress.startsWith("0x") && data->bpCorrectedLineNumber.isEmpty()) { // Prevent endless loop. @@ -3958,7 +3977,7 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr } if (!foundPython) { debugMessage(_("UNSUPPORTED GDB %1 DOES NOT HAVE PYTHON.").arg(m_gdb)); - showStatusMessage(_("Gdb at %1 does not have python.").arg(m_gdb)); + showStatusMessage(_("Gdb at %1 does not have python").arg(m_gdb)); } #endif diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 2093e54346ff13fd6f1169d76370ca25d47bb276..b5950703f39fc93a2864b1454cb1d1f779dab8c4 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -348,7 +348,7 @@ private: ////////// View & Data Stuff ////////// void handleInfoLine(const GdbResponse &response); void extractDataFromInfoBreak(const QString &output, BreakpointData *data); void breakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt); - QByteArray breakpointLocation(int index); + QByteArray breakpointLocation(const BreakpointData *data); void sendInsertBreakpoint(int index); QString breakLocation(const QString &file) const; void reloadBreakListInternal(); diff --git a/src/plugins/debugger/gdb/pythongdbengine.cpp b/src/plugins/debugger/gdb/pythongdbengine.cpp index 3edf26905ac4ef280b50aafecee4efa69da03528..ebe0dff8f8337552d707891e13aef5cb810636a5 100644 --- a/src/plugins/debugger/gdb/pythongdbengine.cpp +++ b/src/plugins/debugger/gdb/pythongdbengine.cpp @@ -114,8 +114,8 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response) //qDebug() << "SECOND CHUNK: " << out; int pos = out.indexOf("data="); if (pos != 0) { - qDebug() << "DISCARDING JUNK AT BEGIN OF RESPONSE: " - << out.left(pos); + debugMessage(_("DISCARDING JUNK AT BEGIN OF RESPONSE: " + + out.left(pos))); out = out.mid(pos); } GdbMi all; diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index 1705327ffa59084ad55266868dbcfd7a6d594ec9..8d700848c7f8f2e8bb988ce3df670768c405b399 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -1218,10 +1218,13 @@ public: void run() { + int j = 2; + ++j; for (int i = 0; i != 100000; ++i) { //sleep(1); std::cerr << m_id; } + std::cerr << j; } private: @@ -1655,7 +1658,7 @@ int main(int argc, char *argv[]) #endif testQStringList(); testStruct(); - //testThreads(); + testQThread(); testQVariant1(); testQVariant2(); testQVariant3();