ScriptConsole: Refactor to QtMessageLogWindow

Move QML/JS independent classes to common Debugger
code. A Debugger Engine needs to override
evaluateScriptExpression() to provide engine
specific script evaluation.

Change-Id: I02b23b380a3eb1b12003b30ded0b7d075e44dfed
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
Aurindam Jana
2012-02-15 12:35:43 +01:00
committed by hjk
parent a8ab1fd70f
commit 147396d764
31 changed files with 1123 additions and 1597 deletions

View File

@@ -1,326 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#include "consolewindow.h"
#include "logwindow.h"
#include "debuggeractions.h"
#include "debuggercore.h"
#include <QDebug>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QKeyEvent>
#include <QMenu>
#include <QSyntaxHighlighter>
#include <QPlainTextEdit>
#include <aggregation/aggregate.h>
#include <coreplugin/findplaceholder.h>
#include <find/basetextfind.h>
#include <utils/savedaction.h>
namespace Debugger {
namespace Internal {
/////////////////////////////////////////////////////////////////////
//
// ConsoleHighlighter
//
/////////////////////////////////////////////////////////////////////
class ConsoleHighlighter : public QSyntaxHighlighter
{
public:
ConsoleHighlighter(QPlainTextEdit *parent)
: QSyntaxHighlighter(parent->document()), m_parent(parent)
{}
private:
void highlightBlock(const QString &text)
{
QTextCharFormat format;
switch (LogWindow::channelForChar(text.isEmpty() ? QChar() : text.at(0))) {
case LogInput:
format.setForeground(Qt::blue);
setFormat(1, text.size(), format);
break;
case LogStatus:
format.setForeground(Qt::darkGreen);
setFormat(1, text.size(), format);
break;
case LogWarning:
format.setForeground(Qt::darkYellow);
setFormat(1, text.size(), format);
break;
case LogError:
format.setForeground(Qt::red);
setFormat(1, text.size(), format);
break;
case LogTime:
format.setForeground(Qt::darkRed);
setFormat(1, text.size(), format);
break;
default:
break;
}
QColor base = m_parent->palette().color(QPalette::Base);
format.setForeground(base);
format.setFontPointSize(1);
setFormat(0, 1, format);
/*
if (text.size() > 3 && text.at(2) == QLatin1Char(':')) {
QTextCharFormat format;
format.setForeground(Qt::darkRed);
setFormat(1, text.size(), format);
}
*/
}
QPlainTextEdit *m_parent;
};
/////////////////////////////////////////////////////////////////////
//
// DebbuggerPane base class
//
/////////////////////////////////////////////////////////////////////
// FIXME: Code duplication with FakeVim
class History
{
public:
History() : m_index(0) {}
void append(const QString &item) {
m_items.removeAll(item);
m_items.append(item); m_index = m_items.size() - 1;
}
void down() { m_index = qMin(m_index + 1, m_items.size()); }
void up() { m_index = qMax(m_index - 1, 0); }
//void clear() { m_items.clear(); m_index = 0; }
void restart() { m_index = m_items.size(); }
QString current() const { return m_items.value(m_index, QString()); }
QStringList items() const { return m_items; }
private:
QStringList m_items;
int m_index;
};
class Console : public QPlainTextEdit
{
Q_OBJECT
public:
Console(QWidget *parent)
: QPlainTextEdit(parent)
{
setMaximumBlockCount(100000);
setFrameStyle(QFrame::NoFrame);
m_clearContentsAction = new QAction(this);
m_clearContentsAction->setText(tr("Clear Contents"));
m_clearContentsAction->setEnabled(true);
connect(m_clearContentsAction, SIGNAL(triggered(bool)),
parent, SLOT(clearContents()));
m_saveContentsAction = new QAction(this);
m_saveContentsAction->setText(tr("Save Contents"));
m_saveContentsAction->setEnabled(true);
connect(m_saveContentsAction, SIGNAL(triggered()), this, SLOT(saveContents()));
}
void contextMenuEvent(QContextMenuEvent *ev)
{
debuggerCore()->executeDebuggerCommand(textCursor().block().text());
QMenu *menu = createStandardContextMenu();
menu->addAction(m_clearContentsAction);
menu->addAction(m_saveContentsAction); // X11 clipboard is unreliable for long texts
menu->addAction(debuggerCore()->action(LogTimeStamps));
menu->addAction(debuggerCore()->action(VerboseLog));
menu->addSeparator();
menu->addAction(debuggerCore()->action(SettingsDialog));
menu->exec(ev->globalPos());
delete menu;
}
void keyPressEvent(QKeyEvent *ev)
{
if (ev->key() == Qt::Key_Return) {
if (ev->modifiers() == 0) {
QString cmd = textCursor().block().text();
if (cmd.isEmpty())
cmd = m_history.current();
QString cleanCmd;
foreach (QChar c, cmd)
if (c.unicode() >= 32 && c.unicode() < 128)
cleanCmd.append(c);
if (!cleanCmd.isEmpty()) {
debuggerCore()->executeDebuggerCommand(cleanCmd);
m_history.append(cleanCmd);
}
}
QPlainTextEdit::keyPressEvent(ev);
} else if (ev->key() == Qt::Key_Up) {
m_history.up();
} else if (ev->key() == Qt::Key_Down) {
m_history.down();
} else {
QPlainTextEdit::keyPressEvent(ev);
}
}
void mouseDoubleClickEvent(QMouseEvent *ev)
{
QString line = cursorForPosition(ev->pos()).block().text();
int n = 0;
// cut time string
if (line.size() > 18 && line.at(0) == QLatin1Char('['))
line = line.mid(18);
//qDebug() << line;
for (int i = 0; i != line.size(); ++i) {
QChar c = line.at(i);
if (!c.isDigit())
break;
n = 10 * n + c.unicode() - '0';
}
//emit commandSelected(n);
}
private slots:
void saveContents();
private:
QAction *m_clearContentsAction;
QAction *m_saveContentsAction;
History m_history;
};
void Console::saveContents()
{
LogWindow::writeLogContents(this, this);
}
/////////////////////////////////////////////////////////////////////
//
// ConsoleWindow
//
/////////////////////////////////////////////////////////////////////
ConsoleWindow::ConsoleWindow(QWidget *parent)
: QWidget(parent)
{
setWindowTitle(tr("Console"));
setObjectName(QLatin1String("Console"));
m_console = new Console(this);
m_console->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setMargin(0);
layout->setSpacing(0);
layout->addWidget(m_console);
layout->addWidget(new Core::FindToolBarPlaceHolder(this));
setLayout(layout);
Aggregation::Aggregate *aggregate = new Aggregation::Aggregate;
aggregate->add(m_console);
aggregate->add(new Find::BaseTextFind(m_console));
//connect(m_console, SIGNAL(statusMessageRequested(QString,int)),
// this, SIGNAL(statusMessageRequested(QString,int)));
}
void ConsoleWindow::showOutput(int channel, const QString &output)
{
if (output.isEmpty())
return;
//QTextCursor oldCursor = m_console->textCursor();
//QTextCursor cursor = oldCursor;
//cursor.movePosition(QTextCursor::End);
//bool atEnd = oldCursor.position() == cursor.position();
foreach (QString line, output.split(QLatin1Char('\n'))) {
// FIXME: QTextEdit asserts on really long lines...
const int n = 30000;
if (line.size() > n) {
line.truncate(n);
line += QLatin1String(" [...] <cut off>");
}
m_console->appendPlainText(LogWindow::charForChannel(channel) + line + QLatin1Char('\n'));
}
QTextCursor cursor = m_console->textCursor();
cursor.movePosition(QTextCursor::End);
//if (atEnd) {
m_console->setTextCursor(cursor);
m_console->ensureCursorVisible();
//}
}
void ConsoleWindow::showInput(int channel, const QString &input)
{
Q_UNUSED(channel)
m_console->appendPlainText(input);
QTextCursor cursor = m_console->textCursor();
cursor.movePosition(QTextCursor::End);
m_console->setTextCursor(cursor);
m_console->ensureCursorVisible();
}
void ConsoleWindow::clearContents()
{
m_console->clear();
}
void ConsoleWindow::setCursor(const QCursor &cursor)
{
m_console->viewport()->setCursor(cursor);
QWidget::setCursor(cursor);
}
QString ConsoleWindow::combinedContents() const
{
return m_console->toPlainText();
}
QString ConsoleWindow::inputContents() const
{
return m_console->toPlainText();
}
} // namespace Internal
} // namespace Debugger
#include "consolewindow.moc"

View File

@@ -23,7 +23,6 @@ HEADERS += \
breakpointmarker.h \
breakwindow.h \
commonoptionspage.h \
consolewindow.h \
debugger_global.h \
debuggeractions.h \
debuggercore.h \
@@ -67,7 +66,13 @@ HEADERS += \
debuggertooltipmanager.h \
debuggertoolchaincombobox.h \
debuggersourcepathmappingwidget.h \
memoryview.h
memoryview.h \
qtmessagelogwindow.h \
qtmessagelogeditor.h \
qtmessagelogview.h \
qtmessagelogproxymodel.h \
qtmessagelogitemdelegate.h \
qtmessageloghandler.h
SOURCES += \
basewindow.cpp \
@@ -76,7 +81,6 @@ SOURCES += \
breakpointmarker.cpp \
breakwindow.cpp \
commonoptionspage.cpp \
consolewindow.cpp \
debuggeractions.cpp \
debuggerdialogs.cpp \
debuggerengine.cpp \
@@ -113,7 +117,13 @@ SOURCES += \
debuggertooltipmanager.cpp \
debuggertoolchaincombobox.cpp \
debuggersourcepathmappingwidget.cpp \
memoryview.cpp
memoryview.cpp \
qtmessagelogwindow.cpp \
qtmessagelogproxymodel.cpp \
qtmessagelogview.cpp \
qtmessagelogitemdelegate.cpp \
qtmessageloghandler.cpp \
qtmessagelogeditor.cpp
FORMS += attachexternaldialog.ui \
attachcoredialog.ui \

View File

@@ -178,7 +178,8 @@ enum LogChannel
AppError, // stderr
AppStuff, // (possibly) windows debug channel
StatusBar, // LogStatus and also put to the status bar
ScriptConsoleOutput
QtMessageLogOutput,
QtMessageLogStatus
};
enum DebuggerEngineType

View File

@@ -119,6 +119,7 @@ public:
virtual void openMemoryEditor() = 0;
virtual void languagesChanged() = 0;
virtual void executeDebuggerCommand(const QString &command) = 0;
virtual bool evaluateScriptExpression(const QString &expression) = 0;
virtual Utils::SavedAction *action(int code) const = 0;
virtual bool boolSetting(int code) const = 0;

View File

