1/****************************************************************************
2**
3** Copyright (C) 2018 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtSCriptTools module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qscriptdebugger_p.h"
41#include "qscriptdebuggerconsole_p.h"
42#include "qscriptdebuggerconsolecommandmanager_p.h"
43#include "qscriptdebuggerconsolecommandjob_p.h"
44#include "qscriptstdmessagehandler_p.h"
45#include "qscriptdebuggerfrontend_p.h"
46#include "qscriptdebuggereventhandlerinterface_p.h"
47#include "qscriptdebuggerresponsehandlerinterface_p.h"
48#include "qscriptdebuggerjobschedulerinterface_p.h"
49#include "qscriptdebuggerconsolewidgetinterface_p.h"
50#include "qscriptcompletionproviderinterface_p.h"
51#include "qscriptcompletiontask_p.h"
52#include "qscripttooltipproviderinterface_p.h"
53#include "qscriptdebuggerstackwidgetinterface_p.h"
54#include "qscriptdebuggerstackmodel_p.h"
55#include "qscriptdebuggerscriptswidgetinterface_p.h"
56#include "qscriptdebuggerscriptsmodel_p.h"
57#include "qscriptdebuggerlocalswidgetinterface_p.h"
58#include "qscriptdebuggerlocalsmodel_p.h"
59#include "qscriptdebuggercodewidgetinterface_p.h"
60#include "qscriptdebuggercodeviewinterface_p.h"
61#include "qscriptdebuggercodefinderwidgetinterface_p.h"
62#include "qscriptbreakpointswidgetinterface_p.h"
63#include "qscriptbreakpointsmodel_p.h"
64#include "qscriptdebugoutputwidgetinterface_p.h"
65#include "qscripterrorlogwidgetinterface_p.h"
66#include "qscriptdebuggerwidgetfactoryinterface_p.h"
67#include "qscriptdebuggerevent_p.h"
68#include "qscriptdebuggervalue_p.h"
69#include "qscriptdebuggerresponse_p.h"
70#include "qscriptdebuggercommand_p.h"
71#include "qscriptdebuggercommandschedulerfrontend_p.h"
72#include "qscriptdebuggercommandschedulerjob_p.h"
73#include "qscriptdebuggerjob_p_p.h"
74#include "qscriptxmlparser_p.h"
75
76#include "private/qobject_p.h"
77
78#include <QtScript/qscriptcontext.h>
79#include <QtScript/qscriptcontextinfo.h>
80
81#include <QtCore/qcoreapplication.h>
82#include <QtCore/qdir.h>
83#include <QtCore/qfileinfo.h>
84#include <QtCore/qstringlist.h>
85#include <QtCore/qdebug.h>
86
87#include <QtWidgets/qaction.h>
88#include <QtGui/qevent.h>
89#include <QtGui/qicon.h>
90#include <QtWidgets/qinputdialog.h>
91#include <QtWidgets/qmenu.h>
92#include <QtWidgets/qtoolbar.h>
93#include <QtWidgets/qtooltip.h>
94
95QT_BEGIN_NAMESPACE
96typedef QPair<QList<qint64>, QList<qint64> > QScriptScriptsDelta;
97typedef QPair<QList<qint64>, QList<qint64> > QScriptContextsDelta;
98QT_END_NAMESPACE
99
100Q_DECLARE_METATYPE(QScriptScriptsDelta)
101
102QT_BEGIN_NAMESPACE
103
104Q_SCRIPT_EXPORT QString qt_scriptToXml(const QString &program, int lineNumber = 1);
105
106namespace {
107
108static int scriptDebuggerCount = 0;
109static bool eventCallbackRegistered = false;
110static bool widgetInPaintEvent = false;
111
112static bool scriptDebuggerEventCallback(void **data)
113{
114 QEvent *event = reinterpret_cast<QEvent*>(data[1]);
115 if (event->type() == QEvent::Paint) {
116 QObject *receiver = reinterpret_cast<QObject*>(data[0]);
117 bool was = widgetInPaintEvent;
118 widgetInPaintEvent = true;
119 QCoreApplication::instance()->notify(receiver, event);
120 widgetInPaintEvent = was;
121 bool *result = reinterpret_cast<bool*>(data[2]);
122 *result = true;
123 return true;
124 }
125 return false;
126}
127
128}
129
130/*!
131 \since 4.5
132 \class QScriptDebugger
133 \internal
134
135 \brief The QScriptDebugger class provides a Qt Script debugger.
136
137 \ingroup script
138*/
139
140class QScriptDebuggerPrivate
141 : public QObjectPrivate,
142 public QScriptDebuggerCommandSchedulerInterface,
143 public QScriptDebuggerJobSchedulerInterface,
144 public QScriptDebuggerEventHandlerInterface,
145 public QScriptDebuggerResponseHandlerInterface,
146 public QScriptCompletionProviderInterface,
147 public QScriptToolTipProviderInterface
148{
149 Q_DECLARE_PUBLIC(QScriptDebugger)
150public:
151 QScriptDebuggerPrivate();
152 ~QScriptDebuggerPrivate();
153
154 int scheduleJob(QScriptDebuggerJob *job);
155 void finishJob(QScriptDebuggerJob *job);
156 void hibernateUntilEvaluateFinished(QScriptDebuggerJob *job);
157
158 void maybeStartNewJob();
159
160 int scheduleCommand(const QScriptDebuggerCommand &command,
161 QScriptDebuggerResponseHandlerInterface *responseHandler);
162
163 void handleResponse(
164 const QScriptDebuggerResponse &response, int commandId);
165 bool debuggerEvent(const QScriptDebuggerEvent &event);
166
167 QScriptCompletionTaskInterface *createCompletionTask(
168 const QString &contents, int cursorPosition, int frameIndex, int options);
169
170 void showToolTip(const QPoint &pos, int frameIndex,
171 int lineNumber, const QStringList &path);
172
173 static QPixmap pixmap(const QString &path);
174
175 void startInteraction(QScriptDebuggerEvent::Type type,
176 qint64 scriptId, int lineNumber);
177 void sync();
178 void loadLocals(int frameIndex);
179 QScriptDebuggerLocalsModel *createLocalsModel();
180 void selectScriptForFrame(int frameIndex);
181 void emitStoppedSignal();
182
183 void maybeDelete(QWidget *widget);
184
185 // private slots
186 void _q_onLineEntered(const QString &contents);
187 void _q_onCurrentFrameChanged(int frameIndex);
188 void _q_onCurrentScriptChanged(qint64 scriptId);
189 void _q_onScriptLocationSelected(int lineNumber);
190 void _q_interrupt();
191 void _q_continue();
192 void _q_stepInto();
193 void _q_stepOver();
194 void _q_stepOut();
195 void _q_runToCursor();
196 void _q_runToNewScript();
197 void _q_toggleBreakpoint();
198 void _q_clearDebugOutput();
199 void _q_clearErrorLog();
200 void _q_clearConsole();
201 void _q_findInScript();
202 void _q_findNextInScript();
203 void _q_findPreviousInScript();
204 void _q_onFindCodeRequest(const QString &, int);
205 void _q_goToLine();
206
207 void executeConsoleCommand(const QString &command);
208 void findCode(const QString &exp, int options);
209
210 QScriptDebuggerFrontend *frontend;
211
212 bool interactive;
213 QScriptDebuggerConsole *console;
214
215 int nextJobId;
216 QList<QScriptDebuggerJob*> pendingJobs;
217 QList<int> pendingJobIds;
218 QScriptDebuggerJob *activeJob;
219 bool activeJobHibernating;
220 QHash<int, QScriptDebuggerCommand> watchedCommands;
221 QHash<int, QScriptDebuggerResponseHandlerInterface*> responseHandlers;
222
223 QScriptDebuggerConsoleWidgetInterface *consoleWidget;
224 QScriptDebuggerStackWidgetInterface *stackWidget;
225 QScriptDebuggerStackModel *stackModel;
226 QScriptDebuggerScriptsWidgetInterface *scriptsWidget;
227 QScriptDebuggerScriptsModel *scriptsModel;
228 QScriptDebuggerLocalsWidgetInterface *localsWidget;
229 QHash<int, QScriptDebuggerLocalsModel*> localsModels;
230 QScriptDebuggerCodeWidgetInterface *codeWidget;
231 QScriptDebuggerCodeFinderWidgetInterface *codeFinderWidget;
232 QScriptBreakpointsWidgetInterface *breakpointsWidget;
233 QScriptBreakpointsModel *breakpointsModel;
234 QScriptDebugOutputWidgetInterface *debugOutputWidget;
235 QScriptErrorLogWidgetInterface *errorLogWidget;
236 QScriptDebuggerWidgetFactoryInterface *widgetFactory;
237
238 QAction *interruptAction;
239 QAction *continueAction;
240 QAction *stepIntoAction;
241 QAction *stepOverAction;
242 QAction *stepOutAction;
243 QAction *runToCursorAction;
244 QAction *runToNewScriptAction;
245
246 QAction *toggleBreakpointAction;
247
248 QAction *clearDebugOutputAction;
249 QAction *clearErrorLogAction;
250 QAction *clearConsoleAction;
251
252 QAction *findInScriptAction;
253 QAction *findNextInScriptAction;
254 QAction *findPreviousInScriptAction;
255 QAction *goToLineAction;
256
257 int updatesEnabledTimerId;
258};
259
260QScriptDebuggerPrivate::QScriptDebuggerPrivate()
261{
262 frontend = 0;
263 activeJob = 0;
264 activeJobHibernating = false;
265 nextJobId = 0;
266 interactive = false;
267
268 console = new QScriptDebuggerConsole();
269 QString scriptsPath = QLatin1String(":/qt/scripttools/debugging/scripts/commands");
270 QScriptStdMessageHandler tmp;
271 console->loadScriptedCommands(scriptsPath, messageHandler: &tmp);
272
273 consoleWidget = 0;
274 stackWidget = 0;
275 stackModel = 0;
276 scriptsWidget = 0;
277 scriptsModel = 0;
278 localsWidget = 0;
279 codeWidget = 0;
280 codeFinderWidget = 0;
281 breakpointsWidget = 0;
282 breakpointsModel = 0;
283 debugOutputWidget = 0;
284 errorLogWidget = 0;
285 widgetFactory = 0;
286
287 interruptAction = 0;
288 continueAction = 0;
289 stepIntoAction = 0;
290 stepOverAction = 0;
291 stepOutAction = 0;
292 runToCursorAction = 0;
293 runToNewScriptAction = 0;
294
295 toggleBreakpointAction = 0;
296
297 clearErrorLogAction = 0;
298 clearDebugOutputAction = 0;
299 clearConsoleAction = 0;
300
301 findInScriptAction = 0;
302 findNextInScriptAction = 0;
303 findPreviousInScriptAction = 0;
304 goToLineAction = 0;
305
306 updatesEnabledTimerId = -1;
307}
308
309QScriptDebuggerPrivate::~QScriptDebuggerPrivate()
310{
311 delete console;
312 qDeleteAll(c: pendingJobs);
313 delete activeJob;
314 maybeDelete(widget: consoleWidget);
315 maybeDelete(widget: stackWidget);
316 maybeDelete(widget: scriptsWidget);
317 maybeDelete(widget: localsWidget);
318 maybeDelete(widget: codeWidget);
319 maybeDelete(widget: codeFinderWidget);
320 maybeDelete(widget: breakpointsWidget);
321 maybeDelete(widget: debugOutputWidget);
322 maybeDelete(widget: errorLogWidget);
323}
324
325void QScriptDebuggerPrivate::maybeDelete(QWidget *widget)
326{
327 if (widget && !widget->parent())
328 delete widget;
329}
330
331QPixmap QScriptDebuggerPrivate::pixmap(const QString &path)
332{
333 static QString prefix = QString::fromLatin1(str: ":/qt/scripttools/debugging/images/");
334 return QPixmap(prefix + path);
335}
336
337/*
338 \reimp
339*/
340int QScriptDebuggerPrivate::scheduleJob(QScriptDebuggerJob *job)
341{
342 QScriptDebuggerJobPrivate *priv = QScriptDebuggerJobPrivate::get(q: job);
343 Q_ASSERT(priv->jobScheduler == 0);
344 priv->jobScheduler = this;
345 int id = nextJobId;
346 pendingJobs.append(t: job);
347 pendingJobIds.append(t: id);
348 maybeStartNewJob();
349 return id;
350}
351
352/*
353 \reimp
354*/
355void QScriptDebuggerPrivate::finishJob(QScriptDebuggerJob *job)
356{
357 Q_UNUSED(job);
358 Q_ASSERT(activeJob == job);
359 delete activeJob;
360 activeJob = 0;
361 activeJobHibernating = false;
362 maybeStartNewJob();
363}
364
365/*
366 \reimp
367*/
368void QScriptDebuggerPrivate::hibernateUntilEvaluateFinished(QScriptDebuggerJob *job)
369{
370 Q_UNUSED(job);
371 Q_ASSERT(activeJob == job);
372 activeJobHibernating = true;
373}
374
375/*
376 Starts a new job if appropriate.
377*/
378void QScriptDebuggerPrivate::maybeStartNewJob()
379{
380 if (activeJob || pendingJobs.isEmpty())
381 return;
382 activeJob = pendingJobs.takeFirst();
383 activeJob->start();
384}
385
386/*
387 \reimp
388*/
389int QScriptDebuggerPrivate::scheduleCommand(
390 const QScriptDebuggerCommand &command,
391 QScriptDebuggerResponseHandlerInterface *responseHandler)
392{
393 if (!frontend)
394 return -1;
395 int id = frontend->scheduleCommand(command, responseHandler: this);
396 if (responseHandler && (responseHandler != this))
397 responseHandlers.insert(key: id, value: responseHandler);
398 if ((command.type() == QScriptDebuggerCommand::SetBreakpoint)
399 || (command.type() == QScriptDebuggerCommand::SetBreakpointData)
400 || (command.type() == QScriptDebuggerCommand::DeleteBreakpoint)) {
401 // need to watch this command and update the breakpoints model afterwards
402 watchedCommands.insert(key: id, value: command);
403 }
404 return id;
405}
406
407/*
408 \reimp
409*/
410void QScriptDebuggerPrivate::handleResponse(
411 const QScriptDebuggerResponse &response, int commandId)
412{
413 Q_Q(QScriptDebugger);
414 if (watchedCommands.contains(key: commandId)) {
415 QScriptDebuggerCommand command = watchedCommands.take(key: commandId);
416 if (response.error() == QScriptDebuggerResponse::NoError) {
417 if (!breakpointsModel)
418 breakpointsModel = new QScriptBreakpointsModel(this, this, q);
419 switch (command.type()) {
420 case QScriptDebuggerCommand::SetBreakpoint: {
421 int breakpointId = response.resultAsInt();
422 QScriptBreakpointData data = command.breakpointData();
423 breakpointsModel->addBreakpoint(id: breakpointId, data);
424 } break;
425 case QScriptDebuggerCommand::SetBreakpointData: {
426 int breakpointId = command.breakpointId();
427 QScriptBreakpointData data = command.breakpointData();
428 breakpointsModel->modifyBreakpoint(id: breakpointId, data);
429 } break;
430 case QScriptDebuggerCommand::DeleteBreakpoint: {
431 int breakpointId = command.breakpointId();
432 breakpointsModel->removeBreakpoint(id: breakpointId);
433 } break;
434 default:
435 Q_ASSERT(false);
436 }
437 }
438 } else if (response.async()) {
439 interactive = false;
440 // disable/invalidate/enable stuff
441 if (continueAction)
442 continueAction->setEnabled(false);
443 if (stepIntoAction)
444 stepIntoAction->setEnabled(false);
445 if (stepOverAction)
446 stepOverAction->setEnabled(false);
447 if (stepOutAction)
448 stepOutAction->setEnabled(false);
449 if (runToCursorAction)
450 runToCursorAction->setEnabled(false);
451 if (runToNewScriptAction)
452 runToNewScriptAction->setEnabled(false);
453 if (interruptAction)
454 interruptAction->setEnabled(true);
455
456 // the timer is to avoid flicker when stepping
457 if (stackWidget) {
458 stackWidget->setUpdatesEnabled(false);
459 stackWidget->setEnabled(false);
460 if (updatesEnabledTimerId == -1)
461 updatesEnabledTimerId = q->startTimer(interval: 75);
462 }
463 if (localsWidget) {
464 localsWidget->setUpdatesEnabled(false);
465 localsWidget->setEnabled(false);
466 if (updatesEnabledTimerId == -1)
467 updatesEnabledTimerId = q->startTimer(interval: 75);
468 }
469 if (codeWidget)
470 codeWidget->invalidateExecutionLineNumbers();
471
472 emit q->started();
473 }
474
475 QScriptDebuggerResponseHandlerInterface *realHandler = responseHandlers.take(key: commandId);
476 if (realHandler)
477 realHandler->handleResponse(response, commandId);
478}
479
480/*
481 \reimp
482
483 Handles a debugger event from the frontend.
484*/
485bool QScriptDebuggerPrivate::debuggerEvent(const QScriptDebuggerEvent &event)
486{
487 Q_Q(QScriptDebugger);
488 switch (event.type()) {
489 case QScriptDebuggerEvent::None:
490 case QScriptDebuggerEvent::UserEvent:
491 case QScriptDebuggerEvent::MaxUserEvent:
492 Q_ASSERT(false);
493 break;
494
495 case QScriptDebuggerEvent::Trace:
496 if (!debugOutputWidget && widgetFactory)
497 q->setDebugOutputWidget(widgetFactory->createDebugOutputWidget());
498 if (debugOutputWidget)
499 debugOutputWidget->message(type: QtDebugMsg, text: event.message());
500 return true; // trace doesn't stall execution
501
502 case QScriptDebuggerEvent::SteppingFinished: {
503 if (!consoleWidget && widgetFactory)
504 q->setConsoleWidget(widgetFactory->createConsoleWidget());
505 if (consoleWidget) {
506 QString msg = event.message();
507 if (!msg.isEmpty())
508 consoleWidget->message(type: QtDebugMsg, text: msg);
509 }
510 } break;
511
512 case QScriptDebuggerEvent::Interrupted:
513 case QScriptDebuggerEvent::LocationReached:
514 break;
515
516 case QScriptDebuggerEvent::Breakpoint: {
517 int bpId = event.breakpointId();
518 if (!consoleWidget && widgetFactory)
519 q->setConsoleWidget(widgetFactory->createConsoleWidget());
520 if (consoleWidget) {
521 consoleWidget->message(type: QtDebugMsg,
522 text: QString::fromLatin1(str: "Breakpoint %0 at %1, line %2.")
523 .arg(a: bpId).arg(a: event.fileName())
524 .arg(a: event.lineNumber()));
525 }
526 if (breakpointsModel->breakpointData(id: bpId).isSingleShot())
527 breakpointsModel->removeBreakpoint(id: bpId);
528 } break;
529
530 case QScriptDebuggerEvent::Exception: {
531 if (event.hasExceptionHandler()) {
532 // Let the exception be handled like normal.
533 // We may want to add a "Break on all exceptions" option
534 // to be able to customize this behavior.
535 return true;
536 }
537 if (!consoleWidget && widgetFactory)
538 q->setConsoleWidget(widgetFactory->createConsoleWidget());
539 if (!errorLogWidget && widgetFactory)
540 q->setErrorLogWidget(widgetFactory->createErrorLogWidget());
541 if (consoleWidget || errorLogWidget) {
542 QString fn = event.fileName();
543 if (fn.isEmpty()) {
544 if (event.scriptId() != -1)
545 fn = QString::fromLatin1(str: "<anonymous script, id=%0>").arg(a: event.scriptId());
546 else
547 fn = QString::fromLatin1(str: "<native>");
548 }
549 QString msg = QString::fromLatin1(str: "Uncaught exception at %0:%1: %2").arg(a: fn)
550 .arg(a: event.lineNumber()).arg(a: event.message());
551 if (consoleWidget)
552 consoleWidget->message(type: QtCriticalMsg, text: msg);
553 if (errorLogWidget)
554 errorLogWidget->message(type: QtCriticalMsg, text: msg);
555 }
556 } break;
557
558 case QScriptDebuggerEvent::InlineEvalFinished: {
559 QScriptDebuggerValue result = event.scriptValue();
560 Q_ASSERT(console != 0);
561 int action = console->evaluateAction();
562 console->setEvaluateAction(0);
563 switch (action) {
564 case 0: { // eval command
565 if (activeJob) {
566 if (activeJobHibernating) {
567 activeJobHibernating = false;
568 activeJob->evaluateFinished(result);
569 }
570 } else if (consoleWidget) {
571 // ### if the result is an object, need to do a tostring job on it
572// messageHandler->message(QtDebugMsg, result.toString());
573 if (result.type() != QScriptDebuggerValue::UndefinedValue)
574 consoleWidget->message(type: QtDebugMsg, text: event.message());
575 }
576 } break;
577 case 1: { // return command
578 QScriptDebuggerCommandSchedulerFrontend frontend(this, this);
579 frontend.scheduleForceReturn(contextIndex: console->currentFrameIndex(), value: result);
580 } return false;
581 }
582 if (!event.isNestedEvaluate()) {
583 // in the case when evaluate() was called while the
584 // engine was not running, we don't want to enter interactive mode
585 return true;
586 }
587 } break;
588
589 case QScriptDebuggerEvent::DebuggerInvocationRequest: {
590 if (!consoleWidget && widgetFactory)
591 q->setConsoleWidget(widgetFactory->createConsoleWidget());
592 if (consoleWidget) {
593 QString fn = event.fileName();
594 if (fn.isEmpty())
595 fn = QString::fromLatin1(str: "<anonymous script, id=%0>").arg(a: event.scriptId());
596 consoleWidget->message(type: QtDebugMsg,
597 text: QString::fromLatin1(str: "Debugger invoked from %1, line %2.")
598 .arg(a: fn).arg(a: event.lineNumber()));
599 }
600 } break;
601
602 case QScriptDebuggerEvent::ForcedReturn: {
603 } break;
604
605 }
606
607 if (widgetInPaintEvent) {
608 QString msg = QString::fromLatin1(str: "Suspending evaluation in paintEvent() is not supported; resuming.");
609 if (!consoleWidget && widgetFactory)
610 q->setConsoleWidget(widgetFactory->createConsoleWidget());
611 if (!errorLogWidget && widgetFactory)
612 q->setErrorLogWidget(widgetFactory->createErrorLogWidget());
613 if (consoleWidget)
614 consoleWidget->message(type: QtWarningMsg, text: msg);
615 if (errorLogWidget)
616 errorLogWidget->message(type: QtCriticalMsg, text: msg);
617 return true;
618 }
619
620 if (activeJobHibernating) {
621 // evaluate() did not finish normally (e.g. due to a breakpoint),
622 // so cancel the job that's waiting for it
623 delete activeJob;
624 activeJob = 0;
625 activeJobHibernating = false;
626 }
627
628 startInteraction(type: event.type(), scriptId: event.scriptId(), lineNumber: event.lineNumber());
629 return !interactive;
630}
631
632class QScriptToolTipJob : public QScriptDebuggerCommandSchedulerJob
633{
634public:
635 QScriptToolTipJob(const QPoint &pos, int frameIndex,
636 int lineNumber, const QStringList &path,
637 QScriptDebuggerCommandSchedulerInterface *scheduler)
638 : QScriptDebuggerCommandSchedulerJob(scheduler), m_pos(pos),
639 m_frameIndex(frameIndex), m_lineNumber(lineNumber), m_path(path)
640 {}
641
642 void start()
643 {
644 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
645 frontend.scheduleGetPropertyExpressionValue(contextIndex: m_frameIndex, lineNumber: m_lineNumber, path: m_path);
646 }
647 void handleResponse(const QScriptDebuggerResponse &response, int /*commandId*/)
648 {
649 QString tip = response.result().toString();
650 if (tip.indexOf(c: QLatin1Char('\n')) != -1) {
651 QStringList lines = tip.split(sep: QLatin1Char('\n'));
652 int lineCount = lines.size();
653 if (lineCount > 5) {
654 lines = lines.mid(pos: 0, length: 5);
655 lines.append(t: QString::fromLatin1(str: "(... %0 more lines ...)").arg(a: lineCount - 5));
656 }
657 tip = lines.join(sep: QLatin1String("\n"));
658 }
659#if QT_CONFIG(tooltip)
660 QToolTip::showText(pos: m_pos, text: tip);
661#endif
662 finish();
663 }
664
665private:
666 QPoint m_pos;
667 int m_frameIndex;
668 int m_lineNumber;
669 QStringList m_path;
670};
671
672/*
673 \reimp
674*/
675void QScriptDebuggerPrivate::showToolTip(const QPoint &pos, int frameIndex,
676 int lineNumber, const QStringList &path)
677{
678 if (frameIndex == -1) {
679 if (stackWidget)
680 frameIndex = stackWidget->currentFrameIndex();
681 else
682 frameIndex = console->currentFrameIndex();
683 }
684 QScriptDebuggerJob *job = new QScriptToolTipJob(pos, frameIndex, lineNumber, path, this);
685 scheduleJob(job);
686}
687
688/*
689 \reimp
690*/
691QScriptCompletionTaskInterface *QScriptDebuggerPrivate::createCompletionTask(
692 const QString &contents, int cursorPosition, int frameIndex, int options)
693{
694 return new QScriptCompletionTask(
695 contents, cursorPosition, frameIndex, this, this,
696 (options & QScriptCompletionProviderInterface::ConsoleCommandCompletion) ? console : 0);
697}
698
699/*
700 Slot called when a line has been entered in the console widget.
701*/
702void QScriptDebuggerPrivate::_q_onLineEntered(const QString &contents)
703{
704 QScriptDebuggerConsoleCommandJob *commandJob;
705 commandJob = console->consumeInput(input: contents, messageHandler: consoleWidget, commandScheduler: this);
706 if (commandJob != 0) {
707 scheduleJob(job: commandJob);
708 consoleWidget->setLineContinuationMode(false);
709 } else if (console->hasIncompleteInput()) {
710 consoleWidget->setLineContinuationMode(true);
711 }
712}
713
714/*
715 Slot called when the current index has changed in the stack widget.
716*/
717void QScriptDebuggerPrivate::_q_onCurrentFrameChanged(int frameIndex)
718{
719 loadLocals(frameIndex);
720 selectScriptForFrame(frameIndex);
721}
722
723/*
724 Slot called when the current script has changed in the scripts widget.
725*/
726void QScriptDebuggerPrivate::_q_onCurrentScriptChanged(qint64 scriptId)
727{
728 if (codeWidget && (codeWidget->currentScriptId() != scriptId)) {
729 codeWidget->setCurrentScript(scriptId);
730 QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
731 if (view)
732 view->setExecutionLineNumber(lineNumber: -1, /*error=*/false);
733 }
734}
735
736void QScriptDebuggerPrivate::_q_onScriptLocationSelected(int lineNumber)
737{
738 QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
739 if (!view)
740 return;
741 view->gotoLine(lineNumber);
742}
743
744void QScriptDebuggerPrivate::_q_interrupt()
745{
746 executeConsoleCommand(command: QString::fromLatin1(str: "interrupt"));
747}
748
749void QScriptDebuggerPrivate::_q_continue()
750{
751 executeConsoleCommand(command: QString::fromLatin1(str: "continue"));
752}
753
754void QScriptDebuggerPrivate::_q_stepInto()
755{
756 executeConsoleCommand(command: QString::fromLatin1(str: "step"));
757}
758
759void QScriptDebuggerPrivate::_q_stepOver()
760{
761 executeConsoleCommand(command: QString::fromLatin1(str: "next"));
762}
763
764void QScriptDebuggerPrivate::_q_stepOut()
765{
766 executeConsoleCommand(command: QString::fromLatin1(str: "finish"));
767}
768
769void QScriptDebuggerPrivate::_q_runToCursor()
770{
771 qint64 scriptId = codeWidget->currentScriptId();
772 int lineNumber = codeWidget->currentView()->cursorLineNumber();
773 QScriptDebuggerCommandSchedulerFrontend frontend(this, this);
774 frontend.scheduleRunToLocation(scriptId, lineNumber);
775}
776
777void QScriptDebuggerPrivate::_q_runToNewScript()
778{
779 QScriptDebuggerCommandSchedulerFrontend frontend(this, this);
780 frontend.scheduleRunToLocation(fileName: QString(), lineNumber: -1);
781}
782
783void QScriptDebuggerPrivate::_q_toggleBreakpoint()
784{
785 Q_ASSERT(codeWidget != 0);
786 QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
787 if (!view)
788 return;
789 qint64 scriptId = codeWidget->currentScriptId();
790 int lineNumber = view->cursorLineNumber();
791 Q_ASSERT(breakpointsModel != 0);
792 int bpId = breakpointsModel->resolveBreakpoint(scriptId, lineNumber);
793 if (bpId != -1) {
794 breakpointsModel->deleteBreakpoint(id: bpId);
795 } else {
796 QScriptBreakpointData data(scriptId, lineNumber);
797 if (scriptsModel)
798 data.setFileName(scriptsModel->scriptData(id: scriptId).fileName());
799 breakpointsModel->setBreakpoint(data);
800 }
801}
802
803void QScriptDebuggerPrivate::_q_clearDebugOutput()
804{
805 if (debugOutputWidget)
806 debugOutputWidget->clear();
807}
808
809void QScriptDebuggerPrivate::_q_clearErrorLog()
810{
811 if (errorLogWidget)
812 errorLogWidget->clear();
813}
814
815void QScriptDebuggerPrivate::_q_clearConsole()
816{
817 if (consoleWidget)
818 consoleWidget->clear();
819}
820
821void QScriptDebuggerPrivate::executeConsoleCommand(const QString &command)
822{
823 QString tmp = console->incompleteInput();
824 console->setIncompleteInput(QString());
825 QScriptDebuggerJob *job = console->consumeInput(input: console->commandPrefix() + command, messageHandler: debugOutputWidget, commandScheduler: this);
826 console->setIncompleteInput(tmp);
827 if (job != 0) {
828 scheduleJob(job);
829 // once to send the command...
830 QCoreApplication::processEvents();
831 // ... and once to receive the response
832 QCoreApplication::processEvents();
833 }
834}
835
836void QScriptDebuggerPrivate::_q_findInScript()
837{
838 if (!codeFinderWidget && widgetFactory)
839 q_func()->setCodeFinderWidget(widgetFactory->createCodeFinderWidget());
840 if (codeFinderWidget) {
841 codeFinderWidget->show();
842 codeFinderWidget->setFocus(Qt::OtherFocusReason);
843 }
844}
845
846void QScriptDebuggerPrivate::_q_findNextInScript()
847{
848 findCode(exp: codeFinderWidget->text(), options: codeFinderWidget->findOptions());
849}
850
851void QScriptDebuggerPrivate::_q_findPreviousInScript()
852{
853 int options = codeFinderWidget->findOptions();
854 options |= QTextDocument::FindBackward;
855 findCode(exp: codeFinderWidget->text(), options);
856}
857
858void QScriptDebuggerPrivate::_q_onFindCodeRequest(
859 const QString &exp, int options)
860{
861 findCode(exp, options);
862 if (findNextInScriptAction)
863 findNextInScriptAction->setEnabled(!exp.isEmpty());
864 if (findPreviousInScriptAction)
865 findPreviousInScriptAction->setEnabled(!exp.isEmpty());
866}
867
868void QScriptDebuggerPrivate::findCode(const QString &exp, int options)
869{
870 QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
871 if (!view)
872 return;
873 int result = view->find(exp, options);
874 codeFinderWidget->setOK(((result & 0x1) != 0) || exp.isEmpty());
875 codeFinderWidget->setWrapped((result & 0x2) != 0);
876}
877
878void QScriptDebuggerPrivate::_q_goToLine()
879{
880 QScriptDebuggerCodeViewInterface *view = codeWidget->currentView();
881 if (!view)
882 return;
883#ifndef QT_NO_INPUTDIALOG
884 bool ok = false;
885 int lineNumber = QInputDialog::getInt(parent: 0, title: QScriptDebugger::tr(s: "Go to Line"),
886 label: QScriptDebugger::tr(s: "Line:"),
887 value: view->cursorLineNumber(),
888 minValue: 1, INT_MAX, step: 1, ok: &ok);
889 if (ok)
890 view->gotoLine(lineNumber);
891#endif
892}
893
894class QScriptDebuggerShowLineJob : public QScriptDebuggerCommandSchedulerJob
895{
896public:
897 QScriptDebuggerShowLineJob(qint64 scriptId, int lineNumber,
898 QScriptMessageHandlerInterface *messageHandler,
899 QScriptDebuggerCommandSchedulerInterface *scheduler)
900 : QScriptDebuggerCommandSchedulerJob(scheduler),
901 m_scriptId(scriptId), m_lineNumber(lineNumber),
902 m_messageHandler(messageHandler) {}
903
904 void start()
905 {
906 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
907 frontend.scheduleGetScriptData(id: m_scriptId);
908 }
909 void handleResponse(const QScriptDebuggerResponse &response, int /*commandId*/)
910 {
911 QScriptScriptData data = response.resultAsScriptData();
912 QString line = data.lines(startLineNumber: m_lineNumber, count: 1).value(i: 0);
913 m_messageHandler->message(type: QtDebugMsg, text: QString::fromLatin1(str: "%0\t%1")
914 .arg(a: m_lineNumber).arg(a: line));
915 finish();
916 }
917
918private:
919 qint64 m_scriptId;
920 int m_lineNumber;
921 QScriptMessageHandlerInterface *m_messageHandler;
922};
923
924namespace {
925
926class SyncStackJob : public QScriptDebuggerCommandSchedulerJob
927{
928public:
929 SyncStackJob(QScriptDebuggerPrivate *debugger)
930 : QScriptDebuggerCommandSchedulerJob(debugger),
931 m_debugger(debugger), m_index(0) {}
932 void start()
933 {
934 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
935 frontend.scheduleGetContextInfo(contextIndex: m_index); // ### getContextInfos()
936 }
937 void handleResponse(const QScriptDebuggerResponse &response,
938 int)
939 {
940 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
941 if (response.error() != QScriptDebuggerResponse::InvalidContextIndex) {
942 m_infos.append(t: response.resultAsContextInfo());
943 frontend.scheduleGetContextInfo(contextIndex: ++m_index);
944 } else {
945 m_debugger->stackModel->setContextInfos(m_infos);
946 if (m_debugger->stackWidget->currentFrameIndex() == -1)
947 m_debugger->stackWidget->setCurrentFrameIndex(0);
948 m_debugger->stackWidget->setUpdatesEnabled(true);
949 m_debugger->stackWidget->setEnabled(true);
950 finish();
951 }
952 }
953
954private:
955 QScriptDebuggerPrivate *m_debugger;
956 int m_index;
957 QList<QScriptContextInfo> m_infos;
958};
959
960class SyncScriptsJob : public QScriptDebuggerCommandSchedulerJob
961{
962public:
963 SyncScriptsJob(QScriptDebuggerPrivate *debugger)
964 : QScriptDebuggerCommandSchedulerJob(debugger),
965 m_debugger(debugger), m_index(-1) {}
966
967 void start()
968 {
969 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
970 frontend.scheduleScriptsCheckpoint();
971 }
972 void handleResponse(const QScriptDebuggerResponse &response,
973 int)
974 {
975 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
976 if (m_index == -1) {
977 QScriptScriptsDelta delta;
978 delta = qvariant_cast<QScriptScriptsDelta>(v: response.result());
979
980 const QList<qint64> &removed = delta.second;
981 for (int i = 0; i < removed.size(); ++i)
982 m_debugger->scriptsModel->removeScript(id: removed.at(i));
983
984 m_added = delta.first;
985 if (!m_added.isEmpty()) {
986 frontend.scheduleGetScriptData(id: m_added.at(i: ++m_index));
987 } else {
988 m_debugger->scriptsModel->commit();
989 finish();
990 }
991 } else {
992 QScriptScriptData data = response.resultAsScriptData();
993 qint64 scriptId = m_added.at(i: m_index);
994 m_debugger->scriptsModel->addScript(id: scriptId, data);
995
996 // ### could be slow, might want to do this in a separate thread
997// Q_ASSERT_X(false, Q_FUNC_INFO, "implement me");
998 QString xml; // = qt_scriptToXml(data.contents(), data.baseLineNumber());
999 QScriptXmlParser::Result extraInfo = QScriptXmlParser::parse(xml);
1000 m_debugger->scriptsModel->addExtraScriptInfo(
1001 id: scriptId, functionsInfo: extraInfo.functionsInfo, executableLineNumbers: extraInfo.executableLineNumbers);
1002
1003 if (++m_index < m_added.size())
1004 frontend.scheduleGetScriptData(id: m_added.at(i: m_index));
1005 else {
1006 m_debugger->scriptsModel->commit();
1007 finish();
1008 }
1009 }
1010 }
1011
1012private:
1013 QScriptDebuggerPrivate *m_debugger;
1014 int m_index;
1015 QList<qint64> m_added;
1016};
1017
1018class SyncBreakpointsJob : public QScriptDebuggerCommandSchedulerJob
1019{
1020public:
1021 SyncBreakpointsJob(QScriptDebuggerPrivate *debugger)
1022 : QScriptDebuggerCommandSchedulerJob(debugger),
1023 m_debugger(debugger) {}
1024 void start()
1025 {
1026 QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
1027 frontend.scheduleGetBreakpoints();
1028 }
1029 void handleResponse(const QScriptDebuggerResponse &response,
1030 int)
1031 {
1032 QScriptBreakpointMap breakpoints = response.resultAsBreakpoints();
1033 QScriptBreakpointMap::const_iterator it;
1034 for (it = breakpoints.constBegin(); it != breakpoints.constEnd(); ++it) {
1035 int id = it.key();
1036 QScriptBreakpointData newData = it.value();
1037 QScriptBreakpointData existingData = m_debugger->breakpointsModel->breakpointData(id);
1038 if (existingData.isValid() && (existingData != newData))
1039 m_debugger->breakpointsModel->modifyBreakpoint(id, data: newData);
1040 }
1041 finish();
1042 }
1043
1044private:
1045 QScriptDebuggerPrivate *m_debugger;
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>(v: response.result());
1065 for (int i = 0; i < delta.first.size(); ++i) {
1066 QScriptDebuggerLocalsModel *model = m_debugger->localsModels.take(key: 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(contextIndex: 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(key: contextId);
1094 if (model) {
1095 model->sync(frameIndex: m_frameIndex);
1096 } else {
1097 model = m_debugger->createLocalsModel();
1098 m_debugger->localsModels.insert(key: contextId, value: model);
1099 model->init(frameIndex: 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(id: updatesEnabledTimerId);
1156 updatesEnabledTimerId = -1;
1157 }
1158 console->bumpSessionId();
1159 scheduleJob(job: 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(frameIndex: index);
1214 selectScriptForFrame(frameIndex: index);
1215 } else if (codeWidget && (console->currentFrameIndex() != -1)) {
1216 selectScriptForFrame(frameIndex: 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(contextIndex: 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(contextIndex: 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(lineNumber: 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(sender: d->consoleWidget, signal: 0, receiver: this, member: 0);
1466 }
1467 d->consoleWidget = consoleWidget;
1468 if (consoleWidget) {
1469 consoleWidget->setCommandHistorian(d->console);
1470 consoleWidget->setCompletionProvider(d);
1471 QObject::connect(sender: consoleWidget, SIGNAL(lineEntered(QString)),
1472 receiver: this, SLOT(_q_onLineEntered(QString)));
1473
1474 d->console->showDebuggerInfoMessage(messageHandler: 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(sender: d->stackWidget, signal: 0, receiver: this, member: 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(job: new SyncStackJob(d));
1496 }
1497 stackWidget->setStackModel(d->stackModel);
1498 QObject::connect(sender: stackWidget, SIGNAL(currentFrameChanged(int)),
1499 receiver: 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(sender: d->scriptsWidget, signal: 0, receiver: this, member: 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(job: new SyncScriptsJob(d));
1521 }
1522 scriptsWidget->setScriptsModel(d->scriptsModel);
1523 QObject::connect(sender: scriptsWidget, SIGNAL(currentScriptChanged(qint64)),
1524 receiver: this, SLOT(_q_onCurrentScriptChanged(qint64)));
1525 QObject::connect(sender: d->scriptsWidget, SIGNAL(scriptLocationSelected(int)),
1526 receiver: 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(obj: 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(job: 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(job: new SyncBreakpointsJob(d));
1570 }
1571 codeWidget->setBreakpointsModel(d->breakpointsModel);
1572 codeWidget->setToolTipProvider(d);
1573 codeWidget->installEventFilter(filterObj: 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(sender: d->codeFinderWidget, signal: 0, receiver: this, member: 0);
1595 }
1596 d->codeFinderWidget = codeFinderWidget;
1597 if (codeFinderWidget) {
1598 QObject::connect(sender: codeFinderWidget, SIGNAL(findRequest(QString,int)),
1599 receiver: 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(job: 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(pixmap: d->pixmap(path: QString::fromLatin1(str: "interrupt.png")), mode: QIcon::Normal);
1675 interruptIcon.addPixmap(pixmap: d->pixmap(path: QString::fromLatin1(str: "d_interrupt.png")), mode: QIcon::Disabled);
1676 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1677 that->d_func()->interruptAction = new QAction(interruptIcon, QScriptDebugger::tr(s: "Interrupt"), parent);
1678 d->interruptAction->setEnabled(!d->interactive);
1679#ifndef QT_NO_SHORTCUT
1680 d->interruptAction->setShortcut(QScriptDebugger::tr(s: "Shift+F5"));
1681#endif
1682 QObject::connect(sender: d->interruptAction, SIGNAL(triggered()),
1683 receiver: that, SLOT(_q_interrupt()));
1684 }
1685 return d->interruptAction;
1686}
1687
1688QAction *QScriptDebugger::continueAction(QObject *parent) const
1689{
1690 Q_D(const QScriptDebugger);
1691 if (!d->continueAction) {
1692 QIcon continueIcon;
1693 continueIcon.addPixmap(pixmap: d->pixmap(path: QString::fromLatin1(str: "play.png")), mode: QIcon::Normal);
1694 continueIcon.addPixmap(pixmap: d->pixmap(path: QString::fromLatin1(str: "d_play.png")), mode: QIcon::Disabled);
1695 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1696 that->d_func()->continueAction = new QAction(continueIcon, QScriptDebugger::tr(s: "Continue"), parent);
1697 d->continueAction->setEnabled(d->interactive);
1698#ifndef QT_NO_SHORTCUT
1699 d->continueAction->setShortcut(QScriptDebugger::tr(s: "F5"));
1700#endif
1701 QObject::connect(sender: d->continueAction, SIGNAL(triggered()),
1702 receiver: that, SLOT(_q_continue()));
1703 }
1704 return d->continueAction;
1705}
1706
1707QAction *QScriptDebugger::stepIntoAction(QObject *parent) const
1708{
1709 Q_D(const QScriptDebugger);
1710 if (!d->stepIntoAction) {
1711 QIcon stepIntoIcon;
1712 stepIntoIcon.addPixmap(pixmap: d->pixmap(path: QString::fromLatin1(str: "stepinto.png")), mode: QIcon::Normal);
1713 stepIntoIcon.addPixmap(pixmap: d->pixmap(path: QString::fromLatin1(str: "d_stepinto.png")), mode: QIcon::Disabled);
1714 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1715 that->d_func()->stepIntoAction = new QAction(stepIntoIcon, QScriptDebugger::tr(s: "Step Into"), parent);
1716 d->stepIntoAction->setEnabled(d->interactive);
1717#ifndef QT_NO_SHORTCUT
1718 d->stepIntoAction->setShortcut(QScriptDebugger::tr(s: "F11"));
1719#endif
1720 QObject::connect(sender: d->stepIntoAction, SIGNAL(triggered()),
1721 receiver: that, SLOT(_q_stepInto()));
1722 }
1723 return d->stepIntoAction;
1724}
1725
1726QAction *QScriptDebugger::stepOverAction(QObject *parent) const
1727{
1728 Q_D(const QScriptDebugger);
1729 if (!d->stepOverAction) {
1730 QIcon stepOverIcon;
1731 stepOverIcon.addPixmap(pixmap: d->pixmap(path: QString::fromLatin1(str: "stepover.png")), mode: QIcon::Normal);
1732 stepOverIcon.addPixmap(pixmap: d->pixmap(path: QString::fromLatin1(str: "d_stepover.png")), mode: QIcon::Disabled);
1733 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1734 that->d_func()->stepOverAction = new QAction(stepOverIcon, QScriptDebugger::tr(s: "Step Over"), parent);
1735 d->stepOverAction->setEnabled(d->interactive);
1736#ifndef QT_NO_SHORTCUT
1737 d->stepOverAction->setShortcut(QScriptDebugger::tr(s: "F10"));
1738#endif
1739 QObject::connect(sender: d->stepOverAction, SIGNAL(triggered()),
1740 receiver: that, SLOT(_q_stepOver()));
1741 }
1742 return d->stepOverAction;
1743}
1744
1745QAction *QScriptDebugger::stepOutAction(QObject *parent) const
1746{
1747 Q_D(const QScriptDebugger);
1748 if (!d->stepOutAction) {
1749 QIcon stepOutIcon;
1750 stepOutIcon.addPixmap(pixmap: d->pixmap(path: QString::fromLatin1(str: "stepout.png")), mode: QIcon::Normal);
1751 stepOutIcon.addPixmap(pixmap: d->pixmap(path: QString::fromLatin1(str: "d_stepout.png")), mode: QIcon::Disabled);
1752 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1753 that->d_func()->stepOutAction = new QAction(stepOutIcon, QScriptDebugger::tr(s: "Step Out"), parent);
1754 d->stepOutAction->setEnabled(d->interactive);
1755#ifndef QT_NO_SHORTCUT
1756 d->stepOutAction->setShortcut(QScriptDebugger::tr(s: "Shift+F11"));
1757#endif
1758 QObject::connect(sender: d->stepOutAction, SIGNAL(triggered()),
1759 receiver: that, SLOT(_q_stepOut()));
1760 }
1761 return d->stepOutAction;
1762}
1763
1764QAction *QScriptDebugger::runToCursorAction(QObject *parent) const
1765{
1766 Q_D(const QScriptDebugger);
1767 if (!d->runToCursorAction) {
1768 QIcon runToCursorIcon;
1769 runToCursorIcon.addPixmap(pixmap: d->pixmap(path: QString::fromLatin1(str: "runtocursor.png")), mode: QIcon::Normal);
1770 runToCursorIcon.addPixmap(pixmap: d->pixmap(path: QString::fromLatin1(str: "d_runtocursor.png")), mode: QIcon::Disabled);
1771 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1772 that->d_func()->runToCursorAction = new QAction(runToCursorIcon, QScriptDebugger::tr(s: "Run to Cursor"), parent);
1773 d->runToCursorAction->setEnabled(d->interactive);
1774#ifndef QT_NO_SHORTCUT
1775 d->runToCursorAction->setShortcut(QScriptDebugger::tr(s: "Ctrl+F10"));
1776#endif
1777 QObject::connect(sender: d->runToCursorAction, SIGNAL(triggered()),
1778 receiver: that, SLOT(_q_runToCursor()));
1779 }
1780 return d->runToCursorAction;
1781}
1782
1783QAction *QScriptDebugger::runToNewScriptAction(QObject *parent) const
1784{
1785 Q_D(const QScriptDebugger);
1786 if (!d->runToNewScriptAction) {
1787 QIcon runToNewScriptIcon;
1788 runToNewScriptIcon.addPixmap(pixmap: d->pixmap(path: QString::fromLatin1(str: "runtonewscript.png")), mode: QIcon::Normal);
1789 runToNewScriptIcon.addPixmap(pixmap: d->pixmap(path: QString::fromLatin1(str: "d_breakonscriptload.png")), mode: QIcon::Disabled);
1790 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1791 that->d_func()->runToNewScriptAction = new QAction(runToNewScriptIcon,
1792 QScriptDebugger::tr(s: "Run to New Script"), parent);
1793 d->runToNewScriptAction->setEnabled(d->interactive);
1794 QObject::connect(sender: d->runToNewScriptAction, SIGNAL(triggered()),
1795 receiver: that, SLOT(_q_runToNewScript()));
1796 }
1797 return d->runToNewScriptAction;
1798}
1799
1800QAction *QScriptDebugger::toggleBreakpointAction(QObject *parent) const
1801{
1802 Q_D(const QScriptDebugger);
1803 if (!d->toggleBreakpointAction) {
1804 QIcon toggleBreakpointIcon;
1805 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1806 that->d_func()->toggleBreakpointAction = new QAction(toggleBreakpointIcon,
1807 QScriptDebugger::tr(s: "Toggle Breakpoint"), parent);
1808#ifndef QT_NO_SHORTCUT
1809 d->toggleBreakpointAction->setShortcut(QScriptDebugger::tr(s: "F9"));
1810#endif
1811 d->toggleBreakpointAction->setEnabled((d->codeWidget != 0) && (d->codeWidget->currentView() != 0));
1812 QObject::connect(sender: d->toggleBreakpointAction, SIGNAL(triggered()),
1813 receiver: that, SLOT(_q_toggleBreakpoint()));
1814 }
1815 return d->toggleBreakpointAction;
1816}
1817
1818QAction *QScriptDebugger::clearDebugOutputAction(QObject *parent) const
1819{
1820 Q_D(const QScriptDebugger);
1821 if (!d->clearDebugOutputAction) {
1822 QIcon clearDebugOutputIcon;
1823 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1824 that->d_func()->clearDebugOutputAction = new QAction(clearDebugOutputIcon, QScriptDebugger::tr(s: "Clear Debug Output"), parent);
1825 QObject::connect(sender: d->clearDebugOutputAction, SIGNAL(triggered()),
1826 receiver: that, SLOT(_q_clearDebugOutput()));
1827 }
1828 return d->clearDebugOutputAction;
1829}
1830
1831QAction *QScriptDebugger::clearErrorLogAction(QObject *parent) const
1832{
1833 Q_D(const QScriptDebugger);
1834 if (!d->clearErrorLogAction) {
1835 QIcon clearErrorLogIcon;
1836 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1837 that->d_func()->clearErrorLogAction = new QAction(clearErrorLogIcon, QScriptDebugger::tr(s: "Clear Error Log"), parent);
1838 QObject::connect(sender: d->clearErrorLogAction, SIGNAL(triggered()),
1839 receiver: that, SLOT(_q_clearErrorLog()));
1840 }
1841 return d->clearErrorLogAction;
1842}
1843
1844QAction *QScriptDebugger::clearConsoleAction(QObject *parent) const
1845{
1846 Q_D(const QScriptDebugger);
1847 if (!d->clearConsoleAction) {
1848 QIcon clearConsoleIcon;
1849 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1850 that->d_func()->clearConsoleAction = new QAction(clearConsoleIcon, QScriptDebugger::tr(s: "Clear Console"), parent);
1851 QObject::connect(sender: d->clearConsoleAction, SIGNAL(triggered()),
1852 receiver: that, SLOT(_q_clearConsole()));
1853 }
1854 return d->clearConsoleAction;
1855}
1856
1857QAction *QScriptDebugger::findInScriptAction(QObject *parent) const
1858{
1859 Q_D(const QScriptDebugger);
1860 if (!d->findInScriptAction) {
1861 QIcon findInScriptIcon;
1862 findInScriptIcon.addPixmap(pixmap: d->pixmap(path: QString::fromLatin1(str: "find.png")), mode: QIcon::Normal);
1863 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1864 that->d_func()->findInScriptAction = new QAction(findInScriptIcon, QScriptDebugger::tr(s: "&Find in Script..."), parent);
1865#ifndef QT_NO_SHORTCUT
1866 d->findInScriptAction->setShortcut(QScriptDebugger::tr(s: "Ctrl+F"));
1867#endif
1868 d->findInScriptAction->setEnabled(
1869 (d->codeFinderWidget != 0)
1870 && (d->codeWidget != 0)
1871 && (d->codeWidget->currentView() != 0));
1872 QObject::connect(sender: d->findInScriptAction, SIGNAL(triggered()),
1873 receiver: that, SLOT(_q_findInScript()));
1874 }
1875 return d->findInScriptAction;
1876}
1877
1878QAction *QScriptDebugger::findNextInScriptAction(QObject *parent) const
1879{
1880 Q_D(const QScriptDebugger);
1881 if (!d->findNextInScriptAction) {
1882 QIcon findNextInScriptIcon;
1883 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1884 that->d_func()->findNextInScriptAction = new QAction(findNextInScriptIcon, QScriptDebugger::tr(s: "Find &Next"), parent);
1885 d->findNextInScriptAction->setEnabled(d->codeFinderWidget && !d->codeFinderWidget->text().isEmpty());
1886#ifndef QT_NO_SHORTCUT
1887 d->findNextInScriptAction->setShortcut(QScriptDebugger::tr(s: "F3"));
1888#endif
1889 QObject::connect(sender: d->findNextInScriptAction, SIGNAL(triggered()),
1890 receiver: that, SLOT(_q_findNextInScript()));
1891 }
1892 return d->findNextInScriptAction;
1893}
1894
1895QAction *QScriptDebugger::findPreviousInScriptAction(QObject *parent) const
1896{
1897 Q_D(const QScriptDebugger);
1898 if (!d->findPreviousInScriptAction) {
1899 QIcon findPreviousInScriptIcon;
1900 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1901 that->d_func()->findPreviousInScriptAction = new QAction(findPreviousInScriptIcon, QScriptDebugger::tr(s: "Find &Previous"), parent);
1902 d->findPreviousInScriptAction->setEnabled(d->codeFinderWidget && !d->codeFinderWidget->text().isEmpty());
1903#ifndef QT_NO_SHORTCUT
1904 d->findPreviousInScriptAction->setShortcut(QScriptDebugger::tr(s: "Shift+F3"));
1905#endif
1906 QObject::connect(sender: d->findPreviousInScriptAction, SIGNAL(triggered()),
1907 receiver: that, SLOT(_q_findPreviousInScript()));
1908 }
1909 return d->findPreviousInScriptAction;
1910}
1911
1912QAction *QScriptDebugger::goToLineAction(QObject *parent) const
1913{
1914 Q_D(const QScriptDebugger);
1915 if (!d->goToLineAction) {
1916 QIcon goToLineIcon;
1917 QScriptDebugger *that = const_cast<QScriptDebugger*>(this);
1918 that->d_func()->goToLineAction = new QAction(goToLineIcon, QScriptDebugger::tr(s: "Go to Line"), parent);
1919#ifndef QT_NO_SHORTCUT
1920 d->goToLineAction->setShortcut(QScriptDebugger::tr(s: "Ctrl+G"));
1921#endif
1922 d->goToLineAction->setEnabled((d->codeWidget != 0) && (d->codeWidget->currentView() != 0));
1923 QObject::connect(sender: d->goToLineAction, SIGNAL(triggered()),
1924 receiver: that, SLOT(_q_goToLine()));
1925 }
1926 return d->goToLineAction;
1927}
1928
1929QMenu *QScriptDebugger::createStandardMenu(QWidget *widgetParent, QObject *actionParent)
1930{
1931 QMenu *menu = new QMenu(widgetParent);
1932 menu->setTitle(QScriptDebugger::tr(s: "Debug"));
1933 menu->addAction(action: action(action: ContinueAction, parent: actionParent));
1934 menu->addAction(action: action(action: InterruptAction, parent: actionParent));
1935 menu->addAction(action: action(action: StepIntoAction, parent: actionParent));
1936 menu->addAction(action: action(action: StepOverAction, parent: actionParent));
1937 menu->addAction(action: action(action: StepOutAction, parent: actionParent));
1938 menu->addAction(action: action(action: RunToCursorAction, parent: actionParent));
1939 menu->addAction(action: action(action: RunToNewScriptAction, parent: actionParent));
1940
1941 menu->addSeparator();
1942 menu->addAction(action: action(action: ToggleBreakpointAction, parent: actionParent));
1943
1944 menu->addSeparator();
1945 menu->addAction(action: action(action: ClearDebugOutputAction, parent: actionParent));
1946 menu->addAction(action: action(action: ClearErrorLogAction, parent: actionParent));
1947 menu->addAction(action: action(action: ClearConsoleAction, parent: actionParent));
1948
1949 return menu;
1950}
1951
1952#ifndef QT_NO_TOOLBAR
1953QToolBar *QScriptDebugger::createStandardToolBar(QWidget *widgetParent, QObject *actionParent)
1954{
1955 QToolBar *tb = new QToolBar(widgetParent);
1956 tb->setObjectName(QLatin1String("qtscriptdebugger_standardToolBar"));
1957 tb->addAction(action: action(action: ContinueAction, parent: actionParent));
1958 tb->addAction(action: action(action: InterruptAction, parent: actionParent));
1959 tb->addAction(action: action(action: StepIntoAction, parent: actionParent));
1960 tb->addAction(action: action(action: StepOverAction, parent: actionParent));
1961 tb->addAction(action: action(action: StepOutAction, parent: actionParent));
1962 tb->addAction(action: action(action: RunToCursorAction, parent: actionParent));
1963 tb->addAction(action: action(action: RunToNewScriptAction, parent: actionParent));
1964 tb->addSeparator();
1965 tb->addAction(action: action(action: FindInScriptAction, parent: actionParent));
1966 return tb;
1967}
1968#endif
1969
1970bool QScriptDebugger::isInteractive() const
1971{
1972 Q_D(const QScriptDebugger);
1973 return d->interactive;
1974}
1975
1976/*!
1977 \reimp
1978*/
1979bool QScriptDebugger::eventFilter(QObject *watched, QEvent *e)
1980{
1981 Q_D(QScriptDebugger);
1982 if (watched == d->codeWidget) {
1983 if (e->type() == QEvent::KeyPress) {
1984 d->_q_findInScript();
1985 d->codeFinderWidget->setText(static_cast<QKeyEvent*>(e)->text());
1986 return true;
1987 }
1988 }
1989 return false;
1990}
1991
1992/*!
1993 \reimp
1994*/
1995void QScriptDebugger::timerEvent(QTimerEvent *e)
1996{
1997 Q_D(QScriptDebugger);
1998 if (e->timerId() == d->updatesEnabledTimerId) {
1999 killTimer(id: d->updatesEnabledTimerId);
2000 d->updatesEnabledTimerId = -1;
2001 if (d->stackWidget)
2002 d->stackWidget->setUpdatesEnabled(true);
2003 if (d->localsWidget)
2004 d->localsWidget->setUpdatesEnabled(true);
2005 } else {
2006 QObject::timerEvent(event: e);
2007 }
2008}
2009
2010QT_END_NAMESPACE
2011
2012#include "moc_qscriptdebugger_p.cpp"
2013

source code of qtscript/src/scripttools/debugging/qscriptdebugger.cpp