runconfiguration.cpp 20.4 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2 3 4
**
** This file is part of Qt Creator
**
hjk's avatar
hjk committed
5
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
Eike Ziller's avatar
Eike Ziller committed
7
** Contact: http://www.qt-project.org/
con's avatar
con committed
8
**
9
**
10
** GNU Lesser General Public License Usage
11
**
hjk's avatar
hjk committed
12 13 14 15 16 17
** 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.
18
**
con's avatar
con committed
19
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
con's avatar
con committed
21 22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23 24 25 26 27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
con's avatar
con committed
28
**
29
**************************************************************************/
hjk's avatar
hjk committed
30

con's avatar
con committed
31
#include "runconfiguration.h"
32

con's avatar
con committed
33
#include "project.h"
Tobias Hunger's avatar
Tobias Hunger committed
34
#include "target.h"
35
#include "toolchain.h"
36
#include "abi.h"
37
#include "buildconfiguration.h"
38
#include "projectexplorerconstants.h"
Tobias Hunger's avatar
Tobias Hunger committed
39
#include "kitinformation.h"
Tobias Hunger's avatar
Tobias Hunger committed
40
#include <extensionsystem/pluginmanager.h>
41

42
#include <utils/qtcassert.h>
43
#include <utils/outputformatter.h>
44 45 46
#include <utils/checkablemessagebox.h>

#include <coreplugin/icore.h>
Tobias Hunger's avatar
Tobias Hunger committed
47

48 49 50 51
#include <QTimer>
#include <QSettings>
#include <QMessageBox>
#include <QPushButton>
con's avatar
con committed
52 53

#ifdef Q_OS_MAC
Eike Ziller's avatar
Eike Ziller committed
54
#include <ApplicationServices/ApplicationServices.h>
con's avatar
con committed
55 56 57 58
#endif

using namespace ProjectExplorer;

Tobias Hunger's avatar
Tobias Hunger committed
59 60
namespace {

hjk's avatar
hjk committed
61 62 63 64
const char USE_CPP_DEBUGGER_KEY[] = "RunConfiguration.UseCppDebugger";
const char USE_QML_DEBUGGER_KEY[] = "RunConfiguration.UseQmlDebugger";
const char USE_QML_DEBUGGER_AUTO_KEY[] = "RunConfiguration.UseQmlDebuggerAuto";
const char QML_DEBUG_SERVER_PORT_KEY[] = "RunConfiguration.QmlDebugServerPort";
65
const char USE_MULTIPROCESS_KEY[] = "RunConfiguration.UseMultiProcess";
hjk's avatar
hjk committed
66

Tobias Hunger's avatar
Tobias Hunger committed
67 68
} // namespace

69 70 71 72
/*!
    \class ProjectExplorer::ProcessHandle
    \brief  Helper class to describe a process.

73 74
    Encapsulates parameters of a running process, local (PID) or remote (to be done,
    address, port, etc).
75 76
*/

77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
ProcessHandle::ProcessHandle(quint64 pid) :
    m_pid(pid)
{
}

bool ProcessHandle::isValid() const
{
    return m_pid != 0;
}

void ProcessHandle::setPid(quint64 pid)
{
    m_pid = pid;
}

quint64 ProcessHandle::pid() const
{
    return m_pid;
}

QString ProcessHandle::toString() const
{
    if (m_pid)
        return RunControl::tr("PID %1").arg(m_pid);
    //: Invalid process handle.
    return RunControl::tr("Invalid");
}

bool ProcessHandle::equals(const ProcessHandle &rhs) const
{
    return m_pid == rhs.m_pid;
}

110
/*!
111
    \class ProjectExplorer::DebuggerRunConfigurationAspect
112 113
*/

114
DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(RunConfiguration *rc) :
115
    m_runConfiguration(rc),
116 117
    m_useCppDebugger(true),
    m_useQmlDebugger(AutoEnableQmlDebugger),
