Commit 2a959f47 authored by hjk's avatar hjk

debugger: use an expandable tree in the debugger tooltip

parent 1c5be603
......@@ -27,6 +27,7 @@ HEADERS += \
debuggeroutputwindow.h \
debuggerplugin.h \
debuggerrunner.h \
debuggertooltip.h \
disassemblerhandler.h \
disassemblerwindow.h \
watchutils.h \
......@@ -55,6 +56,7 @@ SOURCES += \
debuggeroutputwindow.cpp \
debuggerplugin.cpp \
debuggerrunner.cpp \
debuggertooltip.cpp \
disassemblerhandler.cpp \
disassemblerwindow.cpp \
watchutils.cpp \
......
......@@ -66,6 +66,7 @@
#include <QtCore/QTime>
#include <QtCore/QTimer>
#include <QtGui/QApplication>
#include <QtGui/QAction>
#include <QtGui/QComboBox>
#include <QtGui/QDockWidget>
......@@ -75,16 +76,34 @@
#include <QtGui/QMainWindow>
#include <QtGui/QMessageBox>
#include <QtGui/QPlainTextEdit>
#include <QtGui/QPushButton>
#include <QtGui/QStatusBar>
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
#include <QtGui/QToolBar>
#include <QtGui/QToolButton>
#include <QtGui/QPushButton>
#include <QtGui/QToolTip>
// The creation functions take a list of options pages they can add to.
// This allows for having a "enabled" toggle on the page indepently
// of the engine.
using namespace Debugger::Internal;
IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
IDebuggerEngine *createWinEngine(DebuggerManager *, bool /* cmdLineEnabled */, QList<Core::IOptionsPage*> *)
#ifdef CDB_ENABLED
;
#else
{ return 0; }
#endif
IDebuggerEngine *createScriptEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
IDebuggerEngine *createTcfEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
namespace Debugger {
namespace Internal {
namespace Internal {
QDebug operator<<(QDebug str, const DebuggerStartParameters &p)
{
QDebug nospace = str.nospace();
......@@ -100,12 +119,8 @@ QDebug operator<<(QDebug str, const DebuggerStartParameters &p)
<< " toolchain=" << p.toolChainType << '\n';
return str;
}
} // namespace Internal
} // namespace Debugger
using namespace Debugger;
using namespace Debugger::Internal;
using namespace Debugger::Constants;
using namespace Constants;
static const QString tooltipIName = "tooltip";
......@@ -131,36 +146,15 @@ static const char *stateName(int s)
///////////////////////////////////////////////////////////////////////
//
// DebuggerManager
// DebuggerStartParameters
//
///////////////////////////////////////////////////////////////////////
static IDebuggerEngine *gdbEngine = 0;
static IDebuggerEngine *winEngine = 0;
static IDebuggerEngine *scriptEngine = 0;
static IDebuggerEngine *tcfEngine = 0;
// The creation functions take a list of options pages they can add to.
// This allows for having a "enabled" toggle on the page indepently
// of the engine.
IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
IDebuggerEngine *createWinEngine(DebuggerManager *, bool /* cmdLineEnabled */, QList<Core::IOptionsPage*> *)
#ifdef CDB_ENABLED
;
#else
{ return 0; }
#endif
IDebuggerEngine *createScriptEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
IDebuggerEngine *createTcfEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
// ---------------- DebuggerStartParameters
DebuggerStartParameters::DebuggerStartParameters() :
attachPID(-1),
DebuggerStartParameters::DebuggerStartParameters()
: attachPID(-1),
useTerminal(false),
toolChainType(ProjectExplorer::ToolChain::UNKNOWN)
{
}
{}
void DebuggerStartParameters::clear()
{
......@@ -179,9 +173,20 @@ void DebuggerStartParameters::clear()
toolChainType = ProjectExplorer::ToolChain::UNKNOWN;
}
// --------- DebuggerManager
DebuggerManager::DebuggerManager() :
m_startParameters(new DebuggerStartParameters),
///////////////////////////////////////////////////////////////////////
//
// DebuggerManager
//
///////////////////////////////////////////////////////////////////////
static IDebuggerEngine *gdbEngine = 0;
static IDebuggerEngine *winEngine = 0;
static IDebuggerEngine *scriptEngine = 0;
static IDebuggerEngine *tcfEngine = 0;
DebuggerManager::DebuggerManager()
: m_startParameters(new DebuggerStartParameters),
m_inferiorPid(0)
{
init();
......@@ -228,8 +233,6 @@ void DebuggerManager::init()
m_localsWindow = new WatchWindow(WatchWindow::LocalsType);
m_watchersWindow = new WatchWindow(WatchWindow::WatchersType);
//m_tooltipWindow = new WatchWindow(WatchWindow::TooltipType);
//m_watchersWindow = new QTreeView;
m_tooltipWindow = new QTreeView;
m_statusTimer = new QTimer(this);
m_mainWindow = new QMainWindow;
......@@ -334,8 +337,8 @@ void DebuggerManager::init()
this, SLOT(assignValueInDebugger()), Qt::QueuedConnection);
// Tooltip
QTreeView *tooltipView = qobject_cast<QTreeView *>(m_tooltipWindow);
tooltipView->setModel(m_watchHandler->model(TooltipsWatch));
//QTreeView *tooltipView = qobject_cast<QTreeView *>(m_tooltipWindow);
//tooltipView->setModel(m_watchHandler->model(TooltipsWatch));
connect(m_watchHandler, SIGNAL(watchDataUpdateNeeded(WatchData)),
this, SLOT(updateWatchData(WatchData)));
......@@ -461,8 +464,10 @@ void DebuggerManager::init()
localsAndWatchers->setWindowTitle(m_localsWindow->windowTitle());
localsAndWatchers->addWidget(m_localsWindow);
localsAndWatchers->addWidget(m_watchersWindow);
//localsAndWatchers->addWidget(m_tooltipWindow);
localsAndWatchers->setStretchFactor(0, 3);
localsAndWatchers->setStretchFactor(1, 1);
localsAndWatchers->setStretchFactor(2, 1);
m_watchDock = createDockForWidget(localsAndWatchers);
setStatus(DebuggerProcessNotReady);
......@@ -710,7 +715,7 @@ void DebuggerManager::shutdown()
doDelete(m_stackWindow);
doDelete(m_sourceFilesWindow);
doDelete(m_threadsWindow);
doDelete(m_tooltipWindow);
//doDelete(m_tooltipWindow);
doDelete(m_watchersWindow);
doDelete(m_localsWindow);
......@@ -1275,7 +1280,7 @@ void DebuggerManager::setBusyCursor(bool busy)
m_stackWindow->setCursor(cursor);
m_sourceFilesWindow->setCursor(cursor);
m_threadsWindow->setCursor(cursor);
m_tooltipWindow->setCursor(cursor);
//m_tooltipWindow->setCursor(cursor);
m_watchersWindow->setCursor(cursor);
}
......@@ -1561,3 +1566,7 @@ void DebuggerManager::runTest(const QString &fileName)
m_startParameters->workingDir.clear();
//startNewDebugger(StartInternal);
}
} // namespace Internal
} // namespace Debugger
......@@ -42,6 +42,7 @@ class QAbstractItemModel;
class QDockWidget;
class QLabel;
class QMainWindow;
class QModelIndex;
class QPoint;
class QTimer;
class QWidget;
......@@ -70,16 +71,16 @@ class DebuggerPlugin;
class DebugMode;
class BreakHandler;
class BreakpointData;
class DisassemblerHandler;
class ModulesHandler;
class RegisterHandler;
class SourceFilesWindow;
class StackHandler;
class Symbol;
class ThreadsHandler;
class WatchHandler;
class SourceFilesWindow;
class WatchData;
class BreakpointData;
class Symbol;
class WatchHandler;
// Note: the Debugger process itself is referred to as 'Debugger',
// whereas the debugged process is referred to as 'Inferior' or 'Debuggee'.
......@@ -104,7 +105,6 @@ class Symbol;
// [N] : Step, Next
enum DebuggerStatus
{
DebuggerProcessNotReady, // Debugger not started
......@@ -483,7 +483,7 @@ private:
QWidget *m_localsWindow;
QWidget *m_registerWindow;
QWidget *m_modulesWindow;
QWidget *m_tooltipWindow;
//QWidget *m_tooltipWindow;
QWidget *m_stackWindow;
QWidget *m_threadsWindow;
QWidget *m_watchersWindow;
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
**
**************************************************************************/
#include "debuggertooltip.h"
#include <QtCore/QPointer>
#include <QtCore/QtDebug>
#include <QtGui/QApplication>
#include <QtGui/QHBoxLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QKeyEvent>
#include <QtGui/QLabel>
#include <QtGui/QTreeView>
#include <QtGui/QVBoxLayout>
#include <QtGui/QWidget>
namespace Debugger {
namespace Internal {
///////////////////////////////////////////////////////////////////////
//
// TooltipTreeView
//
///////////////////////////////////////////////////////////////////////
class ToolTipTreeView : public QTreeView
{
public:
ToolTipTreeView(QWidget *parent = 0) : QTreeView(parent) {}
/*
QSize sizeHint() const {
qDebug() << viewport()->size()
<< viewport()->size().boundedTo(QSize(500, 300));
return viewport()->size().boundedTo(QSize(100, 100));
}
*/
};
///////////////////////////////////////////////////////////////////////
//
// TooltipWidget
//
///////////////////////////////////////////////////////////////////////
class ToolTipWidget : public QTreeView
{
Q_OBJECT
public:
ToolTipWidget(QWidget *parent);
void done();
void run(const QPoint &point, QAbstractItemModel *model,
const QModelIndex &index, const QString &msg);
bool eventFilter(QObject *ob, QEvent *ev);
QSize sizeHint() const { return m_size; }
int computeHeight(const QModelIndex &index)
{
int s = rowHeight(index);
for (int i = 0; i < model()->rowCount(index); ++i)
s += computeHeight(model()->index(i, 0, index));
return s;
}
Q_SLOT void computeSize()
{
int columns = 0;
for (int i = 0; i < 3; ++i) {
resizeColumnToContents(i);
columns += sizeHintForColumn(i);
}
int rows = computeHeight(QModelIndex());
m_size = QSize(columns + 5, rows + 5);
setMinimumSize(m_size);
setMaximumSize(m_size);
}
private:
QSize m_size;
};
static QPointer<ToolTipWidget> theToolTipWidget;
ToolTipWidget::ToolTipWidget(QWidget *parent)
: QTreeView(parent)
{
setWindowFlags(Qt::ToolTip | Qt::WindowStaysOnTopHint);
setFocusPolicy(Qt::NoFocus);
header()->hide();
setUniformRowHeights(true);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
connect(this, SIGNAL(collapsed(QModelIndex)), this, SLOT(computeSize()),
Qt::QueuedConnection);
connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(computeSize()),
Qt::QueuedConnection);
qApp->installEventFilter(this);
}
bool ToolTipWidget::eventFilter(QObject *ob, QEvent *ev)
{
Q_UNUSED(ob);
switch (ev->type()) {
case QEvent::ShortcutOverride:
if (static_cast<QKeyEvent *>(ev)->key() == Qt::Key_Escape)
return true;
break;
case QEvent::KeyPress:
if (static_cast<QKeyEvent *>(ev)->key() == Qt::Key_Escape) {
return true;
}
break;
case QEvent::KeyRelease:
if (static_cast<QKeyEvent *>(ev)->key() == Qt::Key_Escape) {
done();
return true;
}
break;
case QEvent::WindowDeactivate:
case QEvent::FocusOut:
done();
break;
default:
break;
}
return false;
}
void ToolTipWidget::done()
{
qApp->removeEventFilter(this);
deleteLater();
}
void ToolTipWidget::run(const QPoint &point, QAbstractItemModel *model,
const QModelIndex &index, const QString &msg)
{
move(point);
setModel(model);
setRootIndex(index.parent());
computeSize();
setRootIsDecorated(model->hasChildren(index));
// FIXME: use something more sensible
QPalette pal = palette();
QColor bg = pal.color(QPalette::Base);
bg.setAlpha(20);
pal.setColor(QPalette::Base, bg);
setPalette(pal);
//viewport()->setPalette(pal);
}
void showDebuggerToolTip(const QPoint &point, QAbstractItemModel *model,
const QModelIndex &index, const QString &msg)
{
if (model) {
if (!theToolTipWidget)
theToolTipWidget = new ToolTipWidget(0);
theToolTipWidget->run(point, model, index, msg);
theToolTipWidget->show();
} else if (theToolTipWidget) {
theToolTipWidget->done();
theToolTipWidget = 0;
}
}
void hideDebuggerToolTip(int delay)
{
Q_UNUSED(delay)
if (theToolTipWidget)
theToolTipWidget->done();
}
} // namespace Internal
} // namespace Debugger
#include "debuggertooltip.moc"
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
**
**************************************************************************/
#ifndef DEBUGGER_DEBUGGERTOOLTIP_H
#define DEBUGGER_DEBUGGERTOOLTIP_H
#include <qglobal.h>
QT_BEGIN_NAMESPACE
class QAbstractItemModel;
class QModelIndex;
class QPoint;
class QString;
QT_END_NAMESPACE
namespace Debugger {
namespace Internal {
void showDebuggerToolTip(const QPoint &point, QAbstractItemModel *model,
const QModelIndex &rootIndex, const QString &msg);
void hideDebuggerToolTip(int delay = 0);
} // namespace Internal
} // namespace Debugger
#endif // DEBUGGER_DEBUGGERTOOLTIP_H
......@@ -36,6 +36,7 @@
#include "debuggeractions.h"
#include "debuggerconstants.h"
#include "debuggermanager.h"
#include "debuggertooltip.h"
#include "gdbmi.h"
#include "procinterrupt.h"
......@@ -65,7 +66,6 @@
#include <QtGui/QLabel>
#include <QtGui/QMainWindow>
#include <QtGui/QMessageBox>
#include <QtGui/QToolTip>
#include <QtGui/QDialogButtonBox>
#include <QtGui/QPushButton>
#ifdef Q_OS_WIN
......@@ -103,8 +103,6 @@ static int &currentToken()
return token;
}
static const QString tooltipIName = _("tooltip");
///////////////////////////////////////////////////////////////////////
//
// GdbEngine
......@@ -2610,18 +2608,42 @@ bool GdbEngine::supportsThreads() const
return m_gdbVersion > 60500;
}
//////////////////////////////////////////////////////////////////////
//
// Tooltip specific stuff
//
//////////////////////////////////////////////////////////////////////
static WatchData m_toolTip;
static QString m_toolTipExpression;
static QPoint m_toolTipPos;
static QMap<QString, WatchData> m_toolTipCache;
void GdbEngine::setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos)
static QString tooltipINameForExpression(const QString &exp)
{
// FIXME: 'exp' can contain illegal characters
//return QLatin1String("tooltip.") + exp;
Q_UNUSED(exp);
return QLatin1String("tooltip.x");
}
bool GdbEngine::showToolTip()
{
WatchHandler *handler = qq->watchHandler();
WatchModel *model = handler->model(TooltipsWatch);
QString iname = tooltipINameForExpression(m_toolTipExpression);
model->setActiveData(iname);
WatchItem *item = model->findItem(iname, model->dummyRoot());
if (!item) {
hideDebuggerToolTip();
return false;
}
QModelIndex index = model->watchIndex(item);
showDebuggerToolTip(m_toolTipPos, model, index, m_toolTipExpression);
return true;
}
void GdbEngine::setToolTipExpression(const QPoint &mousePos,
TextEditor::ITextEditor *editor, int cursorPos)
{
if (q->status() != DebuggerInferiorStopped || !isCppEditor(editor)) {
//qDebug() << "SUPPRESSING DEBUGGER TOOLTIP, INFERIOR NOT STOPPED/Non Cpp editor";
......@@ -2635,30 +2657,21 @@ void GdbEngine::setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEd
m_toolTipPos = mousePos;
int line, column;
m_toolTipExpression = cppExpressionAt(editor, cursorPos, &line, &column);
QString exp = m_toolTipExpression;
/*
if (m_toolTip.isTypePending()) {
qDebug() << "suppressing duplicated tooltip creation";
return;
}
*/
if (m_toolTipCache.contains(exp)) {
const WatchData & data = m_toolTipCache[exp];
// FIXME: qq->watchHandler()->collapseChildren(data.iname);
insertData(data);
return;
}
QString exp = cppExpressionAt(editor, cursorPos, &line, &column);
m_toolTipExpression = exp;
// FIXME: enable caching
//if (showToolTip())
// return;
QToolTip::hideText();
if (exp.isEmpty() || exp.startsWith(_c('#'))) {
QToolTip::hideText();
//QToolTip::hideText();
return;
}
if (!hasLetterOrNumber(exp)) {
QToolTip::showText(m_toolTipPos,
tr("'%1' contains no identifier").arg(exp));
//QToolTip::showText(m_toolTipPos,
// tr("'%1' contains no identifier").arg(exp));
return;
}
......@@ -2666,7 +2679,7 @@ void GdbEngine::setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEd
return;
if (exp.startsWith(_c('"')) && exp.endsWith(_c('"'))) {
QToolTip::showText(m_toolTipPos, tr("String literal %1").arg(exp));
//QToolTip::showText(m_toolTipPos, tr("String literal %1").arg(exp));