debuggerrunner.cpp 23.4 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2 3 4
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
con's avatar
con committed
8
**
9
** Commercial Usage
10
**
11 12 13 14
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
15
**
16
** GNU Lesser General Public License Usage
17
**
18 19 20 21 22 23
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24
**
25
** If you are unsure which license is appropriate for your use, please
hjk's avatar
hjk committed
26
** contact the sales department at http://qt.nokia.com/contact.
con's avatar
con committed
27
**
28
**************************************************************************/
hjk's avatar
hjk committed
29

con's avatar
con committed
30 31
#include "debuggerrunner.h"

32 33 34 35 36
#include "debuggeractions.h"
#include "debuggerconstants.h"
#include "debuggerengine.h"
#include "debuggerplugin.h"
#include "debuggerstringutils.h"
37
#include "debuggeruiswitcher.h"
38 39 40
#include "gdb/gdbengine.h"
#include "gdb/remotegdbserveradapter.h"
#include "gdb/remoteplaingdbadapter.h"
41
#include "qml/qmlengine.h"
42
#include "qml/qmlcppengine.h"
43

Friedemann Kleint's avatar
Friedemann Kleint committed
44 45 46 47
#ifdef Q_OS_WIN
#  include "peutils.h"
#endif

hjk's avatar
hjk committed
48
#include <projectexplorer/debugginghelper.h>
con's avatar
con committed
49
#include <projectexplorer/project.h>
50
#include <projectexplorer/projectexplorer.h>
con's avatar
con committed
51
#include <projectexplorer/projectexplorerconstants.h>
Tobias Hunger's avatar
Tobias Hunger committed
52
#include <projectexplorer/target.h>
53
#include <projectexplorer/buildconfiguration.h>
54
#include <projectexplorer/applicationrunconfiguration.h> // For LocalApplication*
con's avatar
con committed
55

56
#include <utils/environment.h>
hjk's avatar
hjk committed
57
#include <utils/qtcassert.h>
58
#include <utils/fancymainwindow.h>
59
#include <coreplugin/icore.h>
hjk's avatar
hjk committed
60

con's avatar
con committed
61 62 63
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
64
#include <QtCore/QTimer>
Friedemann Kleint's avatar
Friedemann Kleint committed
65
#include <QtCore/QStringList>
hjk's avatar
hjk committed
66

67
#include <QtGui/QAbstractItemView>
68
#include <QtGui/QTextDocument>
69
#include <QtGui/QTreeWidget>
70
#include <QtGui/QMessageBox>
con's avatar
con committed
71

72
using namespace ProjectExplorer;
73 74
using namespace Debugger::Internal;

75 76 77 78 79 80 81 82
namespace Debugger {
namespace Internal {

DebuggerEngine *createGdbEngine(const DebuggerStartParameters &);
DebuggerEngine *createScriptEngine(const DebuggerStartParameters &);
DebuggerEngine *createPdbEngine(const DebuggerStartParameters &);
DebuggerEngine *createTcfEngine(const DebuggerStartParameters &);
DebuggerEngine *createQmlEngine(const DebuggerStartParameters &);
83
DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &);
84

hjk's avatar
hjk committed
85
bool checkGdbConfiguration(int toolChain, QString *errorMsg, QString *settingsPage);
86 87 88 89 90 91 92

// FIXME: Outdated?
// The createCdbEngine function takes a list of options pages it can add to.
// This allows for having a "enabled" toggle on the page independently
// of the engine. That's good for not enabling the related ActiveX control
// unnecessarily.

hjk's avatar
hjk committed
93 94
#ifdef CDB_ENABLED
DebuggerEngine *createCdbEngine(const DebuggerStartParameters &);
95
bool checkCdbConfiguration(int toolChain, QString *errorMsg, QString *settingsPage);
hjk's avatar
hjk committed
96 97 98 99
#else
DebuggerEngine *createCdbEngine(const DebuggerStartParameters &) { return 0; }
bool checkCdbConfiguration(int, QString *, QString *) { return false; }
#endif
100

hjk's avatar
hjk committed
101
} // namespace Internal
102 103 104 105 106 107

static QString toolChainName(int toolChainType)
{
    return ToolChain::toolChainName(ToolChain::ToolChainType(toolChainType));
}

108