118
    m_qmlDebugServerPort(Constants::QML_DEFAULT_DEBUG_SERVER_PORT),
119
    m_useMultiProcess(false),
120
    m_suppressDisplay(false),
121
    m_suppressQmlDebuggingOptions(false),
122
    m_suppressCppDebuggingOptions(false),
123
    m_suppressQmlDebuggingSpinbox(false)
124 125
{}

126 127 128 129 130 131 132 133 134 135 136
DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(RunConfiguration *runConfiguration,
                                                               DebuggerRunConfigurationAspect *other)
    : m_runConfiguration(runConfiguration),
      m_useCppDebugger(other->m_useCppDebugger),
      m_useQmlDebugger(other->m_useQmlDebugger),
      m_qmlDebugServerPort(other->m_qmlDebugServerPort),
      m_useMultiProcess(other->m_useMultiProcess),
      m_suppressDisplay(other->m_suppressDisplay),
      m_suppressQmlDebuggingOptions(other->m_suppressQmlDebuggingOptions),
      m_suppressCppDebuggingOptions(other->m_suppressCppDebuggingOptions),
      m_suppressQmlDebuggingSpinbox(other->m_suppressQmlDebuggingSpinbox)
137 138
{}

139
RunConfiguration *DebuggerRunConfigurationAspect::runConfiguration()
140 141 142 143
{
    return m_runConfiguration;
}

144
void DebuggerRunConfigurationAspect::setUseQmlDebugger(bool value)
145 146 147 148 149
{
    m_useQmlDebugger = value ? EnableQmlDebugger : DisableQmlDebugger;
    emit debuggersChanged();
}

150
void DebuggerRunConfigurationAspect::setUseCppDebugger(bool value)
151 152 153 154 155
{
    m_useCppDebugger = value;
    emit debuggersChanged();
}

156
bool DebuggerRunConfigurationAspect::useCppDebugger() const
157 158 159 160 161 162 163 164 165 166 167
{
    return m_useCppDebugger;
}

static bool isQtQuickAppProject(Project *project)
{
    const QString filePath = project->projectDirectory()
            + QLatin1String("/qmlapplicationviewer/qmlapplicationviewer.pri");
    return project->files(Project::ExcludeGeneratedFiles).contains(filePath);
}

168
bool DebuggerRunConfigurationAspect::useQmlDebugger() const
169
{
170
    if (m_useQmlDebugger == DebuggerRunConfigurationAspect::AutoEnableQmlDebugger)
171
        return isQtQuickAppProject(m_runConfiguration->target()->project());
172
    return m_useQmlDebugger == DebuggerRunConfigurationAspect::EnableQmlDebugger;
173 174
}

175
uint DebuggerRunConfigurationAspect::qmlDebugServerPort() const
176
{
177
    return m_qmlDebugServerPort;
178 179
}

180
void DebuggerRunConfigurationAspect::setQmllDebugServerPort(uint port)
181
{
182
    m_qmlDebugServerPort = port;
183 184
}

185 186 187 188 189 190 191 192 193 194
bool DebuggerRunConfigurationAspect::useMultiProcess() const
{
    return m_useMultiProcess;
}

void DebuggerRunConfigurationAspect::setUseMultiProcess(bool value)
{
    m_useMultiProcess = value;
}

195 196 197 198 199
void DebuggerRunConfigurationAspect::suppressDisplay()
{
    m_suppressDisplay = true;
}

200
void DebuggerRunConfigurationAspect::suppressQmlDebuggingOptions()
201
{
202 203 204
    m_suppressQmlDebuggingOptions = true;
}

205 206 207 208 209
void DebuggerRunConfigurationAspect::suppressCppDebuggingOptions()
{
    m_suppressCppDebuggingOptions = true;
}

210 211 212 213 214
void DebuggerRunConfigurationAspect::suppressQmlDebuggingSpinbox()
{
    m_suppressQmlDebuggingSpinbox = true;
}

