Commit f0b2d653 authored by hjk's avatar hjk

Debugger: Rework editor tooltips handling

Fix expansion and updating.

Persistence and non-locals are still lacking.

Change-Id: I74e25199d50350516afc686a05836e239bfc8acb
Reviewed-by: default avatarJoerg Bornemann <joerg.bornemann@digia.com>
Reviewed-by: default avatarhjk <hjk121@nokiamail.com>
parent a97aa6be
...@@ -1968,8 +1968,10 @@ void CdbEngine::handleLocals(const CdbExtensionCommandPtr &reply) ...@@ -1968,8 +1968,10 @@ void CdbEngine::handleLocals(const CdbExtensionCommandPtr &reply)
foreach (const WatchData &wd, watchData) foreach (const WatchData &wd, watchData)
nsp << wd.toString() <<'\n'; nsp << wd.toString() <<'\n';
} }
if (flags & LocalsUpdateForNewFrame) if (flags & LocalsUpdateForNewFrame) {
emit stackFrameCompleted(); emit stackFrameCompleted();
DebuggerToolTipManager::updateEngine(this);
}
} else { } else {
showMessage(QString::fromLatin1(reply->errorMessage), LogWarning); showMessage(QString::fromLatin1(reply->errorMessage), LogWarning);
} }
......
...@@ -60,7 +60,6 @@ class BreakHandler; ...@@ -60,7 +60,6 @@ class BreakHandler;
class SnapshotHandler; class SnapshotHandler;
class Symbol; class Symbol;
class Section; class Section;
class DebuggerToolTipManager;
class GlobalDebuggerOptions; class GlobalDebuggerOptions;
enum TestCases enum TestCases
...@@ -120,7 +119,6 @@ public: ...@@ -120,7 +119,6 @@ public:
virtual QStringList stringListSetting(int code) const = 0; virtual QStringList stringListSetting(int code) const = 0;
virtual void setThreads(const QStringList &list, int index) = 0; virtual void setThreads(const QStringList &list, int index) = 0;
virtual DebuggerToolTipManager *toolTipManager() const = 0;
virtual QSharedPointer<GlobalDebuggerOptions> globalDebuggerOptions() const = 0; virtual QSharedPointer<GlobalDebuggerOptions> globalDebuggerOptions() const = 0;
static QTreeView *inspectorView(); static QTreeView *inspectorView();
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "debuggerrunner.h" #include "debuggerrunner.h"
#include "debuggerstringutils.h" #include "debuggerstringutils.h"
#include "debuggerstartparameters.h" #include "debuggerstartparameters.h"
#include "debuggertooltipmanager.h"
#include "breakhandler.h" #include "breakhandler.h"
#include "disassembleragent.h" #include "disassembleragent.h"
...@@ -1176,11 +1177,16 @@ void DebuggerEngine::setState(DebuggerState state, bool forced) ...@@ -1176,11 +1177,16 @@ void DebuggerEngine::setState(DebuggerState state, bool forced)
if (!forced && !isAllowedTransition(oldState, state)) if (!forced && !isAllowedTransition(oldState, state))
qDebug() << "*** UNEXPECTED STATE TRANSITION: " << this << msg; qDebug() << "*** UNEXPECTED STATE TRANSITION: " << this << msg;
if (state == EngineRunRequested) {
DebuggerToolTipManager::registerEngine(this);
}
if (state == DebuggerFinished) { if (state == DebuggerFinished) {
// Give up ownership on claimed breakpoints. // Give up ownership on claimed breakpoints.
BreakHandler *handler = breakHandler(); BreakHandler *handler = breakHandler();
foreach (BreakpointModelId id, handler->engineBreakpointIds(this)) foreach (BreakpointModelId id, handler->engineBreakpointIds(this))
handler->notifyBreakpointReleased(id); handler->notifyBreakpointReleased(id);
DebuggerToolTipManager::deregisterEngine(this);
} }
showMessage(msg, LogDebug); showMessage(msg, LogDebug);
......
...@@ -1202,7 +1202,6 @@ public slots: ...@@ -1202,7 +1202,6 @@ public slots:
bool parseArguments(const QStringList &args, QString *errorMessage); bool parseArguments(const QStringList &args, QString *errorMessage);
void parseCommandLineArguments(); void parseCommandLineArguments();
DebuggerToolTipManager *toolTipManager() const { return m_toolTipManager; }
QSharedPointer<GlobalDebuggerOptions> globalDebuggerOptions() const { return m_globalDebuggerOptions; } QSharedPointer<GlobalDebuggerOptions> globalDebuggerOptions() const { return m_globalDebuggerOptions; }
void updateQmlActions() { void updateQmlActions() {
...@@ -2526,7 +2525,7 @@ void DebuggerPluginPrivate::sessionLoaded() ...@@ -2526,7 +2525,7 @@ void DebuggerPluginPrivate::sessionLoaded()
{ {
m_breakHandler->loadSessionData(); m_breakHandler->loadSessionData();
dummyEngine()->watchHandler()->loadSessionData(); dummyEngine()->watchHandler()->loadSessionData();
m_toolTipManager->loadSessionData(); DebuggerToolTipManager::loadSessionData();
} }
void DebuggerPluginPrivate::aboutToUnloadSession() void DebuggerPluginPrivate::aboutToUnloadSession()
...@@ -2537,8 +2536,8 @@ void DebuggerPluginPrivate::aboutToUnloadSession() ...@@ -2537,8 +2536,8 @@ void DebuggerPluginPrivate::aboutToUnloadSession()
void DebuggerPluginPrivate::aboutToSaveSession() void DebuggerPluginPrivate::aboutToSaveSession()
{ {
dummyEngine()->watchHandler()->saveSessionData(); dummyEngine()->watchHandler()->saveSessionData();
m_toolTipManager->saveSessionData();
m_breakHandler->saveSessionData(); m_breakHandler->saveSessionData();
DebuggerToolTipManager::saveSessionData();
} }
void DebuggerPluginPrivate::showStatusMessage(const QString &msg0, int timeout) void DebuggerPluginPrivate::showStatusMessage(const QString &msg0, int timeout)
......
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
#include "debuggerrunconfigurationaspect.h" #include "debuggerrunconfigurationaspect.h"
#include "debuggerstartparameters.h" #include "debuggerstartparameters.h"
#include "debuggerstringutils.h" #include "debuggerstringutils.h"
#include "debuggertooltipmanager.h"
#include "breakhandler.h" #include "breakhandler.h"
#include "shared/peutils.h" #include "shared/peutils.h"
...@@ -136,9 +135,7 @@ DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration, ...@@ -136,9 +135,7 @@ DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration,
QString errorMessage; QString errorMessage;
d->m_engine = DebuggerRunControlFactory::createEngine(sp.masterEngineType, sp, &errorMessage); d->m_engine = DebuggerRunControlFactory::createEngine(sp.masterEngineType, sp, &errorMessage);
if (d->m_engine) { if (!d->m_engine) {
DebuggerToolTipManager::registerEngine(d->m_engine);
} else {
debuggingFinished(); debuggingFinished();
Core::ICore::showWarningWithOptions(DebuggerRunControl::tr("Debugger"), errorMessage); Core::ICore::showWarningWithOptions(DebuggerRunControl::tr("Debugger"), errorMessage);
} }
......
...@@ -52,14 +52,17 @@ class DebuggerToolTipContext ...@@ -52,14 +52,17 @@ class DebuggerToolTipContext
{ {
public: public:
DebuggerToolTipContext(); DebuggerToolTipContext();
static DebuggerToolTipContext fromEditor(Core::IEditor *ed, int pos); bool isValid() const { return !expression.isEmpty(); }
bool isValid() const { return !fileName.isEmpty(); } bool matchesFrame(const QString &frameFile, const QString &frameFunction) const;
bool isSame(const DebuggerToolTipContext &other) const;
QString fileName; QString fileName;
int position; int position;
int line; int line;
int column; int column;
QString function; //!< Optional function. This must be set by the engine as it is language-specific. QString function; //!< Optional function. This must be set by the engine as it is language-specific.
QString engineType;
QDate creationDate;
QPoint mousePosition; QPoint mousePosition;
QString expression; QString expression;
...@@ -85,7 +88,6 @@ private slots: ...@@ -85,7 +88,6 @@ private slots:
void computeSize(); void computeSize();
void expandNode(const QModelIndex &idx); void expandNode(const QModelIndex &idx);
void collapseNode(const QModelIndex &idx); void collapseNode(const QModelIndex &idx);
void handleItemIsExpanded(const QModelIndex &sourceIdx);
private: private:
int computeHeight(const QModelIndex &index) const; int computeHeight(const QModelIndex &index) const;
...@@ -102,37 +104,40 @@ public: ...@@ -102,37 +104,40 @@ public:
~DebuggerToolTipManager(); ~DebuggerToolTipManager();
static void registerEngine(DebuggerEngine *engine); static void registerEngine(DebuggerEngine *engine);
static void deregisterEngine(DebuggerEngine *engine);
static void updateEngine(DebuggerEngine *engine);
static bool hasToolTips(); static bool hasToolTips();
// Collect all expressions of DebuggerTreeViewToolTipWidget // Collect all expressions of DebuggerTreeViewToolTipWidget
static DebuggerToolTipContexts treeWidgetExpressions(const QString &fileName, static DebuggerToolTipContexts treeWidgetExpressions(DebuggerEngine *engine,
const QString &engineType = QString(), const QString &fileName, const QString &function = QString());
const QString &function= QString());
static void showToolTip(const DebuggerToolTipContext &context, static void showToolTip(const DebuggerToolTipContext &context,
DebuggerEngine *engine); DebuggerEngine *engine);
virtual bool eventFilter(QObject *, QEvent *); virtual bool eventFilter(QObject *, QEvent *);
static bool debug(); static QString treeModelClipboardContents(const QAbstractItemModel *model);
static QString treeModelClipboardContents(const QAbstractItemModel *m);
public slots: public slots:
void debugModeEntered(); void debugModeEntered();
void leavingDebugMode(); void leavingDebugMode();
void sessionAboutToChange(); void sessionAboutToChange();
void loadSessionData(); static void loadSessionData();
void saveSessionData(); static void saveSessionData();
static void closeAllToolTips(); static void closeAllToolTips();
void hide(); static void hide();
private slots: private slots:
void slotUpdateVisibleToolTips(); static void slotUpdateVisibleToolTips();
void slotDebuggerStateChanged(Debugger::DebuggerState); void slotDebuggerStateChanged(Debugger::DebuggerState);
void slotStackFrameCompleted();
void slotEditorOpened(Core::IEditor *); void slotEditorOpened(Core::IEditor *);
void slotTooltipOverrideRequested(TextEditor::ITextEditor *editor, void slotTooltipOverrideRequested(TextEditor::ITextEditor *editor,
const QPoint &point, int pos, bool *handled); const QPoint &point, int pos, bool *handled);
private:
bool tryHandleToolTipOverride(TextEditor::ITextEditor *editor,
const QPoint &point, int pos);
}; };
} // namespace Internal } // namespace Internal
......
...@@ -3629,39 +3629,30 @@ void GdbEngine::handleRegisterListValues(const GdbResponse &response) ...@@ -3629,39 +3629,30 @@ void GdbEngine::handleRegisterListValues(const GdbResponse &response)
// //
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
void GdbEngine::showToolTip() //void GdbEngine::showToolTip()
{ //{
if (m_toolTipContext.isNull()) // const QString expression = m_toolTipContext.expression;
return; // if (DebuggerToolTipManager::debug())
const QString expression = m_toolTipContext->expression; // qDebug() << "GdbEngine::showToolTip " << expression << m_toolTipContext.iname << m_toolTipContext;
if (DebuggerToolTipManager::debug())
qDebug() << "GdbEngine::showToolTip " << expression << m_toolTipContext->iname << (*m_toolTipContext); // if (m_toolTipContext.iname.startsWith("tooltip")
// && (!debuggerCore()->boolSetting(UseToolTipsInMainEditor)
if (m_toolTipContext->iname.startsWith("tooltip") // || !watchHandler()->isValidToolTip(m_toolTipContext.iname))) {
&& (!debuggerCore()->boolSetting(UseToolTipsInMainEditor) // watchHandler()->removeData(m_toolTipContext.iname);
|| !watchHandler()->isValidToolTip(m_toolTipContext->iname))) { // return;
watchHandler()->removeData(m_toolTipContext->iname); // }
return;
} // DebuggerToolTipManager::showToolTip(m_toolTipContext, this);
//}
DebuggerToolTipManager::showToolTip(*m_toolTipContext, this);
// Prevent tooltip from re-occurring (classic GDB, QTCREATORBUG-4711).
m_toolTipContext.reset();
}
QString GdbEngine::tooltipExpression() const
{
return m_toolTipContext.isNull() ? QString() : m_toolTipContext->expression;
}
void GdbEngine::resetLocation() void GdbEngine::resetLocation()
{ {
m_toolTipContext.reset(); m_toolTipContext.expression.clear();
DebuggerEngine::resetLocation(); DebuggerEngine::resetLocation();
} }
bool GdbEngine::setToolTipExpression(TextEditor::ITextEditor *editor, bool GdbEngine::setToolTipExpression(TextEditor::ITextEditor *editor,
const DebuggerToolTipContext &contextIn) const DebuggerToolTipContext &context)
{ {
if (state() != InferiorStopOk || !isCppEditor(editor)) { if (state() != InferiorStopOk || !isCppEditor(editor)) {
//qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED " //qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED "
...@@ -3669,45 +3660,13 @@ bool GdbEngine::setToolTipExpression(TextEditor::ITextEditor *editor, ...@@ -3669,45 +3660,13 @@ bool GdbEngine::setToolTipExpression(TextEditor::ITextEditor *editor,
return false; return false;
} }
DebuggerToolTipContext context = contextIn; m_toolTipContext = context;
int line, column; // qDebug() << "GdbEngine::setToolTipExpression2 " << exp << m_toolTipContext;
QString exp = fixCppExpression(cppExpressionAt(editor, context.position, &line, &column, &context.function));
if (exp.isEmpty())
return false;
// Prefer a filter on an existing local variable if it can be found.
QByteArray iname;
if (const WatchData *localVariable = watchHandler()->findCppLocalVariable(exp)) {
exp = QLatin1String(localVariable->exp);
iname = localVariable->iname;
} else {
iname = tooltipIName(exp);
}
if (DebuggerToolTipManager::debug())
qDebug() << "GdbEngine::setToolTipExpression1 " << exp << iname << context;
// Same expression: Display synchronously.
if (!m_toolTipContext.isNull() && m_toolTipContext->expression == exp) {
showToolTip();
return true;
}
m_toolTipContext.reset(new DebuggerToolTipContext(context));
m_toolTipContext->expression = exp;
m_toolTipContext->iname = iname;
// Local variable: Display synchronously.
if (iname.startsWith("local")) {
showToolTip();
return true;
}
if (DebuggerToolTipManager::debug())
qDebug() << "GdbEngine::setToolTipExpression2 " << exp << (*m_toolTipContext);
UpdateParameters params; UpdateParameters params;
params.tryPartial = true; params.tryPartial = true;
params.tooltipOnly = true; params.tooltipOnly = true;
params.varList = iname; params.varList = context.iname;
updateLocalsPython(params); updateLocalsPython(params);
return true; return true;
} }
...@@ -3773,7 +3732,12 @@ void GdbEngine::rebuildWatchModel() ...@@ -3773,7 +3732,12 @@ void GdbEngine::rebuildWatchModel()
showMessage(LogWindow::logTimeStamp(), LogMiscInput); showMessage(LogWindow::logTimeStamp(), LogMiscInput);
showMessage(_("<Rebuild Watchmodel %1>").arg(count), LogMiscInput); showMessage(_("<Rebuild Watchmodel %1>").arg(count), LogMiscInput);
showStatusMessage(tr("Finished retrieving data"), 400); showStatusMessage(tr("Finished retrieving data"), 400);
showToolTip();
if (m_toolTipContext.isValid()) {
DebuggerToolTipManager::showToolTip(m_toolTipContext, this);
m_toolTipContext = DebuggerToolTipContext();
}
DebuggerToolTipManager::updateEngine(this);
} }
void GdbEngine::handleVarAssign(const GdbResponse &) void GdbEngine::handleVarAssign(const GdbResponse &)
...@@ -4875,9 +4839,9 @@ void GdbEngine::updateLocalsPython(const UpdateParameters &params) ...@@ -4875,9 +4839,9 @@ void GdbEngine::updateLocalsPython(const UpdateParameters &params)
// Re-create tooltip items that are not filters on existing local variables in // Re-create tooltip items that are not filters on existing local variables in
// the tooltip model. // the tooltip model.
DebuggerToolTipContexts toolTips = DebuggerToolTipContexts toolTips =
DebuggerToolTipManager::treeWidgetExpressions(fileName, objectName(), function); DebuggerToolTipManager::treeWidgetExpressions(this, fileName, function);
const QString currentExpression = tooltipExpression(); const QString currentExpression = m_toolTipContext.expression;
if (!currentExpression.isEmpty()) { if (!currentExpression.isEmpty()) {
int currentIndex = -1; int currentIndex = -1;
for (int i = 0; i < toolTips.size(); ++i) { for (int i = 0; i < toolTips.size(); ++i) {
...@@ -5015,8 +4979,10 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response) ...@@ -5015,8 +4979,10 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response)
//PENDING_DEBUG("\n\n .... AND TRIGGERS MODEL UPDATE\n"); //PENDING_DEBUG("\n\n .... AND TRIGGERS MODEL UPDATE\n");
rebuildWatchModel(); rebuildWatchModel();
//} //}
if (!partial) if (!partial) {
emit stackFrameCompleted(); emit stackFrameCompleted();
DebuggerToolTipManager::updateEngine(this);
}
} else { } else {
showMessage(_("DUMPER FAILED: " + response.toString())); showMessage(_("DUMPER FAILED: " + response.toString()));
} }
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <debugger/watchhandler.h> #include <debugger/watchhandler.h>
#include <debugger/watchutils.h> #include <debugger/watchutils.h>
#include <debugger/debuggertooltipmanager.h>
#include <coreplugin/id.h> #include <coreplugin/id.h>
...@@ -467,8 +468,7 @@ protected: ...@@ -467,8 +468,7 @@ protected:
void showExecutionError(const QString &message); void showExecutionError(const QString &message);
static QByteArray tooltipIName(const QString &exp); static QByteArray tooltipIName(const QString &exp);
QString tooltipExpression() const; DebuggerToolTipContext m_toolTipContext;
QScopedPointer<DebuggerToolTipContext> m_toolTipContext;
// For short-circuiting stack and thread list evaluation. // For short-circuiting stack and thread list evaluation.
bool m_stackNeeded; bool m_stackNeeded;
......
...@@ -821,31 +821,23 @@ static QHash<QString, WatchData> m_toolTipCache; ...@@ -821,31 +821,23 @@ static QHash<QString, WatchData> m_toolTipCache;
void LldbEngine::showToolTip() void LldbEngine::showToolTip()
{ {
if (m_toolTipContext.isNull()) if (m_toolTipContext.expression.isEmpty())
return; return;
const QString expression = m_toolTipContext->expression; //const QString expression = m_toolTipContext->expression;
if (DebuggerToolTipManager::debug()) // qDebug() << "LldbEngine::showToolTip " << expression << m_toolTipContext->iname << (*m_toolTipContext);
qDebug() << "LldbEngine::showToolTip " << expression << m_toolTipContext->iname << (*m_toolTipContext);
if (m_toolTipContext->iname.startsWith("tooltip")
&& (!debuggerCore()->boolSetting(UseToolTipsInMainEditor)
|| !watchHandler()->isValidToolTip(m_toolTipContext->iname))) {
watchHandler()->removeData(m_toolTipContext->iname);
return;
}
DebuggerToolTipManager::showToolTip(*m_toolTipContext, this); DebuggerToolTipManager::showToolTip(m_toolTipContext, this);
// Prevent tooltip from re-occurring (classic GDB, QTCREATORBUG-4711). // Prevent tooltip from re-occurring (classic GDB, QTCREATORBUG-4711).
m_toolTipContext.reset(); m_toolTipContext.expression.clear();
} }
void LldbEngine::resetLocation() void LldbEngine::resetLocation()
{ {
m_toolTipContext.reset(); m_toolTipContext.expression.clear();
DebuggerEngine::resetLocation(); DebuggerEngine::resetLocation();
} }
bool LldbEngine::setToolTipExpression(TextEditor::ITextEditor *editor, const DebuggerToolTipContext &contextIn) bool LldbEngine::setToolTipExpression(TextEditor::ITextEditor *editor, const DebuggerToolTipContext &context)
{ {
if (state() != InferiorStopOk || !isCppEditor(editor)) { if (state() != InferiorStopOk || !isCppEditor(editor)) {
//qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED " //qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED "
...@@ -853,45 +845,12 @@ bool LldbEngine::setToolTipExpression(TextEditor::ITextEditor *editor, const Deb ...@@ -853,45 +845,12 @@ bool LldbEngine::setToolTipExpression(TextEditor::ITextEditor *editor, const Deb
return false; return false;
} }
DebuggerToolTipContext context = contextIn; m_toolTipContext = context;
int line, column;
QString exp = fixCppExpression(cppExpressionAt(editor, context.position, &line, &column, &context.function));
if (exp.isEmpty())
return false;
// Prefer a filter on an existing local variable if it can be found.
QByteArray iname;
if (const WatchData *localVariable = watchHandler()->findCppLocalVariable(exp)) {
exp = QLatin1String(localVariable->exp);
iname = localVariable->iname;
} else {
iname = tooltipIName(exp);
}
if (DebuggerToolTipManager::debug())
qDebug() << "GdbEngine::setToolTipExpression1 " << exp << iname << context;
// Same expression: Display synchronously.
if (!m_toolTipContext.isNull() && m_toolTipContext->expression == exp) {
showToolTip();
return true;
}
m_toolTipContext.reset(new DebuggerToolTipContext(context));
m_toolTipContext->expression = exp;
m_toolTipContext->iname = iname;
// Local variable: Display synchronously.
if (iname.startsWith("local")) {
showToolTip();
return true;
}
if (DebuggerToolTipManager::debug())
qDebug() << "GdbEngine::setToolTipExpression2 " << exp << (*m_toolTipContext);
UpdateParameters params; UpdateParameters params;
params.tryPartial = true; params.tryPartial = true;
params.tooltipOnly = true; params.tooltipOnly = true;
params.varList = iname; params.varList = context.iname;
doUpdateLocals(params); doUpdateLocals(params);
return true; return true;
...@@ -980,10 +939,9 @@ void LldbEngine::doUpdateLocals(UpdateParameters params) ...@@ -980,10 +939,9 @@ void LldbEngine::doUpdateLocals(UpdateParameters params)
// Re-create tooltip items that are not filters on existing local variables in // Re-create tooltip items that are not filters on existing local variables in
// the tooltip model. // the tooltip model.
DebuggerToolTipContexts toolTips = DebuggerToolTipContexts toolTips =
DebuggerToolTipManager::treeWidgetExpressions(frame.file, objectName(), frame.function); DebuggerToolTipManager::treeWidgetExpressions(this, frame.file, frame.function);
const QString currentExpression = const QString currentExpression = m_toolTipContext.expression;
m_toolTipContext.isNull() ? QString() : m_toolTipContext->expression;
if (!currentExpression.isEmpty()) { if (!currentExpression.isEmpty()) {
int currentIndex = -1; int currentIndex = -1;
for (int i = 0; i < toolTips.size(); ++i) { for (int i = 0; i < toolTips.size(); ++i) {
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@