con's avatar
con committed
109 110
////////////////////////////////////////////////////////////////////////
//
111
// DebuggerRunControlFactory
con's avatar
con committed
112 113 114
//
////////////////////////////////////////////////////////////////////////

115 116 117 118 119 120 121
static QString msgEngineNotAvailable(const char *engine)
{
    return DebuggerPlugin::tr("The application requires the debugger engine '%1', "
        "which is disabled.").arg(QLatin1String(engine));
}

static DebuggerPlugin *plugin() { return DebuggerPlugin::instance(); }
122

123
// A factory to create DebuggerRunControls
124 125 126
DebuggerRunControlFactory::DebuggerRunControlFactory(QObject *parent,
        DebuggerEngineType enabledEngines)
    : IRunControlFactory(parent), m_enabledEngines(enabledEngines)
con's avatar
con committed
127 128
{}

129
bool DebuggerRunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const
con's avatar
con committed
130
{
131
//    return mode == ProjectExplorer::Constants::DEBUGMODE;
132
    return mode == ProjectExplorer::Constants::DEBUGMODE
133
            && qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
con's avatar
con committed
134 135
}

136
QString DebuggerRunControlFactory::displayName() const
con's avatar
con committed
137
{
Oswald Buddenhagen's avatar
Oswald Buddenhagen committed
138
    return tr("Debug");
con's avatar
con committed
139 140
}

141
static DebuggerStartParameters localStartParameters(RunConfiguration *runConfiguration)
142
{
143
    DebuggerStartParameters sp;
144 145 146 147 148
    QTC_ASSERT(runConfiguration, return sp);
    LocalApplicationRunConfiguration *rc =
            qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
    QTC_ASSERT(rc, return sp);

149 150
    sp.startMode = StartInternal;
    sp.environment = rc->environment().toStringList();
151 152 153
    sp.workingDirectory = rc->workingDirectory();
    sp.executable = rc->executable();
    sp.processArgs = rc->commandLineArguments();
154 155 156 157
    sp.toolChainType = rc->toolChainType();
    sp.useTerminal = rc->runMode() == LocalApplicationRunConfiguration::Console;
    sp.dumperLibrary = rc->dumperLibrary();
    sp.dumperLibraryLocations = rc->dumperLibraryLocations();
158

159 160
    DebuggerLanguages activeLangs = DebuggerUISwitcher::instance()->activeDebugLanguages();
    if (activeLangs & QmlLanguage) {
161
        sp.qmlServerAddress = QLatin1String("127.0.0.1");
162
        sp.qmlServerPort = runConfiguration->qmlDebugServerPort();
163

164 165 166 167
        sp.projectDir = runConfiguration->target()->project()->projectDirectory();
        if (runConfiguration->target()->activeBuildConfiguration())
            sp.projectBuildDir = runConfiguration->target()->activeBuildConfiguration()->buildDirectory();

168
        sp.processArgs.append(QLatin1String("-qmljsdebugger=port:") + QString::number(sp.qmlServerPort));
169 170
    }

171 172 173 174
    // FIXME: If it's not yet build this will be empty and not filled
    // when rebuild as the runConfiguration is not stored and therefore
    // cannot be used to retrieve the dumper location.
    //qDebug() << "DUMPER: " << sp.dumperLibrary << sp.dumperLibraryLocations;
175
    sp.displayName = rc->displayName();
176

177 178
    // Find qtInstallPath.
    QString qmakePath = DebuggingHelperLibrary::findSystemQt(rc->environment());
179 180 181 182 183 184 185 186 187
    if (!qmakePath.isEmpty()) {
        QProcess proc;
        QStringList args;
        args.append(QLatin1String("-query"));
        args.append(QLatin1String("QT_INSTALL_HEADERS"));
        proc.start(qmakePath, args);
        proc.waitForFinished();
        QByteArray ba = proc.readAllStandardOutput().trimmed();
        QFileInfo fi(QString::fromLocal8Bit(ba) + "/..");
188
        sp.qtInstallPath = fi.absoluteFilePath();
189 190
    }
    return sp;
191 192
}

193 194
RunControl *DebuggerRunControlFactory::create
    (RunConfiguration *runConfiguration, const QString &mode)