215 216 217 218 219
bool DebuggerRunConfigurationAspect::isDisplaySuppressed() const
{
    return m_suppressDisplay;
}

220
bool DebuggerRunConfigurationAspect::areQmlDebuggingOptionsSuppressed() const
221 222
{
    return m_suppressQmlDebuggingOptions;
223 224
}

225 226 227 228 229
bool DebuggerRunConfigurationAspect::areCppDebuggingOptionsSuppressed() const
{
    return m_suppressCppDebuggingOptions;
}

230 231 232 233 234
bool DebuggerRunConfigurationAspect::isQmlDebuggingSpinboxSuppressed() const
{
    return m_suppressQmlDebuggingSpinbox;
}

235
QString DebuggerRunConfigurationAspect::displayName() const
236 237 238 239
{
    return tr("Debugger settings");
}

240
QVariantMap DebuggerRunConfigurationAspect::toMap() const
241 242 243 244 245 246
{
    QVariantMap map;
    map.insert(QLatin1String(USE_CPP_DEBUGGER_KEY), m_useCppDebugger);
    map.insert(QLatin1String(USE_QML_DEBUGGER_KEY), m_useQmlDebugger == EnableQmlDebugger);
    map.insert(QLatin1String(USE_QML_DEBUGGER_AUTO_KEY), m_useQmlDebugger == AutoEnableQmlDebugger);
    map.insert(QLatin1String(QML_DEBUG_SERVER_PORT_KEY), m_qmlDebugServerPort);
247
    map.insert(QLatin1String(USE_MULTIPROCESS_KEY), m_useMultiProcess);
248 249 250
    return map;
}

251
void DebuggerRunConfigurationAspect::fromMap(const QVariantMap &map)
252 253 254 255 256 257 258 259
{
    m_useCppDebugger = map.value(QLatin1String(USE_CPP_DEBUGGER_KEY), true).toBool();
    if (map.value(QLatin1String(USE_QML_DEBUGGER_AUTO_KEY), false).toBool()) {
        m_useQmlDebugger = AutoEnableQmlDebugger;
    } else {
        bool useQml = map.value(QLatin1String(USE_QML_DEBUGGER_KEY), false).toBool();
        m_useQmlDebugger = useQml ? EnableQmlDebugger : DisableQmlDebugger;
    }
260
    m_useMultiProcess = map.value(QLatin1String(USE_MULTIPROCESS_KEY), false).toBool();
261 262 263
}


264 265 266 267 268 269 270 271 272 273 274 275 276 277
/*!
    \class ProjectExplorer::RunConfiguration
    \brief  Base class for a run configuration. A run configuration specifies how a
    target should be run, while the runner (see below) does the actual running.

    Note that all RunControls and the target hold a shared pointer to the RunConfiguration.
    That is the lifetime of the RunConfiguration might exceed the life of the target.
    The user might still have a RunControl running (or output tab of that RunControl open)
    and yet unloaded the target.

    Also, a RunConfiguration might be already removed from the list of RunConfigurations
    for a target, but still be runnable via the output tab.
*/

278
RunConfiguration::RunConfiguration(Target *target, const Core::Id id) :
279
    ProjectConfiguration(target, id),
280
    m_debuggerAspect(new DebuggerRunConfigurationAspect(this))
con's avatar
con committed
281
{
Tobias Hunger's avatar
Tobias Hunger committed
282
    Q_ASSERT(target);
283
    addExtraAspects();
284 285
}

Tobias Hunger's avatar
Tobias Hunger committed
286
RunConfiguration::RunConfiguration(Target *target, RunConfiguration *source) :
287
    ProjectConfiguration(target, source),
288
    m_debuggerAspect(new DebuggerRunConfigurationAspect(this, source->debuggerAspect()))
