summaryrefslogtreecommitdiff
path: root/src/plugins/debugger/watchwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/debugger/watchwindow.cpp')
-rw-r--r--src/plugins/debugger/watchwindow.cpp253
1 files changed, 253 insertions, 0 deletions
diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp
new file mode 100644
index 0000000000..6f153d2de5
--- /dev/null
+++ b/src/plugins/debugger/watchwindow.cpp
@@ -0,0 +1,253 @@
+/***************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** Non-Open Source Usage
+**
+** Licensees may use this file in accordance with the Qt Beta Version
+** License Agreement, Agreement version 2.2 provided with the Software or,
+** alternatively, in accordance with the terms contained in a written
+** agreement between you and Nokia.
+**
+** GNU General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the packaging
+** of this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+**
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt GPL Exception version
+** 1.2, included in the file GPL_EXCEPTION.txt in this package.
+**
+***************************************************************************/
+#include "watchwindow.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+
+#include <QtGui/QAction>
+#include <QtGui/QContextMenuEvent>
+#include <QtGui/QHeaderView>
+#include <QtGui/QLineEdit>
+#include <QtGui/QMenu>
+#include <QtGui/QResizeEvent>
+#include <QtGui/QSplitter>
+
+using namespace Debugger::Internal;
+
+enum { INameRole = Qt::UserRole, VisualRole };
+
+/////////////////////////////////////////////////////////////////////
+//
+// WatchWindow
+//
+/////////////////////////////////////////////////////////////////////
+
+WatchWindow::WatchWindow(Type type, QWidget *parent)
+ : QTreeView(parent), m_type(type)
+{
+ m_blocked = false;
+ setWindowTitle(tr("Locals and Watchers"));
+ setAlternatingRowColors(true);
+ setIndentation(indentation() * 9/10);
+ setUniformRowHeights(true);
+
+ connect(itemDelegate(), SIGNAL(commitData(QWidget *)),
+ this, SLOT(handleChangedItem(QWidget *)));
+ connect(this, SIGNAL(expanded(QModelIndex)),
+ this, SLOT(expandNode(QModelIndex)));
+ connect(this, SIGNAL(collapsed(QModelIndex)),
+ this, SLOT(collapseNode(QModelIndex)));
+}
+
+void WatchWindow::expandNode(const QModelIndex &idx)
+{
+ //QModelIndex mi0 = idx.sibling(idx.row(), 0);
+ //QString iname = model()->data(mi0, INameRole).toString();
+ //QString name = model()->data(mi0, Qt::DisplayRole).toString();
+ //qDebug() << "\n\nEXPAND NODE " // << iname << name
+ // << idx << (m_blocked ? "blocked" : "passed");
+ //if (isExpanded(idx))
+ // return;
+ //if (m_blocked)
+ // return;
+ emit requestExpandChildren(idx);
+}
+
+void WatchWindow::collapseNode(const QModelIndex &idx)
+{
+ //QModelIndex mi0 = idx.sibling(idx.row(), 0);
+ //QString iname = model()->data(mi0, INameRole).toString();
+ //QString name = model()->data(mi0, Qt::DisplayRole).toString();
+ //qDebug() << "COLLAPSE NODE " << idx;
+ if (m_blocked)
+ return;
+ emit requestCollapseChildren(idx);
+}
+
+void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
+{
+ QMenu menu;
+ QAction *act1 = new QAction("Adjust column widths to contents", &menu);
+ QAction *act2 = new QAction("Always adjust column widths to contents", &menu);
+ act2->setCheckable(true);
+ act2->setChecked(m_alwaysResizeColumnsToContents);
+
+ menu.addAction(act1);
+ menu.addAction(act2);
+
+ QAction *act3 = 0;
+ QAction *act4 = 0;
+ QModelIndex idx = indexAt(ev->pos());
+ QModelIndex mi0 = idx.sibling(idx.row(), 0);
+ QString exp = model()->data(mi0).toString();
+ QString iname = model()->data(mi0, INameRole).toString();
+ QModelIndex mi1 = idx.sibling(idx.row(), 0);
+ QString value = model()->data(mi1).toString();
+ bool visual = false;
+ if (idx.isValid()) {
+ menu.addSeparator();
+ if (m_type == LocalsType)
+ act3 = new QAction("Watch expression '" + exp + "'", &menu);
+ else
+ act3 = new QAction("Remove expression '" + exp + "'", &menu);
+ menu.addAction(act3);
+
+ visual = model()->data(mi0, VisualRole).toBool();
+ act4 = new QAction("Watch expression '" + exp + "' in separate widget", &menu);
+ act4->setCheckable(true);
+ act4->setChecked(visual);
+ // FIXME: menu.addAction(act4);
+ }
+
+ QAction *act = menu.exec(ev->globalPos());
+
+ if (!act)
+ ;
+ else if (act == act1)
+ resizeColumnsToContents();
+ else if (act == act2)
+ setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
+ else if (act == act3)
+ if (m_type == LocalsType)
+ emit requestWatchExpression(exp);
+ else
+ emit requestRemoveWatchExpression(iname);
+ else if (act == act4)
+ model()->setData(mi0, !visual, VisualRole);
+}
+
+void WatchWindow::resizeColumnsToContents()
+{
+ resizeColumnToContents(0);
+ resizeColumnToContents(1);
+}
+
+void WatchWindow::setAlwaysResizeColumnsToContents(bool on)
+{
+ if (!header())
+ return;
+ m_alwaysResizeColumnsToContents = on;
+ QHeaderView::ResizeMode mode = on
+ ? QHeaderView::ResizeToContents : QHeaderView::Interactive;
+ header()->setResizeMode(0, mode);
+ header()->setResizeMode(1, mode);
+}
+
+void WatchWindow::editItem(const QModelIndex &idx)
+{
+ Q_UNUSED(idx); // FIXME
+}
+
+void WatchWindow::reset()
+{
+ int row = 0;
+ if (m_type == TooltipType)
+ row = 1;
+ else if (m_type == WatchersType)
+ row = 2;
+ //qDebug() << "WATCHWINDOW::RESET" << row;
+ QTreeView::reset();
+ setRootIndex(model()->index(row, 0, model()->index(0, 0)));
+ //setRootIndex(model()->index(0, 0));
+}
+
+void WatchWindow::setModel(QAbstractItemModel *model)
+{
+ QTreeView::setModel(model);
+
+ setRootIsDecorated(true);
+ header()->setDefaultAlignment(Qt::AlignLeft);
+ header()->setResizeMode(QHeaderView::ResizeToContents);
+ if (m_type != LocalsType)
+ header()->hide();
+
+ connect(model, SIGNAL(modelAboutToBeReset()),
+ this, SLOT(modelAboutToBeReset()));
+ connect(model, SIGNAL(modelReset()),
+ this, SLOT(modelReset()));
+}
+
+void WatchWindow::modelAboutToBeReset()
+{
+ m_blocked = true;
+ //qDebug() << "Model about to be reset";
+ m_expandedItems.clear();
+ m_expandedItems.insert("local");
+ m_expandedItems.insert("watch");
+ modelAboutToBeResetHelper(model()->index(0, 0));
+ //qDebug() << " expanded: " << m_expandedItems;
+}
+
+void WatchWindow::modelAboutToBeResetHelper(const QModelIndex &idx)
+{
+ QString iname = model()->data(idx, INameRole).toString();
+ //qDebug() << "Model about to be reset helper" << iname << idx
+ // << isExpanded(idx);
+ if (isExpanded(idx))
+ m_expandedItems.insert(iname);
+ for (int i = 0, n = model()->rowCount(idx); i != n; ++i) {
+ QModelIndex idx1 = model()->index(i, 0, idx);
+ modelAboutToBeResetHelper(idx1);
+ }
+}
+
+void WatchWindow::modelReset()
+{
+ //qDebug() << "Model reset";
+ expand(model()->index(0, 0));
+ modelResetHelper(model()->index(0, 0));
+ m_blocked = false;
+}
+
+void WatchWindow::modelResetHelper(const QModelIndex &idx)
+{
+ QString name = model()->data(idx, Qt::DisplayRole).toString();
+ QString iname = model()->data(idx, INameRole).toString();
+ //qDebug() << "Model reset helper" << iname << name;
+ if (m_expandedItems.contains(iname)) {
+ expand(idx);
+ for (int i = 0, n = model()->rowCount(idx); i != n; ++i) {
+ QModelIndex idx1 = model()->index(i, 0, idx);
+ modelResetHelper(idx1);
+ }
+ }
+}
+
+void WatchWindow::handleChangedItem(QWidget *widget)
+{
+ QLineEdit *lineEdit = qobject_cast<QLineEdit *>(widget);
+ if (lineEdit)
+ requestAssignValue("foo", lineEdit->text());
+}
+