source: trunk/src/scripttools/debugging/qscriptdebugger.cpp@ 617

Last change on this file since 617 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 66.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtSCriptTools module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qscriptdebugger_p.h"
43#include "qscriptdebuggerconsole_p.h"
44#include "qscriptdebuggerconsolecommandmanager_p.h"
45#include "qscriptdebuggerconsolecommandjob_p.h"
46#include "qscriptstdmessagehandler_p.h"
47#include "qscriptdebuggerfrontend_p.h"
48#include "qscriptdebuggereventhandlerinterface_p.h"
49#include "qscriptdebuggerresponsehandlerinterface_p.h"
50#include "qscriptdebuggerjobschedulerinterface_p.h"
51#include "qscriptdebuggerconsolewidgetinterface_p.h"
52#include "qscriptcompletionproviderinterface_p.h"
53#include "qscriptcompletiontask_p.h"
54#include "qscripttooltipproviderinterface_p.h"
55#include "qscriptdebuggerstackwidgetinterface_p.h"
56#include "qscriptdebuggerstackmodel_p.h"
57#include "qscriptdebuggerscriptswidgetinterface_p.h"
58#include "qscriptdebuggerscriptsmodel_p.h"
59#include "qscriptdebuggerlocalswidgetinterface_p.h"
60#include "qscriptdebuggerlocalsmodel_p.h"
61#include "qscriptdebuggercodewidgetinterface_p.h"
62#include "qscriptdebuggercodeviewinterface_p.h"
63#include "qscriptdebuggercodefinderwidgetinterface_p.h"
64#include "qscriptbreakpointswidgetinterface_p.h"
65#include "qscriptbreakpointsmodel_p.h"
66#include "qscriptdebugoutputwidgetinterface_p.h"
67#include "qscripterrorlogwidgetinterface_p.h"
68#include "qscriptdebuggerwidgetfactoryinterface_p.h"
69#include "qscriptdebuggerevent_p.h"
70#include "qscriptdebuggervalue_p.h"
71#include "qscriptdebuggerresponse_p.h"
72#include "qscriptdebuggercommand_p.h"
73#include "qscriptdebuggercommandschedulerfrontend_p.h"
74#include "qscriptdebuggercommandschedulerjob_p.h"
75#include "qscriptdebuggerjob_p_p.h"
76#include "qscriptxmlparser_p.h"
77
78#include "private/qobject_p.h"
79
80#include <QtScript/qscriptcontext.h>
81#include <QtScript/qscriptcontextinfo.h>
82
83#include <QtCore/qcoreapplication.h>
84#include <QtCore/qdir.h>
85#include <QtCore/qfileinfo.h>
86#include <QtCore/qstringlist.h>
87#include <QtCore/qdebug.h>
88
89#include <QtGui/qaction.h>
90#include <QtGui/qevent.h>
91#include <QtGui/qicon.h>
92#include <QtGui/qinputdialog.h>
93#include <QtGui/qmenu.h>
94#include <QtGui/qtoolbar.h>
95#include <QtGui/qtooltip.h>
96
97QT_BEGIN_NAMESPACE
98typedef QPair<QList<qint64>, QList<qint64> > QScriptScriptsDelta;
99typedef QPair<QList<qint64>, QList<qint64> > QScriptContextsDelta;
100QT_END_NAMESPACE
101
102Q_DECLARE_METATYPE(QScriptScriptsDelta)
103
104QT_BEGIN_NAMESPACE
105
106Q_SCRIPT_EXPORT QString qt_scriptToXml(const QString &program, int lineNumber = 1);
107
108namespace {
109
110static int scriptDebuggerCount = 0;
111static bool eventCallbackRegistered = false;
112static bool widgetInPaintEvent = false;
113
114static bool scriptDebuggerEventCallback(void **data)
115{
116 QEvent *event = reinterpret_cast<QEvent*>(data[1]);
117 if (event->type() == QEvent::Paint) {
118 QObject *receiver = reinterpret_cast<QObject*>(data[0]);
119 bool was = widgetInPaintEvent;
120 widgetInPaintEvent = true;
121 QCoreApplication::instance()->notify(receiver, event);
122 widgetInPaintEvent = was;
123 bool *result = reinterpret_cast<bool*>(data[2]);
124 *result = true;
125 return true;
126 }
127 return false;
128}
129
130}
131
132/*!
133 \since 4.5
134 \class QScriptDebugger
135 \internal
136
137 \brief The QScriptDebugger class provides a Qt Script debugger.
138
139 \ingroup script
140
141*/
142
143class QScriptDebuggerPrivate
144 : public QObjectPrivate,
145 public QScriptDebuggerCommandSchedulerInterface,
146 public QScriptDebuggerJobSchedulerInterface,
147 public QScriptDebuggerEventHandlerInterface,
148 public QScriptDebuggerResponseHandlerInterface,
149 public QScriptCompletionProviderInterface,
150 public QScriptToolTipProviderInterface
151{
152 Q_DECLARE_PUBLIC(QScriptDebugger)
153public:
154 QScriptDebuggerPrivate();
155 ~QScriptDebuggerPrivate();
156
157 int scheduleJob(QScriptDebuggerJob *job);
158 void finishJob(QScriptDebuggerJob *job);
159 void hibernateUntilEvaluateFinished(QScriptDebuggerJob *job);
160
161 void maybeStartNewJob();
162
163 int scheduleCommand(const QScriptDebuggerCommand &command,
164 QScriptDebuggerResponseHandlerInterface *responseHandler);
165
166 void handleResponse(
167 const QScriptDebuggerResponse &response, int commandId);
168 bool debuggerEvent(const QScriptDebuggerEvent &event);
169
170 QScriptCompletionTaskInterface *createCompletionTask(
171 const QString &contents, int cursorPosition, int frameIndex, int options);
172
173 void showToolTip(const QPoint &pos, int frameIndex,
174 int lineNumber, const QStringList &path);
175
176 static QPixmap pixmap(const QString &path);
177
178 void startInteraction(QScriptDebuggerEvent::Type type,
179 qint64 scriptId, int lineNumber);
180 void sync();
181 void loadLocals(int frameIndex);
182 QScriptDebuggerLocalsModel *createLocalsModel();
183 void selectScriptForFrame(int frameIndex);
184 void emitStoppedSignal();
185
186 void maybeDelete(QWidget *widget);
187
188 // private slots
189 void _q_onLineEntered(const QString &contents);
190 void _q_onCurrentFrameChanged(int frameIndex);
191 void _q_onCurrentScriptChanged(qint64 scriptId);
192 void _q_onScriptLocationSelected(int lineNumber);
193 void _q_interrupt();
194 void _q_continue();
195 void _q_stepInto();
196 void _q_stepOver();
197 void _q_stepOut();
198 void _q_runToCursor();
199 void _q_runToNewScript();
200 void _q_toggleBreakpoint();
201 void _q_clearDebugOutput();
202 void _q_clearErrorLog();
203 void _q_clearConsole();
204 void _q_findInScript();
205 void _q_findNextInScript();
206 void _q_findPreviousInScript();
207 void _q_onFindCodeRequest(const QString &, int);
208 void _q_goToLine();
209
210 void executeConsoleCommand(const QString &command);
211 void findCode(const QString &exp, int options);
212
213 QScriptDebuggerFrontend *frontend;
214
215 bool interactive;
216 QScriptDebuggerConsole *console;
217
218 int nextJobId;
219 QList<QScriptDebuggerJob*> pendingJobs;
220 QList<int> pendingJobIds;
221 QScriptDebuggerJob *activeJob;
222 bool activeJobHibernating;
223 QHash<int, QScriptDebuggerCommand> watchedCommands;
224 QHash<int, QScriptDebuggerResponseHandlerInterface*> responseHandlers;
225
226 QScriptDebuggerConsoleWidgetInterface *consoleWidget;
227 QScriptDebuggerStackWidgetInterface *stackWidget;
228 QScriptDebuggerStackModel *stackModel;
229 QScriptDebuggerScriptsWidgetInterface *scriptsWidget;
230 QScriptDebuggerScriptsModel *scriptsModel;
231 QScriptDebuggerLocalsWidgetInterface *localsWidget;
232 QHash<int, QScriptDebuggerLocalsModel*> localsModels;
233 QScriptDebuggerCodeWidgetInterface *codeWidget;
234 QScriptDebuggerCodeFinderWidgetInterface *codeFinderWidget;
235 QScriptBreakpointsWidgetInterface *breakpointsWidget;
236 QScriptBreakpointsModel *breakpointsModel;
237 QScriptDebugOutputWidgetInterface *debugOutputWidget;
238 QScriptErrorLogWidgetInterface *errorLogWidget;
239 QScriptDebuggerWidgetFactoryInterface *widgetFactory;
240
241 QAction *interruptAction;
242 QAction *continueAction;
243 QAction *stepIntoAction;
244 QAction *stepOverAction;
245 QAction *stepOutAction;
246 QAction *runToCursorAction;
247 QAction *runToNewScriptAction;
248
249 QAction *toggleBreakpointAction;
250
251 QAction *clearDebugOutputAction;
252 QAction *clearErrorLogAction;
253 QAction *clearConsoleAction;
254
255 QAction *findInScriptAction;
256 QAction *findNextInScriptAction;
257 QAction *findPreviousInScriptAction;
258 QAction *goToLineAction;
259
260 int updatesEnabledTimerId;
261};
262
263QScriptDebuggerPrivate::QScriptDebuggerPrivate()
264{
265 frontend = 0;
266 activeJob = 0;
267 activeJobHibernating = false;
268 nextJobId = 0;
269 interactive = false;
270
271 console = new QScriptDebuggerConsole();
272 QString scriptsPath = QLatin1String(":/qt/scripttools/debugging/scripts/commands");
273 QScriptStdMessageHandler tmp;
274 console->loadScriptedCommands(scriptsPath, &tmp);
275
276 consoleWidget = 0;
277 stackWidget = 0;
278 stackModel = 0;
279 scriptsWidget = 0;
280 scriptsModel = 0;
281 localsWidget = 0;
282 codeWidget = 0;
283 codeFinderWidget = 0;
284 breakpointsWidget = 0;
285 breakpointsModel = 0;
286 debugOutputWidget = 0;
287 errorLogWidget = 0;
288 widgetFactory = 0;
289
290 interruptAction = 0;
291 continueAction = 0;
292 stepIntoAction = 0;
293 stepOverAction = 0;
294 stepOutAction = 0;
295 runToCursorAction = 0;
296 runToNewScriptAction = 0;
297
298 toggleBreakpointAction = 0;
299
300 clearErrorLogAction = 0;
301 clearDebugOutputAction = 0;
302 clearConsoleAction = 0;
303
304 findInScriptAction = 0;
305 findNextInScriptAction = 0;
306 findPreviousInScriptAction = 0;
307 goToLineAction = 0;
308
309 updatesEnabledTimerId = -1;
310}
311
312QScriptDebuggerPrivate::~QScriptDebuggerPrivate()
313{
314 delete console;
315 qDeleteAll(pendingJobs);
316 delete activeJob;
317 maybeDelete(consoleWidget);
318 maybeDelete(stackWidget);
319 maybeDelete(scriptsWidget);
320 maybeDelete(localsWidget);
321 maybeDelete(codeWidget);
322 maybeDelete(codeFinderWidget);
323 maybeDelete(breakpointsWidget);
324 maybeDelete(debugOutputWidget);
325 maybeDelete(errorLogWidget);
326}
327
328void QScriptDebuggerPrivate::maybeDelete(QWidget *widget)
329{
330 if (widget && !widget->parent())
331 delete widget;
332}
333
334QPixmap QScriptDebuggerPrivate::pixmap(const QString &path)
335{
336 static QString prefix = QString::fromLatin1(":/qt/scripttools/debugging/images/");
337 return QPixmap(prefix + path);
338}
339
340/*!
341 \reimp
342*/
343int QScriptDebuggerPrivate::scheduleJob(QScriptDebuggerJob *job)
344{
345 QScriptDebuggerJobPrivate *priv = QScriptDebuggerJobPrivate::get(job);
346 Q_ASSERT(priv->jobScheduler == 0);
347 priv->jobScheduler = this;
348 int id = nextJobId;
349 pendingJobs.append(job);
350 pendingJobIds.append(id);
351 maybeStartNewJob();
352 return id;
353}
354
355/*!
356 \reimp
357*/
358void QScriptDebuggerPrivate::finishJob(QScriptDebuggerJob *job)
359{
360 Q_UNUSED(job);
361 Q_ASSERT(activeJob == job);
362 delete activeJob;
363 activeJob = 0;
364 activeJobHibernating = false;
365 maybeStartNewJob();
366}
367
368/*!
369 \reimp
370*/
371void QScriptDebuggerPrivate::hibernateUntilEvaluateFinished(QScriptDebuggerJob *job)
372{
373 Q_UNUSED(job);
374 Q_ASSERT(activeJob == job);
375 activeJobHibernating = true;
376}
377
378/*!
379 Starts a new job if appropriate.
380*/
381void QScriptDebuggerPrivate::maybeStartNewJob()
382{
383 if (activeJob || pendingJobs.isEmpty())
384 return;
385 activeJob = pendingJobs.takeFirst();
386 activeJob->start();
387}
388
389/*!
390 \reimp
391*/
392int QScriptDebuggerPrivate::scheduleCommand(
393 const QScriptDebuggerCommand &command,
394 QScriptDebuggerResponseHandlerInterface *responseHandler)
395{
396 if (!frontend)
397 return -1;
398 int id = frontend->scheduleCommand(command, this);
399 if (responseHandler && (responseHandler != this))
400 responseHandlers.insert(id, responseHandler);
401 if ((command.type() == QScriptDebuggerCommand::SetBreakpoint)
402 || (command.type() == QScriptDebuggerCommand::SetBreakpointData)
403 || (command.type() == QScriptDebuggerCommand::DeleteBreakpoint)) {
404 // need to watch this command and update the breakpoints model afterwards
405 watchedCommands.insert(id, command);
406 }
407 return id;
408}
409
410/*!
411 \reimp
412*/
413void QScriptDebuggerPrivate::handleResponse(
414 const QScriptDebuggerResponse &response, int commandId)
415{
416 Q_Q(QScriptDebugger);
417 if (watchedCommands.contains(commandId)) {
418 QScriptDebuggerCommand command = watchedCommands.take(commandId);
419 if (response.error() == QScriptDebuggerResponse::NoError) {
420 if (!breakpointsModel)
421 breakpointsModel = new QScriptBreakpointsModel(this, this, q);
422 switch (command.type()) {
423 case QScriptDebuggerCommand::SetBreakpoint: {
424 int breakpointId = response.resultAsInt();
425 QScriptBreakpointData data = command.breakpointData();
426 breakpointsModel->addBreakpoint(breakpointId, data);
427 } break;
428 case QScriptDebuggerCommand::SetBreakpointData: {
429 int breakpointId = command.breakpointId();
430 QScriptBreakpointData data = command.breakpointData();
431 breakpointsModel->modifyBreakpoint(breakpointId, data);
432 } break;
433 case QScriptDebuggerCommand::DeleteBreakpoint: {
434 int breakpointId = command.breakpointId();
435 breakpointsModel->removeBreakpoint(breakpointId);
436 } break;
437 default:
438 Q_ASSERT(false);
439 }
440 }
441 } else if (response.async()) {
442 interactive = false;
443 // disable/invalidate/enable stuff
444 if (continueAction)
445 continueAction->setEnabled(false);
446 if (stepIntoAction)
447 stepIntoAction->setEnabled(false);
448 if (stepOverAction)
449 stepOverAction->setEnabled(false);
450 if (stepOutAction)
451 stepOutAction->setEnabled(false);
452 if (runToCursorAction)
453 runToCursorAction->setEnabled(false);
454 if (runToNewScriptAction)
455 runToNewScriptAction->setEnabled(false);
456 if (interruptAction)
457 interruptAction->setEnabled(true);
458
459 // the timer is to avoid flicker when stepping
460 if (stackWidget) {
461 stackWidget->setUpdatesEnabled(false);
462 stackWidget->setEnabled(false);
463 if (updatesEnabledTimerId == -1)
464 updatesEnabledTimerId = q->startTimer(75);
465 }
466 if (localsWidget) {
467 localsWidget->setUpdatesEnabled(false);
468 localsWidget->setEnabled(false);
469 if (updatesEnabledTimerId == -1)
470 updatesEnabledTimerId = q->startTimer(75);
471 }
472 if (codeWidget)
473 codeWidget->invalidateExecutionLineNumbers();
474
475 emit q->started();
476 }
477
478 QScriptDebuggerResponseHandlerInterface *realHandler = responseHandlers.take(commandId);
479 if (realHandler)
480 realHandler->handleResponse(response, commandId);
481}
482
483/*!
484 \reimp
485
486 Handles a debugger event from the frontend.
487*/
488bool QScriptDebuggerPrivate::debuggerEvent(const QScriptDebuggerEvent &event)
489{
490 Q_Q(QScriptDebugger);
491 switch (event.type()) {
492 case QScriptDebuggerEvent::None:
493 case QScriptDebuggerEvent::UserEvent:
494 case QScriptDebuggerEvent::MaxUserEvent:
495 Q_ASSERT(false);
496 break;
497
498 case QScriptDebuggerEvent::Trace:
499 if (!debugOutputWidget && widgetFactory)
500 q->setDebugOutputWidget(widgetFactory->createDebugOutputWidget());
501 if (debugOutputWidget)
502 debugOutputWidget->message(QtDebugMsg, event.message());
503 return true; // trace doesn't stall execution
504
505 case QScriptDebuggerEvent::SteppingFinished: {
506 if (!consoleWidget && widgetFactory)
507 q->setConsoleWidget(widgetFactory->createConsoleWidget());
508 if (consoleWidget) {
509 QString msg = event.message();
510 if (!msg.isEmpty())
511 consoleWidget->message(QtDebugMsg, msg);
512 }
513 } break;
514
515 case QScriptDebuggerEvent::Interrupted:
516 case QScriptDebuggerEvent::LocationReached:
517 break;
518
519 case QScriptDebuggerEvent::Breakpoint: {
520 int bpId = event.breakpointId();
521 if (!consoleWidget && widgetFactory)
522 q->setConsoleWidget(widgetFactory->createConsoleWidget());
523 if (consoleWidget) {
524 consoleWidget->message(QtDebugMsg,
525 QString::fromLatin1("Breakpoint %0 at %1, line %2.")
526 .arg(bpId).arg(event.fileName())
527 .arg(event.lineNumber()));
528 }
529 if (breakpointsModel->breakpointData(bpId).isSingleShot())
530 breakpointsModel->removeBreakpoint(bpId);
531 } break;
532
533 case QScriptDebuggerEvent::Exception: {
534 if (event.hasExceptionHandler()) {
535 // Let the exception be handled like normal.
536 // We may want to add a "Break on all exceptions" option
537 // to be able to customize this behavior.
538 return true;
539 }
540 if (!consoleWidget && widgetFactory)
541 q->setConsoleWidget(widgetFactory->createConsoleWidget());
542 if (!errorLogWidget && widgetFactory)
543 q->setErrorLogWidget(widgetFactory->createErrorLogWidget());
544 if (consoleWidget || errorLogWidget) {
545 QString fn = event.fileName();
546 if (fn.isEmpty()) {
547 if (event.scriptId() != -1)
548 fn = QString::fromLatin1("<anonymous script, id=%0>").arg(event.scriptId());
549 else
550 fn = QString::fromLatin1("<native>");
551 }
552 QString msg = QString::fromLatin1("Uncaught exception at %0:%1: %2").arg(fn)
553 .arg(event.lineNumber()).arg(event.message());
554 if (consoleWidget)
555 consoleWidget->message(QtCriticalMsg, msg);
556 if (errorLogWidget)
557 errorLogWidget->message(QtCriticalMsg, msg);
558 }
559 } break;
560
561 case QScriptDebuggerEvent::InlineEvalFinished: {
562 QScriptDebuggerValue result = event.scriptValue();
563 Q_ASSERT(console != 0);
564 int action = console->evaluateAction();
565 console->setEvaluateAction(0);
566 switch (action) {
567 case 0: { // eval command
568 if (activeJob) {
569 if (activeJobHibernating) {
570 activeJobHibernating = false;
571 activeJob->evaluateFinished(result);
572 }
573 } else if (consoleWidget) {
574 // ### if the result is an object, need to do a tostring job on it
575// messageHandler->message(QtDebugMsg, result.toString());
576 if (result.type() != QScriptDebuggerValue::UndefinedValue)
577 consoleWidget->message(QtDebugMsg, event.message());
578 }
579 } break;
580 case 1: { // return command
581 QScriptDebuggerCommandSchedulerFrontend frontend(this, this);
582 frontend.scheduleForceReturn(console->currentFrameIndex(), result);
583 } return false;
584 }
585 if (!event.isNestedEvaluate()) {
586 // in the case when evaluate() was called while the
587 // engine was not running, we don't want to enter interactive mode
588 return true;
589 }
590 } break;
591
592 case QScriptDebuggerEvent::DebuggerInvocationRequest: {
593 if (!consoleWidget && widgetFactory)
594 q->setConsoleWidget(widgetFactory->createConsoleWidget());
595 if (consoleWidget) {
596 QString fn = event.fileName();
597 if (fn.isEmpty())
598 fn = QString::fromLatin1("<anonymous script, id=%0>").arg(event.scriptId());
599 consoleWidget->message(QtDebugMsg,
600 QString::fromLatin1("Debugger invoked from %1, line %2.")
601 .arg(fn).arg(event.lineNumber()));
602 }
603 } break;
604
605 case QScriptDebuggerEvent::ForcedReturn: {
606 } break;
607
608 }
609
610 if (widgetInPaintEvent) {
611 QString msg = QString::fromLatin1("Suspending evaluation in paintEvent() is not supported; resuming.");
612 if (!consoleWidget && widgetFactory)
613 q->setConsoleWidget(widgetFactory->createConsoleWidget());
614 if (!errorLogWidget && widgetFactory)
615 q->setErrorLogWidget(widgetFactory->createErrorLogWidget());
616 if (consoleWidget)
617 consoleWidget->message(QtWarningMsg, msg);
618 if (errorLogWidget)
619 errorLogWidget->message(QtCriticalMsg, msg);
620 return true;
621 }
622
623 if (activeJobHibernating) {
624 // evaluate() did not finish normally (e.g. due to a breakpoint),
625 // so cancel the job that's waiting for it
626 delete activeJob;
627 activeJob = 0;
628 activeJobHibernating = false;
629 }
630
631 startInteraction(event.type(), event.scriptId(), event.lineNumber());
632 return !interactive;
633}
634
635class QScriptToolTipJob : public QScriptDebuggerCommandSchedulerJob
636{
637public:
638 QScriptToolTipJob(const QPoint &pos, int frameIndex,
639 int lineNumber, const QStringList &path,
640 QScriptDebuggerCommandSchedulerInterface *scheduler)
641 : QScriptDebuggerCommandSchedulerJob(scheduler), m_pos(pos),
642 m_frameIndex(frameIndex), m_lineNumber(lineNumber), m_path(path)
643 {}
644
645 void start()
646 {
647 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
648 frontend.scheduleGetPropertyExpressionValue(m_frameIndex, m_lineNumber, m_path);
649 }
650 void handleResponse(const QScriptDebuggerResponse &response, int /*commandId*/)
651 {
652 QString tip = response.result().toString();
653 if (tip.indexOf(QLatin1Char('\n')) != -1) {
654 QStringList lines = tip.split(QLatin1Char('\n'));
655 int lineCount = lines.size();
656 if (lineCount > 5) {
657 lines = lines.mid(0, 5);
658 lines.append(QString::fromLatin1("(... %0 more lines ...)").arg(lineCount - 5));
659 }
660 tip = lines.join(QLatin1String("\n"));
661 }
662 QToolTip::showText(m_pos, tip);
663 finish();
664 }
665
666private:
667 QPoint m_pos;
668 int m_frameIndex;
669 int m_lineNumber;
670 QStringList m_path;
671};
672
673/*!
674 \reimp
675*/
676void QScriptDebuggerPrivate::showToolTip(const QPoint &pos, int frameIndex,
677 int lineNumber, const QStringList &path)
678{
679 if (frameIndex == -1) {
680 if (stackWidget)
681 frameIndex = stackWidget->currentFrameIndex();
682 else
683 frameIndex = console->currentFrameIndex();
684 }
685 QScriptDebuggerJob *job = new QScriptToolTipJob(pos, frameIndex, lineNumber, path, this);
686 scheduleJob(job);
687}
688
689/*!
690 \reimp
691*/
692QScriptCompletionTaskInterface *QScriptDebuggerPrivate::createCompletionTask(
693 const QString &contents, int cursorPosition, int frameIndex, int options)
694{
695 return new QScriptCompletionTask(
696 contents, cursorPosition, frameIndex, this, this,
697 (options & QScriptCompletionProviderInterface::ConsoleCommandCompletion) ? console : 0);
698}
699
700/*!
701 Slot called when a line has been entered in the console widget.
702*/
703void QScriptDebuggerPrivate::_q_onLineEntered(const QString &contents)
704{
705 QScriptDebuggerConsoleCommandJob *commandJob;
706 commandJob = console->consumeInput(contents, consoleWidget, this);
707 if (commandJob != 0) {
708 scheduleJob(commandJob);
709 consoleWidget->setLineContinuationMode(false);
710 } else if (console->hasIncompleteInput()) {
711 consoleWidget->setLineContinuationMode(true);
712 }
713}
714
715/*!
716 Slot called when the current index has changed in the stack widget.
717*/
718void QScriptDebuggerPrivate::_q_onCurrentFrameChanged(int frameIndex)
719{
720 loadLocals(frameIndex);
721 selectScriptForFrame(frameIndex);
722}
723
724/*!
725 Slot called when the current script has changed in the scripts widget.
726*/
727void QScriptDebuggerPrivate::_q_onCurrentScriptChanged(qint64 scriptId)
728{
729 if (codeWidget && (codeWidget->currentScriptId() != scriptId)) {
730 codeWidget->setCurrentScript(scriptId);
731 QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
732 if (view)
733 view->setExecutionLineNumber(-1, /*error=*/false);
734 }
735}
736
737void QScriptDebuggerPrivate::_q_onScriptLocationSelected(int lineNumber)
738{
739 QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
740 if (!view)
741 return;
742 view->gotoLine(lineNumber);
743}
744
745void QScriptDebuggerPrivate::_q_interrupt()
746{
747 executeConsoleCommand(QString::fromLatin1("interrupt"));
748}
749
750void QScriptDebuggerPrivate::_q_continue()
751{
752 executeConsoleCommand(QString::fromLatin1("continue"));
753}
754
755void QScriptDebuggerPrivate::_q_stepInto()
756{
757 executeConsoleCommand(QString::fromLatin1("step"));
758}
759
760void QScriptDebuggerPrivate::_q_stepOver()
761{
762 executeConsoleCommand(QString::fromLatin1("next"));
763}
764
765void QScriptDebuggerPrivate::_q_stepOut()
766{
767 executeConsoleCommand(QString::fromLatin1("finish"));
768}
769
770void QScriptDebuggerPrivate::_q_runToCursor()
771{
772 qint64 scriptId = codeWidget->currentScriptId();
773 int lineNumber = codeWidget->currentView()->cursorLineNumber();
774 QScriptDebuggerCommandSchedulerFrontend frontend(this, this);
775 frontend.scheduleRunToLocation(scriptId, lineNumber);
776}
777
778void QScriptDebuggerPrivate::_q_runToNewScript()
779{
780 QScriptDebuggerCommandSchedulerFrontend frontend(this, this);
781 frontend.scheduleRunToLocation(QString(), -1);
782}
783
784void QScriptDebuggerPrivate::_q_toggleBreakpoint()
785{
786 Q_ASSERT(codeWidget != 0);
787 QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
788 if (!view)
789 return;
790 qint64 scriptId = codeWidget->currentScriptId();
791 int lineNumber = view->cursorLineNumber();
792 Q_ASSERT(breakpointsModel != 0);
793 int bpId = breakpointsModel->resolveBreakpoint(scriptId, lineNumber);
794 if (bpId != -1) {
795 breakpointsModel->deleteBreakpoint(bpId);
796 } else {
797 QScriptBreakpointData data(scriptId, lineNumber);
798 if (scriptsModel)
799 data.setFileName(scriptsModel->scriptData(scriptId).fileName());
800 breakpointsModel->setBreakpoint(data);
801 }
802}
803
804void QScriptDebuggerPrivate::_q_clearDebugOutput()
805{
806 if (debugOutputWidget)
807 debugOutputWidget->clear();
808}
809
810void QScriptDebuggerPrivate::_q_clearErrorLog()
811{
812 if (errorLogWidget)
813 errorLogWidget->clear();
814}
815
816void QScriptDebuggerPrivate::_q_clearConsole()
817{
818 if (consoleWidget)
819 consoleWidget->clear();
820}
821
822void QScriptDebuggerPrivate::executeConsoleCommand(const QString &command)
823{
824 QString tmp = console->incompleteInput();
825 console->setIncompleteInput(QString());
826 QScriptDebuggerJob *job = console->consumeInput(console->commandPrefix() + command, debugOutputWidget, this);
827 console->setIncompleteInput(tmp);
828 if (job != 0) {
829 scheduleJob(job);
830 // once to send the command...
831 QCoreApplication::processEvents();
832 // ... and once to receive the response
833 QCoreApplication::processEvents();
834 }
835}
836
837void QScriptDebuggerPrivate::_q_findInScript()
838{
839 if (!codeFinderWidget && widgetFactory)
840 q_func()->setCodeFinderWidget(widgetFactory->createCodeFinderWidget());
841 if (codeFinderWidget) {
842 codeFinderWidget->show();
843 codeFinderWidget->setFocus(Qt::OtherFocusReason);
844 }
845}
846
847void QScriptDebuggerPrivate::_q_findNextInScript()
848{
849 findCode(codeFinderWidget->text(), codeFinderWidget->findOptions());
850}
851
852void QScriptDebuggerPrivate::_q_findPreviousInScript()
853{
854 int options = codeFinderWidget->findOptions();
855 options |= QTextDocument::FindBackward;
856 findCode(codeFinderWidget->text(), options);
857}
858
859void QScriptDebuggerPrivate::_q_onFindCodeRequest(
860 const QString &exp, int options)
861{
862 findCode(exp, options);
863 if (findNextInScriptAction)
864 findNextInScriptAction->setEnabled(!exp.isEmpty());
865 if (findPreviousInScriptAction)
866 findPreviousInScriptAction->setEnabled(!exp.isEmpty());
867}
868
869void QScriptDebuggerPrivate::findCode(const QString &exp, int options)
870{
871 QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
872 if (!view)
873 return;
874 int result = view->find(exp, options);
875 codeFinderWidget->setOK(((result & 0x1) != 0) || exp.isEmpty());
876 codeFinderWidget->setWrapped((result & 0x2) != 0);
877}
878
879void QScriptDebuggerPrivate::_q_goToLine()
880{
881 QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
882 if (!view)
883 return;
884 bool ok = false;
885 int lineNumber = QInputDialog::getInteger(0, QScriptDebugger::tr("Go to Line"),
886 QScriptDebugger::tr("Line:"),
887 view->cursorLineNumber(),
888 1, INT_MAX, 1, &ok);
889 if (ok)
890 view->gotoLine(lineNumber);
891}
892
893class QScriptDebuggerShowLineJob : public QScriptDebuggerCommandSchedulerJob
894{
895public:
896 QScriptDebuggerShowLineJob(qint64 scriptId, int lineNumber,
897 QScriptMessageHandlerInterface *messageHandler,
898 QScriptDebuggerCommandSchedulerInterface *scheduler)
899 : QScriptDebuggerCommandSchedulerJob(scheduler),
900 m_scriptId(scriptId), m_lineNumber(lineNumber),
901 m_messageHandler(messageHandler) {}
902
903 void start()
904 {
905 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
906 frontend.scheduleGetScriptData(m_scriptId);
907 }
908 void handleResponse(const QScriptDebuggerResponse &response, int /*commandId*/)
909 {
910 QScriptScriptData data = response.resultAsScriptData();
911 QString line = data.lines(m_lineNumber, 1).value(0);
912 m_messageHandler->message(QtDebugMsg, QString::fromLatin1("%0\t%1")
913 .arg(m_lineNumber).arg(line));
914 finish();
915 }
916
917private:
918 qint64 m_scriptId;
919 int m_lineNumber;
920 QScriptMessageHandlerInterface *m_messageHandler;
921};
922
923namespace {
924
925class SyncStackJob : public QScriptDebuggerCommandSchedulerJob
926{
927public:
928 SyncStackJob(QScriptDebuggerPrivate *debugger)
929 : QScriptDebuggerCommandSchedulerJob(debugger),
930 m_debugger(debugger), m_index(0) {}
931 void start()
932 {
933 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
934 frontend.scheduleGetContextInfo(m_index); // ### getContextInfos()
935 }
936 void handleResponse(const QScriptDebuggerResponse &response,
937 int)
938 {
939 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
940 if (response.error() != QScriptDebuggerResponse::InvalidContextIndex) {
941 m_infos.append(response.resultAsContextInfo());
942 frontend.scheduleGetContextInfo(++m_index);
943 } else {
944 m_debugger->stackModel->setContextInfos(m_infos);
945 if (m_debugger->stackWidget->currentFrameIndex() == -1)
946 m_debugger->stackWidget->setCurrentFrameIndex(0);
947 m_debugger->stackWidget->setUpdatesEnabled(true);
948 m_debugger->stackWidget->setEnabled(true);
949 finish();
950 }
951 }
952
953private:
954 QScriptDebuggerPrivate *m_debugger;
955 int m_index;
956 QList<QScriptContextInfo> m_infos;
957};
958
959class SyncScriptsJob : public QScriptDebuggerCommandSchedulerJob
960{
961public:
962 SyncScriptsJob(QScriptDebuggerPrivate *debugger)
963 : QScriptDebuggerCommandSchedulerJob(debugger),
964 m_debugger(debugger), m_index(-1) {}
965
966 void start()
967 {
968 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
969 frontend.scheduleScriptsCheckpoint();
970 }
971 void handleResponse(const QScriptDebuggerResponse &response,
972 int)
973 {
974 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
975 if (m_index == -1) {
976 QScriptScriptsDelta delta;
977 delta = qvariant_cast<QScriptScriptsDelta>(response.result());
978
979 const QList<qint64> &removed = delta.second;
980 for (int i = 0; i < removed.size(); ++i)
981 m_debugger->scriptsModel->removeScript(removed.at(i));
982
983 m_added = delta.first;
984 if (!m_added.isEmpty()) {
985 frontend.scheduleGetScriptData(m_added.at(++m_index));
986 } else {
987 m_debugger->scriptsModel->commit();
988 finish();
989 }
990 } else {
991 QScriptScriptData data = response.resultAsScriptData();
992 qint64 scriptId = m_added.at(m_index);
993 m_debugger->scriptsModel->addScript(scriptId, data);
994
995 // ### could be slow, might want to do this in a separate thread
996// Q_ASSERT_X(false, Q_FUNC_INFO, "implement me");
997 QString xml; // = qt_scriptToXml(data.contents(), data.baseLineNumber());
998 QScriptXmlParser::Result extraInfo = QScriptXmlParser::parse(xml);
999 m_debugger->scriptsModel->addExtraScriptInfo(
1000 scriptId, extraInfo.functionsInfo, extraInfo.executableLineNumbers);
1001
1002 if (++m_index < m_added.size())
1003 frontend.scheduleGetScriptData(m_added.at(m_index));
1004 else {
1005 m_debugger->scriptsModel->commit();
1006 finish();
1007 }
1008 }
1009 }
1010
1011private:
1012 QScriptDebuggerPrivate *m_debugger;
1013 int m_index;
1014 QList<qint64> m_added;
1015};
1016
1017class SyncBreakpointsJob : public QScriptDebuggerCommandSchedulerJob
1018{
1019public:
1020 SyncBreakpointsJob(QScriptDebuggerPrivate *debugger)
1021 : QScriptDebuggerCommandSchedulerJob(debugger),
1022 m_debugger(debugger), m_index(-1) {}
1023 void start()
1024 {
1025 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
1026 frontend.scheduleGetBreakpoints();
1027 }
1028 void handleResponse(const QScriptDebuggerResponse &response,
1029 int)
1030 {
1031 QScriptBreakpointMap breakpoints = response.resultAsBreakpoints();
1032 QScriptBreakpointMap::const_iterator it;
1033 for (it = breakpoints.constBegin(); it != breakpoints.constEnd(); ++it) {
1034 int id = it.key();
1035 QScriptBreakpointData newData = it.value();
1036 QScriptBreakpointData existingData = m_debugger->breakpointsModel->breakpointData(id);
1037 if (existingData.isValid() && (existingData != newData))
1038 m_debugger->breakpointsModel->modifyBreakpoint(id, newData);
1039 }
1040 finish();
1041 }
1042
1043private:
1044 QScriptDebuggerPrivate *m_debugger;
1045 int m_index;
1046 QList<QScriptContextInfo> m_infos;
1047};
1048
1049class SyncLocalsJob : public QScriptDebuggerCommandSchedulerJob
1050{
1051public:
1052 SyncLocalsJob(QScriptDebuggerPrivate *debugger)
1053 : QScriptDebuggerCommandSchedulerJob(debugger),
1054 m_debugger(debugger) {}
1055
1056 void start()
1057 {
1058 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
1059 frontend.scheduleContextsCheckpoint();
1060 }
1061 void handleResponse(const QScriptDebuggerResponse &response,
1062 int)
1063 {
1064 QScriptContextsDelta delta = qvariant_cast<QScriptContextsDelta>(response.result());
1065 for (int i = 0; i < delta.first.size(); ++i) {
1066 QScriptDebuggerLocalsModel *model = m_debugger->localsModels.take(delta.first.at(i));
1067 delete model;
1068 }
1069 finish();
1070 }
1071
1072private:
1073 QScriptDebuggerPrivate *m_debugger;
1074};
1075
1076class LoadLocalsJob : public QScriptDebuggerCommandSchedulerJob
1077{
1078public:
1079 LoadLocalsJob(QScriptDebuggerPrivate *debugger, int frameIndex)
1080 : QScriptDebuggerCommandSchedulerJob(debugger),
1081 m_debugger(debugger), m_frameIndex(frameIndex) {}
1082
1083 void start()
1084 {
1085 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
1086 frontend.scheduleGetContextId(m_frameIndex);
1087 }
1088 void handleResponse(const QScriptDebuggerResponse &response,
1089 int)
1090 {
1091 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
1092 qint64 contextId = response.resultAsLongLong();
1093 QScriptDebuggerLocalsModel *model = m_debugger->localsModels.value(contextId);
1094 if (model) {
1095 model->sync(m_frameIndex);
1096 } else {
1097 model = m_debugger->createLocalsModel();
1098 m_debugger->localsModels.insert(contextId, model);
1099 model->init(m_frameIndex);
1100 }
1101 if (m_debugger->localsWidget) {
1102 if (m_debugger->localsWidget->localsModel() != model) // ### bug in qtreeview
1103 m_debugger->localsWidget->setLocalsModel(model);
1104 m_debugger->localsWidget->setUpdatesEnabled(true);
1105 m_debugger->localsWidget->setEnabled(true);
1106 }
1107 finish();
1108 }
1109
1110private:
1111 QScriptDebuggerPrivate *m_debugger;
1112 int m_frameIndex;
1113};
1114
1115class EmitStoppedSignalJob : public QScriptDebuggerJob
1116{
1117public:
1118 EmitStoppedSignalJob(QScriptDebuggerPrivate *debugger)
1119 : m_debugger(debugger) {}
1120
1121 void start()
1122 {
1123 m_debugger->emitStoppedSignal();
1124 finish();
1125 }
1126
1127private:
1128 QScriptDebuggerPrivate *m_debugger;
1129};
1130
1131} // namespace
1132
1133void QScriptDebuggerPrivate::startInteraction(QScriptDebuggerEvent::Type type,
1134 qint64 scriptId, int lineNumber)
1135{
1136 Q_Q(QScriptDebugger);
1137 if (type != QScriptDebuggerEvent::InlineEvalFinished) {
1138 if (stackWidget)
1139 stackWidget->setCurrentFrameIndex(0);
1140 console->setCurrentFrameIndex(0);
1141 console->setCurrentScriptId(scriptId);
1142 console->setCurrentLineNumber(lineNumber);
1143 }
1144
1145 if ((scriptId != -1) && consoleWidget) {
1146 QScriptDebuggerJob *job = new QScriptDebuggerShowLineJob(scriptId, lineNumber, consoleWidget, this);
1147 scheduleJob(job);
1148 }
1149
1150 sync();
1151
1152 if (!interactive) {
1153 interactive = true;
1154 if (updatesEnabledTimerId != -1) {
1155 q->killTimer(updatesEnabledTimerId);
1156 updatesEnabledTimerId = -1;
1157 }
1158 console->bumpSessionId();
1159 scheduleJob(new EmitStoppedSignalJob(this));
1160 }
1161
1162 if (consoleWidget)
1163 consoleWidget->activateWindow();
1164 else if (codeWidget)
1165 codeWidget->activateWindow();
1166
1167 if (continueAction)
1168 continueAction->setEnabled(true);
1169 if (stepIntoAction)
1170 stepIntoAction->setEnabled(true);
1171 if (stepOverAction)
1172 stepOverAction->setEnabled(true);
1173 if (stepOutAction)
1174 stepOutAction->setEnabled(true);
1175 if (runToCursorAction)
1176 runToCursorAction->setEnabled(true);
1177 if (runToNewScriptAction)
1178 runToNewScriptAction->setEnabled(true);
1179 if (interruptAction)
1180 interruptAction->setEnabled(false);
1181
1182 bool hasScript = (codeWidget != 0);
1183 if (findInScriptAction)
1184 findInScriptAction->setEnabled(hasScript);
1185 if (toggleBreakpointAction)
1186 toggleBreakpointAction->setEnabled(hasScript);
1187 if (goToLineAction)
1188 goToLineAction->setEnabled(hasScript);
1189}
1190
1191void QScriptDebuggerPrivate::sync()
1192{
1193 if (localsWidget) {
1194 QScriptDebuggerJob *job = new SyncLocalsJob(this);
1195 scheduleJob(job);
1196 }
1197 if (scriptsModel) {
1198 QScriptDebuggerJob *job = new SyncScriptsJob(this);
1199 scheduleJob(job);
1200 }
1201 if (stackModel) {
1202 QScriptDebuggerJob *job = new SyncStackJob(this);
1203 scheduleJob(job);
1204 }
1205 if (breakpointsModel) {
1206 // need to sync because the ignore-count could have changed
1207 QScriptDebuggerJob *job = new SyncBreakpointsJob(this);
1208 scheduleJob(job);
1209 }
1210
1211 if (stackWidget && (stackWidget->currentFrameIndex() != -1)) {
1212 int index = stackWidget->currentFrameIndex();
1213 loadLocals(index);
1214 selectScriptForFrame(index);
1215 } else if (codeWidget && (console->currentFrameIndex() != -1)) {
1216 selectScriptForFrame(console->currentFrameIndex());
1217 }
1218}
1219
1220void QScriptDebuggerPrivate::loadLocals(int frameIndex)
1221{
1222 LoadLocalsJob *job = new LoadLocalsJob(this, frameIndex);
1223 scheduleJob(job);
1224}
1225
1226QScriptDebuggerLocalsModel *QScriptDebuggerPrivate::createLocalsModel()
1227{
1228 return new QScriptDebuggerLocalsModel(this, this, q_func());
1229}
1230
1231namespace {
1232
1233class ShowFrameCodeJob : public QScriptDebuggerCommandSchedulerJob
1234{
1235public:
1236 ShowFrameCodeJob(QScriptDebuggerPrivate *debugger, int frameIndex)
1237 : QScriptDebuggerCommandSchedulerJob(debugger),
1238 m_debugger(debugger), m_frameIndex(frameIndex) {}
1239
1240 void start()
1241 {
1242 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
1243 frontend.scheduleGetContextInfo(m_frameIndex);
1244 }
1245 void handleResponse(const QScriptDebuggerResponse &response,
1246 int)
1247 {
1248 if (m_info.isNull()) {
1249 m_info = response.resultAsContextInfo();
1250 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
1251 frontend.scheduleGetContextState(m_frameIndex);
1252 } else {
1253 int contextState = response.resultAsInt();
1254 bool error = (contextState == QScriptContext::ExceptionState);
1255 if (m_debugger->scriptsWidget) {
1256 m_debugger->scriptsWidget->setCurrentScript(m_info.scriptId());
1257 }
1258 if (m_debugger->codeWidget) {
1259 m_debugger->codeWidget->setCurrentScript(m_info.scriptId());
1260 QScriptDebuggerCodeViewInterface *view = m_debugger->codeWidget->currentView();
1261 if (view)
1262 view->setExecutionLineNumber(m_info.lineNumber(), error);
1263 }
1264 finish();
1265 }
1266 }
1267
1268private:
1269 QScriptDebuggerPrivate *m_debugger;
1270 int m_frameIndex;
1271 QScriptContextInfo m_info;
1272};
1273
1274} // namespace
1275
1276void QScriptDebuggerPrivate::selectScriptForFrame(int frameIndex)
1277{
1278 QScriptDebuggerJob *job = new ShowFrameCodeJob(this, frameIndex);
1279 scheduleJob(job);
1280}
1281
1282void QScriptDebuggerPrivate::emitStoppedSignal()
1283{
1284 emit q_func()->stopped();
1285}
1286
1287/*!
1288 Constructs a new QScriptDebugger object.
1289*/
1290QScriptDebugger::QScriptDebugger(QObject *parent)
1291 : QObject(*new QScriptDebuggerPrivate, parent)
1292{
1293 ++scriptDebuggerCount;
1294}
1295
1296/*!
1297 Destroys this QScriptDebugger.
1298*/
1299QScriptDebugger::~QScriptDebugger()
1300{
1301 --scriptDebuggerCount;
1302 if ((scriptDebuggerCount == 0) && eventCallbackRegistered) {
1303 eventCallbackRegistered = false;
1304 QInternal::unregisterCallback(QInternal::EventNotifyCallback,
1305 scriptDebuggerEventCallback);
1306 }
1307}
1308
1309/*!
1310 \internal
1311*/
1312QScriptDebugger::QScriptDebugger(QScriptDebuggerPrivate &dd, QObject *parent)
1313 : QObject(dd, parent)
1314{
1315}
1316
1317QScriptDebuggerFrontend *QScriptDebugger::frontend() const
1318{
1319 Q_D(const QScriptDebugger);
1320 return d->frontend;
1321}
1322
1323void QScriptDebugger::setFrontend(QScriptDebuggerFrontend *frontend)
1324{
1325 Q_D(QScriptDebugger);
1326 if (d->frontend)
1327 d->frontend->setEventHandler(0);
1328 d->frontend = frontend;
1329 if (frontend) {
1330 frontend->setEventHandler(d);
1331 if (!eventCallbackRegistered) {
1332 eventCallbackRegistered = true;
1333 QInternal::registerCallback(QInternal::EventNotifyCallback,
1334 scriptDebuggerEventCallback);
1335 }
1336 }
1337}
1338
1339QAction *QScriptDebugger::action(DebuggerAction action, QObject *parent)
1340{
1341 switch (action) {
1342 case InterruptAction:
1343 return interruptAction(parent);
1344 case ContinueAction:
1345 return continueAction(parent);
1346 case StepIntoAction:
1347 return stepIntoAction(parent);
1348 case StepOverAction:
1349 return stepOverAction(parent);
1350 case StepOutAction:
1351 return stepOutAction(parent);
1352 case RunToCursorAction:
1353 return runToCursorAction(parent);
1354 case RunToNewScriptAction:
1355 return runToNewScriptAction(parent);
1356 case ToggleBreakpointAction:
1357 return toggleBreakpointAction(parent);
1358 case ClearDebugOutputAction:
1359 return clearDebugOutputAction(parent);
1360 case ClearErrorLogAction:
1361 return clearErrorLogAction(parent);
1362 case ClearConsoleAction:
1363 return clearConsoleAction(parent);
1364 case FindInScriptAction:
1365 return findInScriptAction(parent);
1366 case FindNextInScriptAction:
1367 return findNextInScriptAction(parent);
1368 case FindPreviousInScriptAction:
1369 return findPreviousInScriptAction(parent);
1370 case GoToLineAction:
1371 return goToLineAction(parent);
1372 }
1373 return 0;
1374}
1375
1376QWidget *QScriptDebugger::widget(DebuggerWidget widget)
1377{
1378 switch (widget) {
1379 case ConsoleWidget: {
1380 QScriptDebuggerConsoleWidgetInterface *w = consoleWidget();
1381 if (!w && widgetFactory()) {
1382 w = widgetFactory()->createConsoleWidget();
1383 setConsoleWidget(w);
1384 }
1385 return w;
1386 }
1387 case StackWidget: {
1388 QScriptDebuggerStackWidgetInterface *w = stackWidget();
1389 if (!w && widgetFactory()) {
1390 w = widgetFactory()->createStackWidget();
1391 setStackWidget(w);
1392 }
1393 return w;
1394 }
1395 case ScriptsWidget: {
1396 QScriptDebuggerScriptsWidgetInterface *w = scriptsWidget();
1397 if (!w && widgetFactory()) {
1398 w = widgetFactory()->createScriptsWidget();
1399 setScriptsWidget(w);
1400 }
1401 return w;
1402 }
1403 case LocalsWidget: {
1404 QScriptDebuggerLocalsWidgetInterface *w = localsWidget();
1405 if (!w && widgetFactory()) {
1406 w = widgetFactory()->createLocalsWidget();
1407 setLocalsWidget(w);
1408 }
1409 return w;
1410 }
1411 case CodeWidget: {
1412 QScriptDebuggerCodeWidgetInterface *w = codeWidget();
1413 if (!w && widgetFactory()) {
1414 w = widgetFactory()->createCodeWidget();
1415 setCodeWidget(w);
1416 }
1417 return w;
1418 }
1419 case CodeFinderWidget: {
1420 QScriptDebuggerCodeFinderWidgetInterface *w = codeFinderWidget();
1421 if (!w && widgetFactory()) {
1422 w = widgetFactory()->createCodeFinderWidget();
1423 setCodeFinderWidget(w);
1424 }
1425 return w;
1426 }
1427 case BreakpointsWidget: {
1428 QScriptBreakpointsWidgetInterface *w = breakpointsWidget();
1429 if (!w && widgetFactory()) {
1430 w = widgetFactory()->createBreakpointsWidget();
1431 setBreakpointsWidget(w);
1432 }
1433 return w;
1434 }
1435 case DebugOutputWidget: {
1436 QScriptDebugOutputWidgetInterface *w = debugOutputWidget();
1437 if (!w && widgetFactory()) {
1438 w = widgetFactory()->createDebugOutputWidget();
1439 setDebugOutputWidget(w);
1440 }
1441 return w;
1442 }
1443 case ErrorLogWidget: {
1444 QScriptErrorLogWidgetInterface *w = errorLogWidget();
1445 if (!w && widgetFactory()) {
1446 w = widgetFactory()->createErrorLogWidget();
1447 setErrorLogWidget(w);
1448 }
1449 return w;
1450 }
1451 }
1452 return 0;
1453}
1454
1455QScriptDebuggerConsoleWidgetInterface *QScriptDebugger::consoleWidget() const
1456{
1457 Q_D(const QScriptDebugger);
1458 return d->consoleWidget;
1459}
1460
1461void QScriptDebugger::setConsoleWidget(QScriptDebuggerConsoleWidgetInterface *consoleWidget)
1462{
1463 Q_D(QScriptDebugger);
1464 if (d->consoleWidget) {
1465 QObject::disconnect(d->consoleWidget, 0, this, 0);
1466 }
1467 d->consoleWidget = consoleWidget;
1468 if (consoleWidget) {
1469 consoleWidget->setCommandHistorian(d->console);
1470 consoleWidget->setCompletionProvider(d);
1471 QObject::connect(consoleWidget, SIGNAL(lineEntered(QString)),
1472 this, SLOT(_q_onLineEntered(QString)));
1473
1474 d->console->showDebuggerInfoMessage(consoleWidget);
1475 }
1476}
1477
1478QScriptDebuggerStackWidgetInterface *QScriptDebugger::stackWidget() const
1479{
1480 Q_D(const QScriptDebugger);
1481 return d->stackWidget;
1482}
1483
1484void QScriptDebugger::setStackWidget(QScriptDebuggerStackWidgetInterface *stackWidget)
1485{
1486 Q_D(QScriptDebugger);
1487 if (d->stackWidget) {
1488 QObject::disconnect(d->stackWidget, 0, this, 0);
1489 }
1490 d->stackWidget = stackWidget;
1491 if (stackWidget) {
1492 if (!d->stackModel) {
1493 d->stackModel = new QScriptDebuggerStackModel(this);
1494 if (d->interactive)
1495 d->scheduleJob(new SyncStackJob(d));
1496 }
1497 stackWidget->setStackModel(d->stackModel);
1498 QObject::connect(stackWidget, SIGNAL(currentFrameChanged(int)),
1499 this, SLOT(_q_onCurrentFrameChanged(int)));
1500 }
1501}
1502
1503QScriptDebuggerScriptsWidgetInterface *QScriptDebugger::scriptsWidget() const
1504{
1505 Q_D(const QScriptDebugger);
1506 return d->scriptsWidget;
1507}
1508
1509void QScriptDebugger::setScriptsWidget(QScriptDebuggerScriptsWidgetInterface *scriptsWidget)
1510{
1511 Q_D(QScriptDebugger);
1512 if (d->scriptsWidget) {
1513 QObject::disconnect(d->scriptsWidget, 0, this, 0);
1514 }
1515 d->scriptsWidget = scriptsWidget;
1516 if (scriptsWidget) {
1517 if (!d->scriptsModel) {
1518 d->scriptsModel = new QScriptDebuggerScriptsModel(this);
1519 if (d->interactive)
1520 d->scheduleJob(new SyncScriptsJob(d));
1521 }
1522 scriptsWidget->setScriptsModel(d->scriptsModel);
1523 QObject::connect(scriptsWidget, SIGNAL(currentScriptChanged(qint64)),
1524 this, SLOT(_q_onCurrentScriptChanged(qint64)));
1525 QObject::connect(d->scriptsWidget, SIGNAL(scriptLocationSelected(int)),
1526 this, SLOT(_q_onScriptLocationSelected(int)));
1527 }
1528}
1529
1530QScriptDebuggerLocalsWidgetInterface *QScriptDebugger::localsWidget() const
1531{
1532 Q_D(const QScriptDebugger);
1533 return d->localsWidget;
1534}
1535
1536void QScriptDebugger::setLocalsWidget(QScriptDebuggerLocalsWidgetInterface *localsWidget)
1537{
1538 Q_D(QScriptDebugger);
1539 if (d->localsWidget) {
1540 // ### d->localsWidget->setLocalsModel(0);
1541 }
1542 localsWidget->setCompletionProvider(d);
1543 d->localsWidget = localsWidget;
1544}
1545
1546QScriptDebuggerCodeWidgetInterface *QScriptDebugger::codeWidget() const
1547{
1548 Q_D(const QScriptDebugger);
1549 return d->codeWidget;
1550}
1551
1552void QScriptDebugger::setCodeWidget(QScriptDebuggerCodeWidgetInterface *codeWidget)
1553{
1554 Q_D(QScriptDebugger);
1555 if (d->codeWidget) {
1556 d->codeWidget->removeEventFilter(this);
1557 }
1558 d->codeWidget = codeWidget;
1559 if (codeWidget) {
1560 if (!d->scriptsModel) {
1561 d->scriptsModel = new QScriptDebuggerScriptsModel(this);
1562 if (d->interactive)
1563 d->scheduleJob(new SyncScriptsJob(d));
1564 }
1565 codeWidget->setScriptsModel(d->scriptsModel);
1566 if (!d->breakpointsModel) {
1567 d->breakpointsModel = new QScriptBreakpointsModel(d, d, this);
1568 if (d->interactive)
1569 d->scheduleJob(new SyncBreakpointsJob(d));
1570 }
1571 codeWidget->setBreakpointsModel(d->breakpointsModel);
1572 codeWidget->setToolTipProvider(d);
1573 codeWidget->installEventFilter(this);
1574 }
1575 bool hasScript = (codeWidget != 0) && (codeWidget->currentView() != 0);
1576 if (d->findInScriptAction)
1577 d->findInScriptAction->setEnabled(hasScript && (d->codeFinderWidget != 0));
1578 if (d->goToLineAction)
1579 d->goToLineAction->setEnabled(hasScript);
1580 if (d->toggleBreakpointAction)
1581 d->toggleBreakpointAction->setEnabled(hasScript);
1582}
1583
1584QScriptDebuggerCodeFinderWidgetInterface *QScriptDebugger::codeFinderWidget() const
1585{
1586 Q_D(const QScriptDebugger);
1587 return d->codeFinderWidget;
1588}
1589
1590void QScriptDebugger::setCodeFinderWidget(QScriptDebuggerCodeFinderWidgetInterface *codeFinderWidget)
1591{
1592 Q_D(QScriptDebugger);
1593 if (d->codeFinderWidget) {
1594 QObject::disconnect(d->codeFinderWidget, 0, this, 0);
1595 }
1596 d->codeFinderWidget = codeFinderWidget;
1597 if (codeFinderWidget) {
1598 QObject::connect(codeFinderWidget, SIGNAL(findRequest(QString,int)),
1599 this, SLOT(_q_onFindCodeRequest(QString,int)));
1600 }
1601 if (d->findInScriptAction) {
1602 d->findInScriptAction->setEnabled(
1603 (codeFinderWidget != 0)
1604 && (d->codeWidget != 0)
1605 && (d->codeWidget->currentView() != 0));
1606 }
1607}
1608
1609QScriptDebugOutputWidgetInterface *QScriptDebugger::debugOutputWidget() const
1610{
1611 Q_D(const QScriptDebugger);
1612 return d->debugOutputWidget;
1613}
1614
1615void QScriptDebugger::setDebugOutputWidget(QScriptDebugOutputWidgetInterface *debugOutputWidget)
1616{
1617 Q_D(QScriptDebugger);
1618 d->debugOutputWidget = debugOutputWidget;
1619}
1620
1621QScriptBreakpointsWidgetInterface *QScriptDebugger::breakpointsWidget() const
1622{
1623 Q_D(const QScriptDebugger);
1624 return d->breakpointsWidget;
1625}
1626
1627void QScriptDebugger::setBreakpointsWidget(QScriptBreakpointsWidgetInterface *breakpointsWidget)
1628{
1629 Q_D(QScriptDebugger);
1630 if (d->breakpointsWidget) {
1631 // ### invalidate
1632 }
1633 d->breakpointsWidget = breakpointsWidget;
1634 if (breakpointsWidget) {
1635 if (!d->breakpointsModel) {
1636 d->breakpointsModel = new QScriptBreakpointsModel(d, d, this);
1637 if (d->interactive)
1638 d->scheduleJob(new SyncBreakpointsJob(d));
1639 }
1640 d->breakpointsWidget->setBreakpointsModel(d->breakpointsModel);
1641 d->breakpointsWidget->setScriptsModel(d->scriptsModel);
1642 }
1643}
1644
1645QScriptErrorLogWidgetInterface *QScriptDebugger::errorLogWidget() const
1646{
1647 Q_D(const QScriptDebugger);
1648 return d->errorLogWidget;
1649}
1650
1651void QScriptDebugger::setErrorLogWidget(QScriptErrorLogWidgetInterface *errorLogWidget)
1652{
1653 Q_D(QScriptDebugger);
1654 d->errorLogWidget = errorLogWidget;
1655}
1656
1657QScriptDebuggerWidgetFactoryInterface *QScriptDebugger::widgetFactory() const
1658{
1659 Q_D(const QScriptDebugger);
1660 return d->widgetFactory;
1661}
1662
1663void QScriptDebugger::setWidgetFactory(QScriptDebuggerWidgetFactoryInterface *factory)
1664{
1665 Q_D(QScriptDebugger);
1666 d->widgetFactory = factory;
1667}
1668
1669QAction *QScriptDebugger::interruptAction(QObject *parent) const
1670{
1671 Q_D(const QScriptDebugger);
1672 if (!d->interruptAction) {
1673 QIcon interruptIcon;
1674 interruptIcon.addPixmap(d->pixmap(QString::fromLatin1("interrupt.png")), QIcon::Normal);
1675 interruptIcon.addPixmap(d->pixmap(QString::fromLatin1("d_interrupt.png")), QIcon::Disabled);
1676 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1677 that->d_func()->interruptAction = new QAction(interruptIcon, QScriptDebugger::tr("Interrupt"), parent);
1678 d->interruptAction->setEnabled(!d->interactive);
1679 d->interruptAction->setShortcut(QScriptDebugger::tr("Shift+F5"));
1680 QObject::connect(d->interruptAction, SIGNAL(triggered()),
1681 that, SLOT(_q_interrupt()));
1682 }
1683 return d->interruptAction;
1684}
1685
1686QAction *QScriptDebugger::continueAction(QObject *parent) const
1687{
1688 Q_D(const QScriptDebugger);
1689 if (!d->continueAction) {
1690 QIcon continueIcon;
1691 continueIcon.addPixmap(d->pixmap(QString::fromLatin1("play.png")), QIcon::Normal);
1692 continueIcon.addPixmap(d->pixmap(QString::fromLatin1("d_play.png")), QIcon::Disabled);
1693 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1694 that->d_func()->continueAction = new QAction(continueIcon, QScriptDebugger::tr("Continue"), parent);
1695 d->continueAction->setEnabled(d->interactive);
1696 d->continueAction->setShortcut(QScriptDebugger::tr("F5"));
1697 QObject::connect(d->continueAction, SIGNAL(triggered()),
1698 that, SLOT(_q_continue()));
1699 }
1700 return d->continueAction;
1701}
1702
1703QAction *QScriptDebugger::stepIntoAction(QObject *parent) const
1704{
1705 Q_D(const QScriptDebugger);
1706 if (!d->stepIntoAction) {
1707 QIcon stepIntoIcon;
1708 stepIntoIcon.addPixmap(d->pixmap(QString::fromLatin1("stepinto.png")), QIcon::Normal);
1709 stepIntoIcon.addPixmap(d->pixmap(QString::fromLatin1("d_stepinto.png")), QIcon::Disabled);
1710 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1711 that->d_func()->stepIntoAction = new QAction(stepIntoIcon, QScriptDebugger::tr("Step Into"), parent);
1712 d->stepIntoAction->setEnabled(d->interactive);
1713 d->stepIntoAction->setShortcut(QScriptDebugger::tr("F11"));
1714 QObject::connect(d->stepIntoAction, SIGNAL(triggered()),
1715 that, SLOT(_q_stepInto()));
1716 }
1717 return d->stepIntoAction;
1718}
1719
1720QAction *QScriptDebugger::stepOverAction(QObject *parent) const
1721{
1722 Q_D(const QScriptDebugger);
1723 if (!d->stepOverAction) {
1724 QIcon stepOverIcon;
1725 stepOverIcon.addPixmap(d->pixmap(QString::fromLatin1("stepover.png")), QIcon::Normal);
1726 stepOverIcon.addPixmap(d->pixmap(QString::fromLatin1("d_stepover.png")), QIcon::Disabled);
1727 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1728 that->d_func()->stepOverAction = new QAction(stepOverIcon, QScriptDebugger::tr("Step Over"), parent);
1729 d->stepOverAction->setEnabled(d->interactive);
1730 d->stepOverAction->setShortcut(QScriptDebugger::tr("F10"));
1731 QObject::connect(d->stepOverAction, SIGNAL(triggered()),
1732 that, SLOT(_q_stepOver()));
1733 }
1734 return d->stepOverAction;
1735}
1736
1737QAction *QScriptDebugger::stepOutAction(QObject *parent) const
1738{
1739 Q_D(const QScriptDebugger);
1740 if (!d->stepOutAction) {
1741 QIcon stepOutIcon;
1742 stepOutIcon.addPixmap(d->pixmap(QString::fromLatin1("stepout.png")), QIcon::Normal);
1743 stepOutIcon.addPixmap(d->pixmap(QString::fromLatin1("d_stepout.png")), QIcon::Disabled);
1744 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1745 that->d_func()->stepOutAction = new QAction(stepOutIcon, QScriptDebugger::tr("Step Out"), parent);
1746 d->stepOutAction->setEnabled(d->interactive);
1747 d->stepOutAction->setShortcut(QScriptDebugger::tr("Shift+F11"));
1748 QObject::connect(d->stepOutAction, SIGNAL(triggered()),
1749 that, SLOT(_q_stepOut()));
1750 }
1751 return d->stepOutAction;
1752}
1753
1754QAction *QScriptDebugger::runToCursorAction(QObject *parent) const
1755{
1756 Q_D(const QScriptDebugger);
1757 if (!d->runToCursorAction) {
1758 QIcon runToCursorIcon;
1759 runToCursorIcon.addPixmap(d->pixmap(QString::fromLatin1("runtocursor.png")), QIcon::Normal);
1760 runToCursorIcon.addPixmap(d->pixmap(QString::fromLatin1("d_runtocursor.png")), QIcon::Disabled);
1761 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1762 that->d_func()->runToCursorAction = new QAction(runToCursorIcon, QScriptDebugger::tr("Run to Cursor"), parent);
1763 d->runToCursorAction->setEnabled(d->interactive);
1764 d->runToCursorAction->setShortcut(QScriptDebugger::tr("Ctrl+F10"));
1765 QObject::connect(d->runToCursorAction, SIGNAL(triggered()),
1766 that, SLOT(_q_runToCursor()));
1767 }
1768 return d->runToCursorAction;
1769}
1770
1771QAction *QScriptDebugger::runToNewScriptAction(QObject *parent) const
1772{
1773 Q_D(const QScriptDebugger);
1774 if (!d->runToNewScriptAction) {
1775 QIcon runToNewScriptIcon;
1776 runToNewScriptIcon.addPixmap(d->pixmap(QString::fromLatin1("runtonewscript.png")), QIcon::Normal);
1777 runToNewScriptIcon.addPixmap(d->pixmap(QString::fromLatin1("d_breakonscriptload.png")), QIcon::Disabled);
1778 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1779 that->d_func()->runToNewScriptAction = new QAction(runToNewScriptIcon,
1780 QScriptDebugger::tr("Run to New Script"), parent);
1781 d->runToNewScriptAction->setEnabled(d->interactive);
1782 QObject::connect(d->runToNewScriptAction, SIGNAL(triggered()),
1783 that, SLOT(_q_runToNewScript()));
1784 }
1785 return d->runToNewScriptAction;
1786}
1787
1788QAction *QScriptDebugger::toggleBreakpointAction(QObject *parent) const
1789{
1790 Q_D(const QScriptDebugger);
1791 if (!d->toggleBreakpointAction) {
1792 QIcon toggleBreakpointIcon;
1793 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1794 that->d_func()->toggleBreakpointAction = new QAction(toggleBreakpointIcon,
1795 QScriptDebugger::tr("Toggle Breakpoint"), parent);
1796 d->toggleBreakpointAction->setShortcut(QScriptDebugger::tr("F9"));
1797 d->toggleBreakpointAction->setEnabled((d->codeWidget != 0) && (d->codeWidget->currentView() != 0));
1798 QObject::connect(d->toggleBreakpointAction, SIGNAL(triggered()),
1799 that, SLOT(_q_toggleBreakpoint()));
1800 }
1801 return d->toggleBreakpointAction;
1802}
1803
1804QAction *QScriptDebugger::clearDebugOutputAction(QObject *parent) const
1805{
1806 Q_D(const QScriptDebugger);
1807 if (!d->clearDebugOutputAction) {
1808 QIcon clearDebugOutputIcon;
1809 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1810 that->d_func()->clearDebugOutputAction = new QAction(clearDebugOutputIcon, QScriptDebugger::tr("Clear Debug Output"), parent);
1811 QObject::connect(d->clearDebugOutputAction, SIGNAL(triggered()),
1812 that, SLOT(_q_clearDebugOutput()));
1813 }
1814 return d->clearDebugOutputAction;
1815}
1816
1817QAction *QScriptDebugger::clearErrorLogAction(QObject *parent) const
1818{
1819 Q_D(const QScriptDebugger);
1820 if (!d->clearErrorLogAction) {
1821 QIcon clearErrorLogIcon;
1822 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1823 that->d_func()->clearErrorLogAction = new QAction(clearErrorLogIcon, QScriptDebugger::tr("Clear Error Log"), parent);
1824 QObject::connect(d->clearErrorLogAction, SIGNAL(triggered()),
1825 that, SLOT(_q_clearErrorLog()));
1826 }
1827 return d->clearErrorLogAction;
1828}
1829
1830QAction *QScriptDebugger::clearConsoleAction(QObject *parent) const
1831{
1832 Q_D(const QScriptDebugger);
1833 if (!d->clearConsoleAction) {
1834 QIcon clearConsoleIcon;
1835 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1836 that->d_func()->clearConsoleAction = new QAction(clearConsoleIcon, QScriptDebugger::tr("Clear Console"), parent);
1837 QObject::connect(d->clearConsoleAction, SIGNAL(triggered()),
1838 that, SLOT(_q_clearConsole()));
1839 }
1840 return d->clearConsoleAction;
1841}
1842
1843QAction *QScriptDebugger::findInScriptAction(QObject *parent) const
1844{
1845 Q_D(const QScriptDebugger);
1846 if (!d->findInScriptAction) {
1847 QIcon findInScriptIcon;
1848 findInScriptIcon.addPixmap(d->pixmap(QString::fromLatin1("find.png")), QIcon::Normal);
1849 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1850 that->d_func()->findInScriptAction = new QAction(findInScriptIcon, QScriptDebugger::tr("&Find in Script..."), parent);
1851 d->findInScriptAction->setShortcut(QScriptDebugger::tr("Ctrl+F"));
1852 d->findInScriptAction->setEnabled(
1853 (d->codeFinderWidget != 0)
1854 && (d->codeWidget != 0)
1855 && (d->codeWidget->currentView() != 0));
1856 QObject::connect(d->findInScriptAction, SIGNAL(triggered()),
1857 that, SLOT(_q_findInScript()));
1858 }
1859 return d->findInScriptAction;
1860}
1861
1862QAction *QScriptDebugger::findNextInScriptAction(QObject *parent) const
1863{
1864 Q_D(const QScriptDebugger);
1865 if (!d->findNextInScriptAction) {
1866 QIcon findNextInScriptIcon;
1867 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1868 that->d_func()->findNextInScriptAction = new QAction(findNextInScriptIcon, QScriptDebugger::tr("Find &Next"), parent);
1869 d->findNextInScriptAction->setEnabled(d->codeFinderWidget && !d->codeFinderWidget->text().isEmpty());
1870 d->findNextInScriptAction->setShortcut(QScriptDebugger::tr("F3"));
1871 QObject::connect(d->findNextInScriptAction, SIGNAL(triggered()),
1872 that, SLOT(_q_findNextInScript()));
1873 }
1874 return d->findNextInScriptAction;
1875}
1876
1877QAction *QScriptDebugger::findPreviousInScriptAction(QObject *parent) const
1878{
1879 Q_D(const QScriptDebugger);
1880 if (!d->findPreviousInScriptAction) {
1881 QIcon findPreviousInScriptIcon;
1882 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1883 that->d_func()->findPreviousInScriptAction = new QAction(findPreviousInScriptIcon, QScriptDebugger::tr("Find &Previous"), parent);
1884 d->findPreviousInScriptAction->setEnabled(d->codeFinderWidget && !d->codeFinderWidget->text().isEmpty());
1885 d->findPreviousInScriptAction->setShortcut(QScriptDebugger::tr("Shift+F3"));
1886 QObject::connect(d->findPreviousInScriptAction, SIGNAL(triggered()),
1887 that, SLOT(_q_findPreviousInScript()));
1888 }
1889 return d->findPreviousInScriptAction;
1890}
1891
1892QAction *QScriptDebugger::goToLineAction(QObject *parent) const
1893{
1894 Q_D(const QScriptDebugger);
1895 if (!d->goToLineAction) {
1896 QIcon goToLineIcon;
1897 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1898 that->d_func()->goToLineAction = new QAction(goToLineIcon, QScriptDebugger::tr("Go to Line"), parent);
1899 d->goToLineAction->setShortcut(QScriptDebugger::tr("Ctrl+G"));
1900 d->goToLineAction->setEnabled((d->codeWidget != 0) && (d->codeWidget->currentView() != 0));
1901 QObject::connect(d->goToLineAction, SIGNAL(triggered()),
1902 that, SLOT(_q_goToLine()));
1903 }
1904 return d->goToLineAction;
1905}
1906
1907QMenu *QScriptDebugger::createStandardMenu(QWidget *widgetParent, QObject *actionParent)
1908{
1909 QMenu *menu = new QMenu(widgetParent);
1910 menu->setTitle(QScriptDebugger::tr("Debug"));
1911 menu->addAction(action(ContinueAction, actionParent));
1912 menu->addAction(action(InterruptAction, actionParent));
1913 menu->addAction(action(StepIntoAction, actionParent));
1914 menu->addAction(action(StepOverAction, actionParent));
1915 menu->addAction(action(StepOutAction, actionParent));
1916 menu->addAction(action(RunToCursorAction, actionParent));
1917 menu->addAction(action(RunToNewScriptAction, actionParent));
1918
1919 menu->addSeparator();
1920 menu->addAction(action(ToggleBreakpointAction, actionParent));
1921
1922 menu->addSeparator();
1923 menu->addAction(action(ClearDebugOutputAction, actionParent));
1924 menu->addAction(action(ClearErrorLogAction, actionParent));
1925 menu->addAction(action(ClearConsoleAction, actionParent));
1926
1927 return menu;
1928}
1929
1930#ifndef QT_NO_TOOLBAR
1931QToolBar *QScriptDebugger::createStandardToolBar(QWidget *widgetParent, QObject *actionParent)
1932{
1933 QToolBar *tb = new QToolBar(widgetParent);
1934 tb->setObjectName(QLatin1String("qtscriptdebugger_standardToolBar"));
1935 tb->addAction(action(ContinueAction, actionParent));
1936 tb->addAction(action(InterruptAction, actionParent));
1937 tb->addAction(action(StepIntoAction, actionParent));
1938 tb->addAction(action(StepOverAction, actionParent));
1939 tb->addAction(action(StepOutAction, actionParent));
1940 tb->addAction(action(RunToCursorAction, actionParent));
1941 tb->addAction(action(RunToNewScriptAction, actionParent));
1942 tb->addSeparator();
1943 tb->addAction(action(FindInScriptAction, actionParent));
1944 return tb;
1945}
1946#endif
1947
1948bool QScriptDebugger::isInteractive() const
1949{
1950 Q_D(const QScriptDebugger);
1951 return d->interactive;
1952}
1953
1954/*!
1955 \reimp
1956*/
1957bool QScriptDebugger::eventFilter(QObject *watched, QEvent *e)
1958{
1959 Q_D(QScriptDebugger);
1960 if (watched == d->codeWidget) {
1961 if (e->type() == QEvent::KeyPress) {
1962 d->_q_findInScript();
1963 d->codeFinderWidget->setText(static_cast<QKeyEvent*>(e)->text());
1964 return true;
1965 }
1966 }
1967 return false;
1968}
1969
1970/*!
1971 \reimp
1972*/
1973void QScriptDebugger::timerEvent(QTimerEvent *e)
1974{
1975 Q_D(QScriptDebugger);
1976 if (e->timerId() == d->updatesEnabledTimerId) {
1977 killTimer(d->updatesEnabledTimerId);
1978 d->updatesEnabledTimerId = -1;
1979 if (d->stackWidget)
1980 d->stackWidget->setUpdatesEnabled(true);
1981 if (d->localsWidget)
1982 d->localsWidget->setUpdatesEnabled(true);
1983 } else {
1984 QObject::timerEvent(e);
1985 }
1986}
1987
1988QT_END_NAMESPACE
1989
1990#include "moc_qscriptdebugger_p.cpp"
Note: See TracBrowser for help on using the repository browser.