289
{
Tobias Hunger's avatar
Tobias Hunger committed
290
    Q_ASSERT(target);
291 292 293 294 295 296 297 298 299
    QList<IRunControlFactory *> factories = ExtensionSystem::PluginManager::getObjects<IRunControlFactory>();
    foreach (IRunConfigurationAspect *aspect, source->m_aspects) {
        foreach (IRunControlFactory *factory, factories) {
            if (IRunConfigurationAspect *clone = factory->cloneRunConfigurationAspect(aspect)) {
                m_aspects.append(clone);
                break;
            }
        }
    }
con's avatar
con committed
300 301 302 303
}

RunConfiguration::~RunConfiguration()
{
304
    delete m_debuggerAspect;
305 306 307 308 309
    qDeleteAll(m_aspects);
}

void RunConfiguration::addExtraAspects()
{
310
    foreach (IRunControlFactory *factory, ExtensionSystem::PluginManager::getObjects<IRunControlFactory>())
311 312
        if (IRunConfigurationAspect *aspect = factory->createRunConfigurationAspect())
            m_aspects.append(aspect);
con's avatar
con committed
313 314
}

315
/*!
316
    \brief Used to find out whether a runconfiguration is enabled
317 318
*/

319
bool RunConfiguration::isEnabled() const
con's avatar
con committed
320
{
321
    return true;
con's avatar
con committed
322 323
}

dt_'s avatar
dt_ committed
324 325 326 327 328
QString RunConfiguration::disabledReason() const
{
    return QString();
}

Tobias Hunger's avatar
Tobias Hunger committed
329 330 331 332 333
bool RunConfiguration::isConfigured() const
{
    return true;
}

334 335 336 337 338 339 340 341 342 343
bool RunConfiguration::ensureConfigured(QString *errorMessage)
{
    if (isConfigured())
        return true;
    if (errorMessage)
        *errorMessage = tr("Unknown error.");
    return false;
}


344 345 346 347 348 349
/*!
    \fn virtual QWidget *ProjectExplorer::RunConfiguration::createConfigurationWidget()

    \brief Returns the widget used to configure this run configuration. Ownership is transferred to the caller
*/

350
BuildConfiguration *RunConfiguration::activeBuildConfiguration() const
con's avatar
con committed
351
{
Tobias Hunger's avatar
Tobias Hunger committed
352
    if (!target())
353
        return 0;
Tobias Hunger's avatar
Tobias Hunger committed
354
    return target()->activeBuildConfiguration();
con's avatar
con committed
355 356
}

Tobias Hunger's avatar
Tobias Hunger committed
357
Target *RunConfiguration::target() const
con's avatar
con committed
358
{
Tobias Hunger's avatar
Tobias Hunger committed
359
    return static_cast<Target *>(parent());
con's avatar
con committed
360 361
}

362 363
QVariantMap RunConfiguration::toMap() const
{
364 365 366
    QVariantMap map = ProjectConfiguration::toMap();

    map.unite(m_debuggerAspect->toMap());
367

368 369 370
    foreach (IRunConfigurationAspect *aspect, m_aspects)
        map.unite(aspect->toMap());

371 372 373
    return map;
}

374 375 376 377 378
ProjectExplorer::Abi RunConfiguration::abi() const
{
    BuildConfiguration *bc = target()->activeBuildConfiguration();
    if (!bc)
        return Abi::hostAbi();
Tobias Hunger's avatar
Tobias Hunger committed
379
    ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit());
380 381 382 383 384
    if (!tc)
        return Abi::hostAbi();
    return tc->targetAbi();
}

385 386
bool RunConfiguration::fromMap(const QVariantMap &map)
{
387
    m_debuggerAspect->fromMap(map);
388

389
    foreach (IRunConfigurationAspect *aspect, m_aspects)
390
        aspect->fromMap(map);
391

392 393 394
    return ProjectConfiguration::fromMap(map);
}