@@ -50,6 +50,7 @@
#include "stackhandler.h"
#include "threadshandler.h"
#include "watchhandler.h"
#include "qtmessageloghandler.h"
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
@@ -301,6 +302,7 @@ public:
StackHandler m_stackHandler;
ThreadsHandler m_threadsHandler;
WatchHandler m_watchHandler;
QtMessageLogHandler m_qtMessageHandler;
QFutureInterface<void> m_progress;
DisassemblerAgent m_disassemblerAgent;
@@ -434,6 +436,11 @@ WatchHandler *DebuggerEngine::watchHandler() const
: &d->m_watchHandler;
}
QtMessageLogHandler *DebuggerEngine::qtMessageLogHandler() const
{
return &d->m_qtMessageHandler;
}
SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
return d->m_masterEngine
@@ -513,6 +520,14 @@ QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
return model;
}
QAbstractItemModel *DebuggerEngine::qtMessageLogModel() const
{
QAbstractItemModel *model = qtMessageLogHandler()->model();
if (model->objectName().isEmpty()) // Make debugging easier.
model->setObjectName(objectName() + QLatin1String("QtMessageLogModel"));
return model;
}
void DebuggerEngine::fetchMemory(MemoryAgent *, QObject *,
quint64 addr, quint64 length)
{
@@ -541,6 +556,9 @@ void DebuggerEngine::showMessage(const QString &msg, int channel, int timeout) c
}
//if (msg.size() && msg.at(0).isUpper() && msg.at(1).isUpper())
// qDebug() << qPrintable(msg) << "IN STATE" << state();
if (channel == QtMessageLogOutput)
qtMessageLogHandler()->appendMessage(QtMessageLogHandler::UndefinedType, msg);
debuggerCore()->showMessage(msg, channel, timeout);
if (d->m_runControl) {
d->m_runControl->showMessage(msg, channel);
@@ -1617,6 +1635,12 @@ void DebuggerEngine::executeDebuggerCommand(const QString &)
showStatusMessage(tr("This debugger cannot handle user input."));
}
bool DebuggerEngine::evaluateScriptExpression(const QString &)
{
showStatusMessage(tr("This debugger cannot handle user input."));
return false;
}
BreakHandler *DebuggerEngine::breakHandler() const
{
return debuggerCore()->breakHandler();

View File

@@ -82,6 +82,7 @@ class BreakpointParameters;
class QmlCppEngine;
class DebuggerToolTipContext;
class MemoryMarkup;
class QtMessageLogHandler;
struct WatchUpdateFlags
{
@@ -224,6 +225,7 @@ public:
virtual Internal::WatchHandler *watchHandler() const;
virtual Internal::SourceFilesHandler *sourceFilesHandler() const;
virtual Internal::BreakHandler *breakHandler() const;
virtual Internal::QtMessageLogHandler *qtMessageLogHandler() const;
virtual QAbstractItemModel *modulesModel() const;
virtual QAbstractItemModel *registerModel() const;
@@ -234,6 +236,7 @@ public:
virtual QAbstractItemModel *returnModel() const;
virtual QAbstractItemModel *toolTipsModel() const;
virtual QAbstractItemModel *sourceFilesModel() const;
virtual QAbstractItemModel *qtMessageLogModel() const;
void progressPing();
void handleFinished();
@@ -361,6 +364,7 @@ protected:
virtual void executeRunToFunction(const QString &functionName);
virtual void executeJumpToLine(const Internal::ContextData &data);
virtual void executeDebuggerCommand(const QString &command);
virtual bool evaluateScriptExpression(const QString &expression);
virtual void frameUp();
virtual void frameDown();

View File

@@ -660,7 +660,7 @@ void DebuggerMainWindowPrivate::setSimpleDockWidgetArrangement()
QDockWidget *threadsDock = q->dockWidget(QLatin1String(DOCKWIDGET_THREADS));
QDockWidget *outputDock = q->dockWidget(QLatin1String(DOCKWIDGET_OUTPUT));
QDockWidget *qmlInspectorDock = q->dockWidget(QLatin1String(DOCKWIDGET_QML_INSPECTOR));
QDockWidget *scriptConsoleDock = q->dockWidget(QLatin1String(DOCKWIDGET_QML_SCRIPTCONSOLE));
QDockWidget *consoleDock = q->dockWidget(QLatin1String(DOCKWIDGET_QML_SCRIPTCONSOLE));
QDockWidget *modulesDock = q->dockWidget(QLatin1String(DOCKWIDGET_MODULES));
QDockWidget *registerDock = q->dockWidget(QLatin1String(DOCKWIDGET_REGISTER));
QDockWidget *sourceFilesDock = q->dockWidget(QLatin1String(DOCKWIDGET_SOURCE_FILES));
@@ -671,7 +671,7 @@ void DebuggerMainWindowPrivate::setSimpleDockWidgetArrangement()
QTC_ASSERT(snapshotsDock, return);
QTC_ASSERT(threadsDock, return);
QTC_ASSERT(outputDock, return);
QTC_ASSERT(scriptConsoleDock, return);
QTC_ASSERT(consoleDock, return);
QTC_ASSERT(modulesDock, return);
QTC_ASSERT(registerDock, return);
QTC_ASSERT(sourceFilesDock, return);
@@ -697,13 +697,13 @@ void DebuggerMainWindowPrivate::setSimpleDockWidgetArrangement()
q->tabifyDockWidget(breakDock, threadsDock);
q->tabifyDockWidget(breakDock, sourceFilesDock);
q->tabifyDockWidget(breakDock, snapshotsDock);
q->tabifyDockWidget(breakDock, scriptConsoleDock);
q->tabifyDockWidget(breakDock, consoleDock);
if (m_activeDebugLanguages.testFlag(Debugger::QmlLanguage)) {
if (qmlInspectorDock)
qmlInspectorDock->show();
if (scriptConsoleDock)
scriptConsoleDock->show();
if (consoleDock)
consoleDock->show();
} else {
// CPP only
threadsDock->show();

View File

@@ -47,7 +47,7 @@
#include "breakpoint.h"
#include "breakhandler.h"
#include "breakwindow.h"
#include "consolewindow.h"
#include "qtmessagelogwindow.h"
#include "disassemblerlines.h"
#include "logwindow.h"
#include "moduleswindow.h"
@@ -114,8 +114,6 @@
#include <utils/statuslabel.h>
#include <utils/fileutils.h>
#include <qml/qmljsscriptconsole.h>
#include <QTimer>
#include <QtPlugin>
#include <QComboBox>
@@ -849,7 +847,7 @@ public slots:
void aboutToSaveSession();
void executeDebuggerCommand(const QString &command);
void evaluateExpression(const QString &expression);
bool evaluateScriptExpression(const QString &expression);
void coreShutdown();
#ifdef WITH_TESTS
@@ -1172,7 +1170,7 @@ public:
BreakWindow *m_breakWindow;
BreakHandler *m_breakHandler;
//ConsoleWindow *m_consoleWindow;
QtMessageLogWindow *m_qtMessageLogWindow;
QTreeView *m_returnWindow;
QTreeView *m_localsWindow;
QTreeView *m_watchersWindow;
@@ -1183,7 +1181,6 @@ public:
QAbstractItemView *m_stackWindow;
QAbstractItemView *m_threadsWindow;
LogWindow *m_logWindow;
QmlJSScriptConsoleWidget *m_scriptConsoleWindow;
bool m_busy;
QString m_lastPermanentStatusMessage;
@@ -1237,7 +1234,7 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) :
m_stackWindow = 0;
m_threadsWindow = 0;
m_logWindow = 0;
m_scriptConsoleWindow = 0;
m_qtMessageLogWindow = 0;
m_mainWindow = 0;
m_snapshotHandler = 0;
@@ -2096,8 +2093,7 @@ void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine)
//m_threadBox->setModel(engine->threadsModel());
//m_threadBox->setModelColumn(ThreadData::ComboNameColumn);
m_watchersWindow->setModel(engine->watchersModel());
m_scriptConsoleWindow->setEngine(engine);
m_qtMessageLogWindow->setModel(engine->qtMessageLogModel());
engine->watchHandler()->rebuildModel();
@@ -2219,7 +2215,7 @@ void DebuggerPluginPrivate::setInitialState()
action(AutoDerefPointers)->setEnabled(true);
action(ExpandStack)->setEnabled(false);
m_scriptConsoleWindow->setEnabled(false);
m_qtMessageLogWindow->setEnabled(true);
}
void DebuggerPluginPrivate::updateWatchersWindow()
@@ -2519,9 +2515,9 @@ void DebuggerPluginPrivate::showStatusMessage(const QString &msg0, int timeout)
m_statusLabel->showStatusMessage(msg, timeout);
}
void DebuggerPluginPrivate::evaluateExpression(const QString &expression)
bool DebuggerPluginPrivate::evaluateScriptExpression(const QString &expression)
{
currentEngine()->executeDebuggerCommand(expression);
return currentEngine()->evaluateScriptExpression(expression);
}
void DebuggerPluginPrivate::openMemoryEditor()
@@ -2595,9 +2591,6 @@ void DebuggerPluginPrivate::showMessage(const QString &msg, int channel, int tim
m_logWindow->showInput(LogInput, msg);
m_logWindow->showOutput(LogInput, msg);
break;
case ScriptConsoleOutput:
m_scriptConsoleWindow->appendResult(msg);
break;
case LogError: {
m_logWindow->showOutput(channel, msg);
QAction *action = m_mainWindow->dockWidget(_(DOCKWIDGET_OUTPUT))
@@ -2606,6 +2599,10 @@ void DebuggerPluginPrivate::showMessage(const QString &msg, int channel, int tim
action->trigger();
break;
}
case QtMessageLogStatus:
QTC_ASSERT(m_qtMessageLogWindow, return);
m_qtMessageLogWindow->showStatus(msg, timeout);
break;
default:
m_logWindow->showOutput(channel, msg);
break;
@@ -2874,8 +2871,8 @@ void DebuggerPluginPrivate::extensionsInitialized()
m_breakWindow->setObjectName(QLatin1String(DOCKWIDGET_BREAK));
m_breakWindow->setModel(m_breakHandler->model());
//m_consoleWindow = new ConsoleWindow;
//m_consoleWindow->setObjectName(QLatin1String("CppDebugConsole"));
m_qtMessageLogWindow = new QtMessageLogWindow();
m_qtMessageLogWindow->setObjectName(QLatin1String(DOCKWIDGET_QML_SCRIPTCONSOLE));
m_modulesWindow = new ModulesWindow;
m_modulesWindow->setObjectName(QLatin1String(DOCKWIDGET_MODULES));
m_logWindow = new LogWindow;
@@ -2894,11 +2891,6 @@ void DebuggerPluginPrivate::extensionsInitialized()
m_localsWindow->setObjectName(QLatin1String("CppDebugLocals"));
m_watchersWindow = new WatchWindow(WatchWindow::WatchersType);
m_watchersWindow->setObjectName(QLatin1String("CppDebugWatchers"));
m_scriptConsoleWindow = new QmlJSScriptConsoleWidget;
m_scriptConsoleWindow->setWindowTitle(tr("QML Script Console"));
m_scriptConsoleWindow->setObjectName(QLatin1String(DOCKWIDGET_QML_SCRIPTCONSOLE));
connect(m_scriptConsoleWindow, SIGNAL(evaluateExpression(QString)),
SLOT(evaluateExpression(QString)));
// Snapshot
m_snapshotHandler = new SnapshotHandler;
@@ -3011,11 +3003,10 @@ void DebuggerPluginPrivate::extensionsInitialized()
dock->setProperty(DOCKWIDGET_DEFAULT_AREA, Qt::TopDockWidgetArea);
m_mainWindow->createDockWidget(CppLanguage, m_breakWindow);
//m_mainWindow->createDockWidget(CppLanguage, m_consoleWindow);
m_mainWindow->createDockWidget(QmlLanguage, m_qtMessageLogWindow);
m_mainWindow->createDockWidget(CppLanguage, m_snapshotWindow);
m_mainWindow->createDockWidget(CppLanguage, m_stackWindow);
m_mainWindow->createDockWidget(CppLanguage, m_threadsWindow);
m_mainWindow->createDockWidget(QmlLanguage, m_scriptConsoleWindow);
QSplitter *localsAndWatchers = new MiniSplitter(Qt::Vertical);
localsAndWatchers->setObjectName(QLatin1String(DOCKWIDGET_WATCHERS));

View File

@@ -1,179 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#include "consolebackend.h"
#include "qmlengine.h"
#include "qmladapter.h"
#include "debuggerstringutils.h"
#include <utils/qtcassert.h>
namespace Debugger {
namespace Internal {
///////////////////////////////////////////////////////////////////////
//
// ConsoleBackend
//
///////////////////////////////////////////////////////////////////////
ConsoleBackend::ConsoleBackend(QObject *parent) :
QObject(parent)
{
}
///////////////////////////////////////////////////////////////////////
//
// QmlJSConsoleBackend
//
///////////////////////////////////////////////////////////////////////
QmlJSConsoleBackend::QmlJSConsoleBackend(QObject *parent) :
ConsoleBackend(parent),
m_engine(0),
m_inferiorStopped(false),
m_isValidContext(false),
m_Error(false)
{
}
void QmlJSConsoleBackend::setInferiorStopped(bool isInferiorStopped)
{
m_inferiorStopped = isInferiorStopped;
}
bool QmlJSConsoleBackend::inferiorStopped() const
{
return m_inferiorStopped;
}
void QmlJSConsoleBackend::setEngine(QmlEngine *engine)
{
m_engine = engine;
}
QmlEngine *QmlJSConsoleBackend::engine() const
{
return m_engine;
}
void QmlJSConsoleBackend::setIsValidContext(bool isValidContext)
{
m_isValidContext = isValidContext;
}
bool QmlJSConsoleBackend::isValidContext() const
{
return m_isValidContext;
}
void QmlJSConsoleBackend::onDebugQueryStateChanged(
QmlJsDebugClient::QDeclarativeDebugQuery::State state)
{
QmlJsDebugClient::QDeclarativeDebugExpressionQuery *query =
qobject_cast<QmlJsDebugClient::QDeclarativeDebugExpressionQuery *>(
sender());
if (query && state != QmlJsDebugClient::QDeclarativeDebugQuery::Error)
emit message(ConsoleItemModel::UndefinedType,
query->result().toString());
else
emit message(ConsoleItemModel::ErrorType,
_("Error evaluating expression."));
delete query;
}
void QmlJSConsoleBackend::evaluate(const QString &script,
bool *returnKeyConsumed)
{
*returnKeyConsumed = true;
m_Error = false;
//Check if string is only white spaces
if (!script.trimmed().isEmpty()) {
//Check for a valid context
if (m_isValidContext) {
//check if it can be evaluated
if (canEvaluateScript(script)) {
//Evaluate expression based on engine state
//When engine->state() == InferiorStopOk, the expression
//is sent to V8DebugService. In all other cases, the
//expression is evaluated by QDeclarativeEngine.
if (!m_inferiorStopped) {
QmlAdapter *adapter = m_engine->adapter();
QTC_ASSERT(adapter, return);
QDeclarativeEngineDebug *engineDebug =
adapter->engineDebugClient();
int id = adapter->currentSelectedDebugId();
if (engineDebug && id != -1) {
QDeclarativeDebugExpressionQuery *query =
engineDebug->queryExpressionResult(id, script);
connect(query,
SIGNAL(stateChanged(
QmlJsDebugClient::QDeclarativeDebugQuery
::State)),
this,
SLOT(onDebugQueryStateChanged(
QmlJsDebugClient::QDeclarativeDebugQuery
::State)));
}
} else {
emit evaluateExpression(script);
}
} else {
*returnKeyConsumed = false;
}
} else {
//Incase of invalid context, append the expression to history
//and show Error message
m_Error = true;
}
}
}
void QmlJSConsoleBackend::emitErrorMessage()
{
if (m_Error)
emit message(
ConsoleItemModel::ErrorType,
_("Cannot evaluate without a valid QML/JS Context"));
}
bool QmlJSConsoleBackend::canEvaluateScript(const QString &script)
{
m_interpreter.clearText();
m_interpreter.appendText(script);
return m_interpreter.canEvaluate();
}
}
}

View File

@@ -1,100 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#ifndef CONSOLEBACKEND_H
#define CONSOLEBACKEND_H
#include "consoleitemmodel.h"
#include "interactiveinterpreter.h"
#include <qmljsdebugclient/qdeclarativeenginedebug.h>
#include <QtCore/QObject>
namespace Debugger {
namespace Internal {
class ConsoleBackend : public QObject
{
Q_OBJECT
public:
explicit ConsoleBackend(QObject *parent = 0);
virtual void emitErrorMessage() = 0;
virtual void evaluate(const QString &, bool *returnKeyConsumed) = 0;
signals:
void message(ConsoleItemModel::ItemType itemType, const QString &msg);
};
class QmlEngine;
class QmlJSConsoleBackend : public ConsoleBackend
{
Q_OBJECT
public:
explicit QmlJSConsoleBackend(QObject *parent = 0);
void setInferiorStopped(bool inferiorStopped);
bool inferiorStopped() const;
void setEngine(QmlEngine *engine);
QmlEngine *engine() const;
void setIsValidContext(bool isValidContext);
bool isValidContext() const;
virtual void evaluate(const QString &, bool *returnKeyConsumed);
void emitErrorMessage();
private slots:
void onDebugQueryStateChanged(
QmlJsDebugClient::QDeclarativeDebugQuery::State state);
signals:
void evaluateExpression(const QString &);
private:
bool canEvaluateScript(const QString &script);
private:
QmlEngine *m_engine;
InteractiveInterpreter m_interpreter;
bool m_inferiorStopped;
bool m_isValidContext;
bool m_Error;
};
} //Internal
} //Debugger
#endif // CONSOLEBACKEND_H

View File

@@ -1,348 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#include "consoleitemmodel.h"
namespace Debugger {
namespace Internal {
class ConsoleItem
{
public:
ConsoleItem(const QString &data = QString(),
ConsoleItemModel::ItemType type = ConsoleItemModel::UndefinedType,
ConsoleItem *parent = 0);
~ConsoleItem();
ConsoleItem *child(int number);
int childCount() const;
QString text() const;
ConsoleItemModel::ItemType itemType() const;
bool insertChildren(int position, int count);
ConsoleItem *parent();
bool removeChildren(int position, int count);
bool removeColumns(int position, int columns);
int childNumber() const;
bool setData(const QString &text, ConsoleItemModel::ItemType itemType);
bool setText(const QString &text);
bool setItemType(ConsoleItemModel::ItemType itemType);
private:
QList<ConsoleItem *> m_childItems;
QString m_text;
ConsoleItemModel::ItemType m_itemType;
ConsoleItem *m_parentItem;
};
///////////////////////////////////////////////////////////////////////
//
// ConsoleItem
//
///////////////////////////////////////////////////////////////////////
ConsoleItem::ConsoleItem(const QString &text,
ConsoleItemModel::ItemType itemType,
ConsoleItem *parent)
: m_text(text),
m_itemType(itemType),
m_parentItem(parent)
{
}
ConsoleItem::~ConsoleItem()
{
qDeleteAll(m_childItems);
}
ConsoleItem *ConsoleItem::child(int number)
{
return m_childItems.value(number);
}
int ConsoleItem::childCount() const
{
return m_childItems.count();
}
int ConsoleItem::childNumber() const
{
if (m_parentItem)
return m_parentItem->m_childItems.indexOf(const_cast<ConsoleItem *>(this));
return 0;
}
QString ConsoleItem::text() const
{
return m_text;
}
ConsoleItemModel::ItemType ConsoleItem::itemType() const
{
return m_itemType;
}
\
bool ConsoleItem::insertChildren(int position, int count)
{
if (position < 0 || position > m_childItems.size())
return false;
for (int row = 0; row < count; ++row) {
ConsoleItem *item = new ConsoleItem(QString(),
ConsoleItemModel::UndefinedType, this);
m_childItems.insert(position, item);
}
return true;
}
ConsoleItem *ConsoleItem::parent()
{
return m_parentItem;
}
bool ConsoleItem::removeChildren(int position, int count)
{
if (position < 0 || position + count > m_childItems.size())
return false;
for (int row = 0; row < count; ++row)
delete m_childItems.takeAt(position);
return true;
}
bool ConsoleItem::removeColumns(int /*position*/, int /*columns*/)
{
return false;
}
bool ConsoleItem::setData(const QString &text,
ConsoleItemModel::ItemType itemType)
{
m_text = text;
m_itemType = itemType;
return true;
}
bool ConsoleItem::setText(const QString &text)
{
m_text = text;
return true;
}
bool ConsoleItem::setItemType(ConsoleItemModel::ItemType itemType)
{
m_itemType = itemType;
return true;
}
///////////////////////////////////////////////////////////////////////
//
// ConsoleItemModel
//
///////////////////////////////////////////////////////////////////////
ConsoleItemModel::ConsoleItemModel(QObject *parent) :
QAbstractItemModel(parent)
{
m_rootItem = new ConsoleItem();
}
ConsoleItemModel::~ConsoleItemModel()
{
delete m_rootItem;
}
void ConsoleItemModel::clear()
{
beginResetModel();
reset();
delete m_rootItem;
m_rootItem = new ConsoleItem();
endResetModel();
//Insert an empty row
appendEditableRow();
}
void ConsoleItemModel::appendItem(ItemType itemType, QString message)
{
int position = m_rootItem->childCount() - 1;
insertRow(position);
QModelIndex idx = index(position, 0);
if (getItem(idx)->setData(message, itemType))
emit dataChanged(idx, idx);
}
void ConsoleItemModel::appendEditableRow()
{
int position = m_rootItem->childCount();
insertRow(position);
QModelIndex idx = index(position, 0);
if (getItem(idx)->setData(QString(), ConsoleItemModel::InputType)) {
QModelIndex idx = index(position, 0);
emit dataChanged(idx, idx);
emit editableRowAppended(idx, QItemSelectionModel::ClearAndSelect);
}
}
///////////////////////////////////////////////////////////////////////
//
// ConsoleEditor
//
///////////////////////////////////////////////////////////////////////
QVariant ConsoleItemModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
ConsoleItem *item = getItem(index);
if (role == Qt::DisplayRole )
return item->text();
else if (role == ConsoleItemModel::TypeRole)
return int(item->itemType());
else
return QVariant();
}
QModelIndex ConsoleItemModel::index(int row, int column,
const QModelIndex &parent) const
{
if (parent.isValid() && parent.column() != 0)
return QModelIndex();
if (column > 0)
return QModelIndex();
ConsoleItem *parentItem = getItem(parent);
ConsoleItem *childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
else
return QModelIndex();
}
QModelIndex ConsoleItemModel::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
ConsoleItem *childItem = getItem(index);
ConsoleItem *parentItem = childItem->parent();
if (parentItem == m_rootItem)
return QModelIndex();
return createIndex(parentItem->childNumber(), 0, parentItem);
}
int ConsoleItemModel::rowCount(const QModelIndex &parent) const
{
ConsoleItem *parentItem = getItem(parent);
return parentItem->childCount();
}
int ConsoleItemModel::columnCount(const QModelIndex & /* parent */) const
{
return 1;
}
Qt::ItemFlags ConsoleItemModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
ConsoleItem *item = getItem(index);
if (item->parent() == m_rootItem && index.row() == m_rootItem->childCount() - 1)
return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
bool ConsoleItemModel::setData(const QModelIndex &index, const QVariant &value,
int role)
{
ConsoleItem *item = getItem(index);
bool result = false;
if (role == Qt::DisplayRole )
result = item->setText(value.toString());
else if (role == ConsoleItemModel::TypeRole)
result = item->setItemType((ItemType)value.toInt());
else if (value.canConvert(QVariant::String))
result = item->setText(value.toString());
if (result)
emit dataChanged(index, index);
return result;
}
bool ConsoleItemModel::insertRows(int position, int rows, const QModelIndex &parent)
{
ConsoleItem *parentItem = getItem(parent);
bool success;
beginInsertRows(parent, position, position + rows - 1);
success = parentItem->insertChildren(position, rows);
endInsertRows();
return success;
}
bool ConsoleItemModel::removeRows(int position, int rows, const QModelIndex &parent)
{
ConsoleItem *parentItem = getItem(parent);
bool success = true;
beginRemoveRows(parent, position, position + rows - 1);
success = parentItem->removeChildren(position, rows);
endRemoveRows();
return success;
}
ConsoleItem *ConsoleItemModel::getItem(const QModelIndex &index) const
{
if (index.isValid()) {
ConsoleItem *item = static_cast<ConsoleItem*>(index.internalPointer());
if (item) return item;
}
return m_rootItem;
}
} //Internal
} //Debugger