con's avatar
con committed
195
{
hjk's avatar
hjk committed
196
    QTC_ASSERT(mode == ProjectExplorer::Constants::DEBUGMODE, return 0);
197
    DebuggerStartParameters sp = localStartParameters(runConfiguration);
198
    return create(sp, runConfiguration);
199 200
}

201 202
DebuggerRunControl *DebuggerRunControlFactory::create(
    const DebuggerStartParameters &sp,
203
    RunConfiguration *runConfiguration)
204
{
205 206
    DebuggerRunControl *runControl =
        new DebuggerRunControl(runConfiguration, m_enabledEngines, sp);
207 208 209 210 211 212
    if (!runControl->engine()) {
        qDebug() << "FAILED TO CREATE ENGINE";
        delete runControl;
        return 0;
    }
    return runControl;
con's avatar
con committed
213 214
}

215 216
QWidget *DebuggerRunControlFactory::createConfigurationWidget
    (RunConfiguration *runConfiguration)
con's avatar
con committed
217 218
{
    // NBS TODO: Add GDB-specific configuration widget
219
    Q_UNUSED(runConfiguration)
con's avatar
con committed
220 221 222 223
    return 0;
}


224 225
////////////////////////////////////////////////////////////////////////
//
226
// DebuggerRunControl
227 228 229
//
////////////////////////////////////////////////////////////////////////

230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
struct DebuggerRunnerPrivate {
    explicit DebuggerRunnerPrivate(RunConfiguration *runConfiguration,
                                   DebuggerEngineType enabledEngines);

    DebuggerEngine *m_engine;
    const QWeakPointer<RunConfiguration> m_myRunConfiguration;
    bool m_running;
    bool m_started;
    const DebuggerEngineType m_enabledEngines;
    QString m_errorMessage;
    QString m_settingsIdHint;
};

DebuggerRunnerPrivate::DebuggerRunnerPrivate(RunConfiguration *runConfiguration,
                                             DebuggerEngineType enabledEngines) :
      m_myRunConfiguration(runConfiguration)
246 247
    , m_running(false)
    , m_started(false)
248
    , m_enabledEngines(enabledEngines)
249 250
{
}
251

252 253 254 255
DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration,
        DebuggerEngineType enabledEngines, const DebuggerStartParameters &sp)
    : RunControl(runConfiguration, ProjectExplorer::Constants::DEBUGMODE),
      d(new DebuggerRunnerPrivate(runConfiguration, enabledEngines))
256
{
Friedemann Kleint's avatar
Friedemann Kleint committed
257
    connect(this, SIGNAL(finished()), this, SLOT(handleFinished()));
258 259
    DebuggerStartParameters startParams = sp;
    createEngine(startParams);
260 261
}

262 263 264
DebuggerRunControl::~DebuggerRunControl()
{
    disconnect();
265 266
    DebuggerEngine *engine = d->m_engine;
    d->m_engine = 0;
267 268 269 270
    engine->disconnect();
    delete engine;
}

271 272
const DebuggerStartParameters &DebuggerRunControl::startParameters() const
{
273 274
    QTC_ASSERT(d->m_engine, return *(new DebuggerStartParameters()));
    return d->m_engine->startParameters();
275 276
}

277 278 279 280 281 282 283 284 285 286 287 288
static DebuggerEngineType engineForToolChain(int toolChainType)
{
    switch (toolChainType) {
        case ProjectExplorer::ToolChain::LINUX_ICC:
        case ProjectExplorer::ToolChain::MinGW:
        case ProjectExplorer::ToolChain::GCC:
        case ProjectExplorer::ToolChain::WINSCW: // S60
        case ProjectExplorer::ToolChain::GCCE:
        case ProjectExplorer::ToolChain::RVCT_ARMV5:
        case ProjectExplorer::ToolChain::RVCT_ARMV6:
        case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC:
        case ProjectExplorer::ToolChain::GCCE_GNUPOC:
289
        case ProjectExplorer::ToolChain::GCC_MAEMO:
290 291 292 293 294 295 296 297 298 299 300 301 302
            return GdbEngineType;

        case ProjectExplorer::ToolChain::MSVC:
        case ProjectExplorer::ToolChain::WINCE:
            return CdbEngineType;

        case ProjectExplorer::ToolChain::OTHER:
        case ProjectExplorer::ToolChain::UNKNOWN:
        case ProjectExplorer::ToolChain::INVALID:
        default:
            break;
    }
    return NoEngineType;
303 304
}