395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
/*!
    \class ProjectExplorer::IRunConfigurationAspect

    \brief Extra configuration aspect.

    Aspects are a mechanism to add RunControl-specific options to a RunConfiguration without
    subclassing the RunConfiguration for every addition, preventing a combinatorical explosion
    of subclasses or the need to add all options to the base class.
*/

/*!
    \brief Return extra aspects.

    \sa ProjectExplorer::IRunConfigurationAspect
*/

411 412 413 414 415
QList<IRunConfigurationAspect *> RunConfiguration::extraAspects() const
{
    return m_aspects;
}

con's avatar
con committed
416
Utils::OutputFormatter *RunConfiguration::createOutputFormatter() const
dt's avatar
dt committed
417
{
con's avatar
con committed
418
    return new Utils::OutputFormatter();
dt's avatar
dt committed
419 420
}

421

422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
/*!
    \class ProjectExplorer::IRunConfigurationFactory

    \brief Restores RunConfigurations from settings.

    The run configuration factory is used for restoring run configurations from
    settings. And used to create new runconfigurations in the "Run Settings" Dialog.
    For the first case, bool canRestore(Target *parent, const QString &id) and
    RunConfiguration* create(Target *parent, const QString &id) are used.
    For the second type, the functions QStringList availableCreationIds(Target *parent) and
    QString displayNameForType(const QString&) are used to generate a list of creatable
    RunConfigurations, and create(..) is used to create it.
*/

/*!
    \fn QStringList ProjectExplorer::IRunConfigurationFactory::availableCreationIds(Target *parent) const

    \brief Used to show the list of possible additons to a target, returns a list of types.
*/

/*!
    \fn QString ProjectExplorer::IRunConfigurationFactory::displayNameForId(const QString &id) const
    \brief Used to translate the types to names to display to the user.
*/

447 448
IRunConfigurationFactory::IRunConfigurationFactory(QObject *parent) :
    QObject(parent)
con's avatar
con committed
449 450 451 452 453 454 455
{
}

IRunConfigurationFactory::~IRunConfigurationFactory()
{
}

Tobias Hunger's avatar
Tobias Hunger committed
456
IRunConfigurationFactory *IRunConfigurationFactory::find(Target *parent, const QVariantMap &map)
Tobias Hunger's avatar
Tobias Hunger committed
457
{
Tobias Hunger's avatar
Tobias Hunger committed
458 459 460 461 462 463 464
    QList<IRunConfigurationFactory *> factories
            = ExtensionSystem::PluginManager::instance()->getObjects<IRunConfigurationFactory>();
    foreach (IRunConfigurationFactory *factory, factories) {
        if (factory->canRestore(parent, map))
            return factory;
    }
    return 0;
Tobias Hunger's avatar
Tobias Hunger committed
465 466
}

467 468 469 470 471 472 473 474 475 476 477
IRunConfigurationFactory *IRunConfigurationFactory::find(Target *parent, RunConfiguration *rc)
{
    QList<IRunConfigurationFactory *> factories
            = ExtensionSystem::PluginManager::instance()->getObjects<IRunConfigurationFactory>();
    foreach (IRunConfigurationFactory *factory, factories) {
        if (factory->canClone(parent, rc))
            return factory;
    }
    return 0;
}

Tobias Hunger's avatar
Tobias Hunger committed
478
QList<IRunConfigurationFactory *> IRunConfigurationFactory::find(Target *parent)
Tobias Hunger's avatar
Tobias Hunger committed
479
{
Tobias Hunger's avatar
Tobias Hunger committed
480 481 482 483 484 485 486 487
    QList<IRunConfigurationFactory *> factories
            = ExtensionSystem::PluginManager::instance()->getObjects<IRunConfigurationFactory>();
    QList<IRunConfigurationFactory *> result;
    foreach (IRunConfigurationFactory *factory, factories) {
        if (!factory->availableCreationIds(parent).isEmpty())
            result << factory;
    }
    return result;
Tobias Hunger's avatar
Tobias Hunger committed
488 489
}