View File

@@ -6,29 +6,16 @@ HEADERS += \
$$PWD/qmldebuggerclient.h \
$$PWD/qmljsprivateapi.h \
$$PWD/qmlcppengine.h \
$$PWD/qmljsscriptconsole.h \
$$PWD/qscriptdebuggerclient.h \
$$PWD/qmlv8debuggerclient.h \
$$PWD/interactiveinterpreter.h \
$$PWD/qmlv8debuggerclientconstants.h \
$$PWD/consoletreeview.h \
$$PWD/consoleitemmodel.h \
$$PWD/consoleitemdelegate.h \
$$PWD/consoleeditor.h \
$$PWD/consolebackend.h
$$PWD/qmlv8debuggerclientconstants.h
SOURCES += \
$$PWD/qmlengine.cpp \
$$PWD/qmladapter.cpp \
$$PWD/qmldebuggerclient.cpp \
$$PWD/qmlcppengine.cpp \
$$PWD/qmljsscriptconsole.cpp \
$$PWD/qscriptdebuggerclient.cpp \
$$PWD/qmlv8debuggerclient.cpp \
$$PWD/interactiveinterpreter.cpp \
$$PWD/consoletreeview.cpp \
$$PWD/consoleitemmodel.cpp \
$$PWD/consoleitemdelegate.cpp \
$$PWD/consoleeditor.cpp \
$$PWD/consolebackend.cpp
$$PWD/interactiveinterpreter.cpp

View File

@@ -36,6 +36,7 @@
#include "debuggerstartparameters.h"
#include "stackhandler.h"
#include "qmlengine.h"
#include "qtmessageloghandler.h"
#include <coreplugin/icore.h>
#include <utils/qtcassert.h>
@@ -426,6 +427,11 @@ void QmlCppEngine::executeDebuggerCommand(const QString &command)
}
}
bool QmlCppEngine::evaluateScriptExpression(const QString &expression)
{
return d->m_qmlEngine->evaluateScriptExpression(expression);
}
/////////////////////////////////////////////////////////
void QmlCppEngine::setupEngine()
@@ -811,6 +817,11 @@ void QmlCppEngine::resetLocation()
DebuggerEngine::resetLocation();
}
Internal::QtMessageLogHandler *QmlCppEngine::qtMessageLogHandler() const
{
return d->m_qmlEngine->qtMessageLogHandler();
}
DebuggerEngine *QmlCppEngine::cppEngine() const
{
return d->m_cppEngine;

View File

@@ -96,6 +96,8 @@ public:
int timeout = -1) const;
void resetLocation();
Internal::QtMessageLogHandler *qtMessageLogHandler() const;
protected:
void detachDebugger();
void executeStep();
@@ -112,6 +114,7 @@ protected:
void executeRunToFunction(const QString &functionName);
void executeJumpToLine(const ContextData &data);
void executeDebuggerCommand(const QString &command);
bool evaluateScriptExpression(const QString &expression);
void setupEngine();
void setupInferior();

View File

