debuggerrunner.cpp 23.2 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 41
#include "gdb/gdbengine.h"
#include "gdb/remotegdbserveradapter.h"
#include "gdb/remoteplaingdbadapter.h"
#include "qml/qmlcppengine.h"
42

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

hjk's avatar
hjk committed
47
#include <projectexplorer/debugginghelper.h>
con's avatar
con committed
48 49
#include <projectexplorer/environment.h>
#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

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

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

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

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

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

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

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

// 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
92 93
#ifdef CDB_ENABLED
DebuggerEngine *createCdbEngine(const DebuggerStartParameters &);
94
bool checkCdbConfiguration(int toolChain, QString *errorMsg, QString *settingsPage);
hjk's avatar
hjk committed
95 96 97 98
#else
DebuggerEngine *createCdbEngine(const DebuggerStartParameters &) { return 0; }
bool checkCdbConfiguration(int, QString *, QString *) { return false; }
#endif
99

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

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

107

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

114 115 116 117 118 119 120
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(); }
121

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

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

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

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

148 149 150 151 152 153 154 155 156
    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();
157

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

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

167 168 169 170
        sp.environment << QString(Constants::E_QML_DEBUG_SERVER_PORT)
                        + QLatin1Char('=') + QString::number(sp.qmlServerPort);
    }

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 384 385 386 387
    bool isQmlExecutable = sp.executable.endsWith(_("qmlviewer")) || sp.executable.endsWith(_("qmlobserver"));
#ifdef Q_OS_MAC
    isQmlExecutable = sp.executable.endsWith(_("QMLViewer.app")) || sp.executable.endsWith(_("QMLObserver.app"));
#endif
    if (isQmlExecutable)
388 389 390 391 392 393 394 395
        engineType = QmlEngineType;
    else if (sp.executable.endsWith(_(".js")))
        engineType = ScriptEngineType;
    else if (sp.executable.endsWith(_(".py")))
        engineType = PdbEngineType;
    else
        engineType = engineForToolChain(sp.toolChainType);

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

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

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

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

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

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

458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
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,
                SIGNAL(gdbAdapterRequestSetup()));
    } else if (RemoteGdbServerAdapter *rgsa = qobject_cast<RemoteGdbServerAdapter *>(adapter)) {
        connect(rgsa, SIGNAL(requestSetup()),
                this, SIGNAL(gdbAdapterRequestSetup()));
    }
}

473
QString DebuggerRunControl::displayName() const
474
{
475 476
    QTC_ASSERT(d->m_engine, return QString());
    return d->m_engine->startParameters().displayName;
477 478
}

479
void DebuggerRunControl::setCustomEnvironment(ProjectExplorer::Environment env)
480
{
481
    d->m_engine->startParameters().environment = env.toStringList();
482 483
}

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

522
    return success;
523 524
}

525
void DebuggerRunControl::start()
526
{
527 528
    QTC_ASSERT(d->m_engine, return);
    const DebuggerStartParameters &sp = d->m_engine->startParameters();
529

530 531 532
    QString errorMessage;
    QString settingsCategory;
    QString settingsPage;
533

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

543
    plugin()->activateDebugMode();
544
    DebuggerUISwitcher::instance()->aboutToStartDebugger();
Friedemann Kleint's avatar
Friedemann Kleint committed
545 546

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

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

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

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

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

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

612
void DebuggerRunControl::debuggingFinished()
613
{
614
    d->m_running = false;
615
    emit finished();
616 617
}

618
bool DebuggerRunControl::isRunning() const
619
{
620
    return d->m_running;
621 622
}

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

629
DebuggerEngine *DebuggerRunControl::engine()
630
{
631 632
    QTC_ASSERT(d->m_engine, /**/);
    return d->m_engine;
633 634
}

635 636
Internal::GdbEngine *DebuggerRunControl::gdbEngine() const
{
637 638
    QTC_ASSERT(d->m_engine, return 0);
    if (GdbEngine *gdbEngine = qobject_cast<GdbEngine *>(d->m_engine))
639
        return gdbEngine;
640
    if (QmlCppEngine * const qmlEngine = qobject_cast<QmlCppEngine *>(d->m_engine))
641
        if (Internal::GdbEngine *embeddedGdbEngine = qobject_cast<GdbEngine *>(qmlEngine->cppEngine()))
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
            return embeddedGdbEngine;
    return 0;
}

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

void DebuggerRunControl::remoteGdbHandleSetupDone()
{
    Internal::AbstractGdbAdapter *adapter = gdbAdapter();
    QTC_ASSERT(adapter, return);
    if (RemotePlainGdbAdapter *rpga = qobject_cast<RemotePlainGdbAdapter *>(adapter)) {
        rpga->handleSetupDone();
    } else if (RemoteGdbServerAdapter *rgsa = qobject_cast<RemoteGdbServerAdapter *>(adapter)) {
        rgsa->handleSetupDone();
    } else {
        QTC_ASSERT(false, /* */ );
    }
}

void DebuggerRunControl::remoteGdbHandleSetupFailed(const QString &message)
{
    Internal::AbstractGdbAdapter *adapter = gdbAdapter();
    QTC_ASSERT(adapter, return);
    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, /* */ );
    }
}
678 679 680 681 682 683 684 685 686 687

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);
}
688 689 690 691 692

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