debuggerrunner.cpp 22 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
DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration,
231 232 233 234 235
        DebuggerEngineType enabledEngines, const DebuggerStartParameters &sp)
    : RunControl(runConfiguration, ProjectExplorer::Constants::DEBUGMODE)
    , m_myRunConfiguration(runConfiguration)
    , m_running(false)
    , m_started(false)
236
    , m_enabledEngines(enabledEngines)
237

238
{
Friedemann Kleint's avatar
Friedemann Kleint committed
239
    connect(this, SIGNAL(finished()), this, SLOT(handleFinished()));
240 241
    DebuggerStartParameters startParams = sp;
    createEngine(startParams);
242 243
}

244 245 246 247 248 249 250 251 252
DebuggerRunControl::~DebuggerRunControl()
{
    disconnect();
    DebuggerEngine *engine = m_engine;
    m_engine = 0;
    engine->disconnect();
    delete engine;
}

253 254 255 256 257 258
const DebuggerStartParameters &DebuggerRunControl::startParameters() const
{
    QTC_ASSERT(m_engine, return *(new DebuggerStartParameters()));
    return m_engine->startParameters();
}

259 260 261 262 263 264 265 266 267 268 269 270
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:
271
        case ProjectExplorer::ToolChain::GCC_MAEMO:
272 273 274 275 276 277 278 279 280 281 282 283 284
            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;
285 286
}

287 288 289 290

// Figure out the debugger type of an executable. Analyze executable
// unless the toolchain provides a hint.
DebuggerEngineType DebuggerRunControl::engineForExecutable(const QString &executable)
291
{
292 293 294 295 296
    if (executable.endsWith(_("qmlviewer"))) {
        if (m_enabledEngines & QmlEngineType)
            return QmlEngineType;
        m_errorMessage = msgEngineNotAvailable("Qml Engine");
    }
297

298 299 300 301 302
    if (executable.endsWith(_(".js"))) {
        if (m_enabledEngines & ScriptEngineType)
            return ScriptEngineType;
        m_errorMessage = msgEngineNotAvailable("Script Engine");
    }
con's avatar
con committed
303

304 305 306 307 308
    if (executable.endsWith(_(".py"))) {
        if (m_enabledEngines & PdbEngineType)
            return PdbEngineType;
        m_errorMessage = msgEngineNotAvailable("Pdb Engine");
    }
con's avatar
con committed
309

310 311 312
#ifdef Q_OS_WIN
    // A remote executable?
    if (!executable.endsWith(_(".exe")))
Friedemann Kleint's avatar
Friedemann Kleint committed
313
        return GdbEngineType;
314 315 316

    // If a file has PDB files, it has been compiled by VS.
    QStringList pdbFiles;
Friedemann Kleint's avatar
Friedemann Kleint committed
317
    if (!getPDBFiles(executable, &pdbFiles, &m_errorMessage)) {
318 319
        qWarning("Cannot determine type of executable %s: %s",
                 qPrintable(executable), qPrintable(m_errorMessage));
Friedemann Kleint's avatar
Friedemann Kleint committed
320
        return NoEngineType;
321 322 323
    }
    if (pdbFiles.empty())
        return GdbEngineType;
324

325 326
    // We need the CDB debugger in order to be able to debug VS
    // executables
Friedemann Kleint's avatar
Friedemann Kleint committed
327
    if (checkDebugConfiguration(ToolChain::MSVC, &m_errorMessage, 0, &m_settingsIdHint))
328 329 330 331 332 333
        return CdbEngineType;
#else
    if (m_enabledEngines & GdbEngineType)
        return GdbEngineType;
    m_errorMessage = msgEngineNotAvailable("Gdb Engine");
#endif
334

335
    return NoEngineType;
336 337
}

