diff options
author | hjk <hjk121@nokiamail.com> | 2014-11-11 11:00:32 +0100 |
---|---|---|
committer | hjk <hjk121@nokiamail.com> | 2014-11-14 12:58:05 +0100 |
commit | 011ddc09c41b3822afe796b0330bc998a3faa505 (patch) | |
tree | d522f42a11428e56ead282c8f1f4afa090368778 | |
parent | 620ded809355d43b00723349539171618e8e668e (diff) | |
download | qt-creator-011ddc09c41b3822afe796b0330bc998a3faa505.tar.gz |
Debugger: Fix async tooltip handling
For now, only the gdb engine can handle complex tooltips
requiring async re-evaluation, cdb and lldb will show
and expand only items that are available in the Locals view.
This patch disables also the save/restore feature for
pinned tooltips.
Task-number: QTCREATORBUG-13255
Task-number: QTCREATORBUG-13052
Change-Id: Ic25616fede0f5c4343a92b631f01e60bfc5e9d81
Reviewed-by: David Schulz <david.schulz@theqtcompany.com>
Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
-rw-r--r-- | src/plugins/debugger/cdb/cdbengine.cpp | 28 | ||||
-rw-r--r-- | src/plugins/debugger/cdb/cdbengine.h | 2 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerengine.cpp | 1 | ||||
-rw-r--r-- | src/plugins/debugger/debuggertooltipmanager.cpp | 625 | ||||
-rw-r--r-- | src/plugins/debugger/debuggertooltipmanager.h | 10 | ||||
-rw-r--r-- | src/plugins/debugger/gdb/gdbengine.cpp | 79 | ||||
-rw-r--r-- | src/plugins/debugger/gdb/gdbengine.h | 2 | ||||
-rw-r--r-- | src/plugins/debugger/lldb/lldbengine.cpp | 70 | ||||
-rw-r--r-- | src/plugins/debugger/lldb/lldbengine.h | 3 | ||||
-rw-r--r-- | src/plugins/debugger/watchhandler.cpp | 8 | ||||
-rw-r--r-- | src/plugins/debugger/watchhandler.h | 1 |
11 files changed, 426 insertions, 403 deletions
diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 86acd62f2f..fc3c40f231 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -442,28 +442,14 @@ void CdbEngine::syncVerboseLog(bool verboseLog) } bool CdbEngine::setToolTipExpression(TextEditor::TextEditorWidget *editorWidget, - const DebuggerToolTipContext &contextIn) + const DebuggerToolTipContext &context) { - if (debug) - qDebug() << Q_FUNC_INFO; - // Need a stopped debuggee and a cpp file in a valid frame - if (state() != InferiorStopOk || !isCppEditor(editorWidget) || stackHandler()->currentIndex() < 0) - return false; - // Determine expression and function - int line; - int column; - DebuggerToolTipContext context = contextIn; - QString exp = fixCppExpression(cppExpressionAt(editorWidget, context.position, &line, &column, &context.function)); - // Are we in the current stack frame - if (context.function.isEmpty() || exp.isEmpty() || context.function != stackHandler()->currentFrame().function) - return false; - // Show tooltips of local variables only. Anything else can slow debugging down. - const WatchData *localVariable = watchHandler()->findCppLocalVariable(exp); - if (!localVariable) - return false; - context.iname = localVariable->iname; - DebuggerToolTipManager::showToolTip(context, this); - return true; + Q_UNUSED(editorWidget); + Q_UNUSED(context); + // Tooltips matching local variables are already handled in the + // base class. We don't handle anything else here in CDB + // as it can slow debugging down. + return false; } // Determine full path to the CDB extension library. diff --git a/src/plugins/debugger/cdb/cdbengine.h b/src/plugins/debugger/cdb/cdbengine.h index 33b92042c2..37ed92c68b 100644 --- a/src/plugins/debugger/cdb/cdbengine.h +++ b/src/plugins/debugger/cdb/cdbengine.h @@ -78,7 +78,7 @@ public: // Factory function that returns 0 if the debug engine library cannot be found. virtual bool setToolTipExpression(TextEditor::TextEditorWidget *editorWidget, - const DebuggerToolTipContext &ctx); + const DebuggerToolTipContext &context); virtual void setupEngine(); virtual void setupInferior(); virtual void runEngine(); diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index b978f95af6..9c767602c2 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -269,6 +269,7 @@ public slots: m_watchHandler.resetLocation(); m_threadsHandler.resetLocation(); m_disassemblerAgent.resetLocation(); + DebuggerToolTipManager::resetLocation(); } public: diff --git a/src/plugins/debugger/debuggertooltipmanager.cpp b/src/plugins/debugger/debuggertooltipmanager.cpp index 2079511b21..2e86567380 100644 --- a/src/plugins/debugger/debuggertooltipmanager.cpp +++ b/src/plugins/debugger/debuggertooltipmanager.cpp @@ -47,6 +47,7 @@ #include <utils/tooltip/tipcontents.h> #include <utils/qtcassert.h> +#include <QAbstractItemModel> #include <QApplication> #include <QClipboard> #include <QDebug> @@ -68,9 +69,8 @@ using namespace TextEditor; namespace Debugger { namespace Internal { -class DebuggerToolTipWidget; -QList<QPointer<DebuggerToolTipWidget>> m_tooltips; -bool m_debugModeActive; +//#define DEBUG(x) qDebug() << x +#define DEBUG(x) // Expire tooltips after n days on (no longer load them) in order // to avoid them piling up. @@ -98,12 +98,11 @@ const char modelColumnCountAttributeC[] = "columncount"; const char modelRowElementC[] = "row"; const char modelItemElementC[] = "item"; -static void purgeClosedToolTips() -{ - for (int i = m_tooltips.size(); --i >= 0; ) - if (!m_tooltips.at(i)) - m_tooltips.removeAt(i); -} +static void purgeClosedToolTips(); + +class DebuggerToolTipHolder; +QList<QPointer<DebuggerToolTipHolder>> m_tooltips; +bool m_debugModeActive; // Forward a stream reader across end elements looking for the // next start element of a desired type. @@ -407,7 +406,7 @@ static QDebug operator<<(QDebug d, const QAbstractItemModel &model) QTextStream str(&s); Debugger::Internal::DumpTreeModelVisitor v(&model, Debugger::Internal::DumpTreeModelVisitor::DebugMode, str); v.run(); - qDebug().nospace() << s; + qCDebug(tooltip).nospace() << s; return d; } */ @@ -443,7 +442,7 @@ public: { const QModelIndex nameIndex = sourceModel()->index(sourceRow, 0, sourceParent); const QByteArray iname = nameIndex.data(LocalsINameRole).toByteArray(); -// qDebug() << "ACCEPTING FILTER" << iname +// DEBUG("ACCEPTING FILTER" << iname // << (iname == m_iname || isSubIname(iname, m_iname) || isSubIname(m_iname, iname)); return iname == m_iname || isSubIname(iname, m_iname) || isSubIname(m_iname, iname); } @@ -612,68 +611,149 @@ QString DebuggerToolTipManager::treeModelClipboardContents(const QAbstractItemMo class DebuggerToolTipWidget : public QWidget { public: - DebuggerToolTipWidget(const DebuggerToolTipContext &context); + DebuggerToolTipWidget() + { + setAttribute(Qt::WA_DeleteOnClose); + + isPinned = false; + const QIcon pinIcon(QLatin1String(":/debugger/images/pin.xpm")); + + pinButton = new QToolButton; + pinButton->setIcon(pinIcon); + + auto copyButton = new QToolButton; + copyButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_COPY))); + + titleLabel = new DraggableLabel(this); + titleLabel->setMinimumWidth(40); // Ensure a draggable area even if text is empty. + titleLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + + auto toolBar = new QToolBar(this); + toolBar->setProperty("_q_custom_style_disabled", QVariant(true)); + const QList<QSize> pinIconSizes = pinIcon.availableSizes(); + if (!pinIconSizes.isEmpty()) + toolBar->setIconSize(pinIconSizes.front()); + toolBar->addWidget(pinButton); + toolBar->addWidget(copyButton); + toolBar->addWidget(titleLabel); + + treeView = new DebuggerToolTipTreeView(this); + treeView->setFocusPolicy(Qt::NoFocus); + + auto mainLayout = new QVBoxLayout(this); + mainLayout->setSizeConstraint(QLayout::SetFixedSize); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->addWidget(toolBar); + mainLayout->addWidget(treeView); + + connect(copyButton, &QAbstractButton::clicked, [this] { + QString clipboardText = DebuggerToolTipManager::treeModelClipboardContents(treeView->model()); + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(clipboardText, QClipboard::Selection); + clipboard->setText(clipboardText, QClipboard::Clipboard); + }); + DEBUG("CREATE DEBUGGERTOOLTIP WIDGET"); + } + + ~DebuggerToolTipWidget() + { + DEBUG("DESTROY DEBUGGERTOOLTIP WIDGET"); + } + + void closeEvent(QCloseEvent *) + { + DEBUG("CLOSE DEBUGGERTOOLTIP WIDGET"); + } + + void enterEvent(QEvent *) + { + DEBUG("ENTER DEBUGGERTOOLTIP WIDGET"); + } + + void leaveEvent(QEvent *) + { + DEBUG("LEAVE DEBUGGERTOOLTIP WIDGET"); + if (BaseTextEditor *editor = BaseTextEditor::currentTextEditor()) + editor->editorWidget()->activateWindow(); + } + + void pin() + { + if (isPinned) + return; + isPinned = true; + pinButton->setIcon(style()->standardIcon(QStyle::SP_DockWidgetCloseButton)); + + if (parentWidget()) { + // We are currently within a text editor tooltip: + // Rip out of parent widget and re-show as a tooltip + Utils::WidgetContent::pinToolTip(this); + } else { + // We have just be restored from session data. + setWindowFlags(Qt::ToolTip); + } + titleLabel->active = true; // User can now drag + } - bool isPinned() const { return m_isPinned; } - QString fileName() const { return m_context.fileName; } - QString function() const { return m_context.function; } - int position() const { return m_context.position; } +public: + bool isPinned; + QToolButton *pinButton; + DraggableLabel *titleLabel; + DebuggerToolTipTreeView *treeView; +}; - const DebuggerToolTipContext &context() const { return m_context; } +///////////////////////////////////////////////////////////////////////// +// +// DebuggerToolTipHolder +// +///////////////////////////////////////////////////////////////////////// + +class DebuggerToolTipHolder : public QObject +{ +public: + DebuggerToolTipHolder(const DebuggerToolTipContext &context); + ~DebuggerToolTipHolder(); + + enum State { New, Pending, Acquired, Released }; void acquireEngine(); void releaseEngine(); void saveSessionData(QXmlStreamWriter &w) const; - void setWatchModel(WatchModelBase *watchModel); void handleStackFrameCompleted(const QString &frameFile, const QString &frameFunction); - void copy(); void positionShow(const TextEditorWidget *editorWidget); - void pin(); - void handleItemIsExpanded(const QModelIndex &sourceIdx) - { - QTC_ASSERT(m_filterModel.sourceModel() == sourceIdx.model(), return); - QModelIndex mappedIdx = m_filterModel.mapFromSource(sourceIdx); - if (!m_treeView->isExpanded(mappedIdx)) - m_treeView->expand(mappedIdx); - } + void handleItemIsExpanded(const QModelIndex &sourceIdx); + void updateTooltip(const QString &frameFile, const QString &frameFunction); + + void setState(State newState); public: - bool m_isPinned; - QToolButton *m_toolButton; - DraggableLabel *m_titleLabel; - QDate m_creationDate; - DebuggerToolTipTreeView *m_treeView; //!< Pointing to either m_defaultModel oder m_filterModel - DebuggerToolTipContext m_context; - TooltipFilterModel m_filterModel; //!< Pointing to a valid watchModel - QStandardItemModel m_defaultModel; + QPointer<DebuggerToolTipWidget> widget; + QPointer<DebuggerEngine> engine; + QDate creationDate; + DebuggerToolTipContext context; + TooltipFilterModel filterModel; //!< Pointing to a valid watchModel + QStandardItemModel defaultModel; + + State state; }; static void hideAllToolTips() { purgeClosedToolTips(); - foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips) - tw->hide(); + foreach (const DebuggerToolTipHolder *tooltip, m_tooltips) + tooltip->widget->hide(); } -void DebuggerToolTipWidget::pin() +void DebuggerToolTipHolder::handleItemIsExpanded(const QModelIndex &sourceIdx) { - if (m_isPinned) - return; - m_isPinned = true; - m_toolButton->setIcon(style()->standardIcon(QStyle::SP_DockWidgetCloseButton)); - - if (parentWidget()) { - // We are currently within a text editor tooltip: - // Rip out of parent widget and re-show as a tooltip - Utils::WidgetContent::pinToolTip(this); - } else { - // We have just be restored from session data. - setWindowFlags(Qt::ToolTip); - } - m_titleLabel->active = true; // User can now drag + QTC_ASSERT(filterModel.sourceModel() == sourceIdx.model(), return); + QModelIndex mappedIdx = filterModel.mapFromSource(sourceIdx); + QTC_ASSERT(widget.data(), return); + if (!widget->treeView->isExpanded(mappedIdx)) + widget->treeView->expand(mappedIdx); } /*! @@ -752,159 +832,154 @@ QDebug operator<<(QDebug d, const DebuggerToolTipContext &c) of them. On closing or session changes, the contents it saved. */ - -static QString msgReleasedText() { return DebuggerToolTipWidget::tr("Previous"); } - -DebuggerToolTipWidget::DebuggerToolTipWidget(const DebuggerToolTipContext &context) +DebuggerToolTipHolder::DebuggerToolTipHolder(const DebuggerToolTipContext &context_) { - setFocusPolicy(Qt::NoFocus); - - m_isPinned = false; - m_context = context; - m_filterModel.m_iname = context.iname; + widget = new DebuggerToolTipWidget; + widget->setObjectName(QLatin1String("DebuggerTreeViewToolTipWidget: ") + QLatin1String(context_.iname)); - const QIcon pinIcon(QLatin1String(":/debugger/images/pin.xpm")); + context = context_; + context.creationDate = QDate::currentDate(); - m_toolButton = new QToolButton; - m_toolButton->setIcon(pinIcon); + state = New; - auto copyButton = new QToolButton; - copyButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_COPY))); + filterModel.m_iname = context.iname; - m_titleLabel = new DraggableLabel(this); - m_titleLabel->setText(msgReleasedText()); - m_titleLabel->setMinimumWidth(40); // Ensure a draggable area even if text is empty. - m_titleLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); - - auto toolBar = new QToolBar(this); - toolBar->setProperty("_q_custom_style_disabled", QVariant(true)); - const QList<QSize> pinIconSizes = pinIcon.availableSizes(); - if (!pinIconSizes.isEmpty()) - toolBar->setIconSize(pinIconSizes.front()); - toolBar->addWidget(m_toolButton); - toolBar->addWidget(copyButton); - toolBar->addWidget(m_titleLabel); - - m_treeView = new DebuggerToolTipTreeView(this); - m_treeView->setFocusPolicy(Qt::NoFocus); - - auto mainLayout = new QVBoxLayout(this); - mainLayout->setSizeConstraint(QLayout::SetFixedSize); - mainLayout->setContentsMargins(0, 0, 0, 0); - mainLayout->addWidget(toolBar); - mainLayout->addWidget(m_treeView); - - connect(m_toolButton, &QAbstractButton::clicked, [this]() { - if (m_isPinned) - close(); - else - pin(); + QObject::connect(widget->pinButton, &QAbstractButton::clicked, [this] { + if (widget->isPinned) { + widget->close(); + } else { + widget->pin(); + } }); - - connect(copyButton, &QAbstractButton::clicked, this, &DebuggerToolTipWidget::copy); + DEBUG("CREATE DEBUGGERTOOLTIPHOLDER" << context.iname); } -void DebuggerToolTipWidget::setWatchModel(WatchModelBase *watchModel) +DebuggerToolTipHolder::~DebuggerToolTipHolder() { - QTC_ASSERT(watchModel, return); - m_filterModel.setSourceModel(watchModel); - connect(watchModel, &WatchModelBase::itemIsExpanded, - this, &DebuggerToolTipWidget::handleItemIsExpanded, Qt::UniqueConnection); - connect(watchModel, &WatchModelBase::columnAdjustmentRequested, - m_treeView, &DebuggerToolTipTreeView::computeSize, Qt::UniqueConnection); + DEBUG("DESTROY DEBUGGERTOOLTIPHOLDER" << context.iname << " STATE: " << state); + delete widget; widget.clear(); } -void DebuggerToolTipWidget::handleStackFrameCompleted(const QString &frameFile, const QString &frameFunction) +void DebuggerToolTipHolder::updateTooltip(const QString &frameFile, const QString &frameFunction) { - const bool sameFrame = m_context.matchesFrame(frameFile, frameFunction); - const bool isAcquired = m_treeView->model() == &m_filterModel; - if (isAcquired && !sameFrame) - releaseEngine(); - else if (!isAcquired && sameFrame) - acquireEngine(); + const bool sameFrame = context.matchesFrame(frameFile, frameFunction); + DEBUG("UPDATE TOOLTIP: STATE " << state << context.iname + << "PINNED: " << widget->isPinned << "SAME FRAME: " << sameFrame); + + if (state == Pending) { + acquireEngine(); + } else if (state == Acquired && !sameFrame) { + releaseEngine(); + } else if (state == Released && sameFrame) { + acquireEngine(); + } + + if (!widget->isPinned) { + DEBUG("SHOW UNPINNED"); + const Utils::WidgetContent widgetContent(widget, true); + Utils::ToolTip::show(context.mousePosition, widgetContent, Internal::mainWindow()); + } - if (isAcquired) { - m_treeView->expand(m_filterModel.index(0, 0)); - WatchTreeView::reexpand(m_treeView, m_filterModel.index(0, 0)); + if (state == Acquired) { + // Save data to stream and restore to the backup m_defaultModel. + // Doing it on releaseEngine() is too later. + defaultModel.removeRows(0, defaultModel.rowCount()); + TreeModelCopyVisitor v(&filterModel, &defaultModel); + v.run(); + + widget->treeView->expand(filterModel.index(0, 0)); + WatchTreeView::reexpand(widget->treeView, filterModel.index(0, 0)); } } -void DebuggerToolTipWidget::acquireEngine() +void DebuggerToolTipHolder::setState(DebuggerToolTipHolder::State newState) { - m_titleLabel->setText(m_context.expression); - m_treeView->setModel(&m_filterModel); - m_treeView->setRootIndex(m_filterModel.index(0, 0)); - m_treeView->expand(m_filterModel.index(0, 0)); - WatchTreeView::reexpand(m_treeView, m_filterModel.index(0, 0)); + bool ok = (state == New && newState == Pending) + || (state == Pending && (newState == Acquired || newState == Released)) + || (state == Acquired && (newState == Released)) + || (state == Released && (newState == Acquired)); + + // FIXME: These happen when a tooltip is re-used in findOrCreate. + ok = ok + || (state == Acquired && newState == Pending) + || (state == Released && newState == Pending); + + DEBUG("TRANSITION STATE FROM " << state << " TO " << newState); + QTC_ASSERT(ok, qDebug() << "Unexpected tooltip state transition from " + << state << " to " << newState); + + state = newState; } -void DebuggerToolTipWidget::releaseEngine() +void DebuggerToolTipHolder::acquireEngine() { - // Save data to stream and restore to the backup m_defaultModel. - m_defaultModel.removeRows(0, m_defaultModel.rowCount()); - TreeModelCopyVisitor v(&m_filterModel, &m_defaultModel); - v.run(); + DEBUG("ACQUIRE ENGINE: STATE " << state); + setState(Acquired); - m_titleLabel->setText(msgReleasedText()); - m_treeView->setModel(&m_defaultModel); - m_treeView->setRootIndex(m_defaultModel.index(0, 0)); - m_treeView->expandAll(); + QTC_ASSERT(widget, return); + widget->titleLabel->setText(context.expression); + widget->treeView->setModel(&filterModel); + widget->treeView->setRootIndex(filterModel.index(0, 0)); + widget->treeView->expand(filterModel.index(0, 0)); + WatchTreeView::reexpand(widget->treeView, filterModel.index(0, 0)); } -void DebuggerToolTipWidget::copy() +void DebuggerToolTipHolder::releaseEngine() { - QString clipboardText = DebuggerToolTipManager::treeModelClipboardContents(m_treeView->model()); - QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(clipboardText, QClipboard::Selection); - clipboard->setText(clipboardText, QClipboard::Clipboard); + DEBUG("RELEASE ENGINE: STATE " << state); + setState(Released); + + QTC_ASSERT(widget, return); + widget->titleLabel->setText(DebuggerToolTipManager::tr("%1 (Previous)").arg(context.expression)); + widget->treeView->setModel(&defaultModel); + widget->treeView->setRootIndex(defaultModel.index(0, 0)); + widget->treeView->expandAll(); } -void DebuggerToolTipWidget::positionShow(const TextEditorWidget *editorWidget) +void DebuggerToolTipHolder::positionShow(const TextEditorWidget *editorWidget) { // Figure out new position of tooltip using the text edit. // If the line changed too much, close this tip. QTC_ASSERT(editorWidget, return); QTextCursor cursor = editorWidget->textCursor(); - cursor.setPosition(m_context.position); + cursor.setPosition(context.position); const int line = cursor.blockNumber(); - if (qAbs(m_context.line - line) > 2) { - close(); + if (qAbs(context.line - line) > 2) { + widget->close(); return ; } - const QPoint screenPos = editorWidget->toolTipPosition(cursor) + m_titleLabel->m_offset; - const QRect toolTipArea = QRect(screenPos, QSize(sizeHint())); + const QPoint screenPos = editorWidget->toolTipPosition(cursor) + widget->titleLabel->m_offset; + const QRect toolTipArea = QRect(screenPos, QSize(widget->sizeHint())); const QRect plainTextArea = QRect(editorWidget->mapToGlobal(QPoint(0, 0)), editorWidget->size()); const bool visible = plainTextArea.intersects(toolTipArea); - // qDebug() << "DebuggerToolTipWidget::positionShow() " << this << m_context + // DEBUG("DebuggerToolTipWidget::positionShow() " << this << m_context // << " line: " << line << " plainTextPos " << toolTipArea // << " offset: " << m_titleLabel->m_offset // << " Area: " << plainTextArea << " Screen pos: " - // << screenPos << te.widget << " visible=" << visible; + // << screenPos << te.widget << " visible=" << visible); - if (!visible) { - hide(); - return; + if (visible) { + widget->move(screenPos); + widget->show(); + } else { + widget->hide(); } - - move(screenPos); - show(); } -static DebuggerToolTipWidget *findOrCreateWidget(const DebuggerToolTipContext &context) +static DebuggerToolTipHolder *findOrCreateTooltip(const DebuggerToolTipContext &context) { - foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips) - if (tw && tw->m_context.isSame(context)) - return tw; - - auto tw = new DebuggerToolTipWidget(context); - tw->setAttribute(Qt::WA_DeleteOnClose); - tw->setObjectName(QLatin1String("DebuggerTreeViewToolTipWidget: ") + QLatin1String(context.iname)); - tw->m_context.creationDate = QDate::currentDate(); + purgeClosedToolTips(); - m_tooltips.push_back(tw); + for (int i = 0, n = m_tooltips.size(); i != n; ++i) { + DebuggerToolTipHolder *tooltip = m_tooltips.at(i); + if (tooltip->context.isSame(context)) + return tooltip; + } - return tw; + auto newTooltip = new DebuggerToolTipHolder(context); + m_tooltips.push_back(newTooltip); + return newTooltip; } static void restoreTreeModel(QXmlStreamReader &r, QStandardItemModel *m) @@ -975,27 +1050,26 @@ static void loadSessionDataHelper(QXmlStreamReader &r) context.iname = attributes.value(QLatin1String(treeInameAttributeC)).toString().toLatin1(); context.expression = attributes.value(QLatin1String(treeExpressionAttributeC)).toString(); - const QStringRef className = attributes.value(QLatin1String(toolTipClassAttributeC)); +// const QStringRef className = attributes.value(QLatin1String(toolTipClassAttributeC)); context.engineType = attributes.value(QLatin1String(engineTypeAttributeC)).toString(); context.creationDate = dateFromString(attributes.value(QLatin1String(dateAttributeC)).toString()); bool readTree = context.isValid(); if (!context.creationDate.isValid() || context.creationDate.daysTo(QDate::currentDate()) > toolTipsExpiryDays) { - // qDebug() << "Expiring tooltip " << context.fileName << '@' << context.position << " from " << creationDate; + // DEBUG("Expiring tooltip " << context.fileName << '@' << context.position << " from " << creationDate) + //readTree = false; + } else { //if (className != QLatin1String("Debugger::Internal::DebuggerToolTipWidget")) { + //qWarning("Unable to create debugger tool tip widget of class %s", qPrintable(className.toString())); //readTree = false; - } else if (className != QLatin1String("Debugger::Internal::DebuggerToolTipWidget")) { - qWarning("Unable to create debugger tool tip widget of class %s", qPrintable(className.toString())); - readTree = false; } if (readTree) { - DebuggerToolTipWidget *tw = findOrCreateWidget(context); - restoreTreeModel(r, &tw->m_defaultModel); - tw->pin(); - tw->acquireEngine(); - tw->m_titleLabel->setText(DebuggerToolTipManager::tr("Restored")); - tw->m_treeView->setModel(&tw->m_defaultModel); - tw->m_treeView->setRootIndex(tw->m_defaultModel.index(0, 0)); - tw->m_treeView->expandAll(); + DebuggerToolTipHolder *tw = findOrCreateTooltip(context); + restoreTreeModel(r, &tw->defaultModel); + tw->widget->pin(); + tw->widget->titleLabel->setText(DebuggerToolTipManager::tr("%1 (Restored").arg(context.expression)); + tw->widget->treeView->setModel(&tw->defaultModel); + tw->widget->treeView->setRootIndex(tw->defaultModel.index(0, 0)); + tw->widget->treeView->expandAll(); } else { r.readElementText(QXmlStreamReader::SkipChildElements); // Skip } @@ -1003,29 +1077,30 @@ static void loadSessionDataHelper(QXmlStreamReader &r) r.readNext(); // Skip </tree> } -void DebuggerToolTipWidget::saveSessionData(QXmlStreamWriter &w) const +void DebuggerToolTipHolder::saveSessionData(QXmlStreamWriter &w) const { w.writeStartElement(QLatin1String(toolTipElementC)); QXmlStreamAttributes attributes; - attributes.append(QLatin1String(toolTipClassAttributeC), QString::fromLatin1(metaObject()->className())); - attributes.append(QLatin1String(fileNameAttributeC), m_context.fileName); - if (!m_context.function.isEmpty()) - attributes.append(QLatin1String(functionAttributeC), m_context.function); - attributes.append(QLatin1String(textPositionAttributeC), QString::number(m_context.position)); - attributes.append(QLatin1String(textLineAttributeC), QString::number(m_context.line)); - attributes.append(QLatin1String(textColumnAttributeC), QString::number(m_context.column)); - attributes.append(QLatin1String(dateAttributeC), m_creationDate.toString(QLatin1String("yyyyMMdd"))); - if (m_titleLabel->m_offset.x()) - attributes.append(QLatin1String(offsetXAttributeC), QString::number(m_titleLabel->m_offset.x())); - if (m_titleLabel->m_offset.y()) - attributes.append(QLatin1String(offsetYAttributeC), QString::number(m_titleLabel->m_offset.y())); - attributes.append(QLatin1String(engineTypeAttributeC), m_context.engineType); - attributes.append(QLatin1String(treeExpressionAttributeC), m_context.expression); - attributes.append(QLatin1String(treeInameAttributeC), QLatin1String(m_context.iname)); +// attributes.append(QLatin1String(toolTipClassAttributeC), QString::fromLatin1(metaObject()->className())); + attributes.append(QLatin1String(fileNameAttributeC), context.fileName); + if (!context.function.isEmpty()) + attributes.append(QLatin1String(functionAttributeC), context.function); + attributes.append(QLatin1String(textPositionAttributeC), QString::number(context.position)); + attributes.append(QLatin1String(textLineAttributeC), QString::number(context.line)); + attributes.append(QLatin1String(textColumnAttributeC), QString::number(context.column)); + attributes.append(QLatin1String(dateAttributeC), creationDate.toString(QLatin1String("yyyyMMdd"))); + QPoint offset = widget->titleLabel->m_offset; + if (offset.x()) + attributes.append(QLatin1String(offsetXAttributeC), QString::number(offset.x())); + if (offset.y()) + attributes.append(QLatin1String(offsetYAttributeC), QString::number(offset.y())); + attributes.append(QLatin1String(engineTypeAttributeC), context.engineType); + attributes.append(QLatin1String(treeExpressionAttributeC), context.expression); + attributes.append(QLatin1String(treeInameAttributeC), QLatin1String(context.iname)); w.writeAttributes(attributes); w.writeStartElement(QLatin1String(treeElementC)); - XmlWriterTreeModelVisitor v(&m_filterModel, w); + XmlWriterTreeModelVisitor v(&filterModel, w); v.run(); w.writeEndElement(); @@ -1047,18 +1122,16 @@ void DebuggerToolTipWidget::saveSessionData(QXmlStreamWriter &w) const (by file name and function) acquire the engine, others release. */ +static DebuggerToolTipManager *m_instance = 0; DebuggerToolTipManager::DebuggerToolTipManager() { + m_instance = this; } DebuggerToolTipManager::~DebuggerToolTipManager() { -} - -void DebuggerToolTipManager::registerEngine(DebuggerEngine *) -{ - loadSessionData(); + m_instance = 0; } void DebuggerToolTipManager::slotUpdateVisibleToolTips() @@ -1084,11 +1157,26 @@ void DebuggerToolTipManager::slotUpdateVisibleToolTips() } // Reposition and show all tooltips of that file. - foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips) { - if (tw->fileName() == fileName) - tw->positionShow(toolTipEditor->editorWidget()); + foreach (DebuggerToolTipHolder *tooltip, m_tooltips) { + if (tooltip->context.fileName == fileName) + tooltip->positionShow(toolTipEditor->editorWidget()); else - tw->hide(); + tooltip->widget->hide(); + } +} + +void DebuggerToolTipManager::slotItemIsExpanded(const QModelIndex &idx) +{ + foreach (DebuggerToolTipHolder *tooltip, m_tooltips) + tooltip->handleItemIsExpanded(idx); +} + +void DebuggerToolTipManager::slotColumnAdjustmentRequested() +{ + foreach (DebuggerToolTipHolder *tooltip, m_tooltips) { + QTC_ASSERT(tooltip, continue); + QTC_ASSERT(tooltip->widget, continue); + tooltip->widget->treeView->computeSize(); } } @@ -1111,17 +1199,42 @@ void DebuggerToolTipManager::updateEngine(DebuggerEngine *engine) function = frame.function; } } - foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips) - tw->handleStackFrameCompleted(fileName, function); - slotUpdateVisibleToolTips(); // Move out when stepping in same file. + foreach (DebuggerToolTipHolder *tooltip, m_tooltips) + tooltip->updateTooltip(fileName, function); + slotUpdateVisibleToolTips(); // Move tooltip when stepping in same file. +} + + +void DebuggerToolTipManager::registerEngine(DebuggerEngine *engine) +{ + DEBUG("REGISTER ENGINE"); + WatchModelBase *watchModel = engine->watchHandler()->model(); + connect(watchModel, &WatchModelBase::itemIsExpanded, + m_instance, &DebuggerToolTipManager::slotItemIsExpanded); + connect(watchModel, &WatchModelBase::columnAdjustmentRequested, + m_instance, &DebuggerToolTipManager::slotColumnAdjustmentRequested); } void DebuggerToolTipManager::deregisterEngine(DebuggerEngine *engine) { + DEBUG("DEREGISTER ENGINE"); QTC_ASSERT(engine, return); - foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips) - if (tw && tw->m_context.engineType == engine->objectName()) - tw->releaseEngine(); + + // FIXME: For now remove all. + purgeClosedToolTips(); + foreach (const DebuggerToolTipHolder *tooltip, m_tooltips) + tooltip->widget->close(); + purgeClosedToolTips(); + return; + + WatchModelBase *watchModel = engine->watchHandler()->model(); + disconnect(watchModel, &WatchModelBase::itemIsExpanded, + m_instance, &DebuggerToolTipManager::slotItemIsExpanded); + disconnect(watchModel, &WatchModelBase::columnAdjustmentRequested, + m_instance, &DebuggerToolTipManager::slotColumnAdjustmentRequested); + foreach (DebuggerToolTipHolder *tooltip, m_tooltips) + if (tooltip->context.engineType == engine->objectName()) + tooltip->releaseEngine(); saveSessionData(); } @@ -1130,20 +1243,6 @@ bool DebuggerToolTipManager::hasToolTips() return !m_tooltips.isEmpty(); } -void DebuggerToolTipManager::showToolTip - (const DebuggerToolTipContext &context, DebuggerEngine *engine) -{ - QTC_ASSERT(engine, return); - QTC_ASSERT(!context.expression.isEmpty(), qDebug(" BUT EMPTY"); return); - - DebuggerToolTipWidget *tw = findOrCreateWidget(context); - tw->setWatchModel(engine->watchHandler()->model()); - tw->acquireEngine(); - - const Utils::WidgetContent widgetContent(tw, true); - Utils::ToolTip::show(context.mousePosition, widgetContent, Internal::mainWindow()); -} - void DebuggerToolTipManager::sessionAboutToChange() { closeAllToolTips(); @@ -1151,6 +1250,8 @@ void DebuggerToolTipManager::sessionAboutToChange() void DebuggerToolTipManager::loadSessionData() { + return; // FIXME + const QString data = sessionValue(sessionSettingsKeyC).toString(); QXmlStreamReader r(data); r.readNextStartElement(); @@ -1161,6 +1262,8 @@ void DebuggerToolTipManager::loadSessionData() void DebuggerToolTipManager::saveSessionData() { + return; // FIXME + QString data; purgeClosedToolTips(); @@ -1168,9 +1271,9 @@ void DebuggerToolTipManager::saveSessionData() w.writeStartDocument(); w.writeStartElement(QLatin1String(sessionDocumentC)); w.writeAttribute(QLatin1String(sessionVersionAttributeC), QLatin1String("1.0")); - foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips) - if (tw->isPinned()) - tw->saveSessionData(w); + foreach (DebuggerToolTipHolder *tooltip, m_tooltips) + if (tooltip->widget->isPinned) + tooltip->saveSessionData(w); w.writeEndDocument(); setSessionValue(sessionSettingsKeyC, QVariant(data)); @@ -1178,12 +1281,18 @@ void DebuggerToolTipManager::saveSessionData() void DebuggerToolTipManager::closeAllToolTips() { - purgeClosedToolTips(); - foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips) - tw->close(); + foreach (DebuggerToolTipHolder *tooltip, m_tooltips) + tooltip->widget->close(); m_tooltips.clear(); } +void DebuggerToolTipManager::resetLocation() +{ + purgeClosedToolTips(); + foreach (DebuggerToolTipHolder *tooltip, m_tooltips) + tooltip->widget->pin(); +} + static void slotTooltipOverrideRequested (TextEditorWidget *editorWidget, const QPoint &point, int pos, bool *handled) { @@ -1208,29 +1317,49 @@ static void slotTooltipOverrideRequested context.expression = fixCppExpression(raw); if (context.expression.isEmpty()) { - const Utils::WidgetContent widgetContent(new QLabel(DebuggerToolTipManager::tr("No valid expression")), true); - Utils::ToolTip::show(context.mousePosition, widgetContent, Internal::mainWindow()); + const Utils::TextContent text(DebuggerToolTipManager::tr("No valid expression")); + Utils::ToolTip::show(context.mousePosition, text, Internal::mainWindow()); *handled = true; return; } // Prefer a filter on an existing local variable if it can be found. - if (const WatchData *localVariable = engine->watchHandler()->findCppLocalVariable(context.expression)) { + const WatchData *localVariable = engine->watchHandler()->findCppLocalVariable(context.expression); + if (localVariable) { context.expression = QLatin1String(localVariable->exp); if (context.expression.isEmpty()) context.expression = localVariable->name; context.iname = localVariable->iname; - DebuggerToolTipManager::showToolTip(context, engine); + } else { + context.iname = "tooltip." + context.expression.toLatin1().toHex(); + } + + DebuggerToolTipHolder *tooltip = findOrCreateTooltip(context); + if (tooltip->state == DebuggerToolTipHolder::Pending) { + DEBUG("FOUND PENDING TOOLTIP, WAITING..."); *handled = true; return; } - context.iname = "tooltip." + context.expression.toLatin1().toHex(); + tooltip->filterModel.setSourceModel(engine->watchHandler()->model()); + tooltip->widget->titleLabel->setText(DebuggerToolTipManager::tr("Updating")); + tooltip->setState(DebuggerToolTipHolder::Pending); - *handled = engine->setToolTipExpression(editorWidget, context); - - // Other tooltip, close all in case mouse never entered the tooltip - // and no leave was triggered. + if (localVariable) { + tooltip->acquireEngine(); + DEBUG("SYNC IN STATE" << tooltip->state); + const Utils::WidgetContent widgetContent(tooltip->widget, true); + Utils::ToolTip::show(context.mousePosition, widgetContent, Internal::mainWindow()); + *handled = true; + } else { + DEBUG("ASYNC TIP IN STATE" << tooltip->state); + *handled = engine->setToolTipExpression(editorWidget, context); + if (!*handled) { + const Utils::TextContent text(DebuggerToolTipManager::tr("Expression too complex")); + Utils::ToolTip::show(context.mousePosition, text, Internal::mainWindow()); + tooltip->widget->close(); + } + } } @@ -1284,13 +1413,14 @@ void DebuggerToolTipManager::leavingDebugMode() } } -DebuggerToolTipContexts DebuggerToolTipManager::treeWidgetExpressions - (DebuggerEngine *, const QString &fileName, const QString &function) +DebuggerToolTipContexts DebuggerToolTipManager::pendingTooltips(DebuggerEngine *engine) { + StackFrame frame = engine->stackHandler()->currentFrame(); DebuggerToolTipContexts rc; - foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips) { - if (tw && tw->context().matchesFrame(fileName, function)) - rc.push_back(tw->context()); + foreach (DebuggerToolTipHolder *tooltip, m_tooltips) { + if (tooltip->context.iname.startsWith("tooltip") + && tooltip->context.matchesFrame(frame.file, frame.function)) + rc.push_back(tooltip->context); } return rc; } @@ -1304,9 +1434,9 @@ bool DebuggerToolTipManager::eventFilter(QObject *o, QEvent *e) const QMoveEvent *me = static_cast<const QMoveEvent *>(e); const QPoint dist = me->pos() - me->oldPos(); purgeClosedToolTips(); - foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips) - if (tw->isVisible()) - tw->move(tw->pos() + dist); + foreach (DebuggerToolTipHolder *tooltip, m_tooltips) + if (tooltip->widget && tooltip->widget->isVisible()) + tooltip->widget->move(tooltip->widget->pos() + dist); } break; case QEvent::WindowStateChange: { // Hide/Show along with parent (toplevel) @@ -1315,8 +1445,8 @@ bool DebuggerToolTipManager::eventFilter(QObject *o, QEvent *e) const bool isMinimized = static_cast<const QWidget *>(o)->windowState() & Qt::WindowMinimized; if (wasMinimized ^ isMinimized) { purgeClosedToolTips(); - foreach (const QPointer<DebuggerToolTipWidget> &tw, m_tooltips) - tw->setVisible(!isMinimized); + foreach (DebuggerToolTipHolder *tooltip, m_tooltips) + tooltip->widget->setVisible(!isMinimized); } } break; @@ -1326,5 +1456,16 @@ bool DebuggerToolTipManager::eventFilter(QObject *o, QEvent *e) return false; } +static void purgeClosedToolTips() +{ + for (int i = m_tooltips.size(); --i >= 0; ) { + DebuggerToolTipHolder *tooltip = m_tooltips.at(i); + if (!tooltip || !tooltip->widget) { + DEBUG("PURGE TOOLTIP, LEFT: " << m_tooltips.size()); + m_tooltips.removeAt(i); + } + } +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/debuggertooltipmanager.h b/src/plugins/debugger/debuggertooltipmanager.h index 6fbc5480cc..a184a8b076 100644 --- a/src/plugins/debugger/debuggertooltipmanager.h +++ b/src/plugins/debugger/debuggertooltipmanager.h @@ -83,12 +83,7 @@ public: static void updateEngine(DebuggerEngine *engine); static bool hasToolTips(); - // Collect all expressions of DebuggerTreeViewToolTipWidget - static DebuggerToolTipContexts treeWidgetExpressions(DebuggerEngine *engine, - const QString &fileName, const QString &function = QString()); - - static void showToolTip(const DebuggerToolTipContext &context, - DebuggerEngine *engine); + static DebuggerToolTipContexts pendingTooltips(DebuggerEngine *engine); virtual bool eventFilter(QObject *, QEvent *); @@ -100,9 +95,12 @@ public: static void loadSessionData(); static void saveSessionData(); static void closeAllToolTips(); + static void resetLocation(); public slots: static void slotUpdateVisibleToolTips(); + void slotItemIsExpanded(const QModelIndex &idx); + void slotColumnAdjustmentRequested(); }; } // namespace Internal diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 979e4a00db..54a429933d 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -3632,43 +3632,16 @@ void GdbEngine::handleRegisterListValues(const GdbResponse &response) // ////////////////////////////////////////////////////////////////////// -//void GdbEngine::showToolTip() -//{ -// const QString expression = m_toolTipContext.expression; -// if (DebuggerToolTipManager::debug()) -// qDebug() << "GdbEngine::showToolTip " << expression << m_toolTipContext.iname << m_toolTipContext; - -// if (m_toolTipContext.iname.startsWith("tooltip") -// && (!boolSetting(UseToolTipsInMainEditor) -// || !watchHandler()->isValidToolTip(m_toolTipContext.iname))) { -// watchHandler()->removeData(m_toolTipContext.iname); -// return; -// } - -// DebuggerToolTipManager::showToolTip(m_toolTipContext, this); -//} - -void GdbEngine::resetLocation() -{ - m_toolTipContext.expression.clear(); - DebuggerEngine::resetLocation(); -} - bool GdbEngine::setToolTipExpression(TextEditor::TextEditorWidget *editor, const DebuggerToolTipContext &context) { - if (state() != InferiorStopOk || !isCppEditor(editor)) { - //qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED " - // " OR NOT A CPPEDITOR"; + if (state() != InferiorStopOk || !isCppEditor(editor)) return false; - } - - m_toolTipContext = context; - // qDebug() << "GdbEngine::setToolTipExpression2 " << exp << m_toolTipContext; UpdateParameters params; params.tryPartial = true; params.tooltipOnly = true; + params.tooltipExpression = context.expression; params.varList = context.iname; updateLocalsPython(params); return true; @@ -3736,10 +3709,6 @@ void GdbEngine::rebuildWatchModel() showMessage(_("<Rebuild Watchmodel %1>").arg(count), LogMiscInput); showStatusMessage(tr("Finished retrieving data"), 400); - if (m_toolTipContext.isValid()) { - DebuggerToolTipManager::showToolTip(m_toolTipContext, this); - m_toolTipContext = DebuggerToolTipContext(); - } DebuggerToolTipManager::updateEngine(this); } @@ -4829,42 +4798,16 @@ void GdbEngine::updateLocalsPython(const UpdateParameters ¶ms) + " displaystringlimit:" + action(DisplayStringLimit)->value().toByteArray(); - + // Re-create tooltip items that are not filters on existing local variables in + // the tooltip model. QByteArray watchers; - const QString fileName = stackHandler()->currentFrame().file; - const QString function = stackHandler()->currentFrame().function; - if (!fileName.isEmpty()) { - // Re-create tooltip items that are not filters on existing local variables in - // the tooltip model. - DebuggerToolTipContexts toolTips = - DebuggerToolTipManager::treeWidgetExpressions(this, fileName, function); - - const QString currentExpression = m_toolTipContext.expression; - if (!currentExpression.isEmpty()) { - int currentIndex = -1; - for (int i = 0; i < toolTips.size(); ++i) { - if (toolTips.at(i).expression == currentExpression) { - currentIndex = i; - break; - } - } - if (currentIndex < 0) { - DebuggerToolTipContext context; - context.expression = currentExpression; - context.iname = tooltipIName(currentExpression); - toolTips.push_back(context); - } - } - - foreach (const DebuggerToolTipContext &p, toolTips) { - if (p.iname.startsWith("tooltip")) { - if (!watchers.isEmpty()) - watchers += "##"; - watchers += p.expression.toLatin1(); - watchers += '#'; - watchers += p.iname; - } - } + DebuggerToolTipContexts toolTips = DebuggerToolTipManager::pendingTooltips(this); + foreach (const DebuggerToolTipContext &p, toolTips) { + if (!watchers.isEmpty()) + watchers += "##"; + watchers += p.expression.toLatin1(); + watchers += '#'; + watchers += p.iname; } QHash<QByteArray, int> watcherNames = handler->watcherNames(); diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 4f953e8d69..bcae9fc78e 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -298,7 +298,6 @@ private: ////////// View & Data Stuff ////////// void selectThread(ThreadId threadId); void activateFrame(int index); - void resetLocation(); // // Breakpoint specific stuff @@ -469,7 +468,6 @@ protected: void showExecutionError(const QString &message); static QByteArray tooltipIName(const QString &exp); - DebuggerToolTipContext m_toolTipContext; // For short-circuiting stack and thread list evaluation. bool m_stackNeeded; diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index afb1afe377..0169d80017 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -74,11 +74,6 @@ using namespace Utils; namespace Debugger { namespace Internal { -static QByteArray tooltipIName(const QString &exp) -{ - return "tooltip." + exp.toLatin1().toHex(); -} - /////////////////////////////////////////////////////////////////////// // // LldbEngine @@ -815,41 +810,25 @@ void LldbEngine::refreshSymbols(const GdbMi &symbols) // ////////////////////////////////////////////////////////////////////// -static WatchData m_toolTip; -static QPoint m_toolTipPos; -static QHash<QString, WatchData> m_toolTipCache; - -void LldbEngine::showToolTip() -{ - if (m_toolTipContext.expression.isEmpty()) - return; - //const QString expression = m_toolTipContext->expression; - // qDebug() << "LldbEngine::showToolTip " << expression << m_toolTipContext->iname << (*m_toolTipContext); - - DebuggerToolTipManager::showToolTip(m_toolTipContext, this); - // Prevent tooltip from re-occurring (classic GDB, QTCREATORBUG-4711). - m_toolTipContext.expression.clear(); -} - void LldbEngine::resetLocation() { - m_toolTipContext.expression.clear(); DebuggerEngine::resetLocation(); } bool LldbEngine::setToolTipExpression(TextEditor::TextEditorWidget *editorWidget, const DebuggerToolTipContext &context) { + return false; // FIXME + if (state() != InferiorStopOk || !isCppEditor(editorWidget)) { //qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED " // " OR NOT A CPPEDITOR"; return false; } - m_toolTipContext = context; - UpdateParameters params; params.tryPartial = true; params.tooltipOnly = true; + params.tooltipExpression = context.expression; params.varList = context.iname; doUpdateLocals(params); @@ -924,6 +903,7 @@ void LldbEngine::doUpdateLocals(UpdateParameters params) cmd.arg("tooltiponly", params.tooltipOnly); cmd.beginList("watchers"); + // Watchers QHashIterator<QByteArray, int> it(WatchHandler::watcherNames()); while (it.hasNext()) { @@ -933,38 +913,16 @@ void LldbEngine::doUpdateLocals(UpdateParameters params) .arg("exp", it.key().toHex()) .endGroup(); } - // Tooltip - const StackFrame frame = stackHandler()->currentFrame(); - if (!frame.file.isEmpty()) { - // Re-create tooltip items that are not filters on existing local variables in - // the tooltip model. - DebuggerToolTipContexts toolTips = - DebuggerToolTipManager::treeWidgetExpressions(this, frame.file, frame.function); - - const QString currentExpression = m_toolTipContext.expression; - if (!currentExpression.isEmpty()) { - int currentIndex = -1; - for (int i = 0; i < toolTips.size(); ++i) { - if (toolTips.at(i).expression == currentExpression) { - currentIndex = i; - break; - } - } - if (currentIndex < 0) { - DebuggerToolTipContext context; - context.expression = currentExpression; - context.iname = tooltipIName(currentExpression); - toolTips.push_back(context); - } - } - foreach (const DebuggerToolTipContext &p, toolTips) { - if (p.iname.startsWith("tooltip")) - cmd.beginGroup() - .arg("iname", p.iname) - .arg("exp", p.expression.toLatin1().toHex()) - .endGroup(); - } + + // Tooltips + DebuggerToolTipContexts toolTips = DebuggerToolTipManager::pendingTooltips(this); + foreach (const DebuggerToolTipContext &p, toolTips) { + cmd.beginGroup() + .arg("iname", p.iname) + .arg("exp", p.expression.toLatin1().toHex()) + .endGroup(); } + cmd.endList(); //cmd.arg("resultvarname", m_resultVarName); @@ -1083,7 +1041,7 @@ void LldbEngine::refreshLocals(const GdbMi &vars) } handler->insertData(list); - showToolTip(); + DebuggerToolTipManager::updateEngine(this); } void LldbEngine::refreshStack(const GdbMi &stack) diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h index 955e58fa1d..cb4ce7fc7b 100644 --- a/src/plugins/debugger/lldb/lldbengine.h +++ b/src/plugins/debugger/lldb/lldbengine.h @@ -218,9 +218,6 @@ private: QMap<QPointer<DisassemblerAgent>, int> m_disassemblerAgents; QMap<QPointer<MemoryAgent>, int> m_memoryAgents; QHash<int, QPointer<QObject> > m_memoryAgentTokens; - DebuggerToolTipContext m_toolTipContext; - - void showToolTip(); // Console handling. Q_SLOT void stubError(const QString &msg); diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 0070f3567d..05afb7c061 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -2015,10 +2015,10 @@ const WatchData *WatchHandler::findCppLocalVariable(const QString &name) const QByteArray iname = localsPrefix + name.toLatin1(); if (const WatchData *wd = findData(iname)) return wd; - // Nope, try a 'local.this.m_foo'. - iname.insert(localsPrefix.size(), "this."); - if (const WatchData *wd = findData(iname)) - return wd; +// // Nope, try a 'local.this.m_foo'. +// iname.insert(localsPrefix.size(), "this."); +// if (const WatchData *wd = findData(iname)) +// return wd; return 0; } diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h index e34578bca8..987095c375 100644 --- a/src/plugins/debugger/watchhandler.h +++ b/src/plugins/debugger/watchhandler.h @@ -121,6 +121,7 @@ public: bool tryPartial; bool tooltipOnly; QByteArray varList; + QString tooltipExpression; }; typedef QHash<QString, QStringList> DumperTypeFormats; // Type name -> Dumper Formats |