305 306 307 308

// Figure out the debugger type of an executable. Analyze executable
// unless the toolchain provides a hint.
DebuggerEngineType DebuggerRunControl::engineForExecutable(const QString &executable)
309
{
310
    /*if (executable.endsWith(_("qmlviewer"))) {
311
        if (d->m_enabledEngines & QmlEngineType)
312
            return QmlEngineType;
313
        d->m_errorMessage = msgEngineNotAvailable("Qml Engine");
314
    }*/
315

316
    if (executable.endsWith(_(".js"))) {
317
        if (d->m_enabledEngines & ScriptEngineType)
318
            return ScriptEngineType;
319
        d->m_errorMessage = msgEngineNotAvailable("Script Engine");
320
    }
con's avatar
con committed
321

322
    if (executable.endsWith(_(".py"))) {
323
        if (d->m_enabledEngines & PdbEngineType)
324
            return PdbEngineType;
325
        d->m_errorMessage = msgEngineNotAvailable("Pdb Engine");
326
    }
con's avatar
con committed
327

328 329 330
#ifdef Q_OS_WIN
    // A remote executable?
    if (!executable.endsWith(_(".exe")))
Friedemann Kleint's avatar
Friedemann Kleint committed
331
        return GdbEngineType;
332 333 334

    // If a file has PDB files, it has been compiled by VS.
    QStringList pdbFiles;
335
    if (!getPDBFiles(executable, &pdbFiles, &d->m_errorMessage)) {
336
        qWarning("Cannot determine type of executable %s: %s",
337
                 qPrintable(executable), qPrintable(d->m_errorMessage));
Friedemann Kleint's avatar
Friedemann Kleint committed
338
        return NoEngineType;
339 340 341
    }
    if (pdbFiles.empty())
        return GdbEngineType;
342

343 344
    // We need the CDB debugger in order to be able to debug VS
    // executables
345
    if (checkDebugConfiguration(ToolChain::MSVC, &d->m_errorMessage, 0, &d->m_settingsIdHint))
346 347
        return CdbEngineType;
#else
348
    if (d->m_enabledEngines & GdbEngineType)
349
        return GdbEngineType;
350
    d->m_errorMessage = msgEngineNotAvailable("Gdb Engine");
351
#endif
352

353
    return NoEngineType;
354 355
}

356 357
// Debugger type for mode.
DebuggerEngineType DebuggerRunControl::engineForMode(DebuggerStartMode startMode)
358
{
359 360
    if (startMode == AttachTcf)
        return TcfEngineType;
361

362 363
#ifdef Q_OS_WIN
    // Preferably Windows debugger for attaching locally.
Friedemann Kleint's avatar
Friedemann Kleint committed
364
    if (startMode != AttachToRemote)
365
        return CdbEngineType;
Friedemann Kleint's avatar
Friedemann Kleint committed
366
    return GdbEngineType;
367
    d->m_errorMessage = msgEngineNotAvailable("Gdb Engine");
368 369 370
    return NoEngineType;
#else
    Q_UNUSED(startMode)
371
    //  d->m_errorMessage = msgEngineNotAvailable("Gdb Engine");
372 373
    return GdbEngineType;
#endif
374 375
}