338 339
// Debugger type for mode.
DebuggerEngineType DebuggerRunControl::engineForMode(DebuggerStartMode startMode)
340
{
341 342
    if (startMode == AttachTcf)
        return TcfEngineType;
343

344 345
#ifdef Q_OS_WIN
    // Preferably Windows debugger for attaching locally.
Friedemann Kleint's avatar
Friedemann Kleint committed
346
    if (startMode != AttachToRemote)
347
        return CdbEngineType;
Friedemann Kleint's avatar
Friedemann Kleint committed
348
    return GdbEngineType;
349 350 351 352 353 354 355
    m_errorMessage = msgEngineNotAvailable("Gdb Engine");
    return NoEngineType;
#else
    Q_UNUSED(startMode)
    //  m_errorMessage = msgEngineNotAvailable("Gdb Engine");
    return GdbEngineType;
#endif
356 357
}

358
void DebuggerRunControl::createEngine(const DebuggerStartParameters &startParams)
359
{
360 361
    DebuggerStartParameters sp = startParams;

362 363
    // Figure out engine according to toolchain, executable, attach or default.
    DebuggerEngineType engineType = NoEngineType;
364
    DebuggerLanguages activeLangs = DebuggerPlugin::instance()->activeLanguages();
365 366 367 368 369
    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)
370 371 372 373 374 375 376 377
        engineType = QmlEngineType;
    else if (sp.executable.endsWith(_(".js")))
        engineType = ScriptEngineType;
    else if (sp.executable.endsWith(_(".py")))
        engineType = PdbEngineType;
    else
        engineType = engineForToolChain(sp.toolChainType);

378 379 380 381
    // Fixme: 1 of 3 testing hacks.
    if (sp.processArgs.size() >= 5 && sp.processArgs.at(0) == _("@tcf@"))
        engineType = GdbEngineType;

382 383 384 385 386 387 388 389
    if (engineType == NoEngineType
            && sp.startMode != AttachToRemote
            && !sp.executable.isEmpty())
        engineType = engineForExecutable(sp.executable);

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

390
    if (engineType != QmlEngineType && (activeLangs & QmlLanguage)) {
391
        if (activeLangs & CppLanguage) {
392 393 394 395 396 397 398
            sp.cppEngineType = engineType;
            engineType = QmlCppEngineType;
        } else {
            engineType = QmlEngineType;
        }
    }

Friedemann Kleint's avatar
Friedemann Kleint committed
399
    // qDebug() << "USING ENGINE : " << engineType;
400 401 402 403

    switch (engineType) {
        case GdbEngineType:
            m_engine = createGdbEngine(sp);
404
            initGdbEngine(qobject_cast<Internal::GdbEngine *>(m_engine));
405
            break;
406 407
        case ScriptEngineType:
            m_engine = createScriptEngine(sp);
408
            break;
409 410
        case CdbEngineType:
            m_engine = createCdbEngine(sp);
411
            break;
412 413
        case PdbEngineType:
            m_engine = createPdbEngine(sp);
414
            break;
415 416
        case TcfEngineType:
            m_engine = createTcfEngine(sp);
417
            break;
418 419 420
        case QmlEngineType:
            m_engine = createQmlEngine(sp);
            break;
421 422
        case QmlCppEngineType:
            m_engine = createQmlCppEngine(sp);
423 424
            if (Internal::GdbEngine *embeddedGdbEngine = gdbEngine())
                initGdbEngine(embeddedGdbEngine);
425
            break;
426 427
        default: {
            // Could not find anything suitable.
428
            debuggingFinished();
429 430 431 432 433 434
            // Create Message box with possibility to go to settings
            const QString msg = tr("Cannot debug '%1' (tool chain: '%2'): %3")
                .arg(sp.executable, toolChainName(sp.toolChainType), m_errorMessage);
            Core::ICore::instance()->showWarningWithOptions(tr("Warning"),
                msg, QString(), QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY),
                m_settingsIdHint);
435
            break;
436
        }
437
    }
438 439
}

440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
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()));
    }
}

455
QString DebuggerRunControl::displayName() const
456
{
457 458
    QTC_ASSERT(m_engine, return QString());
    return m_engine->startParameters().displayName;
459 460
}

461
void DebuggerRunControl::setCustomEnvironment(ProjectExplorer::Environment env)
462
{
463
    m_engine->startParameters().environment = env.toStringList();
464 465
}

