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
        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
    /*bool isQmlExecutable = sp.executable.endsWith(_("qmlviewer")) || sp.executable.endsWith(_("qmlobserver"));
384 385 386
#ifdef Q_OS_MAC
    isQmlExecutable = sp.executable.endsWith(_("QMLViewer.app")) || sp.executable.endsWith(_("QMLObserver.app"));
#endif
387
    if (isQmlExecutable && sp.startMode != AttachCore)
388
        engineType = QmlEngineType;
389
    else */if (sp.executable.endsWith(_(".js")))
390 391 392 393 394 395
        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 439 440
            connect(qobject_cast<QmlEngine *>(d->m_engine),
                SIGNAL(remoteStartupRequested()), this,
                SIGNAL(engineRequestSetup()));
441
            break;
442
        case QmlCppEngineType:
443
            d->m_engine = Internal::createQmlCppEngine(sp);
444 445
            if (Internal::GdbEngine *embeddedGdbEngine = gdbEngine())
                initGdbEngine(embeddedGdbEngine);
446
            break;
447 448
        default: {
            // Could not find anything suitable.
449
            debuggingFinished();
450 451
            // Create Message box with possibility to go to settings
            const QString msg = tr("Cannot debug '%1' (tool chain: '%2'): %3")
452
                .arg(sp.executable, toolChainName(sp.toolChainType), d->m_errorMessage);
453 454
            Core::ICore::instance()->showWarningWithOptions(tr("Warning"),
                msg, QString(), QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY),
455
                d->m_settingsIdHint);
456
            break;
457
        }
458
    }
459 460
}

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

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

482
void DebuggerRunControl::setCustomEnvironment(ProjectExplorer::Environment env)
483
{
484
    d->m_engine->startParameters().environment = env.toStringList();
485 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
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)
511
            *errorMessage += msgEngineNotAvailable("Gdb");
512 513 514 515
        break;
    case ProjectExplorer::ToolChain::MSVC:
        success = checkCdbConfiguration(toolChain, errorMessage, settingsPage);
        if (!success) {
516
            *errorMessage += msgEngineNotAvailable("Cdb");
517 518 519 520 521 522 523
            if (settingsPage)
                *settingsPage = QLatin1String("Cdb");
        }
        break;
    }
    if (!success && settingsCategory && settingsPage && !settingsPage->isEmpty())
        *settingsCategory = QLatin1String(Constants::DEBUGGER_SETTINGS_CATEGORY);
hjk's avatar
hjk committed
524

525
    return success;
526 527
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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