376
void DebuggerRunControl::createEngine(const DebuggerStartParameters &startParams)
377
{
378 379
    DebuggerStartParameters sp = startParams;

380 381
    // Figure out engine according to toolchain, executable, attach or default.
    DebuggerEngineType engineType = NoEngineType;
382
    DebuggerLanguages activeLangs = DebuggerPlugin::instance()->activeLanguages();
383
    if (sp.executable.endsWith(_(".js")))
384 385 386 387 388 389
        engineType = ScriptEngineType;
    else if (sp.executable.endsWith(_(".py")))
        engineType = PdbEngineType;
    else
        engineType = engineForToolChain(sp.toolChainType);

390 391 392 393
    // Fixme: 1 of 3 testing hacks.
    if (sp.processArgs.size() >= 5 && sp.processArgs.at(0) == _("@tcf@"))
        engineType = GdbEngineType;

394 395 396 397 398 399 400 401
    if (engineType == NoEngineType
            && sp.startMode != AttachToRemote
            && !sp.executable.isEmpty())
        engineType = engineForExecutable(sp.executable);

    if (!engineType)
        engineType = engineForMode(sp.startMode);

402
    if (engineType != QmlEngineType && (activeLangs & QmlLanguage)) {
403
        if (activeLangs & CppLanguage) {
404 405 406 407 408 409 410
            sp.cppEngineType = engineType;
            engineType = QmlCppEngineType;
        } else {
            engineType = QmlEngineType;
        }
    }

Friedemann Kleint's avatar
Friedemann Kleint committed
411
    // qDebug() << "USING ENGINE : " << engineType;
412 413 414

    switch (engineType) {
        case GdbEngineType:
415 416
            d->m_engine = createGdbEngine(sp);
            initGdbEngine(qobject_cast<Internal::GdbEngine *>(d->m_engine));
417
            break;
418
        case ScriptEngineType:
419
            d->m_engine = Internal::createScriptEngine(sp);
420
            break;
421
        case CdbEngineType:
422
            d->m_engine = Internal::createCdbEngine(sp);
423
            break;
424
        case PdbEngineType:
425
            d->m_engine = Internal::createPdbEngine(sp);
426
            break;
427
        case TcfEngineType:
428
            d->m_engine = Internal::createTcfEngine(sp);
429
            break;
430
        case QmlEngineType:
431
            d->m_engine = Internal::createQmlEngine(sp);
432 433 434
            connect(qobject_cast<QmlEngine *>(d->m_engine),
                SIGNAL(remoteStartupRequested()), this,
                SIGNAL(engineRequestSetup()));
435
            break;
436
        case QmlCppEngineType:
437
            d->m_engine = Internal::createQmlCppEngine(sp);
438 439
            if (Internal::GdbEngine *embeddedGdbEngine = gdbEngine())
                initGdbEngine(embeddedGdbEngine);
440
            break;
441 442
        default: {
            // Could not find anything suitable.
443
            debuggingFinished();
444 445
            // Create Message box with possibility to go to settings
            const QString msg = tr("Cannot debug '%1' (tool chain: '%2'): %3")
446
                .arg(sp.executable, toolChainName(sp.toolChainType), d->m_errorMessage);
447 448
            Core::ICore::instance()->showWarningWithOptions(tr("Warning"),
                msg, QString(), QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY),
449
                d->m_settingsIdHint);
450
            break;
451
        }
452
    }
453 454
}

455 456 457 458 459 460 461 462
void DebuggerRunControl::initGdbEngine(Internal::GdbEngine *engine)
{
    QTC_ASSERT(engine, return)

    // Forward adapter signals.
    Internal::AbstractGdbAdapter *adapter = engine->gdbAdapter();
    if (RemotePlainGdbAdapter *rpga = qobject_cast<RemotePlainGdbAdapter *>(adapter)) {
        connect(rpga, SIGNAL(requestSetup()), this,
463
                SIGNAL(engineRequestSetup()));
464 465
    } else if (RemoteGdbServerAdapter *rgsa = qobject_cast<RemoteGdbServerAdapter *>(adapter)) {
        connect(rgsa, SIGNAL(requestSetup()),
466
                this, SIGNAL(engineRequestSetup()));
467 468 469
    }
}

470
QString DebuggerRunControl::displayName() const
471
{
472 473
    QTC_ASSERT(d->m_engine, return QString());
    return d->m_engine->startParameters().displayName;
474 475
}

476
void DebuggerRunControl::setCustomEnvironment(Utils::Environment env)
477
{
478
    d->m_engine->startParameters().environment = env.toStringList();
479 480
}

