debuggerrunner.cpp 23.8 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 50
#include <projectexplorer/environment.h>
#include <projectexplorer/project.h>
51
#include <projectexplorer/projectexplorer.h>
con's avatar
con committed
52
#include <projectexplorer/projectexplorerconstants.h>
Tobias Hunger's avatar
Tobias Hunger committed
53
#include <projectexplorer/target.h>
54
#include <projectexplorer/buildconfiguration.h>
55
#include <projectexplorer/applicationrunconfiguration.h> // For LocalApplication*
con's avatar
con committed
56

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 151 152 153 154 155 156 157
    sp.startMode = StartInternal;
    sp.executable = rc->executable();
    sp.environment = rc->environment().toStringList();
    sp.workingDirectory = rc->workingDirectory();
    sp.processArgs = rc->commandLineArguments();
    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 169 170 171
        sp.environment << QString(Constants::E_QML_DEBUG_SERVER_PORT)
                        + QLatin1Char('=') + QString::number(sp.qmlServerPort);
    }

172 173 174 175
    // 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;
176
    sp.displayName = rc->displayName();
177

178 179
    // Find qtInstallPath.
    QString qmakePath = DebuggingHelperLibrary::findSystemQt(rc->environment());
180 181 182 183 184 185 186 187 188
    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) + "/..");
189
        sp.qtInstallPath = fi.absoluteFilePath();
190 191
    }
    return sp;
192 193
}

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

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

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


225 226
////////////////////////////////////////////////////////////////////////
//
227
// DebuggerRunControl
228 229 230
//
////////////////////////////////////////////////////////////////////////

231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
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)
247 248
    , m_running(false)
    , m_started(false)
249
    , m_enabledEngines(enabledEngines)
250 251
{
}
252

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

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

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

278 279 280 281 282 283 284 285 286 287 288 289
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:
290
        case ProjectExplorer::ToolChain::GCC_MAEMO:
291 292 293 294 295 296 297 298 299 300 301 302 303
            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;
304 305
}

306 307 308 309

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

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

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

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

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

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

354
    return NoEngineType;
355 356
}

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

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

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

381 382
    // Figure out engine according to toolchain, executable, attach or default.
    DebuggerEngineType engineType = NoEngineType;
383
    DebuggerLanguages activeLangs = DebuggerPlugin::instance()->activeLanguages();
384
    /*bool isQmlExecutable = sp.executable.endsWith(_("qmlviewer")) || sp.executable.endsWith(_("qmlobserver"));
385 386 387
#ifdef Q_OS_MAC
    isQmlExecutable = sp.executable.endsWith(_("QMLViewer.app")) || sp.executable.endsWith(_("QMLObserver.app"));
#endif
388
    if (isQmlExecutable && sp.startMode != AttachCore)
389
        engineType = QmlEngineType;
390
    else */if (sp.executable.endsWith(_(".js")))
391 392 393 394 395 396
        engineType = ScriptEngineType;
    else if (sp.executable.endsWith(_(".py")))
        engineType = PdbEngineType;
    else
        engineType = engineForToolChain(sp.toolChainType);

397 398 399 400
    // Fixme: 1 of 3 testing hacks.
    if (sp.processArgs.size() >= 5 && sp.processArgs.at(0) == _("@tcf@"))
        engineType = GdbEngineType;

401 402 403 404 405 406 407 408
    if (engineType == NoEngineType
            && sp.startMode != AttachToRemote
            && !sp.executable.isEmpty())
        engineType = engineForExecutable(sp.executable);

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

409
    if (engineType != QmlEngineType && (activeLangs & QmlLanguage)) {
410
        if (activeLangs & CppLanguage) {
411 412 413 414 415 416 417
            sp.cppEngineType = engineType;
            engineType = QmlCppEngineType;
        } else {
            engineType = QmlEngineType;
        }
    }

Friedemann Kleint's avatar
Friedemann Kleint committed
418
    // qDebug() << "USING ENGINE : " << engineType;
419 420 421

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

462 463 464 465 466 467 468 469
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,
470
                SIGNAL(engineRequestSetup()));
471 472
    } else if (RemoteGdbServerAdapter *rgsa = qobject_cast<RemoteGdbServerAdapter *>(adapter)) {
        connect(rgsa, SIGNAL(requestSetup()),
473
                this, SIGNAL(engineRequestSetup()));
474 475 476
    }
}

477
QString DebuggerRunControl::displayName() const
478
{
479 480
    QTC_ASSERT(d->m_engine, return QString());
    return d->m_engine->startParameters().displayName;
481 482
}

483
void DebuggerRunControl::setCustomEnvironment(ProjectExplorer::Environment env)
484
{
485
    d->m_engine->startParameters().environment = env.toStringList();
486 487
}

