| 699 | } |
| 700 | |
| 701 | void MIBreakpointController::updateFromDebugger(int row, const Value& miBkpt, BreakpointModel::ColumnFlags lockedColumns) |
| 702 | { |
| 703 | qCDebug(DEBUGGERCOMMON).nospace() << "updating breakpoint #" << row << " from debugger with " << miBkpt; |
| 704 | |
| 705 | IgnoreChanges ignoreChanges(*this); |
| 706 | BreakpointDataPtr breakpoint = m_breakpoints[row]; |
| 707 | Breakpoint* modelBreakpoint = breakpointModel()->breakpoint(row); |
| 708 | |
| 709 | // Commands that are currently in flight will overwrite the modification we have received, |
| 710 | // so do not update the corresponding data |
| 711 | lockedColumns |= breakpoint->sent | breakpoint->dirty; |
| 712 | |
| 713 | const auto setExpressionToFieldValue = [&miBkpt, modelBreakpoint](const QString& fieldName) { |
| 714 | if (miBkpt.hasField(fieldName)) { |
| 715 | modelBreakpoint->setExpression(miBkpt[fieldName].literal()); |
| 716 | return true; |
| 717 | } |
| 718 | return false; |
| 719 | }; |
| 720 | |
| 721 | // TODO: |
| 722 | // Gdb has a notion of "original-location", which is the "expression" or "location" used |
| 723 | // to set the breakpoint, and notions of the actual location of the breakpoint (function name, |
| 724 | // address, source file and line). The breakpoint model currently does not map well to this |
| 725 | // (though it arguably should), and does not support multi-location breakpoints at all. |
| 726 | // We try to do the best we can until the breakpoint model gets cleaned up. |
| 727 | if (const auto actualLocation = ActualBreakpointLocation{miBkpt}) { |
| 728 | modelBreakpoint->setLocation(QUrl::fromLocalFile(actualLocation.filePath()), actualLocation.line()); |
| 729 | } else if (miBkpt.hasField(QStringLiteral("original-location"))) { |
| 730 | QString location = miBkpt[QStringLiteral("original-location")].literal(); |
| 731 | modelBreakpoint->setData(Breakpoint::LocationColumn, Utils::unquoteExpression(location)); |
| 732 | } else if (setExpressionToFieldValue(QStringLiteral("what")) || setExpressionToFieldValue(QStringLiteral("exp"))) { |
| 733 | // The value of the "what" field can contain "exception throw", |
| 734 | // which should be assigned to the breakpoint's expression. |
| 735 | // The usual GDB/MI reply to a watchpoint-adding command is "done,wpt={number=\"<id>\",exp=\"<expression>\"}". |
| 736 | // The value of either the "what" or the "exp" field is assigned |
| 737 | // to modelBreakpoint's expression above. Nothing more to do here. |
| 738 | } else { |
| 739 | qCWarning(DEBUGGERCOMMON) << "Breakpoint doesn't contain required location/expression data"; |
| 740 | } |
| 741 | |
| 742 | if (!(lockedColumns & BreakpointModel::EnableColumnFlag)) { |
| 743 | bool enabled = true; |
| 744 | if (miBkpt.hasField(QStringLiteral("enabled"))) { |
| 745 | if (miBkpt[QStringLiteral("enabled")].literal() == QLatin1String("n")) |
| 746 | enabled = false; |
| 747 | } |
| 748 | modelBreakpoint->setData(Breakpoint::EnableColumn, enabled ? Qt::Checked : Qt::Unchecked); |
| 749 | breakpoint->dirty &= ~BreakpointModel::EnableColumnFlag; |
| 750 | } |
| 751 | |
| 752 | if (!(lockedColumns & BreakpointModel::ConditionColumnFlag)) { |
| 753 | QString condition; |
| 754 | if (miBkpt.hasField(QStringLiteral("cond"))) { |
| 755 | condition = miBkpt[QStringLiteral("cond")].literal(); |
| 756 | } |
| 757 | modelBreakpoint->setCondition(condition); |
| 758 | breakpoint->dirty &= ~BreakpointModel::ConditionColumnFlag; |
no test coverage detected