481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
bool DebuggerRunControl::checkDebugConfiguration(int toolChain,
                                              QString *errorMessage,
                                              QString *settingsCategory /* = 0 */,
                                              QString *settingsPage /* = 0 */)
{
    errorMessage->clear();
    if (settingsCategory)
        settingsCategory->clear();
    if (settingsPage)
        settingsPage->clear();

    bool success = true;

    switch(toolChain) {
    case ProjectExplorer::ToolChain::GCC:
    case ProjectExplorer::ToolChain::LINUX_ICC:
    case ProjectExplorer::ToolChain::MinGW:
    case ProjectExplorer::ToolChain::WINCE: // S60
    case ProjectExplorer::ToolChain::WINSCW:
    case ProjectExplorer::ToolChain::GCCE:
    case ProjectExplorer::ToolChain::RVCT_ARMV5:
    case ProjectExplorer::ToolChain::RVCT_ARMV6:
        success = checkGdbConfiguration(toolChain, errorMessage, settingsPage);
        if (!success)
505
            *errorMessage += msgEngineNotAvailable("Gdb");
506 507 508 509
        break;
    case ProjectExplorer::ToolChain::MSVC:
        success = checkCdbConfiguration(toolChain, errorMessage, settingsPage);
        if (!success) {
510
            *errorMessage += msgEngineNotAvailable("Cdb");
511 512 513 514 515 516 517
            if (settingsPage)
                *settingsPage = QLatin1String("Cdb");
        }
        break;
    }
    if (!success && settingsCategory && settingsPage && !settingsPage->isEmpty())
        *settingsCategory = QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY);
hjk's avatar
hjk committed
518

519
    return success;
520 521
}

522
void DebuggerRunControl::start()
523
{
524 525
    QTC_ASSERT(d->m_engine, return);
    const DebuggerStartParameters &sp = d->m_engine->startParameters();
526

527 528 529
    QString errorMessage;
    QString settingsCategory;
    QString settingsPage;
530

531 532 533 534 535 536
    if (!checkDebugConfiguration(sp.toolChainType,
            &errorMessage, &settingsCategory, &settingsPage)) {
        emit appendMessage(this, errorMessage, true);
        emit finished();
        Core::ICore::instance()->showWarningWithOptions(tr("Debugger"),
            errorMessage, QString(), settingsCategory, settingsPage);
537
        return;
538
    }
539

540
    plugin()->activateDebugMode();
541
    DebuggerUISwitcher::instance()->aboutToStartDebugger();
Friedemann Kleint's avatar
Friedemann Kleint committed
542 543

    const QString message = tr("Starting debugger '%1' for tool chain '%2'...").
544
                  arg(d->m_engine->objectName(), toolChainName(sp.toolChainType));
Friedemann Kleint's avatar
Friedemann Kleint committed
545
    plugin()->showMessage(message, StatusBar);
546
    plugin()->showMessage(DebuggerSettings::instance()->dump(), LogDebug);
Friedemann Kleint's avatar
Friedemann Kleint committed
547
    plugin()->runControlStarted(this);
548

549
    engine()->startDebugger(this);
550
    d->m_running = true;
551 552
    emit addToOutputWindowInline(this, tr("Debugging starts"), false);
    emit addToOutputWindowInline(this, "\n", false);
553
    emit started();
554 555
}

556
void DebuggerRunControl::startFailed()
557
{
558
    emit addToOutputWindowInline(this, tr("Debugging has failed"), false);
559
    d->m_running = false;
560
    emit finished();
561
    engine()->handleStartFailed();
562 563
}

564
void DebuggerRunControl::handleFinished()
565
{
566
    emit addToOutputWindowInline(this, tr("Debugging has finished"), false);
567
    engine()->handleFinished();
568
    plugin()->runControlFinished(this);
569 570
}

571
void DebuggerRunControl::showMessage(const QString &msg, int channel)
572
{
573 574 575 576 577 578 579 580 581 582 583
    switch (channel) {
        case AppOutput:
            emit addToOutputWindowInline(this, msg, false);
            break;
        case AppError:
            emit addToOutputWindowInline(this, msg, true);
            break;
        case AppStuff:
            emit appendMessage(this, msg, true);
            break;
    }
584 585
}

586
bool DebuggerRunControl::aboutToStop() const
587
{
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603
    QTC_ASSERT(isRunning(), return true;)

    const QString question = tr("A debugging session are still in progress. "
            "Terminating the session in the current"
            " state can leave the target in an inconsistent state."
            " Would you still like to terminate it?");

    const QMessageBox::StandardButton answer =
            QMessageBox::question(DebuggerUISwitcher::instance()->mainWindow(),
                                  tr("Close Debugging Session"), question,
                                  QMessageBox::Yes|QMessageBox::No);
    return answer == QMessageBox::Yes;
}

