Debugger: Split ToolTipManager into per-engine parts

Change-Id: If2e601a91ad2a0e5ba30916a5d1f2312ecff944f
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
hjk
2018-08-23 15:21:43 +02:00
parent e1e1790402
commit 893146b8b6
8 changed files with 172 additions and 117 deletions

View File

@@ -31,7 +31,6 @@
#include "debuggerinternalconstants.h"
#include "debuggermainwindow.h"
#include "debuggerprotocol.h"
#include "snapshothandler.h"
#include "sourceutils.h"
#include "stackhandler.h"
#include "watchhandler.h"
@@ -41,9 +40,12 @@
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/documentmodel.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/modemanager.h>
#include <cpptools/cppprojectfile.h>
#include <projectexplorer/session.h>
#include <texteditor/texteditor.h>
#include <texteditor/textdocument.h>
@@ -71,6 +73,7 @@
#include <QXmlStreamWriter>
using namespace Core;
using namespace ProjectExplorer;
using namespace TextEditor;
using namespace Utils;
@@ -106,11 +109,49 @@ const char treeInameAttributeC[] = "iname";
// const char modelRowElementC[] = "row";
const char modelItemElementC[] = "item";
static void purgeClosedToolTips();
class DebuggerToolTipHolder;
static QVector<DebuggerToolTipHolder *> m_tooltips;
static bool m_debugModeActive;
class DebuggerToolTipManagerPrivate : public QObject
{
public:
explicit DebuggerToolTipManagerPrivate(DebuggerEngine *engine);
void slotTooltipOverrideRequested(TextEditor::TextEditorWidget *editorWidget,
const QPoint &point, int pos, bool *handled);
void slotEditorOpened(Core::IEditor *e);
void hideAllToolTips();
void purgeClosedToolTips();
void onModeChanged(Id mode)
{
if (mode == Constants::MODE_DEBUG) {
// if (EngineManager::engines().isEmpty())
// DebuggerMainWindow::instance()->restorePerspective(Constants::PRESET_PERSPRECTIVE_ID);
debugModeEntered();
} else {
leavingDebugMode();
}
}
void setupEditors();
void debugModeEntered();
void leavingDebugMode();
void sessionAboutToChange();
void loadSessionData();
void saveSessionData();
void updateVisibleToolTips();
void closeAllToolTips();
bool eventFilter(QObject *, QEvent *) override;
public:
DebuggerEngine *m_engine;
QVector<DebuggerToolTipHolder *> m_tooltips;
bool m_debugModeActive = false;
};
// Forward a stream reader across end elements looking for the
// next start element of a desired type.
@@ -652,10 +693,10 @@ public:
DebuggerTooltipState state;
};
static void hideAllToolTips()
void DebuggerToolTipManagerPrivate::hideAllToolTips()
{
purgeClosedToolTips();
foreach (const DebuggerToolTipHolder *tooltip, m_tooltips)
for (const DebuggerToolTipHolder *tooltip : qAsConst(m_tooltips))
tooltip->widget->hide();
}
@@ -950,19 +991,17 @@ void DebuggerToolTipHolder::saveSessionData(QXmlStreamWriter &w) const
(by file name and function) acquire the engine, others release.
*/
static DebuggerToolTipManager *m_instance = nullptr;
DebuggerToolTipManager::DebuggerToolTipManager()
DebuggerToolTipManager::DebuggerToolTipManager(DebuggerEngine *engine)
: d(new DebuggerToolTipManagerPrivate(engine))
{
m_instance = this;
}
DebuggerToolTipManager::~DebuggerToolTipManager()
{
m_instance = nullptr;
delete d;
}
void DebuggerToolTipManager::updateVisibleToolTips()
void DebuggerToolTipManagerPrivate::updateVisibleToolTips()
{
purgeClosedToolTips();
if (m_tooltips.isEmpty())
@@ -985,7 +1024,7 @@ void DebuggerToolTipManager::updateVisibleToolTips()
}
// Reposition and show all tooltips of that file.
foreach (DebuggerToolTipHolder *tooltip, m_tooltips) {
for (DebuggerToolTipHolder *tooltip : qAsConst(m_tooltips)) {
if (tooltip->context.fileName == fileName)
tooltip->positionShow(toolTipEditor->editorWidget());
else
@@ -993,56 +1032,48 @@ void DebuggerToolTipManager::updateVisibleToolTips()
}
}
void DebuggerToolTipManager::updateEngine(DebuggerEngine *engine)
void DebuggerToolTipManager::updateToolTips()
{
QTC_ASSERT(engine, return);
purgeClosedToolTips();
if (m_tooltips.isEmpty())
d->purgeClosedToolTips();
if (d->m_tooltips.isEmpty())
return;
// Stack frame changed: All tooltips of that file acquire the engine,
// all others release (arguable, this could be more precise?)
foreach (DebuggerToolTipHolder *tooltip, m_tooltips)
tooltip->updateTooltip(engine);
updateVisibleToolTips(); // Move tooltip when stepping in same file.
for (DebuggerToolTipHolder *tooltip : qAsConst(d->m_tooltips))
tooltip->updateTooltip(d->m_engine);
d->updateVisibleToolTips(); // Move tooltip when stepping in same file.
}
void DebuggerToolTipManager::registerEngine(DebuggerEngine *engine)
{
Q_UNUSED(engine)
DEBUG("REGISTER ENGINE");
}
void DebuggerToolTipManager::deregisterEngine(DebuggerEngine *engine)
void DebuggerToolTipManager::deregisterEngine()
{
DEBUG("DEREGISTER ENGINE");
QTC_ASSERT(engine, return);
purgeClosedToolTips();
d->purgeClosedToolTips();
foreach (DebuggerToolTipHolder *tooltip, m_tooltips)
if (tooltip->context.engineType == engine->objectName())
for (DebuggerToolTipHolder *tooltip : qAsConst(d->m_tooltips))
if (tooltip->context.engineType == d->m_engine->objectName())
tooltip->releaseEngine();
saveSessionData();
d->saveSessionData();
// FIXME: For now remove all.
foreach (DebuggerToolTipHolder *tooltip, m_tooltips)
for (DebuggerToolTipHolder *tooltip : qAsConst(d->m_tooltips))
tooltip->destroy();
purgeClosedToolTips();
d->purgeClosedToolTips();
}
bool DebuggerToolTipManager::hasToolTips()
bool DebuggerToolTipManager::hasToolTips() const
{
return !m_tooltips.isEmpty();
return !d->m_tooltips.isEmpty();
}
void DebuggerToolTipManager::sessionAboutToChange()
void DebuggerToolTipManagerPrivate::sessionAboutToChange()
{
closeAllToolTips();
}
void DebuggerToolTipManager::loadSessionData()
void DebuggerToolTipManagerPrivate::loadSessionData()
{
closeAllToolTips();
const QString data = sessionValue(sessionSettingsKeyC).toString();
@@ -1098,7 +1129,7 @@ void DebuggerToolTipManager::loadSessionData()
}
}
void DebuggerToolTipManager::saveSessionData()
void DebuggerToolTipManagerPrivate::saveSessionData()
{
QString data;
purgeClosedToolTips();
@@ -1107,7 +1138,7 @@ void DebuggerToolTipManager::saveSessionData()
w.writeStartDocument();
w.writeStartElement(QLatin1String(sessionDocumentC));
w.writeAttribute(QLatin1String(sessionVersionAttributeC), QLatin1String("1.0"));
foreach (DebuggerToolTipHolder *tooltip, m_tooltips)
for (DebuggerToolTipHolder *tooltip : qAsConst(m_tooltips))
if (tooltip->widget->isPinned)
tooltip->saveSessionData(w);
w.writeEndDocument();
@@ -1118,19 +1149,38 @@ void DebuggerToolTipManager::saveSessionData()
void DebuggerToolTipManager::closeAllToolTips()
{
foreach (DebuggerToolTipHolder *tooltip, m_tooltips)
d->closeAllToolTips();
}
void DebuggerToolTipManagerPrivate::closeAllToolTips()
{
for (DebuggerToolTipHolder *tooltip : qAsConst(m_tooltips))
tooltip->destroy();
m_tooltips.clear();
}
void DebuggerToolTipManager::resetLocation()
{
purgeClosedToolTips();
foreach (DebuggerToolTipHolder *tooltip, m_tooltips)
d->purgeClosedToolTips();
for (DebuggerToolTipHolder *tooltip : qAsConst(d->m_tooltips))
tooltip->widget->pin();
}
static void slotTooltipOverrideRequested
DebuggerToolTipManagerPrivate::DebuggerToolTipManagerPrivate(DebuggerEngine *engine)
: m_engine(engine)
{
connect(ModeManager::instance(), &ModeManager::currentModeChanged,
this, &DebuggerToolTipManagerPrivate::onModeChanged);
connect(SessionManager::instance(), &SessionManager::sessionLoaded,
this, &DebuggerToolTipManagerPrivate::loadSessionData);
connect(SessionManager::instance(), &SessionManager::aboutToSaveSession,
this, &DebuggerToolTipManagerPrivate::saveSessionData);
connect(SessionManager::instance(), &SessionManager::aboutToUnloadSession,
this, &DebuggerToolTipManagerPrivate::sessionAboutToChange);
setupEditors();
}
void DebuggerToolTipManagerPrivate::slotTooltipOverrideRequested
(TextEditorWidget *editorWidget, const QPoint &point, int pos, bool *handled)
{
QTC_ASSERT(handled, return);
@@ -1141,12 +1191,11 @@ static void slotTooltipOverrideRequested
return;
const TextDocument *document = editorWidget->textDocument();
DebuggerEngine *engine = EngineManager::currentEngine();
if (!engine || !engine->canDisplayTooltip())
if (!m_engine || !m_engine->canDisplayTooltip())
return;
DebuggerToolTipContext context;
context.engineType = engine->objectName();
context.engineType = m_engine->objectName();
context.fileName = document->filePath().toString();
context.position = pos;
editorWidget->convertPosition(pos, &context.line, &context.column);
@@ -1166,7 +1215,7 @@ static void slotTooltipOverrideRequested
purgeClosedToolTips();
// Prefer a filter on an existing local variable if it can be found.
const WatchItem *localVariable = engine->watchHandler()->findCppLocalVariable(context.expression);
const WatchItem *localVariable = m_engine->watchHandler()->findCppLocalVariable(context.expression);
if (localVariable) {
context.expression = localVariable->exp;
if (context.expression.isEmpty())
@@ -1189,7 +1238,7 @@ static void slotTooltipOverrideRequested
ToolTip::show(point, tooltip->widget, DebuggerMainWindow::instance());
}
DEBUG("SYNC IN STATE" << tooltip->state);
tooltip->updateTooltip(engine);
tooltip->updateTooltip(m_engine);
*handled = true;
@@ -1213,8 +1262,8 @@ static void slotTooltipOverrideRequested
tooltip->context.mousePosition = point;
m_tooltips.push_back(tooltip);
tooltip->setState(PendingUnshown);
if (engine->canHandleToolTip(context)) {
engine->updateItem(context.iname);
if (m_engine->canHandleToolTip(context)) {
m_engine->updateItem(context.iname);
} else {
ToolTip::show(point, DebuggerToolTipManager::tr("Expression too complex"),
DebuggerMainWindow::instance());
@@ -1224,19 +1273,19 @@ static void slotTooltipOverrideRequested
}
}
static void slotEditorOpened(IEditor *e)
void DebuggerToolTipManagerPrivate::slotEditorOpened(IEditor *e)
{
// Move tooltip along when scrolled.
if (auto textEditor = qobject_cast<BaseTextEditor *>(e)) {
TextEditorWidget *widget = textEditor->editorWidget();
QObject::connect(widget->verticalScrollBar(), &QScrollBar::valueChanged,
&DebuggerToolTipManager::updateVisibleToolTips);
this, &DebuggerToolTipManagerPrivate::updateVisibleToolTips);
QObject::connect(widget, &TextEditorWidget::tooltipOverrideRequested,
slotTooltipOverrideRequested);
this, &DebuggerToolTipManagerPrivate::slotTooltipOverrideRequested);
}
}
void DebuggerToolTipManager::debugModeEntered()
void DebuggerToolTipManagerPrivate::debugModeEntered()
{
// Hook up all signals in debug mode.
if (!m_debugModeActive) {
@@ -1245,18 +1294,24 @@ void DebuggerToolTipManager::debugModeEntered()
topLevel->installEventFilter(this);
EditorManager *em = EditorManager::instance();
connect(em, &EditorManager::currentEditorChanged,
&DebuggerToolTipManager::updateVisibleToolTips);
connect(em, &EditorManager::editorOpened, slotEditorOpened);
this, &DebuggerToolTipManagerPrivate::updateVisibleToolTips);
connect(em, &EditorManager::editorOpened,
this, &DebuggerToolTipManagerPrivate::slotEditorOpened);
foreach (IEditor *e, DocumentModel::editorsForOpenedDocuments())
slotEditorOpened(e);
// Position tooltips delayed once all the editor placeholder layouting is done.
if (!m_tooltips.isEmpty())
QTimer::singleShot(0, this, &DebuggerToolTipManager::updateVisibleToolTips);
setupEditors();
}
}
void DebuggerToolTipManager::leavingDebugMode()
void DebuggerToolTipManagerPrivate::setupEditors()
{
for (IEditor *e : DocumentModel::editorsForOpenedDocuments())
slotEditorOpened(e);
// Position tooltips delayed once all the editor placeholder layouting is done.
if (!m_tooltips.isEmpty())
QTimer::singleShot(0, this, &DebuggerToolTipManagerPrivate::updateVisibleToolTips);
}
void DebuggerToolTipManagerPrivate::leavingDebugMode()
{
// Remove all signals in debug mode.
if (m_debugModeActive) {
@@ -1274,11 +1329,11 @@ void DebuggerToolTipManager::leavingDebugMode()
}
}
DebuggerToolTipContexts DebuggerToolTipManager::pendingTooltips(DebuggerEngine *engine)
DebuggerToolTipContexts DebuggerToolTipManager::pendingTooltips() const
{
StackFrame frame = engine->stackHandler()->currentFrame();
StackFrame frame = d->m_engine->stackHandler()->currentFrame();
DebuggerToolTipContexts rc;
foreach (DebuggerToolTipHolder *tooltip, m_tooltips) {
for (DebuggerToolTipHolder *tooltip : qAsConst(d->m_tooltips)) {
const DebuggerToolTipContext &context = tooltip->context;
if (context.iname.startsWith("tooltip") && context.matchesFrame(frame))
rc.push_back(context);
@@ -1286,7 +1341,7 @@ DebuggerToolTipContexts DebuggerToolTipManager::pendingTooltips(DebuggerEngine *
return rc;
}
bool DebuggerToolTipManager::eventFilter(QObject *o, QEvent *e)
bool DebuggerToolTipManagerPrivate::eventFilter(QObject *o, QEvent *e)
{
if (m_tooltips.isEmpty())
return false;
@@ -1295,7 +1350,7 @@ bool DebuggerToolTipManager::eventFilter(QObject *o, QEvent *e)
const auto me = static_cast<const QMoveEvent *>(e);
const QPoint dist = me->pos() - me->oldPos();
purgeClosedToolTips();
foreach (DebuggerToolTipHolder *tooltip, m_tooltips) {
for (DebuggerToolTipHolder *tooltip : qAsConst(m_tooltips)) {
if (tooltip->widget && tooltip->widget->isVisible())
tooltip->widget->move(tooltip->widget->pos() + dist);
}
@@ -1307,7 +1362,7 @@ bool DebuggerToolTipManager::eventFilter(QObject *o, QEvent *e)
const bool isMinimized = static_cast<const QWidget *>(o)->windowState() & Qt::WindowMinimized;
if (wasMinimized ^ isMinimized) {
purgeClosedToolTips();
foreach (DebuggerToolTipHolder *tooltip, m_tooltips)
for (DebuggerToolTipHolder *tooltip : qAsConst(m_tooltips))
tooltip->widget->setVisible(!isMinimized);
}
break;
@@ -1318,7 +1373,7 @@ bool DebuggerToolTipManager::eventFilter(QObject *o, QEvent *e)
return false;
}
static void purgeClosedToolTips()
void DebuggerToolTipManagerPrivate::purgeClosedToolTips()
{
for (int i = m_tooltips.size(); --i >= 0; ) {
DebuggerToolTipHolder *tooltip = m_tooltips.at(i);