@@ -32,6 +32,7 @@
#include "qmlengine.h"
#include "qmladapter.h"
#include "interactiveinterpreter.h"
#include "debuggerstartparameters.h"
#include "debuggeractions.h"
@@ -51,11 +52,13 @@
#include "watchhandler.h"
#include "sourcefileshandler.h"
#include "watchutils.h"
#include "qtmessageloghandler.h"
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/applicationlauncher.h>
#include <qmljsdebugclient/qdeclarativeoutputparser.h>
#include <qmljseditor/qmljseditorconstants.h>
#include <qmljsdebugclient/qdebugmessageclient.h>
#include <utils/environment.h>
#include <utils/qtcassert.h>
@@ -112,10 +115,13 @@ private:
QmlJsDebugClient::QDeclarativeOutputParser m_outputParser;
QHash<QString, QTextDocument*> m_sourceDocuments;
QHash<QString, QWeakPointer<TextEditor::ITextEditor> > m_sourceEditors;
InteractiveInterpreter m_interpreter;
bool m_validContext;
};
QmlEnginePrivate::QmlEnginePrivate(QmlEngine *q)
: m_adapter(q)
: m_adapter(q),
m_validContext(false)
{}
@@ -145,6 +151,15 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters,
connect(&d->m_adapter, SIGNAL(connectionStartupFailed()),
SLOT(connectionStartupFailed()));
connect(this, SIGNAL(stateChanged(Debugger::DebuggerState)),
SLOT(updateCurrentContext()));
connect(this->stackHandler(), SIGNAL(currentIndexChanged()),
SLOT(updateCurrentContext()));
connect(&d->m_adapter, SIGNAL(selectionChanged()),
SLOT(updateCurrentContext()));
connect(d->m_adapter.messageClient(), SIGNAL(message(QtMsgType,QString)),
SLOT(appendDebugOutput(QtMsgType,QString)));
connect(&d->m_applicationLauncher,
SIGNAL(processExited(int)),
SLOT(disconnected()));
@@ -169,6 +184,8 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters,
d->m_noDebugOutputTimer.setSingleShot(true);
d->m_noDebugOutputTimer.setInterval(8000);
connect(&d->m_noDebugOutputTimer, SIGNAL(timeout()), this, SLOT(beginConnection()));
qtMessageLogHandler()->setHasEditableRow(true);
}
QmlEngine::~QmlEngine()
@@ -781,6 +798,23 @@ void QmlEngine::synchronizeWatchers()
}
}
void QmlEngine::onDebugQueryStateChanged(
QmlJsDebugClient::QDeclarativeDebugQuery::State state)
{
QmlJsDebugClient::QDeclarativeDebugExpressionQuery *query =
qobject_cast<QmlJsDebugClient::QDeclarativeDebugExpressionQuery *>(
sender());
if (query && state != QmlJsDebugClient::QDeclarativeDebugQuery::Error)
qtMessageLogHandler()->
appendItem(new QtMessageLogItem(QtMessageLogHandler::UndefinedType,
query->result().toString()));
else
qtMessageLogHandler()->
appendItem(new QtMessageLogItem(QtMessageLogHandler::ErrorType,
_("Error evaluating expression.")));
delete query;
}
bool QmlEngine::hasCapability(unsigned cap) const
{
return cap & (AddWatcherCapability
@@ -828,6 +862,36 @@ void QmlEngine::wrongSetupMessageBoxFinished(int result)
}
}
void QmlEngine::updateCurrentContext()
{
const QString context = state() == InferiorStopOk ?
stackHandler()->currentFrame().function :
d->m_adapter.currentSelectedDisplayName();
d->m_validContext = !context.isEmpty();
showMessage(tr("Context: ").append(context), QtMessageLogStatus);
}
void QmlEngine::appendDebugOutput(QtMsgType type, const QString &message)
{
QtMessageLogHandler::ItemType itemType;
switch (type) {
case QtDebugMsg:
itemType = QtMessageLogHandler::DebugType;
break;
case QtWarningMsg:
itemType = QtMessageLogHandler::WarningType;
break;
case QtCriticalMsg:
case QtFatalMsg:
itemType = QtMessageLogHandler::ErrorType;
break;
default:
//This case is not possible
return;
}
qtMessageLogHandler()->appendItem(new QtMessageLogItem(itemType, message));
}
void QmlEngine::executeDebuggerCommand(const QString& command)
{
if (d->m_adapter.activeDebuggerClient()) {
@@ -835,6 +899,54 @@ void QmlEngine::executeDebuggerCommand(const QString& command)
}
}
bool QmlEngine::evaluateScriptExpression(const QString& expression)
{
bool didEvaluate = true;
//Check if string is only white spaces
if (!expression.trimmed().isEmpty()) {
//Check for a valid context
if (d->m_validContext) {
//check if it can be evaluated
if (canEvaluateScript(expression)) {
//Evaluate expression based on engine state
//When engine->state() == InferiorStopOk, the expression
//is sent to V8DebugService. In all other cases, the
//expression is evaluated by QDeclarativeEngine.
if (state() != InferiorStopOk) {
QDeclarativeEngineDebug *engineDebug =
d->m_adapter.engineDebugClient();
int id = d->m_adapter.currentSelectedDebugId();
if (engineDebug && id != -1) {
QDeclarativeDebugExpressionQuery *query =
engineDebug->queryExpressionResult(id, expression);
connect(query,
SIGNAL(stateChanged(
QmlJsDebugClient::QDeclarativeDebugQuery
::State)),
this,
SLOT(onDebugQueryStateChanged(
QmlJsDebugClient::QDeclarativeDebugQuery
::State)));
}
} else {
executeDebuggerCommand(expression);
}
} else {
didEvaluate = false;
}
} else {
//Incase of invalid context, show Error message
qtMessageLogHandler()->
appendItem(new QtMessageLogItem(
QtMessageLogHandler::ErrorType,
_("Cannot evaluate without"
"a valid QML/JS Context.")),
qtMessageLogHandler()->rowCount());
}
}
return didEvaluate;
}
QString QmlEngine::qmlImportPath() const
{
@@ -931,6 +1043,13 @@ void QmlEngine::updateEditor(Core::IEditor *editor, const QTextDocument *documen
plainTextEdit->setReadOnly(true);
}
bool QmlEngine::canEvaluateScript(const QString &script)
{
d->m_interpreter.clearText();
d->m_interpreter.appendText(script);
return d->m_interpreter.canEvaluate();
}
QmlAdapter *QmlEngine::adapter() const
{
return &d->m_adapter;

View File

@@ -34,7 +34,7 @@
#define DEBUGGER_QMLENGINE_H
#include "debuggerengine.h"
#include <qmljsdebugclient/qdeclarativeenginedebug.h>
#include <utils/outputformat.h>
#include <QAbstractSocket>
@@ -96,6 +96,8 @@ private slots:
void retryMessageBoxFinished(int result);
void wrongSetupMessageBox(const QString &errorMessage);
void wrongSetupMessageBoxFinished(int result);
void updateCurrentContext();
void appendDebugOutput(QtMsgType type, const QString &message);
private:
// DebuggerEngine implementation.
@@ -147,6 +149,7 @@ private:
void updateWatchData(const WatchData &data,
const WatchUpdateFlags &flags);
void executeDebuggerCommand(const QString &command);
bool evaluateScriptExpression(const QString &expression);
bool hasCapability(unsigned) const;
@@ -163,6 +166,8 @@ private slots:
void appendMessage(const QString &msg, Utils::OutputFormat);
void synchronizeWatchers();
void onDebugQueryStateChanged(
QmlJsDebugClient::QDeclarativeDebugQuery::State state);
private:
void closeConnection();
@@ -176,6 +181,7 @@ private:
QString qmlImportPath() const;
void updateEditor(Core::IEditor *editor, const QTextDocument *document);
bool canEvaluateScript(const QString &script);
private:
friend class QmlCppEngine;

View File

@@ -1,327 +0,0 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#include "qmljsscriptconsole.h"
#include "qmladapter.h"
#include "debuggerstringutils.h"
#include "consoletreeview.h"
#include "consoleitemmodel.h"
#include "consoleitemdelegate.h"
#include "consolebackend.h"
#include "debuggerstringutils.h"
#include <extensionsystem/pluginmanager.h>
#include <coreplugin/coreconstants.h>
#include <utils/statuslabel.h>
#include <utils/styledbar.h>
#include <utils/savedaction.h>
#include <coreplugin/icore.h>
#include <qmljsdebugclient/qdebugmessageclient.h>
#include <debugger/qml/qmlcppengine.h>
#include <debugger/qml/qmlengine.h>
#include <debugger/stackhandler.h>
#include <debugger/stackframe.h>
#include <QMenu>
#include <QTextBlock>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QToolButton>
#include <QCheckBox>
static const char SCRIPT_CONSOLE[] = "ScriptConsole";
static const char SHOW_LOG[] = "showLog";
static const char SHOW_WARNING[] = "showWarning";
static const char SHOW_ERROR[] = "showError";
namespace Debugger {
namespace Internal {
///////////////////////////////////////////////////////////////////////
//
// QmlJSScriptConsoleWidget
//
///////////////////////////////////////////////////////////////////////
QmlJSScriptConsoleWidget::QmlJSScriptConsoleWidget(QWidget *parent)
: QWidget(parent)
{
const int statusBarHeight = 25;
const int spacing = 7;
const int buttonWidth = 25;
QVBoxLayout *vbox = new QVBoxLayout(this);
vbox->setMargin(0);
vbox->setSpacing(0);
QWidget *statusbarContainer = new QWidget;
statusbarContainer->setFixedHeight(statusBarHeight);
QHBoxLayout *hbox = new QHBoxLayout(statusbarContainer);
hbox->setMargin(0);
hbox->setSpacing(0);
//Status Label
m_statusLabel = new Utils::StatusLabel;
hbox->addSpacing(spacing);
hbox->addWidget(m_statusLabel);
hbox->addWidget(new Utils::StyledSeparator);
//Filters
hbox->addSpacing(spacing);
m_showLog = new QToolButton(this);
m_showLog->setAutoRaise(true);
m_showLog->setFixedWidth(buttonWidth);
m_showLogAction = new Utils::SavedAction(this);
m_showLogAction->setDefaultValue(true);
m_showLogAction->setSettingsKey(_(SCRIPT_CONSOLE), _(SHOW_LOG));
m_showLogAction->setText(tr("Log"));
m_showLogAction->setCheckable(true);
m_showLogAction->setIcon(QIcon(_(":/debugger/images/log.png")));
// connect(m_showLogAction, SIGNAL(toggled(bool)), this, SLOT(setDebugLevel()));
m_showLog->setDefaultAction(m_showLogAction);
m_showWarning = new QToolButton(this);
m_showWarning->setAutoRaise(true);
m_showWarning->setFixedWidth(buttonWidth);
m_showWarningAction = new Utils::SavedAction(this);
m_showWarningAction->setDefaultValue(true);
m_showWarningAction->setSettingsKey(_(SCRIPT_CONSOLE), _(SHOW_WARNING));
m_showWarningAction->setText(tr("Warning"));
m_showWarningAction->setCheckable(true);
m_showWarningAction->setIcon(QIcon(_(":/debugger/images/warning.png")));
// connect(m_showWarningAction, SIGNAL(toggled(bool)), this, SLOT(setDebugLevel()));
m_showWarning->setDefaultAction(m_showWarningAction);
m_showError = new QToolButton(this);
m_showError->setAutoRaise(true);
m_showError->setFixedWidth(buttonWidth);
m_showErrorAction = new Utils::SavedAction(this);
m_showErrorAction->setDefaultValue(true);
m_showErrorAction->setSettingsKey(_(SCRIPT_CONSOLE), _(SHOW_ERROR));
m_showErrorAction->setText(tr("Error"));
m_showErrorAction->setCheckable(true);
m_showErrorAction->setIcon(QIcon(_(":/debugger/images/error.png")));
// connect(m_showErrorAction, SIGNAL(toggled(bool)), this, SLOT(setDebugLevel()));
m_showError->setDefaultAction(m_showErrorAction);
hbox->addWidget(m_showLog);
hbox->addSpacing(spacing);
hbox->addWidget(m_showWarning);
hbox->addSpacing(spacing);
hbox->addWidget(m_showError);
//Clear Button
QToolButton *clearButton = new QToolButton;
clearButton->setAutoRaise(true);
clearButton->setFixedWidth(buttonWidth);
QAction *clearAction = new QAction(tr("Clear Console"), this);
clearAction->setIcon(QIcon(_(Core::Constants::ICON_CLEAN_PANE)));
clearButton->setDefaultAction(clearAction);
hbox->addSpacing(spacing);
hbox->addWidget(clearButton);
hbox->addSpacing(spacing);
m_consoleView = new ConsoleTreeView(this);
m_model = new ConsoleItemModel(this);
m_model->clear();
connect(clearAction, SIGNAL(triggered()), m_model, SLOT(clear()));
m_consoleView->setModel(m_model);
connect(m_model,
SIGNAL(editableRowAppended(QModelIndex,QItemSelectionModel::SelectionFlags)),
m_consoleView->selectionModel(),
SLOT(setCurrentIndex(QModelIndex,QItemSelectionModel::SelectionFlags)));
m_consoleBackend = new QmlJSConsoleBackend(this);
connect(m_consoleBackend, SIGNAL(evaluateExpression(QString)),
this, SIGNAL(evaluateExpression(QString)));
connect(m_consoleBackend, SIGNAL(message(ConsoleItemModel::ItemType,QString)),
this, SLOT(appendOutput(ConsoleItemModel::ItemType,QString)));
m_itemDelegate = new ConsoleItemDelegate(this);
connect(m_itemDelegate, SIGNAL(appendEditableRow()),
m_model, SLOT(appendEditableRow()));
m_itemDelegate->setConsoleBackend(m_consoleBackend);
m_consoleView->setItemDelegate(m_itemDelegate);
vbox->addWidget(statusbarContainer);
vbox->addWidget(m_consoleView);
readSettings();
connect(Core::ICore::instance(),
SIGNAL(saveSettingsRequested()), SLOT(writeSettings()));
}
QmlJSScriptConsoleWidget::~QmlJSScriptConsoleWidget()
{
writeSettings();
}
void QmlJSScriptConsoleWidget::readSettings()
{
QSettings *settings = Core::ICore::settings();
m_showLogAction->readSettings(settings);
m_showWarningAction->readSettings(settings);
m_showErrorAction->readSettings(settings);
}
void QmlJSScriptConsoleWidget::writeSettings() const
{
QSettings *settings = Core::ICore::settings();
m_showLogAction->writeSettings(settings);
m_showWarningAction->writeSettings(settings);
m_showErrorAction->writeSettings(settings);
}
void QmlJSScriptConsoleWidget::setEngine(DebuggerEngine *engine)
{
QmlEngine *qmlEngine = m_consoleBackend->engine();
if (qmlEngine) {
disconnect(qmlEngine, SIGNAL(stateChanged(Debugger::DebuggerState)),
this, SLOT(onEngineStateChanged(Debugger::DebuggerState)));
disconnect(qmlEngine->stackHandler(), SIGNAL(currentIndexChanged()),
this, SLOT(onSelectionChanged()));
disconnect(qmlEngine->adapter(), SIGNAL(selectionChanged()),
this, SLOT(onSelectionChanged()));
disconnect(qmlEngine->adapter()->messageClient(),
SIGNAL(message(QtMsgType,QString)),
this, SLOT(appendMessage(QtMsgType,QString)));
qmlEngine = 0;
}
qmlEngine = qobject_cast<QmlEngine *>(engine);
QmlCppEngine *qmlCppEngine = qobject_cast<QmlCppEngine *>(engine);
if (qmlCppEngine)
qmlEngine = qobject_cast<QmlEngine *>(qmlCppEngine->qmlEngine());
//Supports only QML Engine
if (qmlEngine) {
connect(qmlEngine, SIGNAL(stateChanged(Debugger::DebuggerState)),
this, SLOT(onEngineStateChanged(Debugger::DebuggerState)));
connect(qmlEngine->stackHandler(), SIGNAL(currentIndexChanged()),
this, SLOT(onSelectionChanged()));
connect(qmlEngine->adapter(), SIGNAL(selectionChanged()),
this, SLOT(onSelectionChanged()));
connect(qmlEngine->adapter()->messageClient(),
SIGNAL(message(QtMsgType,QString)),
this, SLOT(appendMessage(QtMsgType,QString)));
onEngineStateChanged(qmlEngine->state());
}
m_consoleBackend->setEngine(qmlEngine);
}
void QmlJSScriptConsoleWidget::appendResult(const QString &result)
{
m_model->appendItem(ConsoleItemModel::UndefinedType, result);
}
void QmlJSScriptConsoleWidget::onEngineStateChanged(Debugger::DebuggerState state)
{
if (state == InferiorRunOk || state == InferiorStopOk) {
setEnabled(true);
m_consoleBackend->setInferiorStopped(state == InferiorStopOk);
} else {
setEnabled(false);
}
}
void QmlJSScriptConsoleWidget::onSelectionChanged()
{
QmlEngine *qmlEngine = m_consoleBackend->engine();
if (qmlEngine && qmlEngine->adapter()) {
const QString context = m_consoleBackend->inferiorStopped() ?
qmlEngine->stackHandler()->currentFrame().function :
qmlEngine->adapter()->currentSelectedDisplayName();
m_consoleBackend->setIsValidContext(!context.isEmpty());
m_statusLabel->showStatusMessage(tr("Context: ").append(context), 0);
}
}
void QmlJSScriptConsoleWidget::appendOutput(ConsoleItemModel::ItemType itemType,
const QString &message)
{
if (itemType == ConsoleItemModel::UndefinedType)
return m_model->appendItem(itemType, message);
QtMsgType type;
switch (itemType) {
case ConsoleItemModel::LogType:
type = QtDebugMsg;
break;
case ConsoleItemModel::WarningType:
type = QtWarningMsg;
break;
case ConsoleItemModel::ErrorType:
type = QtCriticalMsg;
break;
default:
type = QtDebugMsg;
break;
}
appendMessage(type, message);
}
void QmlJSScriptConsoleWidget::appendMessage(QtMsgType type, const QString &message)
{
ConsoleItemModel::ItemType itemType;
switch (type) {
case QtDebugMsg:
if (!m_showLogAction->isChecked())
return;
itemType = ConsoleItemModel::LogType;
break;
case QtWarningMsg:
if (!m_showWarningAction->isChecked())
return;
itemType = ConsoleItemModel::WarningType;
break;
case QtCriticalMsg:
case QtFatalMsg:
if (!m_showErrorAction->isChecked())
return;
itemType = ConsoleItemModel::ErrorType;
break;
default:
//this cannot happen as type has to
//be one of the above
//return since itemType is not known
return;
}
m_model->appendItem(itemType, message);
}
} //Internal
} //Debugger

View File

@@ -1146,7 +1146,9 @@ void QmlV8DebuggerClient::assignValueInDebugger(const QByteArray /*expr*/, const
if (stackHandler->isContentsValid() && stackHandler->currentFrame().isUsable()) {
d->evaluate(expression, false, false, stackHandler->currentIndex());
} else {
d->engine->showMessage(QString(_("Cannot evaluate %1 in current stack frame")).arg(expression), ScriptConsoleOutput);
d->engine->showMessage(QString(_("Cannot evaluate"
"%1 in current stack frame")).
arg(expression), QtMessageLogOutput);
}
}
@@ -1163,8 +1165,9 @@ void QmlV8DebuggerClient::executeDebuggerCommand(const QString &command)
d->evaluatingExpression.insert(d->sequence, command);
} else {
//Currently cannot evaluate if not in a javascript break
d->engine->showMessage(QString(_("Cannot evaluate %1 in current stack frame")).arg(command), ScriptConsoleOutput);
// d->evaluate(command);
d->engine->showMessage(QString(_("Cannot evaluate %1"
"in current stack frame")).
arg(command), QtMessageLogOutput);
}
}
@@ -1825,7 +1828,7 @@ void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success, con
d->engine->watchHandler()->endCycle();
} else {
d->engine->showMessage(body.value.toString(), ScriptConsoleOutput);
d->engine->showMessage(body.value.toString(), QtMessageLogOutput);
//Update the locals
foreach (int index, d->currentFrameScopes)
d->scope(index);
@@ -2014,7 +2017,7 @@ void QmlV8DebuggerClient::highlightExceptionCode(int lineNumber,
QString message = QString(_("%1: %2: %3")).arg(filePath).arg(lineNumber)
.arg(errorMessage);
d->engine->showMessage(message, ScriptConsoleOutput);
d->engine->showMessage(message, QtMessageLogOutput);
}
}
}

