summaryrefslogtreecommitdiff
path: root/src/scripttools/debugging/qscriptdebugger.cpp
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commitc4af45c2914381172e1bd7ee528481edaa2fff1a (patch)
tree01265e109316fda93845e1c96c5e566d870f51d0 /src/scripttools/debugging/qscriptdebugger.cpp
downloadqtscript-c4af45c2914381172e1bd7ee528481edaa2fff1a.tar.gz
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/scripttools/debugging/qscriptdebugger.cpp')
-rw-r--r--src/scripttools/debugging/qscriptdebugger.cpp1990
1 files changed, 1990 insertions, 0 deletions
diff --git a/src/scripttools/debugging/qscriptdebugger.cpp b/src/scripttools/debugging/qscriptdebugger.cpp
new file mode 100644
index 0000000..382ef62
--- /dev/null
+++ b/src/scripttools/debugging/qscriptdebugger.cpp
@@ -0,0 +1,1990 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtSCriptTools module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscriptdebugger_p.h"
+#include "qscriptdebuggerconsole_p.h"
+#include "qscriptdebuggerconsolecommandmanager_p.h"
+#include "qscriptdebuggerconsolecommandjob_p.h"
+#include "qscriptstdmessagehandler_p.h"
+#include "qscriptdebuggerfrontend_p.h"
+#include "qscriptdebuggereventhandlerinterface_p.h"
+#include "qscriptdebuggerresponsehandlerinterface_p.h"
+#include "qscriptdebuggerjobschedulerinterface_p.h"
+#include "qscriptdebuggerconsolewidgetinterface_p.h"
+#include "qscriptcompletionproviderinterface_p.h"
+#include "qscriptcompletiontask_p.h"
+#include "qscripttooltipproviderinterface_p.h"
+#include "qscriptdebuggerstackwidgetinterface_p.h"
+#include "qscriptdebuggerstackmodel_p.h"
+#include "qscriptdebuggerscriptswidgetinterface_p.h"
+#include "qscriptdebuggerscriptsmodel_p.h"
+#include "qscriptdebuggerlocalswidgetinterface_p.h"
+#include "qscriptdebuggerlocalsmodel_p.h"
+#include "qscriptdebuggercodewidgetinterface_p.h"
+#include "qscriptdebuggercodeviewinterface_p.h"
+#include "qscriptdebuggercodefinderwidgetinterface_p.h"
+#include "qscriptbreakpointswidgetinterface_p.h"
+#include "qscriptbreakpointsmodel_p.h"
+#include "qscriptdebugoutputwidgetinterface_p.h"
+#include "qscripterrorlogwidgetinterface_p.h"
+#include "qscriptdebuggerwidgetfactoryinterface_p.h"
+#include "qscriptdebuggerevent_p.h"
+#include "qscriptdebuggervalue_p.h"
+#include "qscriptdebuggerresponse_p.h"
+#include "qscriptdebuggercommand_p.h"
+#include "qscriptdebuggercommandschedulerfrontend_p.h"
+#include "qscriptdebuggercommandschedulerjob_p.h"
+#include "qscriptdebuggerjob_p_p.h"
+#include "qscriptxmlparser_p.h"
+
+#include "private/qobject_p.h"
+
+#include <QtScript/qscriptcontext.h>
+#include <QtScript/qscriptcontextinfo.h>
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qdebug.h>
+
+#include <QtGui/qaction.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qicon.h>
+#include <QtGui/qinputdialog.h>
+#include <QtGui/qmenu.h>
+#include <QtGui/qtoolbar.h>
+#include <QtGui/qtooltip.h>
+
+QT_BEGIN_NAMESPACE
+typedef QPair<QList<qint64>, QList<qint64> > QScriptScriptsDelta;
+typedef QPair<QList<qint64>, QList<qint64> > QScriptContextsDelta;
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QScriptScriptsDelta)
+
+QT_BEGIN_NAMESPACE
+
+Q_SCRIPT_EXPORT QString qt_scriptToXml(const QString &program, int lineNumber = 1);
+
+namespace {
+
+static int scriptDebuggerCount = 0;
+static bool eventCallbackRegistered = false;
+static bool widgetInPaintEvent = false;
+
+static bool scriptDebuggerEventCallback(void **data)
+{
+ QEvent *event = reinterpret_cast<QEvent*>(data[1]);
+ if (event->type() == QEvent::Paint) {
+ QObject *receiver = reinterpret_cast<QObject*>(data[0]);
+ bool was = widgetInPaintEvent;
+ widgetInPaintEvent = true;
+ QCoreApplication::instance()->notify(receiver, event);
+ widgetInPaintEvent = was;
+ bool *result = reinterpret_cast<bool*>(data[2]);
+ *result = true;
+ return true;
+ }
+ return false;
+}
+
+}
+
+/*!
+ \since 4.5
+ \class QScriptDebugger
+ \internal
+
+ \brief The QScriptDebugger class provides a Qt Script debugger.
+
+ \ingroup script
+
+*/
+
+class QScriptDebuggerPrivate
+ : public QObjectPrivate,
+ public QScriptDebuggerCommandSchedulerInterface,
+ public QScriptDebuggerJobSchedulerInterface,
+ public QScriptDebuggerEventHandlerInterface,
+ public QScriptDebuggerResponseHandlerInterface,
+ public QScriptCompletionProviderInterface,
+ public QScriptToolTipProviderInterface
+{
+ Q_DECLARE_PUBLIC(QScriptDebugger)
+public:
+ QScriptDebuggerPrivate();
+ ~QScriptDebuggerPrivate();
+
+ int scheduleJob(QScriptDebuggerJob *job);
+ void finishJob(QScriptDebuggerJob *job);
+ void hibernateUntilEvaluateFinished(QScriptDebuggerJob *job);
+
+ void maybeStartNewJob();
+
+ int scheduleCommand(const QScriptDebuggerCommand &command,
+ QScriptDebuggerResponseHandlerInterface *responseHandler);
+
+ void handleResponse(
+ const QScriptDebuggerResponse &response, int commandId);
+ bool debuggerEvent(const QScriptDebuggerEvent &event);
+
+ QScriptCompletionTaskInterface *createCompletionTask(
+ const QString &contents, int cursorPosition, int frameIndex, int options);
+
+ void showToolTip(const QPoint &pos, int frameIndex,
+ int lineNumber, const QStringList &path);
+
+ static QPixmap pixmap(const QString &path);
+
+ void startInteraction(QScriptDebuggerEvent::Type type,
+ qint64 scriptId, int lineNumber);
+ void sync();
+ void loadLocals(int frameIndex);
+ QScriptDebuggerLocalsModel *createLocalsModel();
+ void selectScriptForFrame(int frameIndex);
+ void emitStoppedSignal();
+
+ void maybeDelete(QWidget *widget);
+
+ // private slots
+ void _q_onLineEntered(const QString &contents);
+ void _q_onCurrentFrameChanged(int frameIndex);
+ void _q_onCurrentScriptChanged(qint64 scriptId);
+ void _q_onScriptLocationSelected(int lineNumber);
+ void _q_interrupt();
+ void _q_continue();
+ void _q_stepInto();
+ void _q_stepOver();
+ void _q_stepOut();
+ void _q_runToCursor();
+ void _q_runToNewScript();
+ void _q_toggleBreakpoint();
+ void _q_clearDebugOutput();
+ void _q_clearErrorLog();
+ void _q_clearConsole();
+ void _q_findInScript();
+ void _q_findNextInScript();
+ void _q_findPreviousInScript();
+ void _q_onFindCodeRequest(const QString &, int);
+ void _q_goToLine();
+
+ void executeConsoleCommand(const QString &command);
+ void findCode(const QString &exp, int options);
+
+ QScriptDebuggerFrontend *frontend;
+
+ bool interactive;
+ QScriptDebuggerConsole *console;
+
+ int nextJobId;
+ QList<QScriptDebuggerJob*> pendingJobs;
+ QList<int> pendingJobIds;
+ QScriptDebuggerJob *activeJob;
+ bool activeJobHibernating;
+ QHash<int, QScriptDebuggerCommand> watchedCommands;
+ QHash<int, QScriptDebuggerResponseHandlerInterface*> responseHandlers;
+
+ QScriptDebuggerConsoleWidgetInterface *consoleWidget;
+ QScriptDebuggerStackWidgetInterface *stackWidget;
+ QScriptDebuggerStackModel *stackModel;
+ QScriptDebuggerScriptsWidgetInterface *scriptsWidget;
+ QScriptDebuggerScriptsModel *scriptsModel;
+ QScriptDebuggerLocalsWidgetInterface *localsWidget;
+ QHash<int, QScriptDebuggerLocalsModel*> localsModels;
+ QScriptDebuggerCodeWidgetInterface *codeWidget;
+ QScriptDebuggerCodeFinderWidgetInterface *codeFinderWidget;
+ QScriptBreakpointsWidgetInterface *breakpointsWidget;
+ QScriptBreakpointsModel *breakpointsModel;
+ QScriptDebugOutputWidgetInterface *debugOutputWidget;
+ QScriptErrorLogWidgetInterface *errorLogWidget;
+ QScriptDebuggerWidgetFactoryInterface *widgetFactory;
+
+ QAction *interruptAction;
+ QAction *continueAction;
+ QAction *stepIntoAction;
+ QAction *stepOverAction;
+ QAction *stepOutAction;
+ QAction *runToCursorAction;
+ QAction *runToNewScriptAction;
+
+ QAction *toggleBreakpointAction;
+
+ QAction *clearDebugOutputAction;
+ QAction *clearErrorLogAction;
+ QAction *clearConsoleAction;
+
+ QAction *findInScriptAction;
+ QAction *findNextInScriptAction;
+ QAction *findPreviousInScriptAction;
+ QAction *goToLineAction;
+
+ int updatesEnabledTimerId;
+};
+
+QScriptDebuggerPrivate::QScriptDebuggerPrivate()
+{
+ frontend = 0;
+ activeJob = 0;
+ activeJobHibernating = false;
+ nextJobId = 0;
+ interactive = false;
+
+ console = new QScriptDebuggerConsole();
+ QString scriptsPath = QLatin1String(":/qt/scripttools/debugging/scripts/commands");
+ QScriptStdMessageHandler tmp;
+ console->loadScriptedCommands(scriptsPath, &tmp);
+
+ consoleWidget = 0;
+ stackWidget = 0;
+ stackModel = 0;
+ scriptsWidget = 0;
+ scriptsModel = 0;
+ localsWidget = 0;
+ codeWidget = 0;
+ codeFinderWidget = 0;
+ breakpointsWidget = 0;
+ breakpointsModel = 0;
+ debugOutputWidget = 0;
+ errorLogWidget = 0;
+ widgetFactory = 0;
+
+ interruptAction = 0;
+ continueAction = 0;
+ stepIntoAction = 0;
+ stepOverAction = 0;
+ stepOutAction = 0;
+ runToCursorAction = 0;
+ runToNewScriptAction = 0;
+
+ toggleBreakpointAction = 0;
+
+ clearErrorLogAction = 0;
+ clearDebugOutputAction = 0;
+ clearConsoleAction = 0;
+
+ findInScriptAction = 0;
+ findNextInScriptAction = 0;
+ findPreviousInScriptAction = 0;
+ goToLineAction = 0;
+
+ updatesEnabledTimerId = -1;
+}
+
+QScriptDebuggerPrivate::~QScriptDebuggerPrivate()
+{
+ delete console;
+ qDeleteAll(pendingJobs);
+ delete activeJob;
+ maybeDelete(consoleWidget);
+ maybeDelete(stackWidget);
+ maybeDelete(scriptsWidget);
+ maybeDelete(localsWidget);
+ maybeDelete(codeWidget);
+ maybeDelete(codeFinderWidget);
+ maybeDelete(breakpointsWidget);
+ maybeDelete(debugOutputWidget);
+ maybeDelete(errorLogWidget);
+}
+
+void QScriptDebuggerPrivate::maybeDelete(QWidget *widget)
+{
+ if (widget && !widget->parent())
+ delete widget;
+}
+
+QPixmap QScriptDebuggerPrivate::pixmap(const QString &path)
+{
+ static QString prefix = QString::fromLatin1(":/qt/scripttools/debugging/images/");
+ return QPixmap(prefix + path);
+}
+
+/*!
+ \reimp
+*/
+int QScriptDebuggerPrivate::scheduleJob(QScriptDebuggerJob *job)
+{
+ QScriptDebuggerJobPrivate *priv = QScriptDebuggerJobPrivate::get(job);
+ Q_ASSERT(priv->jobScheduler == 0);
+ priv->jobScheduler = this;
+ int id = nextJobId;
+ pendingJobs.append(job);
+ pendingJobIds.append(id);
+ maybeStartNewJob();
+ return id;
+}
+
+/*!
+ \reimp
+*/
+void QScriptDebuggerPrivate::finishJob(QScriptDebuggerJob *job)
+{
+ Q_UNUSED(job);
+ Q_ASSERT(activeJob == job);
+ delete activeJob;
+ activeJob = 0;
+ activeJobHibernating = false;
+ maybeStartNewJob();
+}
+
+/*!
+ \reimp
+*/
+void QScriptDebuggerPrivate::hibernateUntilEvaluateFinished(QScriptDebuggerJob *job)
+{
+ Q_UNUSED(job);
+ Q_ASSERT(activeJob == job);
+ activeJobHibernating = true;
+}
+
+/*!
+ Starts a new job if appropriate.
+*/
+void QScriptDebuggerPrivate::maybeStartNewJob()
+{
+ if (activeJob || pendingJobs.isEmpty())
+ return;
+ activeJob = pendingJobs.takeFirst();
+ activeJob->start();
+}
+
+/*!
+ \reimp
+*/
+int QScriptDebuggerPrivate::scheduleCommand(
+ const QScriptDebuggerCommand &command,
+ QScriptDebuggerResponseHandlerInterface *responseHandler)
+{
+ if (!frontend)
+ return -1;
+ int id = frontend->scheduleCommand(command, this);
+ if (responseHandler && (responseHandler != this))
+ responseHandlers.insert(id, responseHandler);
+ if ((command.type() == QScriptDebuggerCommand::SetBreakpoint)
+ || (command.type() == QScriptDebuggerCommand::SetBreakpointData)
+ || (command.type() == QScriptDebuggerCommand::DeleteBreakpoint)) {
+ // need to watch this command and update the breakpoints model afterwards
+ watchedCommands.insert(id, command);
+ }
+ return id;
+}
+
+/*!
+ \reimp
+*/
+void QScriptDebuggerPrivate::handleResponse(
+ const QScriptDebuggerResponse &response, int commandId)
+{
+ Q_Q(QScriptDebugger);
+ if (watchedCommands.contains(commandId)) {
+ QScriptDebuggerCommand command = watchedCommands.take(commandId);
+ if (response.error() == QScriptDebuggerResponse::NoError) {
+ if (!breakpointsModel)
+ breakpointsModel = new QScriptBreakpointsModel(this, this, q);
+ switch (command.type()) {
+ case QScriptDebuggerCommand::SetBreakpoint: {
+ int breakpointId = response.resultAsInt();
+ QScriptBreakpointData data = command.breakpointData();
+ breakpointsModel->addBreakpoint(breakpointId, data);
+ } break;
+ case QScriptDebuggerCommand::SetBreakpointData: {
+ int breakpointId = command.breakpointId();
+ QScriptBreakpointData data = command.breakpointData();
+ breakpointsModel->modifyBreakpoint(breakpointId, data);
+ } break;
+ case QScriptDebuggerCommand::DeleteBreakpoint: {
+ int breakpointId = command.breakpointId();
+ breakpointsModel->removeBreakpoint(breakpointId);
+ } break;
+ default:
+ Q_ASSERT(false);
+ }
+ }
+ } else if (response.async()) {
+ interactive = false;
+ // disable/invalidate/enable stuff
+ if (continueAction)
+ continueAction->setEnabled(false);
+ if (stepIntoAction)
+ stepIntoAction->setEnabled(false);
+ if (stepOverAction)
+ stepOverAction->setEnabled(false);
+ if (stepOutAction)
+ stepOutAction->setEnabled(false);
+ if (runToCursorAction)
+ runToCursorAction->setEnabled(false);
+ if (runToNewScriptAction)
+ runToNewScriptAction->setEnabled(false);
+ if (interruptAction)
+ interruptAction->setEnabled(true);
+
+ // the timer is to avoid flicker when stepping
+ if (stackWidget) {
+ stackWidget->setUpdatesEnabled(false);
+ stackWidget->setEnabled(false);
+ if (updatesEnabledTimerId == -1)
+ updatesEnabledTimerId = q->startTimer(75);
+ }
+ if (localsWidget) {
+ localsWidget->setUpdatesEnabled(false);
+ localsWidget->setEnabled(false);
+ if (updatesEnabledTimerId == -1)
+ updatesEnabledTimerId = q->startTimer(75);
+ }
+ if (codeWidget)
+ codeWidget->invalidateExecutionLineNumbers();
+
+ emit q->started();
+ }
+
+ QScriptDebuggerResponseHandlerInterface *realHandler = responseHandlers.take(commandId);
+ if (realHandler)
+ realHandler->handleResponse(response, commandId);
+}
+
+/*!
+ \reimp
+
+ Handles a debugger event from the frontend.
+*/
+bool QScriptDebuggerPrivate::debuggerEvent(const QScriptDebuggerEvent &event)
+{
+ Q_Q(QScriptDebugger);
+ switch (event.type()) {
+ case QScriptDebuggerEvent::None:
+ case QScriptDebuggerEvent::UserEvent:
+ case QScriptDebuggerEvent::MaxUserEvent:
+ Q_ASSERT(false);
+ break;
+
+ case QScriptDebuggerEvent::Trace:
+ if (!debugOutputWidget && widgetFactory)
+ q->setDebugOutputWidget(widgetFactory->createDebugOutputWidget());
+ if (debugOutputWidget)
+ debugOutputWidget->message(QtDebugMsg, event.message());
+ return true; // trace doesn't stall execution
+
+ case QScriptDebuggerEvent::SteppingFinished: {
+ if (!consoleWidget && widgetFactory)
+ q->setConsoleWidget(widgetFactory->createConsoleWidget());
+ if (consoleWidget) {
+ QString msg = event.message();
+ if (!msg.isEmpty())
+ consoleWidget->message(QtDebugMsg, msg);
+ }
+ } break;
+
+ case QScriptDebuggerEvent::Interrupted:
+ case QScriptDebuggerEvent::LocationReached:
+ break;
+
+ case QScriptDebuggerEvent::Breakpoint: {
+ int bpId = event.breakpointId();
+ if (!consoleWidget && widgetFactory)
+ q->setConsoleWidget(widgetFactory->createConsoleWidget());
+ if (consoleWidget) {
+ consoleWidget->message(QtDebugMsg,
+ QString::fromLatin1("Breakpoint %0 at %1, line %2.")
+ .arg(bpId).arg(event.fileName())
+ .arg(event.lineNumber()));
+ }
+ if (breakpointsModel->breakpointData(bpId).isSingleShot())
+ breakpointsModel->removeBreakpoint(bpId);
+ } break;
+
+ case QScriptDebuggerEvent::Exception: {
+ if (event.hasExceptionHandler()) {
+ // Let the exception be handled like normal.
+ // We may want to add a "Break on all exceptions" option
+ // to be able to customize this behavior.
+ return true;
+ }
+ if (!consoleWidget && widgetFactory)
+ q->setConsoleWidget(widgetFactory->createConsoleWidget());
+ if (!errorLogWidget && widgetFactory)
+ q->setErrorLogWidget(widgetFactory->createErrorLogWidget());
+ if (consoleWidget || errorLogWidget) {
+ QString fn = event.fileName();
+ if (fn.isEmpty()) {
+ if (event.scriptId() != -1)
+ fn = QString::fromLatin1("<anonymous script, id=%0>").arg(event.scriptId());
+ else
+ fn = QString::fromLatin1("<native>");
+ }
+ QString msg = QString::fromLatin1("Uncaught exception at %0:%1: %2").arg(fn)
+ .arg(event.lineNumber()).arg(event.message());
+ if (consoleWidget)
+ consoleWidget->message(QtCriticalMsg, msg);
+ if (errorLogWidget)
+ errorLogWidget->message(QtCriticalMsg, msg);
+ }
+ } break;
+
+ case QScriptDebuggerEvent::InlineEvalFinished: {
+ QScriptDebuggerValue result = event.scriptValue();
+ Q_ASSERT(console != 0);
+ int action = console->evaluateAction();
+ console->setEvaluateAction(0);
+ switch (action) {
+ case 0: { // eval command
+ if (activeJob) {
+ if (activeJobHibernating) {
+ activeJobHibernating = false;
+ activeJob->evaluateFinished(result);
+ }
+ } else if (consoleWidget) {
+ // ### if the result is an object, need to do a tostring job on it
+// messageHandler->message(QtDebugMsg, result.toString());
+ if (result.type() != QScriptDebuggerValue::UndefinedValue)
+ consoleWidget->message(QtDebugMsg, event.message());
+ }
+ } break;
+ case 1: { // return command
+ QScriptDebuggerCommandSchedulerFrontend frontend(this, this);
+ frontend.scheduleForceReturn(console->currentFrameIndex(), result);
+ } return false;
+ }
+ if (!event.isNestedEvaluate()) {
+ // in the case when evaluate() was called while the
+ // engine was not running, we don't want to enter interactive mode
+ return true;
+ }
+ } break;
+
+ case QScriptDebuggerEvent::DebuggerInvocationRequest: {
+ if (!consoleWidget && widgetFactory)
+ q->setConsoleWidget(widgetFactory->createConsoleWidget());
+ if (consoleWidget) {
+ QString fn = event.fileName();
+ if (fn.isEmpty())
+ fn = QString::fromLatin1("<anonymous script, id=%0>").arg(event.scriptId());
+ consoleWidget->message(QtDebugMsg,
+ QString::fromLatin1("Debugger invoked from %1, line %2.")
+ .arg(fn).arg(event.lineNumber()));
+ }
+ } break;
+
+ case QScriptDebuggerEvent::ForcedReturn: {
+ } break;
+
+ }
+
+ if (widgetInPaintEvent) {
+ QString msg = QString::fromLatin1("Suspending evaluation in paintEvent() is not supported; resuming.");
+ if (!consoleWidget && widgetFactory)
+ q->setConsoleWidget(widgetFactory->createConsoleWidget());
+ if (!errorLogWidget && widgetFactory)
+ q->setErrorLogWidget(widgetFactory->createErrorLogWidget());
+ if (consoleWidget)
+ consoleWidget->message(QtWarningMsg, msg);
+ if (errorLogWidget)
+ errorLogWidget->message(QtCriticalMsg, msg);
+ return true;
+ }
+
+ if (activeJobHibernating) {
+ // evaluate() did not finish normally (e.g. due to a breakpoint),
+ // so cancel the job that's waiting for it
+ delete activeJob;
+ activeJob = 0;
+ activeJobHibernating = false;
+ }
+
+ startInteraction(event.type(), event.scriptId(), event.lineNumber());
+ return !interactive;
+}
+
+class QScriptToolTipJob : public QScriptDebuggerCommandSchedulerJob
+{
+public:
+ QScriptToolTipJob(const QPoint &pos, int frameIndex,
+ int lineNumber, const QStringList &path,
+ QScriptDebuggerCommandSchedulerInterface *scheduler)
+ : QScriptDebuggerCommandSchedulerJob(scheduler), m_pos(pos),
+ m_frameIndex(frameIndex), m_lineNumber(lineNumber), m_path(path)
+ {}
+
+ void start()
+ {
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ frontend.scheduleGetPropertyExpressionValue(m_frameIndex, m_lineNumber, m_path);
+ }
+ void handleResponse(const QScriptDebuggerResponse &response, int /*commandId*/)
+ {
+ QString tip = response.result().toString();
+ if (tip.indexOf(QLatin1Char('\n')) != -1) {
+ QStringList lines = tip.split(QLatin1Char('\n'));
+ int lineCount = lines.size();
+ if (lineCount > 5) {
+ lines = lines.mid(0, 5);
+ lines.append(QString::fromLatin1("(... %0 more lines ...)").arg(lineCount - 5));
+ }
+ tip = lines.join(QLatin1String("\n"));
+ }
+ QToolTip::showText(m_pos, tip);
+ finish();
+ }
+
+private:
+ QPoint m_pos;
+ int m_frameIndex;
+ int m_lineNumber;
+ QStringList m_path;
+};
+
+/*!
+ \reimp
+*/
+void QScriptDebuggerPrivate::showToolTip(const QPoint &pos, int frameIndex,
+ int lineNumber, const QStringList &path)
+{
+ if (frameIndex == -1) {
+ if (stackWidget)
+ frameIndex = stackWidget->currentFrameIndex();
+ else
+ frameIndex = console->currentFrameIndex();
+ }
+ QScriptDebuggerJob *job = new QScriptToolTipJob(pos, frameIndex, lineNumber, path, this);
+ scheduleJob(job);
+}
+
+/*!
+ \reimp
+*/
+QScriptCompletionTaskInterface *QScriptDebuggerPrivate::createCompletionTask(
+ const QString &contents, int cursorPosition, int frameIndex, int options)
+{
+ return new QScriptCompletionTask(
+ contents, cursorPosition, frameIndex, this, this,
+ (options & QScriptCompletionProviderInterface::ConsoleCommandCompletion) ? console : 0);
+}
+
+/*!
+ Slot called when a line has been entered in the console widget.
+*/
+void QScriptDebuggerPrivate::_q_onLineEntered(const QString &contents)
+{
+ QScriptDebuggerConsoleCommandJob *commandJob;
+ commandJob = console->consumeInput(contents, consoleWidget, this);
+ if (commandJob != 0) {
+ scheduleJob(commandJob);
+ consoleWidget->setLineContinuationMode(false);
+ } else if (console->hasIncompleteInput()) {
+ consoleWidget->setLineContinuationMode(true);
+ }
+}
+
+/*!
+ Slot called when the current index has changed in the stack widget.
+*/
+void QScriptDebuggerPrivate::_q_onCurrentFrameChanged(int frameIndex)
+{
+ loadLocals(frameIndex);
+ selectScriptForFrame(frameIndex);
+}
+
+/*!
+ Slot called when the current script has changed in the scripts widget.
+*/
+void QScriptDebuggerPrivate::_q_onCurrentScriptChanged(qint64 scriptId)
+{
+ if (codeWidget && (codeWidget->currentScriptId() != scriptId)) {
+ codeWidget->setCurrentScript(scriptId);
+ QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
+ if (view)
+ view->setExecutionLineNumber(-1, /*error=*/false);
+ }
+}
+
+void QScriptDebuggerPrivate::_q_onScriptLocationSelected(int lineNumber)
+{
+ QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
+ if (!view)
+ return;
+ view->gotoLine(lineNumber);
+}
+
+void QScriptDebuggerPrivate::_q_interrupt()
+{
+ executeConsoleCommand(QString::fromLatin1("interrupt"));
+}
+
+void QScriptDebuggerPrivate::_q_continue()
+{
+ executeConsoleCommand(QString::fromLatin1("continue"));
+}
+
+void QScriptDebuggerPrivate::_q_stepInto()
+{
+ executeConsoleCommand(QString::fromLatin1("step"));
+}
+
+void QScriptDebuggerPrivate::_q_stepOver()
+{
+ executeConsoleCommand(QString::fromLatin1("next"));
+}
+
+void QScriptDebuggerPrivate::_q_stepOut()
+{
+ executeConsoleCommand(QString::fromLatin1("finish"));
+}
+
+void QScriptDebuggerPrivate::_q_runToCursor()
+{
+ qint64 scriptId = codeWidget->currentScriptId();
+ int lineNumber = codeWidget->currentView()->cursorLineNumber();
+ QScriptDebuggerCommandSchedulerFrontend frontend(this, this);
+ frontend.scheduleRunToLocation(scriptId, lineNumber);
+}
+
+void QScriptDebuggerPrivate::_q_runToNewScript()
+{
+ QScriptDebuggerCommandSchedulerFrontend frontend(this, this);
+ frontend.scheduleRunToLocation(QString(), -1);
+}
+
+void QScriptDebuggerPrivate::_q_toggleBreakpoint()
+{
+ Q_ASSERT(codeWidget != 0);
+ QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
+ if (!view)
+ return;
+ qint64 scriptId = codeWidget->currentScriptId();
+ int lineNumber = view->cursorLineNumber();
+ Q_ASSERT(breakpointsModel != 0);
+ int bpId = breakpointsModel->resolveBreakpoint(scriptId, lineNumber);
+ if (bpId != -1) {
+ breakpointsModel->deleteBreakpoint(bpId);
+ } else {
+ QScriptBreakpointData data(scriptId, lineNumber);
+ if (scriptsModel)
+ data.setFileName(scriptsModel->scriptData(scriptId).fileName());
+ breakpointsModel->setBreakpoint(data);
+ }
+}
+
+void QScriptDebuggerPrivate::_q_clearDebugOutput()
+{
+ if (debugOutputWidget)
+ debugOutputWidget->clear();
+}
+
+void QScriptDebuggerPrivate::_q_clearErrorLog()
+{
+ if (errorLogWidget)
+ errorLogWidget->clear();
+}
+
+void QScriptDebuggerPrivate::_q_clearConsole()
+{
+ if (consoleWidget)
+ consoleWidget->clear();
+}
+
+void QScriptDebuggerPrivate::executeConsoleCommand(const QString &command)
+{
+ QString tmp = console->incompleteInput();
+ console->setIncompleteInput(QString());
+ QScriptDebuggerJob *job = console->consumeInput(console->commandPrefix() + command, debugOutputWidget, this);
+ console->setIncompleteInput(tmp);
+ if (job != 0) {
+ scheduleJob(job);
+ // once to send the command...
+ QCoreApplication::processEvents();
+ // ... and once to receive the response
+ QCoreApplication::processEvents();
+ }
+}
+
+void QScriptDebuggerPrivate::_q_findInScript()
+{
+ if (!codeFinderWidget && widgetFactory)
+ q_func()->setCodeFinderWidget(widgetFactory->createCodeFinderWidget());
+ if (codeFinderWidget) {
+ codeFinderWidget->show();
+ codeFinderWidget->setFocus(Qt::OtherFocusReason);
+ }
+}
+
+void QScriptDebuggerPrivate::_q_findNextInScript()
+{
+ findCode(codeFinderWidget->text(), codeFinderWidget->findOptions());
+}
+
+void QScriptDebuggerPrivate::_q_findPreviousInScript()
+{
+ int options = codeFinderWidget->findOptions();
+ options |= QTextDocument::FindBackward;
+ findCode(codeFinderWidget->text(), options);
+}
+
+void QScriptDebuggerPrivate::_q_onFindCodeRequest(
+ const QString &exp, int options)
+{
+ findCode(exp, options);
+ if (findNextInScriptAction)
+ findNextInScriptAction->setEnabled(!exp.isEmpty());
+ if (findPreviousInScriptAction)
+ findPreviousInScriptAction->setEnabled(!exp.isEmpty());
+}
+
+void QScriptDebuggerPrivate::findCode(const QString &exp, int options)
+{
+ QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
+ if (!view)
+ return;
+ int result = view->find(exp, options);
+ codeFinderWidget->setOK(((result & 0x1) != 0) || exp.isEmpty());
+ codeFinderWidget->setWrapped((result & 0x2) != 0);
+}
+
+void QScriptDebuggerPrivate::_q_goToLine()
+{
+ QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
+ if (!view)
+ return;
+ bool ok = false;
+ int lineNumber = QInputDialog::getInteger(0, QScriptDebugger::tr("Go to Line"),
+ QScriptDebugger::tr("Line:"),
+ view->cursorLineNumber(),
+ 1, INT_MAX, 1, &ok);
+ if (ok)
+ view->gotoLine(lineNumber);
+}
+
+class QScriptDebuggerShowLineJob : public QScriptDebuggerCommandSchedulerJob
+{
+public:
+ QScriptDebuggerShowLineJob(qint64 scriptId, int lineNumber,
+ QScriptMessageHandlerInterface *messageHandler,
+ QScriptDebuggerCommandSchedulerInterface *scheduler)
+ : QScriptDebuggerCommandSchedulerJob(scheduler),
+ m_scriptId(scriptId), m_lineNumber(lineNumber),
+ m_messageHandler(messageHandler) {}
+
+ void start()
+ {
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ frontend.scheduleGetScriptData(m_scriptId);
+ }
+ void handleResponse(const QScriptDebuggerResponse &response, int /*commandId*/)
+ {
+ QScriptScriptData data = response.resultAsScriptData();
+ QString line = data.lines(m_lineNumber, 1).value(0);
+ m_messageHandler->message(QtDebugMsg, QString::fromLatin1("%0\t%1")
+ .arg(m_lineNumber).arg(line));
+ finish();
+ }
+
+private:
+ qint64 m_scriptId;
+ int m_lineNumber;
+ QScriptMessageHandlerInterface *m_messageHandler;
+};
+
+namespace {
+
+class SyncStackJob : public QScriptDebuggerCommandSchedulerJob
+{
+public:
+ SyncStackJob(QScriptDebuggerPrivate *debugger)
+ : QScriptDebuggerCommandSchedulerJob(debugger),
+ m_debugger(debugger), m_index(0) {}
+ void start()
+ {
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ frontend.scheduleGetContextInfo(m_index); // ### getContextInfos()
+ }
+ void handleResponse(const QScriptDebuggerResponse &response,
+ int)
+ {
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ if (response.error() != QScriptDebuggerResponse::InvalidContextIndex) {
+ m_infos.append(response.resultAsContextInfo());
+ frontend.scheduleGetContextInfo(++m_index);
+ } else {
+ m_debugger->stackModel->setContextInfos(m_infos);
+ if (m_debugger->stackWidget->currentFrameIndex() == -1)
+ m_debugger->stackWidget->setCurrentFrameIndex(0);
+ m_debugger->stackWidget->setUpdatesEnabled(true);
+ m_debugger->stackWidget->setEnabled(true);
+ finish();
+ }
+ }
+
+private:
+ QScriptDebuggerPrivate *m_debugger;
+ int m_index;
+ QList<QScriptContextInfo> m_infos;
+};
+
+class SyncScriptsJob : public QScriptDebuggerCommandSchedulerJob
+{
+public:
+ SyncScriptsJob(QScriptDebuggerPrivate *debugger)
+ : QScriptDebuggerCommandSchedulerJob(debugger),
+ m_debugger(debugger), m_index(-1) {}
+
+ void start()
+ {
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ frontend.scheduleScriptsCheckpoint();
+ }
+ void handleResponse(const QScriptDebuggerResponse &response,
+ int)
+ {
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ if (m_index == -1) {
+ QScriptScriptsDelta delta;
+ delta = qvariant_cast<QScriptScriptsDelta>(response.result());
+
+ const QList<qint64> &removed = delta.second;
+ for (int i = 0; i < removed.size(); ++i)
+ m_debugger->scriptsModel->removeScript(removed.at(i));
+
+ m_added = delta.first;
+ if (!m_added.isEmpty()) {
+ frontend.scheduleGetScriptData(m_added.at(++m_index));
+ } else {
+ m_debugger->scriptsModel->commit();
+ finish();
+ }
+ } else {
+ QScriptScriptData data = response.resultAsScriptData();
+ qint64 scriptId = m_added.at(m_index);
+ m_debugger->scriptsModel->addScript(scriptId, data);
+
+ // ### could be slow, might want to do this in a separate thread
+// Q_ASSERT_X(false, Q_FUNC_INFO, "implement me");
+ QString xml; // = qt_scriptToXml(data.contents(), data.baseLineNumber());
+ QScriptXmlParser::Result extraInfo = QScriptXmlParser::parse(xml);
+ m_debugger->scriptsModel->addExtraScriptInfo(
+ scriptId, extraInfo.functionsInfo, extraInfo.executableLineNumbers);
+
+ if (++m_index < m_added.size())
+ frontend.scheduleGetScriptData(m_added.at(m_index));
+ else {
+ m_debugger->scriptsModel->commit();
+ finish();
+ }
+ }
+ }
+
+private:
+ QScriptDebuggerPrivate *m_debugger;
+ int m_index;
+ QList<qint64> m_added;
+};
+
+class SyncBreakpointsJob : public QScriptDebuggerCommandSchedulerJob
+{
+public:
+ SyncBreakpointsJob(QScriptDebuggerPrivate *debugger)
+ : QScriptDebuggerCommandSchedulerJob(debugger),
+ m_debugger(debugger), m_index(-1) {}
+ void start()
+ {
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ frontend.scheduleGetBreakpoints();
+ }
+ void handleResponse(const QScriptDebuggerResponse &response,
+ int)
+ {
+ QScriptBreakpointMap breakpoints = response.resultAsBreakpoints();
+ QScriptBreakpointMap::const_iterator it;
+ for (it = breakpoints.constBegin(); it != breakpoints.constEnd(); ++it) {
+ int id = it.key();
+ QScriptBreakpointData newData = it.value();
+ QScriptBreakpointData existingData = m_debugger->breakpointsModel->breakpointData(id);
+ if (existingData.isValid() && (existingData != newData))
+ m_debugger->breakpointsModel->modifyBreakpoint(id, newData);
+ }
+ finish();
+ }
+
+private:
+ QScriptDebuggerPrivate *m_debugger;
+ int m_index;
+ QList<QScriptContextInfo> m_infos;
+};
+
+class SyncLocalsJob : public QScriptDebuggerCommandSchedulerJob
+{
+public:
+ SyncLocalsJob(QScriptDebuggerPrivate *debugger)
+ : QScriptDebuggerCommandSchedulerJob(debugger),
+ m_debugger(debugger) {}
+
+ void start()
+ {
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ frontend.scheduleContextsCheckpoint();
+ }
+ void handleResponse(const QScriptDebuggerResponse &response,
+ int)
+ {
+ QScriptContextsDelta delta = qvariant_cast<QScriptContextsDelta>(response.result());
+ for (int i = 0; i < delta.first.size(); ++i) {
+ QScriptDebuggerLocalsModel *model = m_debugger->localsModels.take(delta.first.at(i));
+ delete model;
+ }
+ finish();
+ }
+
+private:
+ QScriptDebuggerPrivate *m_debugger;
+};
+
+class LoadLocalsJob : public QScriptDebuggerCommandSchedulerJob
+{
+public:
+ LoadLocalsJob(QScriptDebuggerPrivate *debugger, int frameIndex)
+ : QScriptDebuggerCommandSchedulerJob(debugger),
+ m_debugger(debugger), m_frameIndex(frameIndex) {}
+
+ void start()
+ {
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ frontend.scheduleGetContextId(m_frameIndex);
+ }
+ void handleResponse(const QScriptDebuggerResponse &response,
+ int)
+ {
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ qint64 contextId = response.resultAsLongLong();
+ QScriptDebuggerLocalsModel *model = m_debugger->localsModels.value(contextId);
+ if (model) {
+ model->sync(m_frameIndex);
+ } else {
+ model = m_debugger->createLocalsModel();
+ m_debugger->localsModels.insert(contextId, model);
+ model->init(m_frameIndex);
+ }
+ if (m_debugger->localsWidget) {
+ if (m_debugger->localsWidget->localsModel() != model) // ### bug in qtreeview
+ m_debugger->localsWidget->setLocalsModel(model);
+ m_debugger->localsWidget->setUpdatesEnabled(true);
+ m_debugger->localsWidget->setEnabled(true);
+ }
+ finish();
+ }
+
+private:
+ QScriptDebuggerPrivate *m_debugger;
+ int m_frameIndex;
+};
+
+class EmitStoppedSignalJob : public QScriptDebuggerJob
+{
+public:
+ EmitStoppedSignalJob(QScriptDebuggerPrivate *debugger)
+ : m_debugger(debugger) {}
+
+ void start()
+ {
+ m_debugger->emitStoppedSignal();
+ finish();
+ }
+
+private:
+ QScriptDebuggerPrivate *m_debugger;
+};
+
+} // namespace
+
+void QScriptDebuggerPrivate::startInteraction(QScriptDebuggerEvent::Type type,
+ qint64 scriptId, int lineNumber)
+{
+ Q_Q(QScriptDebugger);
+ if (type != QScriptDebuggerEvent::InlineEvalFinished) {
+ if (stackWidget)
+ stackWidget->setCurrentFrameIndex(0);
+ console->setCurrentFrameIndex(0);
+ console->setCurrentScriptId(scriptId);
+ console->setCurrentLineNumber(lineNumber);
+ }
+
+ if ((scriptId != -1) && consoleWidget) {
+ QScriptDebuggerJob *job = new QScriptDebuggerShowLineJob(scriptId, lineNumber, consoleWidget, this);
+ scheduleJob(job);
+ }
+
+ sync();
+
+ if (!interactive) {
+ interactive = true;
+ if (updatesEnabledTimerId != -1) {
+ q->killTimer(updatesEnabledTimerId);
+ updatesEnabledTimerId = -1;
+ }
+ console->bumpSessionId();
+ scheduleJob(new EmitStoppedSignalJob(this));
+ }
+
+ if (consoleWidget)
+ consoleWidget->activateWindow();
+ else if (codeWidget)
+ codeWidget->activateWindow();
+
+ if (continueAction)
+ continueAction->setEnabled(true);
+ if (stepIntoAction)
+ stepIntoAction->setEnabled(true);
+ if (stepOverAction)
+ stepOverAction->setEnabled(true);
+ if (stepOutAction)
+ stepOutAction->setEnabled(true);
+ if (runToCursorAction)
+ runToCursorAction->setEnabled(true);
+ if (runToNewScriptAction)
+ runToNewScriptAction->setEnabled(true);
+ if (interruptAction)
+ interruptAction->setEnabled(false);
+
+ bool hasScript = (codeWidget != 0);
+ if (findInScriptAction)
+ findInScriptAction->setEnabled(hasScript);
+ if (toggleBreakpointAction)
+ toggleBreakpointAction->setEnabled(hasScript);
+ if (goToLineAction)
+ goToLineAction->setEnabled(hasScript);
+}
+
+void QScriptDebuggerPrivate::sync()
+{
+ if (localsWidget) {
+ QScriptDebuggerJob *job = new SyncLocalsJob(this);
+ scheduleJob(job);
+ }
+ if (scriptsModel) {
+ QScriptDebuggerJob *job = new SyncScriptsJob(this);
+ scheduleJob(job);
+ }
+ if (stackModel) {
+ QScriptDebuggerJob *job = new SyncStackJob(this);
+ scheduleJob(job);
+ }
+ if (breakpointsModel) {
+ // need to sync because the ignore-count could have changed
+ QScriptDebuggerJob *job = new SyncBreakpointsJob(this);
+ scheduleJob(job);
+ }
+
+ if (stackWidget && (stackWidget->currentFrameIndex() != -1)) {
+ int index = stackWidget->currentFrameIndex();
+ loadLocals(index);
+ selectScriptForFrame(index);
+ } else if (codeWidget && (console->currentFrameIndex() != -1)) {
+ selectScriptForFrame(console->currentFrameIndex());
+ }
+}
+
+void QScriptDebuggerPrivate::loadLocals(int frameIndex)
+{
+ LoadLocalsJob *job = new LoadLocalsJob(this, frameIndex);
+ scheduleJob(job);
+}
+
+QScriptDebuggerLocalsModel *QScriptDebuggerPrivate::createLocalsModel()
+{
+ return new QScriptDebuggerLocalsModel(this, this, q_func());
+}
+
+namespace {
+
+class ShowFrameCodeJob : public QScriptDebuggerCommandSchedulerJob
+{
+public:
+ ShowFrameCodeJob(QScriptDebuggerPrivate *debugger, int frameIndex)
+ : QScriptDebuggerCommandSchedulerJob(debugger),
+ m_debugger(debugger), m_frameIndex(frameIndex) {}
+
+ void start()
+ {
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ frontend.scheduleGetContextInfo(m_frameIndex);
+ }
+ void handleResponse(const QScriptDebuggerResponse &response,
+ int)
+ {
+ if (m_info.isNull()) {
+ m_info = response.resultAsContextInfo();
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ frontend.scheduleGetContextState(m_frameIndex);
+ } else {
+ int contextState = response.resultAsInt();
+ bool error = (contextState == QScriptContext::ExceptionState);
+ if (m_debugger->scriptsWidget) {
+ m_debugger->scriptsWidget->setCurrentScript(m_info.scriptId());
+ }
+ if (m_debugger->codeWidget) {
+ m_debugger->codeWidget->setCurrentScript(m_info.scriptId());
+ QScriptDebuggerCodeViewInterface *view = m_debugger->codeWidget->currentView();
+ if (view)
+ view->setExecutionLineNumber(m_info.lineNumber(), error);
+ }
+ finish();
+ }
+ }
+
+private:
+ QScriptDebuggerPrivate *m_debugger;
+ int m_frameIndex;
+ QScriptContextInfo m_info;
+};
+
+} // namespace
+
+void QScriptDebuggerPrivate::selectScriptForFrame(int frameIndex)
+{
+ QScriptDebuggerJob *job = new ShowFrameCodeJob(this, frameIndex);
+ scheduleJob(job);
+}
+
+void QScriptDebuggerPrivate::emitStoppedSignal()
+{
+ emit q_func()->stopped();
+}
+
+/*!
+ Constructs a new QScriptDebugger object.
+*/
+QScriptDebugger::QScriptDebugger(QObject *parent)
+ : QObject(*new QScriptDebuggerPrivate, parent)
+{
+ ++scriptDebuggerCount;
+}
+
+/*!
+ Destroys this QScriptDebugger.
+*/
+QScriptDebugger::~QScriptDebugger()
+{
+ --scriptDebuggerCount;
+ if ((scriptDebuggerCount == 0) && eventCallbackRegistered) {
+ eventCallbackRegistered = false;
+ QInternal::unregisterCallback(QInternal::EventNotifyCallback,
+ scriptDebuggerEventCallback);
+ }
+}
+
+/*!
+ \internal
+*/
+QScriptDebugger::QScriptDebugger(QScriptDebuggerPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+QScriptDebuggerFrontend *QScriptDebugger::frontend() const
+{
+ Q_D(const QScriptDebugger);
+ return d->frontend;
+}
+
+void QScriptDebugger::setFrontend(QScriptDebuggerFrontend *frontend)
+{
+ Q_D(QScriptDebugger);
+ if (d->frontend)
+ d->frontend->setEventHandler(0);
+ d->frontend = frontend;
+ if (frontend) {
+ frontend->setEventHandler(d);
+ if (!eventCallbackRegistered) {
+ eventCallbackRegistered = true;
+ QInternal::registerCallback(QInternal::EventNotifyCallback,
+ scriptDebuggerEventCallback);
+ }
+ }
+}
+
+QAction *QScriptDebugger::action(DebuggerAction action, QObject *parent)
+{
+ switch (action) {
+ case InterruptAction:
+ return interruptAction(parent);
+ case ContinueAction:
+ return continueAction(parent);
+ case StepIntoAction:
+ return stepIntoAction(parent);
+ case StepOverAction:
+ return stepOverAction(parent);
+ case StepOutAction:
+ return stepOutAction(parent);
+ case RunToCursorAction:
+ return runToCursorAction(parent);
+ case RunToNewScriptAction:
+ return runToNewScriptAction(parent);
+ case ToggleBreakpointAction:
+ return toggleBreakpointAction(parent);
+ case ClearDebugOutputAction:
+ return clearDebugOutputAction(parent);
+ case ClearErrorLogAction:
+ return clearErrorLogAction(parent);
+ case ClearConsoleAction:
+ return clearConsoleAction(parent);
+ case FindInScriptAction:
+ return findInScriptAction(parent);
+ case FindNextInScriptAction:
+ return findNextInScriptAction(parent);
+ case FindPreviousInScriptAction:
+ return findPreviousInScriptAction(parent);
+ case GoToLineAction:
+ return goToLineAction(parent);
+ }
+ return 0;
+}
+
+QWidget *QScriptDebugger::widget(DebuggerWidget widget)
+{
+ switch (widget) {
+ case ConsoleWidget: {
+ QScriptDebuggerConsoleWidgetInterface *w = consoleWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createConsoleWidget();
+ setConsoleWidget(w);
+ }
+ return w;
+ }
+ case StackWidget: {
+ QScriptDebuggerStackWidgetInterface *w = stackWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createStackWidget();
+ setStackWidget(w);
+ }
+ return w;
+ }
+ case ScriptsWidget: {
+ QScriptDebuggerScriptsWidgetInterface *w = scriptsWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createScriptsWidget();
+ setScriptsWidget(w);
+ }
+ return w;
+ }
+ case LocalsWidget: {
+ QScriptDebuggerLocalsWidgetInterface *w = localsWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createLocalsWidget();
+ setLocalsWidget(w);
+ }
+ return w;
+ }
+ case CodeWidget: {
+ QScriptDebuggerCodeWidgetInterface *w = codeWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createCodeWidget();
+ setCodeWidget(w);
+ }
+ return w;
+ }
+ case CodeFinderWidget: {
+ QScriptDebuggerCodeFinderWidgetInterface *w = codeFinderWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createCodeFinderWidget();
+ setCodeFinderWidget(w);
+ }
+ return w;
+ }
+ case BreakpointsWidget: {
+ QScriptBreakpointsWidgetInterface *w = breakpointsWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createBreakpointsWidget();
+ setBreakpointsWidget(w);
+ }
+ return w;
+ }
+ case DebugOutputWidget: {
+ QScriptDebugOutputWidgetInterface *w = debugOutputWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createDebugOutputWidget();
+ setDebugOutputWidget(w);
+ }
+ return w;
+ }
+ case ErrorLogWidget: {
+ QScriptErrorLogWidgetInterface *w = errorLogWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createErrorLogWidget();
+ setErrorLogWidget(w);
+ }
+ return w;
+ }
+ }
+ return 0;
+}
+
+QScriptDebuggerConsoleWidgetInterface *QScriptDebugger::consoleWidget() const
+{
+ Q_D(const QScriptDebugger);
+ return d->consoleWidget;
+}
+
+void QScriptDebugger::setConsoleWidget(QScriptDebuggerConsoleWidgetInterface *consoleWidget)
+{
+ Q_D(QScriptDebugger);
+ if (d->consoleWidget) {
+ QObject::disconnect(d->consoleWidget, 0, this, 0);
+ }
+ d->consoleWidget = consoleWidget;
+ if (consoleWidget) {
+ consoleWidget->setCommandHistorian(d->console);
+ consoleWidget->setCompletionProvider(d);
+ QObject::connect(consoleWidget, SIGNAL(lineEntered(QString)),
+ this, SLOT(_q_onLineEntered(QString)));
+
+ d->console->showDebuggerInfoMessage(consoleWidget);
+ }
+}
+
+QScriptDebuggerStackWidgetInterface *QScriptDebugger::stackWidget() const
+{
+ Q_D(const QScriptDebugger);
+ return d->stackWidget;
+}
+
+void QScriptDebugger::setStackWidget(QScriptDebuggerStackWidgetInterface *stackWidget)
+{
+ Q_D(QScriptDebugger);
+ if (d->stackWidget) {
+ QObject::disconnect(d->stackWidget, 0, this, 0);
+ }
+ d->stackWidget = stackWidget;
+ if (stackWidget) {
+ if (!d->stackModel) {
+ d->stackModel = new QScriptDebuggerStackModel(this);
+ if (d->interactive)
+ d->scheduleJob(new SyncStackJob(d));
+ }
+ stackWidget->setStackModel(d->stackModel);
+ QObject::connect(stackWidget, SIGNAL(currentFrameChanged(int)),
+ this, SLOT(_q_onCurrentFrameChanged(int)));
+ }
+}
+
+QScriptDebuggerScriptsWidgetInterface *QScriptDebugger::scriptsWidget() const
+{
+ Q_D(const QScriptDebugger);
+ return d->scriptsWidget;
+}
+
+void QScriptDebugger::setScriptsWidget(QScriptDebuggerScriptsWidgetInterface *scriptsWidget)
+{
+ Q_D(QScriptDebugger);
+ if (d->scriptsWidget) {
+ QObject::disconnect(d->scriptsWidget, 0, this, 0);
+ }
+ d->scriptsWidget = scriptsWidget;
+ if (scriptsWidget) {
+ if (!d->scriptsModel) {
+ d->scriptsModel = new QScriptDebuggerScriptsModel(this);
+ if (d->interactive)
+ d->scheduleJob(new SyncScriptsJob(d));
+ }
+ scriptsWidget->setScriptsModel(d->scriptsModel);
+ QObject::connect(scriptsWidget, SIGNAL(currentScriptChanged(qint64)),
+ this, SLOT(_q_onCurrentScriptChanged(qint64)));
+ QObject::connect(d->scriptsWidget, SIGNAL(scriptLocationSelected(int)),
+ this, SLOT(_q_onScriptLocationSelected(int)));
+ }
+}
+
+QScriptDebuggerLocalsWidgetInterface *QScriptDebugger::localsWidget() const
+{
+ Q_D(const QScriptDebugger);
+ return d->localsWidget;
+}
+
+void QScriptDebugger::setLocalsWidget(QScriptDebuggerLocalsWidgetInterface *localsWidget)
+{
+ Q_D(QScriptDebugger);
+ if (d->localsWidget) {
+ // ### d->localsWidget->setLocalsModel(0);
+ }
+ localsWidget->setCompletionProvider(d);
+ d->localsWidget = localsWidget;
+}
+
+QScriptDebuggerCodeWidgetInterface *QScriptDebugger::codeWidget() const
+{
+ Q_D(const QScriptDebugger);
+ return d->codeWidget;
+}
+
+void QScriptDebugger::setCodeWidget(QScriptDebuggerCodeWidgetInterface *codeWidget)
+{
+ Q_D(QScriptDebugger);
+ if (d->codeWidget) {
+ d->codeWidget->removeEventFilter(this);
+ }
+ d->codeWidget = codeWidget;
+ if (codeWidget) {
+ if (!d->scriptsModel) {
+ d->scriptsModel = new QScriptDebuggerScriptsModel(this);
+ if (d->interactive)
+ d->scheduleJob(new SyncScriptsJob(d));
+ }
+ codeWidget->setScriptsModel(d->scriptsModel);
+ if (!d->breakpointsModel) {
+ d->breakpointsModel = new QScriptBreakpointsModel(d, d, this);
+ if (d->interactive)
+ d->scheduleJob(new SyncBreakpointsJob(d));
+ }
+ codeWidget->setBreakpointsModel(d->breakpointsModel);
+ codeWidget->setToolTipProvider(d);
+ codeWidget->installEventFilter(this);
+ }
+ bool hasScript = (codeWidget != 0) && (codeWidget->currentView() != 0);
+ if (d->findInScriptAction)
+ d->findInScriptAction->setEnabled(hasScript && (d->codeFinderWidget != 0));
+ if (d->goToLineAction)
+ d->goToLineAction->setEnabled(hasScript);
+ if (d->toggleBreakpointAction)
+ d->toggleBreakpointAction->setEnabled(hasScript);
+}
+
+QScriptDebuggerCodeFinderWidgetInterface *QScriptDebugger::codeFinderWidget() const
+{
+ Q_D(const QScriptDebugger);
+ return d->codeFinderWidget;
+}
+
+void QScriptDebugger::setCodeFinderWidget(QScriptDebuggerCodeFinderWidgetInterface *codeFinderWidget)
+{
+ Q_D(QScriptDebugger);
+ if (d->codeFinderWidget) {
+ QObject::disconnect(d->codeFinderWidget, 0, this, 0);
+ }
+ d->codeFinderWidget = codeFinderWidget;
+ if (codeFinderWidget) {
+ QObject::connect(codeFinderWidget, SIGNAL(findRequest(QString,int)),
+ this, SLOT(_q_onFindCodeRequest(QString,int)));
+ }
+ if (d->findInScriptAction) {
+ d->findInScriptAction->setEnabled(
+ (codeFinderWidget != 0)
+ && (d->codeWidget != 0)
+ && (d->codeWidget->currentView() != 0));
+ }
+}
+
+QScriptDebugOutputWidgetInterface *QScriptDebugger::debugOutputWidget() const
+{
+ Q_D(const QScriptDebugger);
+ return d->debugOutputWidget;
+}
+
+void QScriptDebugger::setDebugOutputWidget(QScriptDebugOutputWidgetInterface *debugOutputWidget)
+{
+ Q_D(QScriptDebugger);
+ d->debugOutputWidget = debugOutputWidget;
+}
+
+QScriptBreakpointsWidgetInterface *QScriptDebugger::breakpointsWidget() const
+{
+ Q_D(const QScriptDebugger);
+ return d->breakpointsWidget;
+}
+
+void QScriptDebugger::setBreakpointsWidget(QScriptBreakpointsWidgetInterface *breakpointsWidget)
+{
+ Q_D(QScriptDebugger);
+ if (d->breakpointsWidget) {
+ // ### invalidate
+ }
+ d->breakpointsWidget = breakpointsWidget;
+ if (breakpointsWidget) {
+ if (!d->breakpointsModel) {
+ d->breakpointsModel = new QScriptBreakpointsModel(d, d, this);
+ if (d->interactive)
+ d->scheduleJob(new SyncBreakpointsJob(d));
+ }
+ d->breakpointsWidget->setBreakpointsModel(d->breakpointsModel);
+ d->breakpointsWidget->setScriptsModel(d->scriptsModel);
+ }
+}
+
+QScriptErrorLogWidgetInterface *QScriptDebugger::errorLogWidget() const
+{
+ Q_D(const QScriptDebugger);
+ return d->errorLogWidget;
+}
+
+void QScriptDebugger::setErrorLogWidget(QScriptErrorLogWidgetInterface *errorLogWidget)
+{
+ Q_D(QScriptDebugger);
+ d->errorLogWidget = errorLogWidget;
+}
+
+QScriptDebuggerWidgetFactoryInterface *QScriptDebugger::widgetFactory() const
+{
+ Q_D(const QScriptDebugger);
+ return d->widgetFactory;
+}
+
+void QScriptDebugger::setWidgetFactory(QScriptDebuggerWidgetFactoryInterface *factory)
+{
+ Q_D(QScriptDebugger);
+ d->widgetFactory = factory;
+}
+
+QAction *QScriptDebugger::interruptAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->interruptAction) {
+ QIcon interruptIcon;
+ interruptIcon.addPixmap(d->pixmap(QString::fromLatin1("interrupt.png")), QIcon::Normal);
+ interruptIcon.addPixmap(d->pixmap(QString::fromLatin1("d_interrupt.png")), QIcon::Disabled);
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->interruptAction = new QAction(interruptIcon, QScriptDebugger::tr("Interrupt"), parent);
+ d->interruptAction->setEnabled(!d->interactive);
+ d->interruptAction->setShortcut(QScriptDebugger::tr("Shift+F5"));
+ QObject::connect(d->interruptAction, SIGNAL(triggered()),
+ that, SLOT(_q_interrupt()));
+ }
+ return d->interruptAction;
+}
+
+QAction *QScriptDebugger::continueAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->continueAction) {
+ QIcon continueIcon;
+ continueIcon.addPixmap(d->pixmap(QString::fromLatin1("play.png")), QIcon::Normal);
+ continueIcon.addPixmap(d->pixmap(QString::fromLatin1("d_play.png")), QIcon::Disabled);
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->continueAction = new QAction(continueIcon, QScriptDebugger::tr("Continue"), parent);
+ d->continueAction->setEnabled(d->interactive);
+ d->continueAction->setShortcut(QScriptDebugger::tr("F5"));
+ QObject::connect(d->continueAction, SIGNAL(triggered()),
+ that, SLOT(_q_continue()));
+ }
+ return d->continueAction;
+}
+
+QAction *QScriptDebugger::stepIntoAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->stepIntoAction) {
+ QIcon stepIntoIcon;
+ stepIntoIcon.addPixmap(d->pixmap(QString::fromLatin1("stepinto.png")), QIcon::Normal);
+ stepIntoIcon.addPixmap(d->pixmap(QString::fromLatin1("d_stepinto.png")), QIcon::Disabled);
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->stepIntoAction = new QAction(stepIntoIcon, QScriptDebugger::tr("Step Into"), parent);
+ d->stepIntoAction->setEnabled(d->interactive);
+ d->stepIntoAction->setShortcut(QScriptDebugger::tr("F11"));
+ QObject::connect(d->stepIntoAction, SIGNAL(triggered()),
+ that, SLOT(_q_stepInto()));
+ }
+ return d->stepIntoAction;
+}
+
+QAction *QScriptDebugger::stepOverAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->stepOverAction) {
+ QIcon stepOverIcon;
+ stepOverIcon.addPixmap(d->pixmap(QString::fromLatin1("stepover.png")), QIcon::Normal);
+ stepOverIcon.addPixmap(d->pixmap(QString::fromLatin1("d_stepover.png")), QIcon::Disabled);
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->stepOverAction = new QAction(stepOverIcon, QScriptDebugger::tr("Step Over"), parent);
+ d->stepOverAction->setEnabled(d->interactive);
+ d->stepOverAction->setShortcut(QScriptDebugger::tr("F10"));
+ QObject::connect(d->stepOverAction, SIGNAL(triggered()),
+ that, SLOT(_q_stepOver()));
+ }
+ return d->stepOverAction;
+}
+
+QAction *QScriptDebugger::stepOutAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->stepOutAction) {
+ QIcon stepOutIcon;
+ stepOutIcon.addPixmap(d->pixmap(QString::fromLatin1("stepout.png")), QIcon::Normal);
+ stepOutIcon.addPixmap(d->pixmap(QString::fromLatin1("d_stepout.png")), QIcon::Disabled);
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->stepOutAction = new QAction(stepOutIcon, QScriptDebugger::tr("Step Out"), parent);
+ d->stepOutAction->setEnabled(d->interactive);
+ d->stepOutAction->setShortcut(QScriptDebugger::tr("Shift+F11"));
+ QObject::connect(d->stepOutAction, SIGNAL(triggered()),
+ that, SLOT(_q_stepOut()));
+ }
+ return d->stepOutAction;
+}
+
+QAction *QScriptDebugger::runToCursorAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->runToCursorAction) {
+ QIcon runToCursorIcon;
+ runToCursorIcon.addPixmap(d->pixmap(QString::fromLatin1("runtocursor.png")), QIcon::Normal);
+ runToCursorIcon.addPixmap(d->pixmap(QString::fromLatin1("d_runtocursor.png")), QIcon::Disabled);
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->runToCursorAction = new QAction(runToCursorIcon, QScriptDebugger::tr("Run to Cursor"), parent);
+ d->runToCursorAction->setEnabled(d->interactive);
+ d->runToCursorAction->setShortcut(QScriptDebugger::tr("Ctrl+F10"));
+ QObject::connect(d->runToCursorAction, SIGNAL(triggered()),
+ that, SLOT(_q_runToCursor()));
+ }
+ return d->runToCursorAction;
+}
+
+QAction *QScriptDebugger::runToNewScriptAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->runToNewScriptAction) {
+ QIcon runToNewScriptIcon;
+ runToNewScriptIcon.addPixmap(d->pixmap(QString::fromLatin1("runtonewscript.png")), QIcon::Normal);
+ runToNewScriptIcon.addPixmap(d->pixmap(QString::fromLatin1("d_breakonscriptload.png")), QIcon::Disabled);
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->runToNewScriptAction = new QAction(runToNewScriptIcon,
+ QScriptDebugger::tr("Run to New Script"), parent);
+ d->runToNewScriptAction->setEnabled(d->interactive);
+ QObject::connect(d->runToNewScriptAction, SIGNAL(triggered()),
+ that, SLOT(_q_runToNewScript()));
+ }
+ return d->runToNewScriptAction;
+}
+
+QAction *QScriptDebugger::toggleBreakpointAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->toggleBreakpointAction) {
+ QIcon toggleBreakpointIcon;
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->toggleBreakpointAction = new QAction(toggleBreakpointIcon,
+ QScriptDebugger::tr("Toggle Breakpoint"), parent);
+ d->toggleBreakpointAction->setShortcut(QScriptDebugger::tr("F9"));
+ d->toggleBreakpointAction->setEnabled((d->codeWidget != 0) && (d->codeWidget->currentView() != 0));
+ QObject::connect(d->toggleBreakpointAction, SIGNAL(triggered()),
+ that, SLOT(_q_toggleBreakpoint()));
+ }
+ return d->toggleBreakpointAction;
+}
+
+QAction *QScriptDebugger::clearDebugOutputAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->clearDebugOutputAction) {
+ QIcon clearDebugOutputIcon;
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->clearDebugOutputAction = new QAction(clearDebugOutputIcon, QScriptDebugger::tr("Clear Debug Output"), parent);
+ QObject::connect(d->clearDebugOutputAction, SIGNAL(triggered()),
+ that, SLOT(_q_clearDebugOutput()));
+ }
+ return d->clearDebugOutputAction;
+}
+
+QAction *QScriptDebugger::clearErrorLogAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->clearErrorLogAction) {
+ QIcon clearErrorLogIcon;
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->clearErrorLogAction = new QAction(clearErrorLogIcon, QScriptDebugger::tr("Clear Error Log"), parent);
+ QObject::connect(d->clearErrorLogAction, SIGNAL(triggered()),
+ that, SLOT(_q_clearErrorLog()));
+ }
+ return d->clearErrorLogAction;
+}
+
+QAction *QScriptDebugger::clearConsoleAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->clearConsoleAction) {
+ QIcon clearConsoleIcon;
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->clearConsoleAction = new QAction(clearConsoleIcon, QScriptDebugger::tr("Clear Console"), parent);
+ QObject::connect(d->clearConsoleAction, SIGNAL(triggered()),
+ that, SLOT(_q_clearConsole()));
+ }
+ return d->clearConsoleAction;
+}
+
+QAction *QScriptDebugger::findInScriptAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->findInScriptAction) {
+ QIcon findInScriptIcon;
+ findInScriptIcon.addPixmap(d->pixmap(QString::fromLatin1("find.png")), QIcon::Normal);
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->findInScriptAction = new QAction(findInScriptIcon, QScriptDebugger::tr("&Find in Script..."), parent);
+ d->findInScriptAction->setShortcut(QScriptDebugger::tr("Ctrl+F"));
+ d->findInScriptAction->setEnabled(
+ (d->codeFinderWidget != 0)
+ && (d->codeWidget != 0)
+ && (d->codeWidget->currentView() != 0));
+ QObject::connect(d->findInScriptAction, SIGNAL(triggered()),
+ that, SLOT(_q_findInScript()));
+ }
+ return d->findInScriptAction;
+}
+
+QAction *QScriptDebugger::findNextInScriptAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->findNextInScriptAction) {
+ QIcon findNextInScriptIcon;
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->findNextInScriptAction = new QAction(findNextInScriptIcon, QScriptDebugger::tr("Find &Next"), parent);
+ d->findNextInScriptAction->setEnabled(d->codeFinderWidget && !d->codeFinderWidget->text().isEmpty());
+ d->findNextInScriptAction->setShortcut(QScriptDebugger::tr("F3"));
+ QObject::connect(d->findNextInScriptAction, SIGNAL(triggered()),
+ that, SLOT(_q_findNextInScript()));
+ }
+ return d->findNextInScriptAction;
+}
+
+QAction *QScriptDebugger::findPreviousInScriptAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->findPreviousInScriptAction) {
+ QIcon findPreviousInScriptIcon;
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->findPreviousInScriptAction = new QAction(findPreviousInScriptIcon, QScriptDebugger::tr("Find &Previous"), parent);
+ d->findPreviousInScriptAction->setEnabled(d->codeFinderWidget && !d->codeFinderWidget->text().isEmpty());
+ d->findPreviousInScriptAction->setShortcut(QScriptDebugger::tr("Shift+F3"));
+ QObject::connect(d->findPreviousInScriptAction, SIGNAL(triggered()),
+ that, SLOT(_q_findPreviousInScript()));
+ }
+ return d->findPreviousInScriptAction;
+}
+
+QAction *QScriptDebugger::goToLineAction(QObject *parent) const
+{
+ Q_D(const QScriptDebugger);
+ if (!d->goToLineAction) {
+ QIcon goToLineIcon;
+ QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
+ that->d_func()->goToLineAction = new QAction(goToLineIcon, QScriptDebugger::tr("Go to Line"), parent);
+ d->goToLineAction->setShortcut(QScriptDebugger::tr("Ctrl+G"));
+ d->goToLineAction->setEnabled((d->codeWidget != 0) && (d->codeWidget->currentView() != 0));
+ QObject::connect(d->goToLineAction, SIGNAL(triggered()),
+ that, SLOT(_q_goToLine()));
+ }
+ return d->goToLineAction;
+}
+
+QMenu *QScriptDebugger::createStandardMenu(QWidget *widgetParent, QObject *actionParent)
+{
+ QMenu *menu = new QMenu(widgetParent);
+ menu->setTitle(QScriptDebugger::tr("Debug"));
+ menu->addAction(action(ContinueAction, actionParent));
+ menu->addAction(action(InterruptAction, actionParent));
+ menu->addAction(action(StepIntoAction, actionParent));
+ menu->addAction(action(StepOverAction, actionParent));
+ menu->addAction(action(StepOutAction, actionParent));
+ menu->addAction(action(RunToCursorAction, actionParent));
+ menu->addAction(action(RunToNewScriptAction, actionParent));
+
+ menu->addSeparator();
+ menu->addAction(action(ToggleBreakpointAction, actionParent));
+
+ menu->addSeparator();
+ menu->addAction(action(ClearDebugOutputAction, actionParent));
+ menu->addAction(action(ClearErrorLogAction, actionParent));
+ menu->addAction(action(ClearConsoleAction, actionParent));
+
+ return menu;
+}
+
+#ifndef QT_NO_TOOLBAR
+QToolBar *QScriptDebugger::createStandardToolBar(QWidget *widgetParent, QObject *actionParent)
+{
+ QToolBar *tb = new QToolBar(widgetParent);
+ tb->setObjectName(QLatin1String("qtscriptdebugger_standardToolBar"));
+ tb->addAction(action(ContinueAction, actionParent));
+ tb->addAction(action(InterruptAction, actionParent));
+ tb->addAction(action(StepIntoAction, actionParent));
+ tb->addAction(action(StepOverAction, actionParent));
+ tb->addAction(action(StepOutAction, actionParent));
+ tb->addAction(action(RunToCursorAction, actionParent));
+ tb->addAction(action(RunToNewScriptAction, actionParent));
+ tb->addSeparator();
+ tb->addAction(action(FindInScriptAction, actionParent));
+ return tb;
+}
+#endif
+
+bool QScriptDebugger::isInteractive() const
+{
+ Q_D(const QScriptDebugger);
+ return d->interactive;
+}
+
+/*!
+ \reimp
+*/
+bool QScriptDebugger::eventFilter(QObject *watched, QEvent *e)
+{
+ Q_D(QScriptDebugger);
+ if (watched == d->codeWidget) {
+ if (e->type() == QEvent::KeyPress) {
+ d->_q_findInScript();
+ d->codeFinderWidget->setText(static_cast<QKeyEvent*>(e)->text());
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
+ \reimp
+*/
+void QScriptDebugger::timerEvent(QTimerEvent *e)
+{
+ Q_D(QScriptDebugger);
+ if (e->timerId() == d->updatesEnabledTimerId) {
+ killTimer(d->updatesEnabledTimerId);
+ d->updatesEnabledTimerId = -1;
+ if (d->stackWidget)
+ d->stackWidget->setUpdatesEnabled(true);
+ if (d->localsWidget)
+ d->localsWidget->setUpdatesEnabled(true);
+ } else {
+ QObject::timerEvent(e);
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qscriptdebugger_p.cpp"