Commit dbae1568 authored by hjk's avatar hjk

Debugger: Simplify tooltip interface

Change-Id: I7ce688e56fb516ef6e77ee2e4f56d9b56379918b
Reviewed-by: default avatarDavid Schulz <david.schulz@digia.com>
Reviewed-by: default avatarhjk <hjk121@nokiamail.com>
parent 08e64797
......@@ -447,8 +447,7 @@ void CdbEngine::syncVerboseLog(bool verboseLog)
postCommand(m_verboseLog ? QByteArray("!sym noisy") : QByteArray("!sym quiet"), 0);
}
bool CdbEngine::setToolTipExpression(const QPoint &mousePos,
TextEditor::ITextEditor *editor,
bool CdbEngine::setToolTipExpression(TextEditor::ITextEditor *editor,
const DebuggerToolTipContext &contextIn)
{
if (debug)
......@@ -469,10 +468,7 @@ bool CdbEngine::setToolTipExpression(const QPoint &mousePos,
if (!localVariable)
return false;
context.iname = localVariable->iname;
DebuggerToolTipWidget *tw = new DebuggerToolTipWidget;
tw->setContext(context);
tw->acquireEngine(this);
DebuggerToolTipManager::showToolTip(mousePos, tw);
DebuggerToolTipManager::showToolTip(context, this);
return true;
}
......
......@@ -76,7 +76,7 @@ public:
// Factory function that returns 0 if the debug engine library cannot be found.
virtual bool setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor,
virtual bool setToolTipExpression(TextEditor::ITextEditor *editor,
const DebuggerToolTipContext &ctx);
virtual void setupEngine();
virtual void setupInferior();
......
......@@ -1355,8 +1355,8 @@ DebuggerRunControl *DebuggerEngine::runControl() const
return d->runControl();
}
bool DebuggerEngine::setToolTipExpression
(const QPoint &, TextEditor::ITextEditor *, const DebuggerToolTipContext &)
bool DebuggerEngine::setToolTipExpression(TextEditor::ITextEditor *,
const DebuggerToolTipContext &)
{
return false;
}
......
......@@ -143,8 +143,8 @@ public:
const DebuggerStartParameters &startParameters() const;
DebuggerStartParameters &startParameters();
virtual bool setToolTipExpression(const QPoint & mousePos,
TextEditor::ITextEditor *editor, const Internal::DebuggerToolTipContext &);
virtual bool setToolTipExpression(TextEditor::ITextEditor *editor,
const Internal::DebuggerToolTipContext &);
virtual void updateWatchData(const Internal::WatchData &data,
const Internal::WatchUpdateFlags & flags = Internal::WatchUpdateFlags());
......
......@@ -43,19 +43,20 @@
#include <utils/tooltip/tipcontents.h>
#include <utils/qtcassert.h>
#include <QToolButton>
#include <QToolBar>
#include <QVBoxLayout>
#include <QApplication>
#include <QClipboard>
#include <QDebug>
#include <QDesktopWidget>
#include <QLabel>
#include <QScrollBar>
#include <QSortFilterProxyModel>
#include <QStandardItemModel>
#include <QLabel>
#include <QClipboard>
#include <QStack>
#include <QDebug>
#include <QStandardItemModel>
#include <QToolBar>
#include <QToolButton>
#include <QVBoxLayout>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
using namespace Core;
using namespace TextEditor;
......@@ -430,9 +431,6 @@ void DumpTreeModelVisitor::rowEnded()
m_level--;
}
} // namespace Internal
} // namespace Debugger
/*
static QDebug operator<<(QDebug d, const QAbstractItemModel &model)
{
......@@ -445,10 +443,54 @@ static QDebug operator<<(QDebug d, const QAbstractItemModel &model)
}
*/
namespace Debugger {
namespace Internal {
/*!
\class Debugger::Internal::TooltipFilterModel
\brief The TooltipFilterModel class is a model for tooltips filtering an
item on the watchhandler matching its tree on the iname.
In addition, suppress the model's tooltip data to avoid a tooltip on a tooltip.
*/
class TooltipFilterModel : public QSortFilterProxyModel
{
public:
TooltipFilterModel(QAbstractItemModel *model, const QByteArray &iname)
: m_iname(iname)
{
setSourceModel(model);
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
{
return role == Qt::ToolTipRole
? QVariant() : QSortFilterProxyModel::data(index, role);
}
static bool isSubIname(const QByteArray &haystack, const QByteArray &needle)
{
return haystack.size() > needle.size()
&& haystack.startsWith(needle)
&& haystack.at(needle.size()) == '.';
}
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
const QModelIndex nameIndex = sourceModel()->index(sourceRow, 0, sourceParent);
const QByteArray iname = nameIndex.data(LocalsINameRole).toByteArray();
return iname == m_iname || isSubIname(iname, m_iname) || isSubIname(m_iname, iname);
}
private:
const QByteArray m_iname;
};
/////////////////////////////////////////////////////////////////////////
//
// TreeModelCopyVisitor builds a QStandardItem from a tree model (copy).
//
/////////////////////////////////////////////////////////////////////////
// Visitor building a QStandardItem from a tree model (copy).
class TreeModelCopyVisitor : public TreeModelVisitor
{
public:
......@@ -466,6 +508,72 @@ private:
};
/////////////////////////////////////////////////////////////////////////
//
// DebuggerToolTipWidget
//
/////////////////////////////////////////////////////////////////////////
class DebuggerToolTipWidget : public QWidget
{
Q_OBJECT
public:
bool isPinned() const { return m_isPinned; }
explicit DebuggerToolTipWidget(QWidget *parent = 0);
bool engineAcquired() const { return m_engineAcquired; }
QString fileName() const { return m_context.fileName; }
QString function() const { return m_context.function; }
int position() const { return m_context.position; }
// Check for a match at position.
bool matches(const QString &fileName,
const QString &engineType = QString(),
const QString &function= QString()) const;
const DebuggerToolTipContext &context() const { return m_context; }
void setContext(const DebuggerToolTipContext &c) { m_context = c; }
QString engineType() const { return m_engineType; }
void setEngineType(const QString &e) { m_engineType = e; }
QDate creationDate() const { return m_creationDate; }
void setCreationDate(const QDate &d) { m_creationDate = d; }
public slots:
void saveSessionData(QXmlStreamWriter &w) const;
void acquireEngine(Debugger::DebuggerEngine *engine);
void releaseEngine();
void copy();
bool positionShow(const DebuggerToolTipEditor &pe);
void pin();
void doLoadSessionData(QXmlStreamReader &r);
private slots:
void slotDragged(const QPoint &p);
void toolButtonClicked();
private:
void doReleaseEngine();
void doSaveSessionData(QXmlStreamWriter &w) const;
QString clipboardContents() const;
QAbstractItemModel *swapModel(QAbstractItemModel *newModel);
bool m_isPinned;
QToolButton *m_toolButton;
DraggableLabel *m_titleLabel;
bool m_engineAcquired;
QString m_engineType;
DebuggerToolTipContext m_context;
QDate m_creationDate;
QPoint m_offset; //!< Offset to text cursor position (user dragging).
int m_debuggerModel;
DebuggerToolTipTreeView *m_treeView;
QStandardItemModel *m_defaultModel;
};
void DebuggerToolTipWidget::pin()
{
if (m_isPinned)
......@@ -633,10 +741,15 @@ void DebuggerToolTipWidget::acquireEngine(DebuggerEngine *engine)
qDebug() << this << " acquiring" << engine << m_engineAcquired;
if (m_engineAcquired)
return;
doAcquireEngine(engine);
m_engineType = engine->objectName();
m_engineAcquired = true;
m_titleLabel->setText(QString());
// Create a filter model on the debugger's model and switch to it.
QAbstractItemModel *model = engine->watchModel();
TooltipFilterModel *filterModel = new TooltipFilterModel(model, m_context.iname);
swapModel(filterModel);
}
void DebuggerToolTipWidget::releaseEngine()
......@@ -712,17 +825,7 @@ static QDate dateFromString(const QString &date)
QDate();
}
DebuggerToolTipWidget *DebuggerToolTipWidget::loadSessionData(QXmlStreamReader &r)
{
if (debugToolTips)
qDebug() << ">DebuggerToolTipWidget::loadSessionData" << r.tokenString() << r.name();
DebuggerToolTipWidget *rc = DebuggerToolTipWidget::loadSessionDataI(r);
if (debugToolTips)
qDebug() << "<DebuggerToolTipWidget::loadSessionData" << r.tokenString() << r.name() << " returns " << rc;
return rc;
}
DebuggerToolTipWidget *DebuggerToolTipWidget::loadSessionDataI(QXmlStreamReader &r)
static DebuggerToolTipWidget *loadSessionDataI(QXmlStreamReader &r)
{
if (!readStartElement(r, toolTipElementC))
return 0;
......@@ -793,50 +896,6 @@ void DebuggerToolTipWidget::saveSessionData(QXmlStreamWriter &w) const
w.writeEndElement();
}
/*!
\class Debugger::Internal::TooltipFilterModel
\brief The TooltipFilterModel class is a model for tooltips filtering an
item on the watchhandler matching its tree on the iname.
In addition, suppress the model's tooltip data to avoid a tooltip on a tooltip.
*/
class TooltipFilterModel : public QSortFilterProxyModel
{
public:
TooltipFilterModel(QAbstractItemModel *model, const QByteArray &iname)
: m_iname(iname)
{
setSourceModel(model);
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
{
return role == Qt::ToolTipRole
? QVariant() : QSortFilterProxyModel::data(index, role);
}
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
private:
const QByteArray m_iname;
};
static bool isSubIname(const QByteArray &haystack, const QByteArray &needle)
{
return haystack.size() > needle.size()
&& haystack.startsWith(needle)
&& haystack.at(needle.size()) == '.';
}
bool TooltipFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
const QModelIndex nameIndex = sourceModel()->index(sourceRow, 0, sourceParent);
const QByteArray iname = nameIndex.data(LocalsINameRole).toByteArray();
return iname == m_iname || isSubIname(iname, m_iname) || isSubIname(m_iname, iname);
}
/*!
\class Debugger::Internal::DebuggerToolTipTreeView
......@@ -967,15 +1026,6 @@ void DebuggerToolTipTreeView::computeSize()
viewport()->update();
}
void DebuggerToolTipWidget::doAcquireEngine(DebuggerEngine *engine)
{
// Create a filter model on the debugger's model and switch to it.
QAbstractItemModel *model = engine->watchModel();
TooltipFilterModel *filterModel =
new TooltipFilterModel(model, m_context.iname);
swapModel(filterModel);
}
QAbstractItemModel *DebuggerToolTipWidget::swapModel(QAbstractItemModel *newModel)
{
QAbstractItemModel *oldModel = m_treeView->swapModel(newModel);
......@@ -1001,7 +1051,7 @@ void DebuggerToolTipWidget::doReleaseEngine()
delete swapModel(m_defaultModel);
}
void DebuggerToolTipWidget::restoreTreeModel(QXmlStreamReader &r, QStandardItemModel *m)
static void restoreTreeModel(QXmlStreamReader &r, QStandardItemModel *m)
{
StandardItemTreeModelBuilder builder(m);
int columnCount = 1;
......@@ -1069,7 +1119,7 @@ void DebuggerToolTipWidget::doLoadSessionData(QXmlStreamReader &r)
m_treeView->swapModel(m_defaultModel);
}
QString DebuggerToolTipWidget::treeModelClipboardContents(const QAbstractItemModel *m)
QString DebuggerToolTipManager::treeModelClipboardContents(const QAbstractItemModel *m)
{
QString rc;
QTextStream str(&rc);
......@@ -1081,7 +1131,7 @@ QString DebuggerToolTipWidget::treeModelClipboardContents(const QAbstractItemMod
QString DebuggerToolTipWidget::clipboardContents() const
{
if (const QAbstractItemModel *model = m_treeView->model())
return DebuggerToolTipWidget::treeModelClipboardContents(model);
return DebuggerToolTipManager::treeModelClipboardContents(model);
return QString();
}
......@@ -1149,13 +1199,15 @@ bool DebuggerToolTipManager::hasToolTips()
return !d->m_tooltips.isEmpty();
}
void DebuggerToolTipManager::showToolTip(const QPoint &p, DebuggerToolTipWidget *toolTipWidget)
void DebuggerToolTipManager::showToolTip(const DebuggerToolTipContext &context,
DebuggerEngine *engine)
{
if (debugToolTipPositioning)
qDebug() << "DebuggerToolTipManager::showToolTip" << p << " Mouse at " << QCursor::pos();
const Utils::WidgetContent widgetContent(toolTipWidget, true);
Utils::ToolTip::show(p, widgetContent, debuggerCore()->mainWindow());
d->registerToolTip(toolTipWidget);
DebuggerToolTipWidget *tw = new DebuggerToolTipWidget;
tw->setContext(context);
tw->acquireEngine(engine);
const Utils::WidgetContent widgetContent(tw, true);
Utils::ToolTip::show(context.mousePosition, widgetContent, debuggerCore()->mainWindow());
d->registerToolTip(tw);
}
void DebuggerToolTipManagerData::registerToolTip(DebuggerToolTipWidget *toolTipWidget)
......@@ -1214,6 +1266,16 @@ void DebuggerToolTipManager::sessionAboutToChange()
closeAllToolTips();
}
static DebuggerToolTipWidget *loadSessionDataX(QXmlStreamReader &r)
{
if (debugToolTips)
qDebug() << ">DebuggerToolTipWidget::loadSessionData" << r.tokenString() << r.name();
DebuggerToolTipWidget *rc = loadSessionDataI(r);
if (debugToolTips)
qDebug() << "<DebuggerToolTipWidget::loadSessionData" << r.tokenString() << r.name() << " returns " << rc;
return rc;
}
void DebuggerToolTipManager::loadSessionData()
{
const QString data = DebuggerCore::sessionValue(sessionSettingsKeyC).toString();
......@@ -1225,7 +1287,7 @@ void DebuggerToolTipManager::loadSessionData()
return;
const double version = r.attributes().value(QLatin1String(sessionVersionAttributeC)).toString().toDouble();
while (!r.atEnd())
if (DebuggerToolTipWidget *tw = DebuggerToolTipWidget::loadSessionData(r))
if (DebuggerToolTipWidget *tw = loadSessionDataX(r))
d->registerToolTip(tw);
if (debugToolTips)
......@@ -1466,8 +1528,9 @@ void DebuggerToolTipManager::slotTooltipOverrideRequested(ITextEditor *editor,
if (!currentEngine || !currentEngine->canDisplayTooltip())
break;
const DebuggerToolTipContext context = DebuggerToolTipContext::fromEditor(editor, pos);
if (context.isValid() && currentEngine->setToolTipExpression(point, editor, context)) {
DebuggerToolTipContext context = DebuggerToolTipContext::fromEditor(editor, pos);
context.mousePosition = point;
if (context.isValid() && currentEngine->setToolTipExpression(editor, context)) {
*handled = true;
d->m_lastToolTipEditor = editor;
d->m_lastToolTipPoint = point;
......
......@@ -32,34 +32,21 @@
#include "debuggerconstants.h"
#include <QTreeView>
#include <QPointer>
#include <QXmlStreamWriter>
#include <QXmlStreamReader>
#include <QDate>
#include <QPointer>
#include <QTreeView>
QT_BEGIN_NAMESPACE
class QVBoxLayout;
class QToolButton;
class QStandardItemModel;
class QToolBar;
class QDebug;
QT_END_NAMESPACE
namespace Core {
class IEditor;
class IMode;
}
namespace Core { class IEditor; }
namespace TextEditor { class ITextEditor; }
namespace Debugger {
class DebuggerEngine;
namespace Internal {
class DraggableLabel;
class DebuggerToolTipEditor;
class DebuggerToolTipContext
{
......@@ -84,81 +71,6 @@ typedef QList<DebuggerToolTipContext> DebuggerToolTipContexts;
QDebug operator<<(QDebug, const DebuggerToolTipContext &);
class DebuggerToolTipTreeView;
class DebuggerToolTipWidget : public QWidget
{
Q_OBJECT
public:
bool isPinned() const { return m_isPinned; }
explicit DebuggerToolTipWidget(QWidget *parent = 0);
bool engineAcquired() const { return m_engineAcquired; }
QString fileName() const { return m_context.fileName; }
QString function() const { return m_context.function; }
int position() const { return m_context.position; }
// Check for a match at position.
bool matches(const QString &fileName,
const QString &engineType = QString(),
const QString &function= QString()) const;
const DebuggerToolTipContext &context() const { return m_context; }
void setContext(const DebuggerToolTipContext &c) { m_context = c; }
QString engineType() const { return m_engineType; }
void setEngineType(const QString &e) { m_engineType = e; }
QDate creationDate() const { return m_creationDate; }
void setCreationDate(const QDate &d) { m_creationDate = d; }
static DebuggerToolTipWidget *loadSessionData(QXmlStreamReader &r);
static QString treeModelClipboardContents(const QAbstractItemModel *m);
public slots:
void saveSessionData(QXmlStreamWriter &w) const;
void acquireEngine(Debugger::DebuggerEngine *engine);
void releaseEngine();
void copy();
bool positionShow(const DebuggerToolTipEditor &pe);
void pin();
private slots:
void slotDragged(const QPoint &p);
void toolButtonClicked();
private:
bool m_isPinned;
QToolButton *m_toolButton;
private:
static DebuggerToolTipWidget *loadSessionDataI(QXmlStreamReader &r);
void doAcquireEngine(Debugger::DebuggerEngine *engine);
void doReleaseEngine();
void doSaveSessionData(QXmlStreamWriter &w) const;
void doLoadSessionData(QXmlStreamReader &r);
QString clipboardContents() const;
DraggableLabel *m_titleLabel;
bool m_engineAcquired;
QString m_engineType;
DebuggerToolTipContext m_context;
QDate m_creationDate;
QPoint m_offset; //!< Offset to text cursor position (user dragging).
private:
QAbstractItemModel *swapModel(QAbstractItemModel *newModel);
static void restoreTreeModel(QXmlStreamReader &r, QStandardItemModel *m);
int m_debuggerModel;
DebuggerToolTipTreeView *m_treeView;
QStandardItemModel *m_defaultModel;
};
class DebuggerToolTipTreeView : public QTreeView
{
Q_OBJECT
......@@ -168,16 +80,15 @@ public:
QAbstractItemModel *swapModel(QAbstractItemModel *model);
QSize sizeHint() const { return m_size; }
int computeHeight(const QModelIndex &index) const;
public slots:
private slots:
void computeSize();
void expandNode(const QModelIndex &idx);
void collapseNode(const QModelIndex &idx);
void handleItemIsExpanded(const QModelIndex &sourceIdx);
private:
void init(QAbstractItemModel *model);
int computeHeight(const QModelIndex &index) const;
QSize m_size;
};
......@@ -198,11 +109,13 @@ public:
const QString &engineType = QString(),
const QString &function= QString());
static void showToolTip(const QPoint &p, DebuggerToolTipWidget *);
static void showToolTip(const DebuggerToolTipContext &context,
DebuggerEngine *engine);
virtual bool eventFilter(QObject *, QEvent *);
static bool debug();
static QString treeModelClipboardContents(const QAbstractItemModel *m);
public slots:
void debugModeEntered();
......
......@@ -3644,10 +3644,7 @@ void GdbEngine::showToolTip()
return;
}
DebuggerToolTipWidget *tw = new DebuggerToolTipWidget;
tw->setContext(*m_toolTipContext);
tw->acquireEngine(this);
DebuggerToolTipManager::showToolTip(m_toolTipContext->mousePosition, tw);
DebuggerToolTipManager::showToolTip(*m_toolTipContext, this);
// Prevent tooltip from re-occurring (classic GDB, QTCREATORBUG-4711).
m_toolTipContext.reset();
}
......@@ -3663,8 +3660,8 @@ void GdbEngine::resetLocation()
DebuggerEngine::resetLocation();
}
bool GdbEngine::setToolTipExpression(const QPoint &mousePos,
TextEditor::ITextEditor *editor, const DebuggerToolTipContext &contextIn)
bool GdbEngine::setToolTipExpression(TextEditor::ITextEditor *editor,
const DebuggerToolTipContext &contextIn)
{
if (state() != InferiorStopOk || !isCppEditor(editor)) {
//qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED "
......@@ -3696,7 +3693,6 @@ bool GdbEngine::setToolTipExpression(const QPoint &mousePos,
}
m_toolTipContext.reset(new DebuggerToolTipContext(context));
m_toolTipContext->mousePosition = mousePos;
m_toolTipContext->expression = exp;
m_toolTipContext->iname = iname;
// Local variable: Display synchronously.
......
......@@ -406,8 +406,8 @@ protected:
//
// Watch specific stuff
//