490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
/*!
    \class ProjectExplorer::IRunControlFactory

    \brief Creates RunControl objects matching a RunConfiguration
*/

/*!
    \fn IRunConfigurationAspect *ProjectExplorer::IRunControlFactory::createRunConfigurationAspect()
    \brief Return an IRunConfigurationAspect to carry options for RunControls this factory can create.

    If no extra options are required it is allowed to return null like the default implementation does.
    This is intended to be called from the RunConfiguration constructor, so passing a RunConfiguration
    pointer makes no sense because that object is under construction at the time.
*/

/*!
    \fn RunConfigWidget *ProjectExplorer::IRunControlFactory::createConfigurationWidget(RunConfiguration *runConfiguration)

    \brief Return a widget used to configure this runner. Ownership is transferred to the caller.

    Return 0 if @p runConfiguration is not suitable for RunControls from this factory, or no user-accessible
    configuration is required.
*/

514
IRunControlFactory::IRunControlFactory(QObject *parent)
515
    : QObject(parent)
con's avatar
con committed
516 517 518
{
}

519
IRunControlFactory::~IRunControlFactory()
con's avatar
con committed
520 521 522
{
}

523 524 525 526 527
IRunConfigurationAspect *IRunControlFactory::createRunConfigurationAspect()
{
    return 0;
}

528 529
IRunConfigurationAspect *IRunControlFactory::cloneRunConfigurationAspect(IRunConfigurationAspect *source)
{
530
    Q_UNUSED(source);
531 532 533
    return 0;
}

534 535 536 537 538
RunConfigWidget *IRunControlFactory::createConfigurationWidget(RunConfiguration *)
{
    return 0;
}

539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
/*!
    \class ProjectExplorer::RunControl
    \brief Each instance of this class represents one item that is run.
*/

/*!
    \fn bool ProjectExplorer::RunControl::promptToStop(bool *optionalPrompt = 0) const

    \brief Prompt to stop. If 'optionalPrompt' is passed, a "Do not ask again"-
    checkbox will show and the result will be returned in '*optionalPrompt'.
*/

/*!
    \fn QIcon ProjectExplorer::RunControl::icon() const
    \brief Eeturns the icon to be shown in the Outputwindow.

    TODO the icon differs currently only per "mode", so this is more flexible then it needs to be.
*/

558
RunControl::RunControl(RunConfiguration *runConfiguration, RunMode mode)
559
    : m_runMode(mode), m_runConfiguration(runConfiguration), m_outputFormatter(0)
con's avatar
con committed
560
{
dt's avatar
dt committed
561
    if (runConfiguration) {
562
        m_displayName  = runConfiguration->displayName();
dt's avatar
dt committed
563 564 565 566
        m_outputFormatter = runConfiguration->createOutputFormatter();
    }
    // We need to ensure that there's always a OutputFormatter
    if (!m_outputFormatter)
con's avatar
con committed
567
        m_outputFormatter = new Utils::OutputFormatter();
con's avatar
con committed
568 569
}

570
RunControl::~RunControl()
con's avatar
con committed
571
{
dt's avatar
dt committed
572 573
    delete m_outputFormatter;
}
574

con's avatar
con committed
575
Utils::OutputFormatter *RunControl::outputFormatter()
dt's avatar
dt committed
576 577
{
    return m_outputFormatter;
con's avatar
con committed
578 579
}

580
RunMode RunControl::runMode() const
dt's avatar
dt committed
581 582 583 584
{
    return m_runMode;
}

585 586 587 588 589
QString RunControl::displayName() const
{
    return m_displayName;
}

590 591 592 593 594 595 596
Abi RunControl::abi() const
{
    if (const RunConfiguration *rc = m_runConfiguration.data())
        return rc->abi();
    return Abi();
}

597 598 599 600 601
RunConfiguration *RunControl::runConfiguration() const
{
    return m_runConfiguration.data();
}