View File

@@ -519,7 +519,7 @@ void QScriptDebuggerClient::messageReceived(const QByteArray &data)
if (iname.startsWith("watch.")) {
d->engine->watchHandler()->insertData(data);
} else if (iname == "console") {
d->engine->showMessage(data.value, ScriptConsoleOutput);
d->engine->showMessage(data.value, QtMessageLogOutput);
} else {
qWarning() << "QmlEngine: Unexcpected result: " << iname << data.value;
}

View File

@@ -30,15 +30,15 @@
**
**************************************************************************/
#include "consoleeditor.h"
#include "consoleitemmodel.h"
#include "consoleitemdelegate.h"
#include "consolebackend.h"
#include "qtmessagelogeditor.h"
#include "qtmessageloghandler.h"
#include "debuggerstringutils.h"
#include "debuggercore.h"
#include "debuggerengine.h"
#include <utils/qtcassert.h>
#include <QUrl>
#include <QMenu>
#include <QKeyEvent>
@@ -47,56 +47,47 @@ namespace Internal {
///////////////////////////////////////////////////////////////////////
//
// ConsoleEditor
// QtMessageLogEditor
//
///////////////////////////////////////////////////////////////////////
ConsoleEditor::ConsoleEditor(const QModelIndex &index,
ConsoleBackend *backend,
QtMessageLogEditor::QtMessageLogEditor(const QModelIndex &index,
QWidget *parent) :
QTextEdit(parent),
m_consoleBackend(backend),
m_historyIndex(index),
m_prompt(QLatin1String(":/debugger/images/prompt.png")),
m_prompt(_(":/debugger/images/prompt.png")),
m_startOfEditableArea(0)
{
setFrameStyle(QFrame::NoFrame);
setUndoRedoEnabled(false);
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
document()->addResource(QTextDocument::ImageResource,
QUrl(QLatin1String("prompt")), m_prompt);
QUrl(_("prompt")), m_prompt);
QTextImageFormat format;
format.setName(QLatin1String("prompt"));
format.setName(_("prompt"));
format.setHeight(9);
format.setWidth(9);
textCursor().insertImage(format);
textCursor().insertText(QLatin1String(" "));
textCursor().insertText(_(" "));
m_startOfEditableArea = textCursor().position();
ensureCursorVisible();
setTextInteractionFlags(Qt::TextEditorInteraction);
}
void ConsoleEditor::keyPressEvent(QKeyEvent *e)
void QtMessageLogEditor::keyPressEvent(QKeyEvent *e)
{
bool keyConsumed = false;
switch (e->key()) {
case Qt::Key_Return:
case Qt::Key_Enter:
if (m_consoleBackend) {
m_consoleBackend->evaluate(getCurrentScript(), &keyConsumed);
if (keyConsumed) {
emit editingFinished();
emit appendEditableRow();
//emit error message if there is an error
m_consoleBackend->emitErrorMessage();
}
} else {
case Qt::Key_Enter: {
keyConsumed = debuggerCore()->evaluateScriptExpression(getCurrentScript());
if (keyConsumed) {
emit editingFinished();
emit appendEditableRow();
keyConsumed = true;
debuggerCore()->currentEngine()->qtMessageLogHandler()->appendEditableRow();
}
}
break;
case Qt::Key_Backspace:
@@ -171,7 +162,7 @@ void ConsoleEditor::keyPressEvent(QKeyEvent *e)
QTextEdit::keyPressEvent(e);
}
void ConsoleEditor::contextMenuEvent(QContextMenuEvent *event)
void QtMessageLogEditor::contextMenuEvent(QContextMenuEvent *event)
{
QTextCursor cursor = textCursor();
bool editable = cursor.position() > m_startOfEditableArea;
@@ -199,12 +190,12 @@ void ConsoleEditor::contextMenuEvent(QContextMenuEvent *event)
delete menu;
}
void ConsoleEditor::focusOutEvent(QFocusEvent * /*e*/)
void QtMessageLogEditor::focusOutEvent(QFocusEvent * /*e*/)
{
emit editingFinished();
}
void ConsoleEditor::handleUpKey()
void QtMessageLogEditor::handleUpKey()
{
QTC_ASSERT(m_historyIndex.isValid(), return);
int currentRow = m_historyIndex.row();
@@ -216,9 +207,8 @@ void ConsoleEditor::handleUpKey()
currentRow--;
if (model->hasIndex(currentRow, 0)) {
QModelIndex index = model->index(currentRow, 0);
if (ConsoleItemModel::InputType ==
(ConsoleItemModel::ItemType)model->data(
index, ConsoleItemModel::TypeRole).toInt()) {
if (QtMessageLogHandler::InputType == (QtMessageLogHandler::ItemType)model->data(
index, QtMessageLogHandler::TypeRole).toInt()) {
m_historyIndex = index;
replaceCurrentScript(model->data(
index, Qt::DisplayRole).
@@ -229,7 +219,7 @@ void ConsoleEditor::handleUpKey()
}
}
void ConsoleEditor::handleDownKey()
void QtMessageLogEditor::handleDownKey()
{
QTC_ASSERT(m_historyIndex.isValid(), return);
int currentRow = m_historyIndex.row();
@@ -238,9 +228,8 @@ void ConsoleEditor::handleDownKey()
currentRow++;
if (model->hasIndex(currentRow, 0)) {
QModelIndex index = model->index(currentRow, 0);
if (ConsoleItemModel::InputType ==
(ConsoleItemModel::ItemType)model->data(
index, ConsoleItemModel::TypeRole).toInt()) {
if (QtMessageLogHandler::InputType == (QtMessageLogHandler::ItemType)model->data(
index, QtMessageLogHandler::TypeRole).toInt()) {
m_historyIndex = index;
if (currentRow == model->rowCount() - 1)
replaceCurrentScript(m_cachedScript);
@@ -254,7 +243,7 @@ void ConsoleEditor::handleDownKey()
}
}
QString ConsoleEditor::getCurrentScript() const
QString QtMessageLogEditor::getCurrentScript() const
{
QTextCursor cursor = textCursor();
cursor.setPosition(m_startOfEditableArea);
@@ -264,7 +253,7 @@ QString ConsoleEditor::getCurrentScript() const
return script.trimmed();
}
void ConsoleEditor::replaceCurrentScript(const QString &script)
void QtMessageLogEditor::replaceCurrentScript(const QString &script)
{
QTextCursor cursor = textCursor();
cursor.setPosition(m_startOfEditableArea);

View File

@@ -30,24 +30,20 @@
**
**************************************************************************/
#ifndef CONSOLEEDITOR_H
#define CONSOLEEDITOR_H
#ifndef QTMESSAGELOGEDITOR_H
#define QTMESSAGELOGEDITOR_H
#include "consoleitemmodel.h"
#include <QTextEdit>
#include <QModelIndex>
#include <QTextEdit>
namespace Debugger {
namespace Internal {
class ConsoleBackend;
class ConsoleEditor : public QTextEdit
class QtMessageLogEditor : public QTextEdit
{
Q_OBJECT
public:
explicit ConsoleEditor(const QModelIndex &index,
ConsoleBackend *backend = 0,
explicit QtMessageLogEditor(const QModelIndex &index,
QWidget *parent = 0);
QString getCurrentScript() const;
@@ -59,7 +55,6 @@ protected:
signals:
void editingFinished();
void appendEditableRow();
protected:
void handleUpKey();
@@ -68,7 +63,6 @@ protected:
void replaceCurrentScript(const QString &script);
private:
ConsoleBackend *m_consoleBackend;
QModelIndex m_historyIndex;
QString m_cachedScript;
QImage m_prompt;
@@ -78,4 +72,4 @@ private:
} //Internal
} //Debugger
#endif // CONSOLEEDITOR_H
#endif // QTMESSAGELOGEDITOR_H

View File

@@ -0,0 +1,352 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#include "qtmessageloghandler.h"
namespace Debugger {
namespace Internal {
///////////////////////////////////////////////////////////////////////
//
// QtMessageLogItem
//
///////////////////////////////////////////////////////////////////////
QtMessageLogItem::QtMessageLogItem(QtMessageLogHandler::ItemType itemType,
const QString &text, QtMessageLogItem *parent)
: m_text(text),
m_itemType(itemType),
m_parentItem(parent)
{
}
QtMessageLogItem::~QtMessageLogItem()
{
qDeleteAll(m_childItems);
}
QtMessageLogItem *QtMessageLogItem::child(int number)
{
return m_childItems.value(number);
}
int QtMessageLogItem::childCount() const
{
return m_childItems.count();
}
int QtMessageLogItem::childNumber() const
{
if (m_parentItem)
return m_parentItem->m_childItems.indexOf(const_cast<QtMessageLogItem *>(this));
return 0;
}
QString QtMessageLogItem::text() const
{
return m_text;
}
QtMessageLogHandler::ItemType QtMessageLogItem::itemType() const
{
return m_itemType;
}
\
bool QtMessageLogItem::insertChildren(int position, int count)
{
if (position < 0 || position > m_childItems.size())
return false;
for (int row = 0; row < count; ++row) {
QtMessageLogItem *item = new QtMessageLogItem(QtMessageLogHandler::UndefinedType, QString(), this);
m_childItems.insert(position, item);
}
return true;
}
bool QtMessageLogItem::insertChild(int position, QtMessageLogItem *item)
{
if (position < 0 || position > m_childItems.size())
return false;
if (item->parent())
item->parent()->detachChild(item->childNumber());
item->m_parentItem = this;
m_childItems.insert(position, item);
return true;
}
QtMessageLogItem *QtMessageLogItem::parent()
{
return m_parentItem;
}
bool QtMessageLogItem::removeChildren(int position, int count)
{
if (position < 0 || position + count > m_childItems.size())
return false;
for (int row = 0; row < count; ++row)
delete m_childItems.takeAt(position);
return true;
}
bool QtMessageLogItem::detachChild(int position)
{
if (position < 0 || position > m_childItems.size())
return false;
m_childItems.removeAt(position);
return true;
}
bool QtMessageLogItem::setText(const QString &text)
{
m_text = text;
return true;
}
bool QtMessageLogItem::setItemType(QtMessageLogHandler::ItemType itemType)
{
m_itemType = itemType;
return true;
}
///////////////////////////////////////////////////////////////////////
//
// QtMessageLogHandler
//
///////////////////////////////////////////////////////////////////////
QtMessageLogHandler::QtMessageLogHandler(QObject *parent) :
QAbstractItemModel(parent),
m_hasEditableRow(false),
m_rootItem(new QtMessageLogItem())
{
}
QtMessageLogHandler::~QtMessageLogHandler()
{
delete m_rootItem;
}
void QtMessageLogHandler::clear()
{
beginResetModel();
reset();
delete m_rootItem;
m_rootItem = new QtMessageLogItem();
endResetModel();
if (m_hasEditableRow)
appendEditableRow();
}
bool QtMessageLogHandler::appendItem(QtMessageLogItem *item, int position)
{
if (position < 0)
position = m_rootItem->childCount() - 1;
beginInsertRows(QModelIndex(), position, position);
bool success = m_rootItem->insertChild(position, item);
endInsertRows();
return success;
}
bool QtMessageLogHandler::appendMessage(QtMessageLogHandler::ItemType itemType,
const QString &message, int position)
{
return appendItem(new QtMessageLogItem(itemType, message), position);
}
void QtMessageLogHandler::setHasEditableRow(bool hasEditableRow)
{
if (m_hasEditableRow && !hasEditableRow)
removeEditableRow();
if (!m_hasEditableRow && hasEditableRow)
appendEditableRow();
m_hasEditableRow = hasEditableRow;
}
bool QtMessageLogHandler::hasEditableRow() const
{
return m_hasEditableRow;
}
void QtMessageLogHandler::appendEditableRow()
{
int position = m_rootItem->childCount();
if (appendItem(new QtMessageLogItem(QtMessageLogHandler::InputType), position))
emit selectEditableRow(index(position, 0),
QItemSelectionModel::ClearAndSelect);
}
void QtMessageLogHandler::removeEditableRow()
{
if (m_rootItem->child(m_rootItem->childCount() - 1)->itemType() == QtMessageLogHandler::InputType)
removeRow(m_rootItem->childCount() - 1);
}
QVariant QtMessageLogHandler::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
QtMessageLogItem *item = getItem(index);
if (role == Qt::DisplayRole )
return item->text();
else if (role == QtMessageLogHandler::TypeRole)
return int(item->itemType());
else
return QVariant();
}
QModelIndex QtMessageLogHandler::index(int row, int column,
const QModelIndex &parent) const
{
if (parent.isValid() && parent.column() != 0)
return QModelIndex();
if (column > 0)
return QModelIndex();
QtMessageLogItem *parentItem = getItem(parent);
QtMessageLogItem *childItem = parentItem->child(row);
if (childItem)
return createIndex(row, column, childItem);
else
return QModelIndex();
}
QModelIndex QtMessageLogHandler::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
QtMessageLogItem *childItem = getItem(index);
QtMessageLogItem *parentItem = childItem->parent();
if (parentItem == m_rootItem)
return QModelIndex();
return createIndex(parentItem->childNumber(), 0, parentItem);
}
int QtMessageLogHandler::rowCount(const QModelIndex &parent) const
{
QtMessageLogItem *parentItem = getItem(parent);
return parentItem->childCount();
}
int QtMessageLogHandler::columnCount(const QModelIndex & /* parent */) const
{
return 1;
}
Qt::ItemFlags QtMessageLogHandler::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
QtMessageLogItem *item = getItem(index);
if (m_hasEditableRow && item->parent() == m_rootItem
&& index.row() == m_rootItem->childCount() - 1)
return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
bool QtMessageLogHandler::setData(const QModelIndex &index, const QVariant &value,
int role)
{
QtMessageLogItem *item = getItem(index);
bool result = false;
if (role == Qt::DisplayRole )
result = item->setText(value.toString());
else if (role == QtMessageLogHandler::TypeRole)
result = item->setItemType((QtMessageLogHandler::ItemType)value.toInt());
else if (value.canConvert(QVariant::String))
result = item->setText(value.toString());
if (result)
emit dataChanged(index, index);
return result;
}
bool QtMessageLogHandler::insertRows(int position, int rows, const QModelIndex &parent)
{
QtMessageLogItem *parentItem = getItem(parent);
bool success;
beginInsertRows(parent, position, position + rows - 1);
success = parentItem->insertChildren(position, rows);
endInsertRows();
return success;
}
bool QtMessageLogHandler::removeRows(int position, int rows, const QModelIndex &parent)
{
QtMessageLogItem *parentItem = getItem(parent);
bool success = true;
beginRemoveRows(parent, position, position + rows - 1);
success = parentItem->removeChildren(position, rows);
endRemoveRows();
return success;
}
QtMessageLogItem *QtMessageLogHandler::getItem(const QModelIndex &index) const
{
if (index.isValid()) {
QtMessageLogItem *item = static_cast<QtMessageLogItem*>(index.internalPointer());
if (item) return item;
}
return m_rootItem;
}
} //Internal
} //Debugger

View File

@@ -30,8 +30,8 @@
**
**************************************************************************/
#ifndef CONSOLEITEMMODEL_H
#define CONSOLEITEMMODEL_H
#ifndef QTMESSAGELOGHANDLER_H
#define QTMESSAGELOGHANDLER_H
#include <QAbstractItemModel>
#include <QItemSelectionModel>
@@ -39,29 +39,48 @@
namespace Debugger {
namespace Internal {
class ConsoleItem;
class ConsoleItemModel : public QAbstractItemModel
class QtMessageLogItem;
class QtMessageLogHandler : public QAbstractItemModel
{
Q_OBJECT
public:
enum ItemType { InputType, LogType, WarningType, ErrorType,
UndefinedType //Can be used for unknown and for Return values
};
enum ItemType
{
InputType = 0x01,
DebugType = 0x02,
WarningType = 0x04,
ErrorType = 0x08,
UndefinedType = 0x10, //Can be used for unknown and for Return values
DefaultTypes = InputType | UndefinedType
};
Q_DECLARE_FLAGS(ItemTypes, ItemType)
enum Roles { TypeRole = Qt::UserRole };
explicit ConsoleItemModel(QObject *parent = 0);
~ConsoleItemModel();
explicit QtMessageLogHandler(QObject *parent = 0);
~QtMessageLogHandler();
void appendItem(ItemType,QString);
void setHasEditableRow(bool hasEditableRow);
bool hasEditableRow() const;
void appendEditableRow();
void removeEditableRow();
bool appendItem(QtMessageLogItem *item, int position = -1);
bool appendMessage(QtMessageLogHandler::ItemType itemType,
const QString &message, int position = -1);
QAbstractItemModel *model() { return this; }
int rowCount(const QModelIndex &parent = QModelIndex()) const;
public slots:
void clear();
void appendEditableRow();
signals:
void editableRowAppended(const QModelIndex &index,
void selectEditableRow(const QModelIndex &index,
QItemSelectionModel::SelectionFlags flags);
void rowInserted(const QModelIndex &index);
protected:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
@@ -70,7 +89,7 @@ protected:
const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &index) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
@@ -82,13 +101,42 @@ protected:
bool removeRows(int position, int rows,
const QModelIndex &parent = QModelIndex());
ConsoleItem *getItem(const QModelIndex &index) const;
QtMessageLogItem *getItem(const QModelIndex &index) const;
private:
ConsoleItem *m_rootItem;
bool m_hasEditableRow;
QtMessageLogItem *m_rootItem;
};
class QtMessageLogItem
{
public:
QtMessageLogItem(QtMessageLogHandler::ItemType type = QtMessageLogHandler::UndefinedType,
const QString &data = QString(),
QtMessageLogItem *parent = 0);
~QtMessageLogItem();
QtMessageLogItem *child(int number);
int childCount() const;
QString text() const;
QtMessageLogHandler::ItemType itemType() const;
bool insertChildren(int position, int count);
bool insertChild(int position, QtMessageLogItem *item);
QtMessageLogItem *parent();
bool removeChildren(int position, int count);
bool detachChild(int position);
int childNumber() const;
bool setText(const QString &text);
bool setItemType(QtMessageLogHandler::ItemType itemType);
private:
QList<QtMessageLogItem *> m_childItems;
QString m_text;
QtMessageLogHandler::ItemType m_itemType;
QtMessageLogItem *m_parentItem;
};
} //Internal
} //Debugger
#endif // CONSOLEITEMMODEL_H
#endif // QTMESSAGELOGHANDLER_H

View File

@@ -30,91 +30,90 @@
**
**************************************************************************/
#include "consoleitemdelegate.h"
#include "consoleeditor.h"
#include "qmlengine.h"
#include "qtmessagelogitemdelegate.h"
#include "qtmessagelogeditor.h"
#include "qtmessageloghandler.h"
#include <QPainter>
#include <QTreeView>
const char CONSOLE_LOG_BACKGROUND_COLOR[] = "#2378B7";
const char CONSOLE_WARNING_BACKGROUND_COLOR[] = "#E6CD49";
const char CONSOLE_ERROR_BACKGROUND_COLOR[] = "#ED471A";
const char CONSOLE_LOG_BACKGROUND_COLOR[] = "#E8EEF2";
const char CONSOLE_WARNING_BACKGROUND_COLOR[] = "#F6F4EB";
const char CONSOLE_ERROR_BACKGROUND_COLOR[] = "#F6EBE7";
const char CONSOLE_EDITOR_BACKGROUND_COLOR[] = "#F7F7F7";
const char CONSOLE_LOG_BACKGROUND_SELECTED_COLOR[] = "#CDDEEA";
const char CONSOLE_WARNING_BACKGROUND_SELECTED_COLOR[] = "#F3EED1";
const char CONSOLE_ERROR_BACKGROUND_SELECTED_COLOR[] = "#F5D4CB";
const char CONSOLE_EDITOR_BACKGROUND_SELECTED_COLOR[] = "#DEDEDE";
const char CONSOLE_LOG_TEXT_COLOR[] = "#333333";
const char CONSOLE_WARNING_TEXT_COLOR[] = "#666666";
const char CONSOLE_ERROR_TEXT_COLOR[] = "#1D5B93";
const char CONSOLE_EDITOR_TEXT_COLOR[] = "#000000";
const char CONSOLE_BORDER_COLOR[] = "#DEDEDE";
const float CONSOLE_ALPHA = 0.7f;
const char CONSOLE_BORDER_COLOR[] = "#C9C9C9";
namespace Debugger {
namespace Internal {
///////////////////////////////////////////////////////////////////////
//
// ConsoleItemDelegate
// QtMessageLogItemDelegate
//
///////////////////////////////////////////////////////////////////////
ConsoleItemDelegate::ConsoleItemDelegate(QObject *parent) :
QtMessageLogItemDelegate::QtMessageLogItemDelegate(QObject *parent) :
QStyledItemDelegate(parent),
m_logIcon(QLatin1String(":/debugger/images/log.png")),
m_warningIcon(QLatin1String(":/debugger/images/warning.png")),
m_errorIcon(QLatin1String(":/debugger/images/error.png")),
m_expandIcon(QLatin1String(":/debugger/images/expand.png")),
m_collapseIcon(QLatin1String(":/debugger/images/collapse.png")),
m_prompt(QLatin1String(":/debugger/images/prompt.png")),
m_consoleBackend(0)
m_prompt(QLatin1String(":/debugger/images/prompt.png"))
{
}
void ConsoleItemDelegate::emitSizeHintChanged(const QModelIndex &index)
void QtMessageLogItemDelegate::emitSizeHintChanged(const QModelIndex &index)
{
emit sizeHintChanged(index);
}
void ConsoleItemDelegate::setConsoleBackend(ConsoleBackend *consoleBackend)
{
m_consoleBackend = consoleBackend;
}
void ConsoleItemDelegate::drawBackground(QPainter *painter, const QRect &rect,
ConsoleItemModel::ItemType itemType,
void QtMessageLogItemDelegate::drawBackground(QPainter *painter, const QRect &rect,
const QModelIndex &index,
bool selected) const
{
painter->save();
QtMessageLogHandler::ItemType itemType = (QtMessageLogHandler::ItemType)index.data(
QtMessageLogHandler::TypeRole).toInt();
QColor backgroundColor;
switch (itemType) {
case ConsoleItemModel::LogType:
backgroundColor = QColor(CONSOLE_LOG_BACKGROUND_COLOR);
case QtMessageLogHandler::DebugType:
backgroundColor = selected ? QColor(CONSOLE_LOG_BACKGROUND_SELECTED_COLOR) :
QColor(CONSOLE_LOG_BACKGROUND_COLOR);
break;
case ConsoleItemModel::WarningType:
backgroundColor = QColor(CONSOLE_WARNING_BACKGROUND_COLOR);
case QtMessageLogHandler::WarningType:
backgroundColor = selected ? QColor(CONSOLE_WARNING_BACKGROUND_SELECTED_COLOR) :
QColor(CONSOLE_WARNING_BACKGROUND_COLOR);
break;
case ConsoleItemModel::ErrorType:
backgroundColor = QColor(CONSOLE_ERROR_BACKGROUND_COLOR);
break;
case ConsoleItemModel::InputType:
backgroundColor = QColor(CONSOLE_EDITOR_BACKGROUND_COLOR);
case QtMessageLogHandler::ErrorType:
backgroundColor = selected ? QColor(CONSOLE_ERROR_BACKGROUND_SELECTED_COLOR) :
QColor(CONSOLE_ERROR_BACKGROUND_COLOR);
break;
case QtMessageLogHandler::InputType:
default:
backgroundColor = QColor(CONSOLE_EDITOR_BACKGROUND_COLOR);
backgroundColor = selected ? QColor(CONSOLE_EDITOR_BACKGROUND_SELECTED_COLOR) :
QColor(CONSOLE_EDITOR_BACKGROUND_COLOR);
break;
}
if (selected)
backgroundColor.setAlphaF(0.5f);
else
backgroundColor.setAlphaF(1 - CONSOLE_ALPHA);
painter->setBrush(backgroundColor);
if (!(index.flags() & Qt::ItemIsEditable))
painter->setBrush(backgroundColor);
painter->setPen(Qt::NoPen);
painter->drawRect(rect);
painter->restore();
}
void ConsoleItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
void QtMessageLogItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyleOptionViewItemV4 opt = option;
@@ -124,23 +123,22 @@ void ConsoleItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o
//Set Colors
QColor textColor;
QIcon taskIcon;
ConsoleItemModel::ItemType type =
(ConsoleItemModel::ItemType)index.data(
ConsoleItemModel::TypeRole).toInt();
QtMessageLogHandler::ItemType type = (QtMessageLogHandler::ItemType)index.data(
QtMessageLogHandler::TypeRole).toInt();
switch (type) {
case ConsoleItemModel::LogType:
case QtMessageLogHandler::DebugType:
textColor = QColor(CONSOLE_LOG_TEXT_COLOR);
taskIcon = m_logIcon;
break;
case ConsoleItemModel::WarningType:
case QtMessageLogHandler::WarningType:
textColor = QColor(CONSOLE_WARNING_TEXT_COLOR);
taskIcon = m_warningIcon;
break;
case ConsoleItemModel::ErrorType:
case QtMessageLogHandler::ErrorType:
textColor = QColor(CONSOLE_ERROR_TEXT_COLOR);
taskIcon = m_errorIcon;
break;
case ConsoleItemModel::InputType:
case QtMessageLogHandler::InputType:
textColor = QColor(CONSOLE_EDITOR_TEXT_COLOR);
taskIcon = m_prompt;
break;
@@ -150,7 +148,7 @@ void ConsoleItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o
}
//Paint background
drawBackground(painter, opt.rect, type,
drawBackground(painter, opt.rect, index,
bool(opt.state & QStyle::State_Selected));
//Calculate positions
@@ -163,8 +161,7 @@ void ConsoleItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o
}
int width = view->width() - level * view->indentation();
bool showTypeIcon = index.parent() == QModelIndex();
bool showExpandableIcon = type != ConsoleItemModel::InputType &&
type != ConsoleItemModel::UndefinedType;
bool showExpandableIcon = type == QtMessageLogHandler::UndefinedType;
QRect rect(opt.rect.x(), opt.rect.top(), width, opt.rect.height());
ConsoleItemPositions positions(rect, opt.font, showTypeIcon,
@@ -203,13 +200,13 @@ void ConsoleItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o
// Separator lines
painter->setPen(QColor(CONSOLE_BORDER_COLOR));
if (!index.flags() & Qt::ItemIsEditable)
if (!(index.flags() & Qt::ItemIsEditable))
painter->drawLine(0, opt.rect.bottom(), opt.rect.right(),
opt.rect.bottom());
painter->restore();
}
QSize ConsoleItemDelegate::sizeHint(const QStyleOptionViewItem &option,
QSize QtMessageLogItemDelegate::sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyleOptionViewItemV4 opt = option;
@@ -226,12 +223,10 @@ QSize ConsoleItemDelegate::sizeHint(const QStyleOptionViewItem &option,
if (index.flags() & Qt::ItemIsEditable)
return QSize(width, view->height() * 1/2);
ConsoleItemModel::ItemType type =
(ConsoleItemModel::ItemType)index.data(
ConsoleItemModel::TypeRole).toInt();
QtMessageLogHandler::ItemType type = (QtMessageLogHandler::ItemType)index.data(
QtMessageLogHandler::TypeRole).toInt();
bool showTypeIcon = index.parent() == QModelIndex();
bool showExpandableIcon = type != ConsoleItemModel::InputType &&
type != ConsoleItemModel::UndefinedType;
bool showExpandableIcon = type == QtMessageLogHandler::UndefinedType;
QRect rect(level * view->indentation(), 0, width, 0);
ConsoleItemPositions positions(rect, opt.font,
@@ -247,36 +242,34 @@ QSize ConsoleItemDelegate::sizeHint(const QStyleOptionViewItem &option,
return QSize(width, height);
}
QWidget *ConsoleItemDelegate::createEditor(QWidget *parent,
QWidget *QtMessageLogItemDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &/*option*/,
const QModelIndex &index) const
{
ConsoleEditor *editor = new ConsoleEditor(index, m_consoleBackend, parent);
connect(editor, SIGNAL(appendEditableRow()),
this, SIGNAL(appendEditableRow()));
QtMessageLogEditor *editor = new QtMessageLogEditor(index, parent);
connect(editor, SIGNAL(editingFinished()),
this, SLOT(commitAndCloseEditor()));
return editor;
}
void ConsoleItemDelegate::setEditorData(QWidget *editor,
void QtMessageLogItemDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
ConsoleEditor *edtr = qobject_cast<ConsoleEditor *>(editor);
QtMessageLogEditor *edtr = qobject_cast<QtMessageLogEditor *>(editor);
edtr->insertPlainText(index.data(Qt::DisplayRole).toString());
}
void ConsoleItemDelegate::setModelData(QWidget *editor,
void QtMessageLogItemDelegate::setModelData(QWidget *editor,
QAbstractItemModel *model,
const QModelIndex &index) const
{
ConsoleEditor *edtr = qobject_cast<ConsoleEditor *>(editor);
QtMessageLogEditor *edtr = qobject_cast<QtMessageLogEditor *>(editor);
model->setData(index, edtr->getCurrentScript(), Qt::DisplayRole);
model->setData(index, edtr->getCurrentScript(), ConsoleItemModel::TypeRole);
model->setData(index, QtMessageLogHandler::InputType, QtMessageLogHandler::TypeRole);
}
void ConsoleItemDelegate::updateEditorGeometry(QWidget *editor,
void QtMessageLogItemDelegate::updateEditorGeometry(QWidget *editor,
const QStyleOptionViewItem &option,
const QModelIndex &/*index*/) const
{
@@ -285,21 +278,21 @@ void ConsoleItemDelegate::updateEditorGeometry(QWidget *editor,
opt.rect.width(), opt.rect.bottom()));
}
void ConsoleItemDelegate::currentChanged(const QModelIndex &current,
void QtMessageLogItemDelegate::currentChanged(const QModelIndex &current,
const QModelIndex &previous)
{
emit sizeHintChanged(current);
emit sizeHintChanged(previous);
}
void ConsoleItemDelegate::commitAndCloseEditor()
void QtMessageLogItemDelegate::commitAndCloseEditor()
{
ConsoleEditor *editor = qobject_cast<ConsoleEditor *>(sender());
QtMessageLogEditor *editor = qobject_cast<QtMessageLogEditor *>(sender());
emit commitData(editor);
emit closeEditor(editor);
}
qreal ConsoleItemDelegate::layoutText(QTextLayout &tl, int width) const
qreal QtMessageLogItemDelegate::layoutText(QTextLayout &tl, int width) const
{
qreal height = 0;
tl.beginLayout();

View File

@@ -30,10 +30,8 @@
**
**************************************************************************/
#ifndef CONSOLEITEMDELEGATE_H
#define CONSOLEITEMDELEGATE_H
#include "consoleitemmodel.h"
#ifndef QTMESSAGELOGITEMDELEGATE_H
#define QTMESSAGELOGITEMDELEGATE_H
#include <QTextLayout>
#include <QStyledItemDelegate>
@@ -41,17 +39,15 @@
namespace Debugger {
namespace Internal {
class ConsoleBackend;
class ConsoleItemDelegate : public QStyledItemDelegate
class QtMessageLogItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit ConsoleItemDelegate(QObject *parent = 0);
explicit QtMessageLogItemDelegate(QObject *parent = 0);
void emitSizeHintChanged(const QModelIndex &index);
void setConsoleBackend(ConsoleBackend *consoleBackend);
void drawBackground(QPainter *painter, const QRect &rect,
ConsoleItemModel::ItemType itemType, bool selected) const;
const QModelIndex &index,
bool selected) const;
public slots:
void currentChanged(const QModelIndex &current, const QModelIndex &previous);
@@ -71,9 +67,6 @@ protected:
const QStyleOptionViewItem &option,
const QModelIndex &index) const;
signals:
void appendEditableRow();
private slots:
void commitAndCloseEditor();
@@ -87,7 +80,6 @@ private:
const QIcon m_expandIcon;
const QIcon m_collapseIcon;
const QIcon m_prompt;
ConsoleBackend *m_consoleBackend;
};
/*
@@ -164,11 +156,11 @@ private:
public:
static const int TASK_ICON_SIZE = 16;
static const int ITEM_PADDING = 2;
static const int ITEM_SPACING = 2 * ITEM_PADDING;
static const int ITEM_PADDING = 7;
static const int ITEM_SPACING = 4;
};
} //Internal
} //Debugger
#endif // CONSOLEITEMDELEGATE_H
#endif // QTMESSAGELOGITEMDELEGATE_H

View File

@@ -0,0 +1,92 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#include "qtmessagelogproxymodel.h"
namespace Debugger {
namespace Internal {
QtMessageLogProxyModel::QtMessageLogProxyModel(QObject *parent) :
QSortFilterProxyModel(parent),
m_filter(QtMessageLogHandler::DefaultTypes)
{
}
void QtMessageLogProxyModel::setShowLogs(bool show)
{
m_filter = show ? m_filter | QtMessageLogHandler::DebugType :
m_filter & ~QtMessageLogHandler::DebugType;
setFilterRegExp(QString());
}
void QtMessageLogProxyModel::setShowWarnings(bool show)
{
m_filter = show ? m_filter | QtMessageLogHandler::WarningType :
m_filter & ~QtMessageLogHandler::WarningType;
setFilterRegExp(QString());
}
void QtMessageLogProxyModel::setShowErrors(bool show)
{
m_filter = show ? m_filter | QtMessageLogHandler::ErrorType :
m_filter & ~QtMessageLogHandler::ErrorType;
setFilterRegExp(QString());
}
void QtMessageLogProxyModel::selectEditableRow(const QModelIndex &index,
QItemSelectionModel::SelectionFlags command)
{
emit setCurrentIndex(mapFromSource(index), command);
}
bool QtMessageLogProxyModel::filterAcceptsRow(int sourceRow,
const QModelIndex &sourceParent) const
{
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
return m_filter.testFlag((QtMessageLogHandler::ItemType)
sourceModel()->data(
index, QtMessageLogHandler::TypeRole).toInt());
}
void QtMessageLogProxyModel::onRowsInserted(const QModelIndex &index, int start, int end)
{
int rowIndex = end;
do {
if (filterAcceptsRow(rowIndex, index)) {
emit scrollToBottom();
break;
}
} while (--rowIndex >= start);
}
} // namespace Internal
} // namespace Debugger

View File

@@ -30,69 +30,44 @@
**
**************************************************************************/
#ifndef QMLJSSCRIPTCONSOLE_H
#define QMLJSSCRIPTCONSOLE_H
#ifndef QTMESSAGELOGPROXYMODEL_H
#define QTMESSAGELOGPROXYMODEL_H
#include "consoleitemmodel.h"
#include <debugger/debuggerconstants.h>
#include <QWidget>
#include "qtmessageloghandler.h"
QT_BEGIN_NAMESPACE
class QToolButton;
QT_END_NAMESPACE
namespace Utils {
class StatusLabel;
class SavedAction;
}
#include <QSortFilterProxyModel>
#include <QItemSelectionModel>
namespace Debugger {
class DebuggerEngine;
namespace Internal {
class ConsoleTreeView;
class ConsoleItemDelegate;
class QmlJSConsoleBackend;
class QmlJSScriptConsoleWidget : public QWidget
class QtMessageLogProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
QmlJSScriptConsoleWidget(QWidget *parent = 0);
~QmlJSScriptConsoleWidget();
void setEngine(DebuggerEngine *engine);
void readSettings();
explicit QtMessageLogProxyModel(QObject *parent = 0);
public slots:
void writeSettings() const;
void appendResult(const QString &result);
void appendOutput(ConsoleItemModel::ItemType, const QString &message);
void appendMessage(QtMsgType type, const QString &message);
void setShowLogs(bool show);
void setShowWarnings(bool show);
void setShowErrors(bool show);
void selectEditableRow(const QModelIndex &index,
QItemSelectionModel::SelectionFlags command);
void onRowsInserted(const QModelIndex &index, int start, int end);
signals:
void evaluateExpression(const QString &expr);
void scrollToBottom();
void setCurrentIndex(const QModelIndex &index,
QItemSelectionModel::SelectionFlags command);
private slots:
void onEngineStateChanged(Debugger::DebuggerState state);
void onSelectionChanged();
protected:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
private:
ConsoleTreeView *m_consoleView;
ConsoleItemModel *m_model;
ConsoleItemDelegate *m_itemDelegate;
QmlJSConsoleBackend *m_consoleBackend;
Utils::StatusLabel *m_statusLabel;
QToolButton *m_showLog;
QToolButton *m_showWarning;
QToolButton *m_showError;
Utils::SavedAction *m_showLogAction;
Utils::SavedAction *m_showWarningAction;
Utils::SavedAction *m_showErrorAction;
QFlags<QtMessageLogHandler::ItemType> m_filter;
};
} //Internal
} //Debugger
} // namespace Internal
} // namespace Debugger
#endif
#endif // QTMESSAGELOGPROXYMODEL_H

View File

@@ -30,10 +30,9 @@
**
**************************************************************************/
#include "consoletreeview.h"
#include "consoleitemdelegate.h"
#include "consoleitemmodel.h"
#include "debuggerinternalconstants.h"
#include "qtmessagelogview.h"
#include "qtmessagelogitemdelegate.h"
#include "qtmessageloghandler.h"
#include <QMouseEvent>
#include <QProxyStyle>
@@ -42,7 +41,7 @@
namespace Debugger {
namespace Internal {
class ConsoleTreeViewStyle : public QProxyStyle
class QtMessageLogViewViewStyle : public QProxyStyle
{
public:
void drawPrimitive(PrimitiveElement element,
@@ -54,7 +53,8 @@ public:
QProxyStyle::drawPrimitive(element, option, painter, widget);
}
int styleHint(StyleHint hint, const QStyleOption *option = 0,
int styleHint(StyleHint hint,
const QStyleOption *option = 0,
const QWidget *widget = 0,
QStyleHintReturn *returnData = 0) const {
if (hint == SH_ItemView_ShowDecorationSelected)
@@ -66,11 +66,11 @@ public:
///////////////////////////////////////////////////////////////////////
//
// ConsoleTreeView
// QtMessageLogView
//
///////////////////////////////////////////////////////////////////////
ConsoleTreeView::ConsoleTreeView(QWidget *parent) :
QtMessageLogView::QtMessageLogView(QWidget *parent) :
QTreeView(parent)
{
setFrameStyle(QFrame::NoFrame);
@@ -94,29 +94,20 @@ ConsoleTreeView::ConsoleTreeView(QWidget *parent) :
"QTreeView::branch:open:has-children:has-siblings {"
"border-image: none;"
"image: none; }"));
ConsoleTreeViewStyle *style = new ConsoleTreeViewStyle;
QtMessageLogViewViewStyle *style = new QtMessageLogViewViewStyle;
setStyle(style);
style->setParent(this);
}
void ConsoleTreeView::setItemDelegate(QAbstractItemDelegate *delegate)
{
connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
delegate, SLOT(currentChanged(QModelIndex,QModelIndex)));
QTreeView::setItemDelegate(delegate);
}
void ConsoleTreeView::mousePressEvent(QMouseEvent *event)
void QtMessageLogView::mousePressEvent(QMouseEvent *event)
{
QPoint pos = event->pos();
QModelIndex index = indexAt(pos);
if (index.isValid()) {
ConsoleItemModel::ItemType type =
(ConsoleItemModel::ItemType)index.data(
ConsoleItemModel::TypeRole).toInt();
QtMessageLogHandler::ItemType type = (QtMessageLogHandler::ItemType)index.data(
QtMessageLogHandler::TypeRole).toInt();
bool showTypeIcon = index.parent() == QModelIndex();
bool showExpandableIcon = type != ConsoleItemModel::InputType &&
type != ConsoleItemModel::UndefinedType;
bool showExpandableIcon = type == QtMessageLogHandler::UndefinedType;
ConsoleItemPositions positions(visualRect(index), viewOptions().font,
showTypeIcon, showExpandableIcon);
@@ -135,21 +126,18 @@ void ConsoleTreeView::mousePressEvent(QMouseEvent *event)
}
}
void ConsoleTreeView::resizeEvent(QResizeEvent *e)
void QtMessageLogView::resizeEvent(QResizeEvent *e)
{
static_cast<ConsoleItemDelegate *>(itemDelegate())->emitSizeHintChanged(
static_cast<QtMessageLogItemDelegate *>(itemDelegate())->emitSizeHintChanged(
selectionModel()->currentIndex());
QTreeView::resizeEvent(e);
}
void ConsoleTreeView::drawBranches(QPainter *painter, const QRect &rect,
void QtMessageLogView::drawBranches(QPainter *painter, const QRect &rect,
const QModelIndex &index) const
{
ConsoleItemModel::ItemType type =
(ConsoleItemModel::ItemType)index.data(
ConsoleItemModel::TypeRole).toInt();
static_cast<ConsoleItemDelegate *>(itemDelegate())->drawBackground(
painter, rect, type, true);
static_cast<QtMessageLogItemDelegate *>(itemDelegate())->drawBackground(
painter, rect, index, false);
QTreeView::drawBranches(painter, rect, index);
}

View File

@@ -30,21 +30,19 @@
**
**************************************************************************/
#ifndef CONSOLETREEVIEW_H
#define CONSOLETREEVIEW_H
#ifndef QTMESSAGELOGVIEW_H
#define QTMESSAGELOGVIEW_H
#include <QTreeView>
namespace Debugger {
namespace Internal {
class ConsoleTreeView : public QTreeView
class QtMessageLogView : public QTreeView
{
Q_OBJECT
public:
explicit ConsoleTreeView(QWidget *parent = 0);
void setItemDelegate(QAbstractItemDelegate *delegate);
explicit QtMessageLogView(QWidget *parent = 0);
protected:
void mousePressEvent(QMouseEvent *event);
@@ -56,4 +54,4 @@ protected:
} //Internal
} //Debugger
#endif // CONSOLETREEVIEW_H
#endif // QTMESSAGELOGVIEW_H

View File

@@ -0,0 +1,223 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/
#include "qtmessagelogwindow.h"
#include "qtmessagelogview.h"
#include "qtmessageloghandler.h"
#include "qtmessagelogitemdelegate.h"
#include "debuggerstringutils.h"
#include "qtmessagelogproxymodel.h"
#include <utils/statuslabel.h>
#include <utils/styledbar.h>
#include <utils/savedaction.h>
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
#include <QSettings>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QToolButton>
static const char CONSOLE[] = "Console";
static const char SHOW_LOG[] = "showLog";
static const char SHOW_WARNING[] = "showWarning";
static const char SHOW_ERROR[] = "showError";
namespace Debugger {
namespace Internal {
/////////////////////////////////////////////////////////////////////
//
// QtMessageLogWindow
//
/////////////////////////////////////////////////////////////////////
QtMessageLogWindow::QtMessageLogWindow(QWidget *parent)
: QWidget(parent)
{
setWindowTitle(tr(CONSOLE));
setObjectName(_(CONSOLE));
const int statusBarHeight = 25;
QVBoxLayout *vbox = new QVBoxLayout(this);
vbox->setMargin(0);
vbox->setSpacing(0);
QWidget *statusbarContainer = new QWidget();
statusbarContainer->setFixedHeight(statusBarHeight);
QHBoxLayout *hbox = new QHBoxLayout(statusbarContainer);
hbox->setMargin(0);
const int spacing = 7;
//Status Label
m_statusLabel = new Utils::StatusLabel;
hbox->addSpacing(spacing);
hbox->addWidget(m_statusLabel);
hbox->addWidget(new Utils::StyledSeparator);
hbox->addSpacing(spacing);
const int buttonWidth = 25;
//Filters
QToolButton *button = new QToolButton(this);
button->setAutoRaise(true);
button->setFixedWidth(buttonWidth);
m_showLogAction = new Utils::SavedAction(this);
m_showLogAction->setDefaultValue(true);
m_showLogAction->setSettingsKey(_(CONSOLE), _(SHOW_LOG));
m_showLogAction->setText(tr("Log"));
m_showLogAction->setCheckable(true);
m_showLogAction->setIcon(QIcon(_(":/debugger/images/log.png")));
button->setDefaultAction(m_showLogAction);
hbox->addWidget(button);
hbox->addSpacing(spacing);
button = new QToolButton(this);
button->setAutoRaise(true);
button->setFixedWidth(buttonWidth);
m_showWarningAction = new Utils::SavedAction(this);
m_showWarningAction->setDefaultValue(true);
m_showWarningAction->setSettingsKey(_(CONSOLE), _(SHOW_WARNING));
m_showWarningAction->setText(tr("Warning"));
m_showWarningAction->setCheckable(true);
m_showWarningAction->setIcon(QIcon(_(":/debugger/images/warning.png")));
button->setDefaultAction(m_showWarningAction);
hbox->addWidget(button);
hbox->addSpacing(spacing);
button = new QToolButton(this);
button->setAutoRaise(true);
button->setFixedWidth(buttonWidth);
m_showErrorAction = new Utils::SavedAction(this);
m_showErrorAction->setDefaultValue(true);
m_showErrorAction->setSettingsKey(_(CONSOLE), _(SHOW_ERROR));
m_showErrorAction->setText(tr("Error"));
m_showErrorAction->setCheckable(true);
m_showErrorAction->setIcon(QIcon(_(":/debugger/images/error.png")));
button->setDefaultAction(m_showErrorAction);
hbox->addWidget(button);
hbox->addSpacing(spacing);
//Clear Button
button = new QToolButton;
button->setAutoRaise(true);
button->setFixedWidth(buttonWidth);
m_clearAction = new QAction(tr("Clear Console"), this);
m_clearAction->setIcon(QIcon(_(Core::Constants::ICON_CLEAN_PANE)));
button->setDefaultAction(m_clearAction);
hbox->addWidget(button);
hbox->addSpacing(spacing);
m_treeView = new QtMessageLogView(this);
m_treeView->setSizePolicy(QSizePolicy::MinimumExpanding,
QSizePolicy::MinimumExpanding);
m_proxyModel = new QtMessageLogProxyModel(this);
connect(m_showLogAction, SIGNAL(toggled(bool)),
m_proxyModel, SLOT(setShowLogs(bool)));
connect(m_showWarningAction, SIGNAL(toggled(bool)),
m_proxyModel, SLOT(setShowWarnings(bool)));
connect(m_showErrorAction, SIGNAL(toggled(bool)),
m_proxyModel, SLOT(setShowErrors(bool)));
m_treeView->setModel(m_proxyModel);
connect(m_proxyModel,
SIGNAL(setCurrentIndex(QModelIndex,QItemSelectionModel::SelectionFlags)),
m_treeView->selectionModel(),
SLOT(setCurrentIndex(QModelIndex,QItemSelectionModel::SelectionFlags)));
connect(m_proxyModel,
SIGNAL(scrollToBottom()),
m_treeView,
SLOT(scrollToBottom()));
QtMessageLogItemDelegate *itemDelegate = new QtMessageLogItemDelegate(this);
connect(m_treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
itemDelegate, SLOT(currentChanged(QModelIndex,QModelIndex)));
m_treeView->setItemDelegate(itemDelegate);
vbox->addWidget(statusbarContainer);
vbox->addWidget(m_treeView);
readSettings();
connect(Core::ICore::instance(),
SIGNAL(saveSettingsRequested()), SLOT(writeSettings()));
}
QtMessageLogWindow::~QtMessageLogWindow()
{
writeSettings();
}
void QtMessageLogWindow::readSettings()
{
QSettings *settings = Core::ICore::settings();
m_showLogAction->readSettings(settings);
m_showWarningAction->readSettings(settings);
m_showErrorAction->readSettings(settings);
}
void QtMessageLogWindow::showStatus(const QString &context, int timeout)
{
m_statusLabel->showStatusMessage(context, timeout);
}
void QtMessageLogWindow::writeSettings() const
{
QSettings *settings = Core::ICore::settings();
m_showLogAction->writeSettings(settings);
m_showWarningAction->writeSettings(settings);
m_showErrorAction->writeSettings(settings);
}
void QtMessageLogWindow::setModel(QAbstractItemModel *model)
{
m_proxyModel->setSourceModel(model);
QtMessageLogHandler *handler = qobject_cast<QtMessageLogHandler *>(model);
connect(m_clearAction, SIGNAL(triggered()), handler, SLOT(clear()));
connect(handler,
SIGNAL(selectEditableRow(QModelIndex,QItemSelectionModel::SelectionFlags)),
m_proxyModel,
SLOT(selectEditableRow(QModelIndex,QItemSelectionModel::SelectionFlags)));
//Scroll to bottom when rows matching current filter settings are inserted
//Not connecting rowsRemoved as the only way to remove rows is to clear the
//model which will automatically reset the view.
connect(handler,
SIGNAL(rowsInserted(QModelIndex,int,int)),
m_proxyModel,
SLOT(onRowsInserted(QModelIndex,int,int)));
}
} // namespace Internal
} // namespace Debugger

View File

@@ -30,50 +30,52 @@
**
**************************************************************************/
#ifndef DEBUGGER_CONSOLEWINDOW_H
#define DEBUGGER_CONSOLEWINDOW_H
#ifndef QTMESSAGELOGWINDOW_H
#define QTMESSAGELOGWINDOW_H
#include <QWidget>
QT_BEGIN_NAMESPACE
class QCursor;
class QAbstractItemModel;
class QAction;
QT_END_NAMESPACE
namespace Utils {
class StatusLabel;
class SavedAction;
}
namespace Debugger {
namespace Internal {
class Console;
class ConsoleWindow : public QWidget
class QtMessageLogView;
class QtMessageLogProxyModel;
class QtMessageLogWindow : public QWidget
{
Q_OBJECT
public:
explicit ConsoleWindow(QWidget *parent = 0);
QtMessageLogWindow(QWidget *parent = 0);
~QtMessageLogWindow();
void setCursor(const QCursor &cursor);
QString combinedContents() const;
QString inputContents() const;
static QString logTimeStamp();
void setModel(QAbstractItemModel *model);
void readSettings();
void showStatus(const QString &context, int timeout);
public slots:
void clearContents();
void showOutput(int channel, const QString &output);
void showInput(int channel, const QString &input);
signals:
void showPage();
void statusMessageRequested(const QString &msg, int);
void writeSettings() const;
private:
Console *m_console; // combined input/output
Utils::StatusLabel *m_statusLabel;
Utils::SavedAction *m_showLogAction;
Utils::SavedAction *m_showWarningAction;
Utils::SavedAction *m_showErrorAction;
QAction *m_clearAction;
QtMessageLogView *m_treeView;
QtMessageLogProxyModel *m_proxyModel;
};
} // namespace Internal
} // namespace Debugger
#endif // DEBUGGER_CONSOLEWINDOW_H
#endif // QTMESSAGELOGWINDOW_H