488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
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)
512
            *errorMessage += msgEngineNotAvailable("Gdb");
513 514 515 516
        break;
    case ProjectExplorer::ToolChain::MSVC:
        success = checkCdbConfiguration(toolChain, errorMessage, settingsPage);
        if (!success) {
517
            *errorMessage += msgEngineNotAvailable("Cdb");
518 519 520 521 522 523 524
            if (settingsPage)
                *settingsPage = QLatin1String("Cdb");
        }
        break;
    }
    if (!success && settingsCategory && settingsPage && !settingsPage->isEmpty())
        *settingsCategory = QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY);
hjk's avatar
hjk committed
525

526
    return success;
527 528
}

529
void DebuggerRunControl::start()
530
{
531 532
    QTC_ASSERT(d->m_engine, return);
    const DebuggerStartParameters &sp = d->m_engine->startParameters();
533

534 535 536
    QString errorMessage;
    QString settingsCategory;
    QString settingsPage;
537

538 539 540 541 542 543
    if (!checkDebugConfiguration(sp.toolChainType,
            &errorMessage, &settingsCategory, &settingsPage)) {
        emit appendMessage(this, errorMessage, true);
        emit finished();
        Core::ICore::instance()->showWarningWithOptions(tr("Debugger"),
            errorMessage, QString(), settingsCategory, settingsPage);
544
        return;
545
    }
546

547
    plugin()->activateDebugMode();
548
    DebuggerUISwitcher::instance()->aboutToStartDebugger();
Friedemann Kleint's avatar
Friedemann Kleint committed
549 550

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

556
    engine()->startDebugger(this);
557
    d->m_running = true;
558 559
    emit addToOutputWindowInline(this, tr("Debugging starts"), false);
    emit addToOutputWindowInline(this, "\n", false);
560
    emit started();
561 562
}

563
void DebuggerRunControl::startFailed()
564
{
565
    emit addToOutputWindowInline(this, tr("Debugging has failed"), false);
566
    d->m_running = false;
567
    emit finished();
568
    engine()->handleStartFailed();
569 570
}

571
void DebuggerRunControl::handleFinished()
572
{
573
    emit addToOutputWindowInline(this, tr("Debugging has finished"), false);
574
    engine()->handleFinished();
575
    plugin()->runControlFinished(this);
576 577
}

578
void DebuggerRunControl::showMessage(const QString &msg, int channel)
579
{
580 581 582 583 584 585 586 587 588 589 590
    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;
    }
591 592
}

593
bool DebuggerRunControl::aboutToStop() const
594
{
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
    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()
{
611 612
    QTC_ASSERT(d->m_engine, return StoppedSynchronously);
    d->m_engine->quitDebugger();
613
    return AsynchronousStop;
614 615
}

616
void DebuggerRunControl::debuggingFinished()
617
{
618
    d->m_running = false;
619
    emit finished();
620 621
}

622
bool DebuggerRunControl::isRunning() const
623
{
624
    return d->m_running;
625 626
}

Friedemann Kleint's avatar
Friedemann Kleint committed
627 628
DebuggerState DebuggerRunControl::state() const
{
629 630
    QTC_ASSERT(d->m_engine, return DebuggerNotReady);
    return d->m_engine->state();
Friedemann Kleint's avatar
Friedemann Kleint committed
631 632
}

633
DebuggerEngine *DebuggerRunControl::engine()
634
{
635 636
    QTC_ASSERT(d->m_engine, /**/);
    return d->m_engine;
637 638
}

639 640
Internal::GdbEngine *DebuggerRunControl::gdbEngine() const
{
641 642
    QTC_ASSERT(d->m_engine, return 0);
    if (GdbEngine *gdbEngine = qobject_cast<GdbEngine *>(d->m_engine))
643
        return gdbEngine;
644
    if (QmlCppEngine * const qmlEngine = qobject_cast<QmlCppEngine *>(d->m_engine))
645
        if (Internal::GdbEngine *embeddedGdbEngine = qobject_cast<GdbEngine *>(qmlEngine->cppEngine()))
646 647 648 649 650 651 652 653 654 655 656
            return embeddedGdbEngine;
    return 0;
}

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

657
void DebuggerRunControl::handleRemoteSetupDone()
658
{
659 660 661 662 663 664 665 666 667 668
    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, /* */ );
        }
669 670 671 672 673
    } else {
        QTC_ASSERT(false, /* */ );
    }
}

674
void DebuggerRunControl::handleRemoteSetupFailed(const QString &message)
675
{
676 677 678 679 680 681 682 683 684 685
    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, /* */ );
        }
686 687 688 689
    } else {
        QTC_ASSERT(false, /* */ );
    }
}
690 691 692 693 694 695 696 697 698 699

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);
}
700 701 702 703 704

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