602 603 604 605 606 607 608
ProcessHandle RunControl::applicationProcessHandle() const
{
    return m_applicationProcessHandle;
}

void RunControl::setApplicationProcessHandle(const ProcessHandle &handle)
{
609 610 611 612
    if (m_applicationProcessHandle != handle) {
        m_applicationProcessHandle = handle;
        emit applicationProcessHandleChanged();
    }
613 614
}

615
bool RunControl::promptToStop(bool *optionalPrompt) const
616
{
617
    QTC_ASSERT(isRunning(), return true);
618

619 620 621 622 623 624 625 626 627 628
    if (optionalPrompt && !*optionalPrompt)
        return true;

    const QString msg = tr("<html><head/><body><center><i>%1</i> is still running.<center/>"
                           "<center>Force it to quit?</center></body></html>").arg(displayName());
    return showPromptToStopDialog(tr("Application Still Running"), msg,
                                  tr("Force Quit"), tr("Keep Running"),
                                  optionalPrompt);
}

629 630 631 632
/*!
    \brief Utility to prompt to terminate application with checkable box.
*/

633 634 635 636 637 638
bool RunControl::showPromptToStopDialog(const QString &title,
                                        const QString &text,
                                        const QString &stopButtonText,
                                        const QString &cancelButtonText,
                                        bool *prompt) const
{
639
    QTC_ASSERT(isRunning(), return true);
640 641
    // Show a question message box where user can uncheck this
    // question for this class.
hjk's avatar
hjk committed
642
    Utils::CheckableMessageBox messageBox(Core::ICore::mainWindow());
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661
    messageBox.setWindowTitle(title);
    messageBox.setText(text);
    messageBox.setStandardButtons(QDialogButtonBox::Yes|QDialogButtonBox::Cancel);
    if (!stopButtonText.isEmpty())
        messageBox.button(QDialogButtonBox::Yes)->setText(stopButtonText);
    if (!cancelButtonText.isEmpty())
        messageBox.button(QDialogButtonBox::Cancel)->setText(cancelButtonText);
    messageBox.setDefaultButton(QDialogButtonBox::Yes);
    if (prompt) {
        messageBox.setCheckBoxText(tr("Do not ask again"));
        messageBox.setChecked(false);
    } else {
        messageBox.setCheckBoxVisible(false);
    }
    messageBox.exec();
    const bool close = messageBox.clickedStandardButton() == QDialogButtonBox::Yes;
    if (close && prompt && messageBox.isChecked())
        *prompt = false;
    return close;
662 663 664
}

bool RunControl::sameRunConfiguration(const RunControl *other) const
con's avatar
con committed
665
{
666
    return other->m_runConfiguration.data() == m_runConfiguration.data();
con's avatar
con committed
667 668 669 670 671 672 673 674
}

void RunControl::bringApplicationToForeground(qint64 pid)
{
#ifdef Q_OS_MAC
    m_internalPid = pid;
    m_foregroundCount = 0;
    bringApplicationToForegroundInternal();
Friedemann Kleint's avatar
Friedemann Kleint committed
675 676
#else
    Q_UNUSED(pid)
con's avatar
con committed
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694
#endif
}

void RunControl::bringApplicationToForegroundInternal()
{
#ifdef Q_OS_MAC
    ProcessSerialNumber psn;
    GetProcessForPID(m_internalPid, &psn);
    if (SetFrontProcess(&psn) == procNotFound && m_foregroundCount < 15) {
        // somehow the mac/carbon api says
        // "-600 no eligible process with specified process id"
        // if we call SetFrontProcess too early
        ++m_foregroundCount;
        QTimer::singleShot(200, this, SLOT(bringApplicationToForegroundInternal()));
        return;
    }
#endif
}
695

con's avatar
con committed
696
void RunControl::appendMessage(const QString &msg, Utils::OutputFormat format)
697 698 699
{
    emit appendMessage(this, msg, format);
}