466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
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)
490
            *errorMessage += msgEngineNotAvailable("Gdb");
491 492 493 494
        break;
    case ProjectExplorer::ToolChain::MSVC:
        success = checkCdbConfiguration(toolChain, errorMessage, settingsPage);
        if (!success) {
495
            *errorMessage += msgEngineNotAvailable("Cdb");
496 497 498 499 500 501 502
            if (settingsPage)
                *settingsPage = QLatin1String("Cdb");
        }
        break;
    }
    if (!success && settingsCategory && settingsPage && !settingsPage->isEmpty())
        *settingsCategory = QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY);
hjk's avatar
hjk committed
503

504
    return success;
505 506
}

507
void DebuggerRunControl::start()
508
{
509 510
    QTC_ASSERT(m_engine, return);
    const DebuggerStartParameters &sp = m_engine->startParameters();
511

512 513 514
    QString errorMessage;
    QString settingsCategory;
    QString settingsPage;
515

516 517 518 519 520 521
    if (!checkDebugConfiguration(sp.toolChainType,
            &errorMessage, &settingsCategory, &settingsPage)) {
        emit appendMessage(this, errorMessage, true);
        emit finished();
        Core::ICore::instance()->showWarningWithOptions(tr("Debugger"),
            errorMessage, QString(), settingsCategory, settingsPage);
522
        return;
523
    }
524

525
    plugin()->activateDebugMode();
526
    DebuggerUISwitcher::instance()->aboutToStartDebugger();
Friedemann Kleint's avatar
Friedemann Kleint committed
527 528 529 530

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

534 535
    engine()->startDebugger(this);
    m_running = true;
536 537
    emit addToOutputWindowInline(this, tr("Debugging starts"), false);
    emit addToOutputWindowInline(this, "\n", false);
538
    emit started();
539 540
}

541
void DebuggerRunControl::startFailed()
542
{
543
    emit addToOutputWindowInline(this, tr("Debugging has failed"), false);
544 545
    m_running = false;
    emit finished();
546
    engine()->handleStartFailed();
547 548
}

549
void DebuggerRunControl::handleFinished()
550
{
551
    emit addToOutputWindowInline(this, tr("Debugging has finished"), false);
552
    engine()->handleFinished();
553
    plugin()->runControlFinished(this);
554 555
}

556
void DebuggerRunControl::showMessage(const QString &msg, int channel)
557
{
558 559 560 561 562 563 564 565 566 567 568
    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;
    }
569 570
}

571
bool DebuggerRunControl::aboutToStop() const
572
{
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
    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()
{
    QTC_ASSERT(m_engine, return StoppedSynchronously);
590
    m_engine->quitDebugger();
591
    return AsynchronousStop;
592 593
}

594
void DebuggerRunControl::debuggingFinished()
595
{
596 597
    m_running = false;
    emit finished();
598 599
}

600
bool DebuggerRunControl::isRunning() const
601
{
602
    return m_running;
603 604
}

Friedemann Kleint's avatar
Friedemann Kleint committed
605 606 607 608 609 610
DebuggerState DebuggerRunControl::state() const
{
    QTC_ASSERT(m_engine, return DebuggerNotReady);
    return m_engine->state();
}

611
Internal::DebuggerEngine *DebuggerRunControl::engine()
612
{
613 614
    QTC_ASSERT(m_engine, /**/);
    return m_engine;
615 616
}

617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
Internal::GdbEngine *DebuggerRunControl::gdbEngine() const
{
    QTC_ASSERT(m_engine, return 0);
    if (GdbEngine *gdbEngine = qobject_cast<GdbEngine *>(m_engine))
        return gdbEngine;
    if (QmlCppEngine * const qmlEngine = qobject_cast<QmlCppEngine *>(m_engine))
        if (GdbEngine *embeddedGdbEngine = qobject_cast<GdbEngine *>(qmlEngine->cppEngine()))
            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, /* */ );
    }
}
hjk's avatar
hjk committed
660
} // namespace Debugger