RunControl::StopResult DebuggerRunControl::stop()
{
604 605
    QTC_ASSERT(d->m_engine, return StoppedSynchronously);
    d->m_engine->quitDebugger();
606
    return AsynchronousStop;
607 608
}

609
void DebuggerRunControl::debuggingFinished()
610
{
611
    d->m_running = false;
612
    emit finished();
613 614
}

615
bool DebuggerRunControl::isRunning() const
616
{
617
    return d->m_running;
618 619
}

Friedemann Kleint's avatar
Friedemann Kleint committed
620 621
DebuggerState DebuggerRunControl::state() const
{
622 623
    QTC_ASSERT(d->m_engine, return DebuggerNotReady);
    return d->m_engine->state();
Friedemann Kleint's avatar
Friedemann Kleint committed
624 625
}

626
DebuggerEngine *DebuggerRunControl::engine()
627
{
628 629
    QTC_ASSERT(d->m_engine, /**/);
    return d->m_engine;
630 631
}

632 633
Internal::GdbEngine *DebuggerRunControl::gdbEngine() const
{
634 635
    QTC_ASSERT(d->m_engine, return 0);
    if (GdbEngine *gdbEngine = qobject_cast<GdbEngine *>(d->m_engine))
636
        return gdbEngine;
637
    if (QmlCppEngine * const qmlEngine = qobject_cast<QmlCppEngine *>(d->m_engine))
638
        if (Internal::GdbEngine *embeddedGdbEngine = qobject_cast<GdbEngine *>(qmlEngine->cppEngine()))
639 640 641 642 643 644 645 646 647 648 649
            return embeddedGdbEngine;
    return 0;
}

Internal::AbstractGdbAdapter *DebuggerRunControl::gdbAdapter() const
{
    GdbEngine *engine = gdbEngine();
    QTC_ASSERT(engine, return 0)
    return engine->gdbAdapter();
}

650
void DebuggerRunControl::handleRemoteSetupDone()
651
{
652 653 654 655 656 657 658 659 660 661
    if (QmlEngine *qmlEngine = qobject_cast<QmlEngine *>(d->m_engine)) {
        qmlEngine->handleRemoteSetupDone();
    } else if (Internal::AbstractGdbAdapter *adapter = gdbAdapter()) {
        if (RemotePlainGdbAdapter *rpga = qobject_cast<RemotePlainGdbAdapter *>(adapter)) {
            rpga->handleSetupDone();
        } else if (RemoteGdbServerAdapter *rgsa = qobject_cast<RemoteGdbServerAdapter *>(adapter)) {
            rgsa->handleSetupDone();
        } else {
            QTC_ASSERT(false, /* */ );
        }
662 663 664 665 666
    } else {
        QTC_ASSERT(false, /* */ );
    }
}

667
void DebuggerRunControl::handleRemoteSetupFailed(const QString &message)
668
{
669 670 671 672 673 674 675 676 677 678
    if (QmlEngine *qmlEngine = qobject_cast<QmlEngine *>(d->m_engine)) {
        qmlEngine->handleRemoteSetupFailed(message);
    } else if (Internal::AbstractGdbAdapter *adapter = gdbAdapter()) {
        if (RemotePlainGdbAdapter *rpga = qobject_cast<RemotePlainGdbAdapter *>(adapter)) {
            rpga->handleSetupFailed(message);
        } else if (RemoteGdbServerAdapter *rgsa = qobject_cast<RemoteGdbServerAdapter *>(adapter)) {
            rgsa->handleSetupFailed(message);
        } else {
            QTC_ASSERT(false, /* */ );
        }
679 680 681 682
    } else {
        QTC_ASSERT(false, /* */ );
    }
}
683 684 685 686 687 688 689 690 691 692

void DebuggerRunControl::emitAddToOutputWindow(const QString &line, bool onStdErr)
{
    emit addToOutputWindow(this, line, onStdErr);
}

void DebuggerRunControl::emitAppendMessage(const QString &m, bool isError)
{
    emit appendMessage(this, m, isError);
}
693 694 695 696 697

RunConfiguration *DebuggerRunControl::runConfiguration() const
{
    return d->m_myRunConfiguration.data();
}
hjk's avatar
hjk committed
698
} // namespace Debugger