runconfiguration.cpp 20.2 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8 9 10 11 12 13 14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17 18 19 20 21 22 23 24 25
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26 27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
hjk's avatar
hjk committed
29

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

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

40
#include <utils/qtcassert.h>
41
#include <utils/outputformatter.h>
42 43 44
#include <utils/checkablemessagebox.h>

#include <coreplugin/icore.h>
45
#include <coreplugin/icontext.h>
Tobias Hunger's avatar
Tobias Hunger committed
46

47 48
#include <QTimer>
#include <QPushButton>
con's avatar
con committed
49 50

#ifdef Q_OS_MAC
Eike Ziller's avatar
Eike Ziller committed
51
#include <ApplicationServices/ApplicationServices.h>
con's avatar
con committed
52 53 54 55
#endif

using namespace ProjectExplorer;

Tobias Hunger's avatar
Tobias Hunger committed
56 57
namespace {

hjk's avatar
hjk committed
58 59 60 61
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";
62
const char USE_MULTIPROCESS_KEY[] = "RunConfiguration.UseMultiProcess";
hjk's avatar
hjk committed
63

Tobias Hunger's avatar
Tobias Hunger committed
64 65
} // namespace

66 67 68 69
/*!
    \class ProjectExplorer::ProcessHandle
    \brief  Helper class to describe a process.

70 71
    Encapsulates parameters of a running process, local (PID) or remote (to be done,
    address, port, etc).
72 73
*/

74 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
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;
}

107
/*!
108
    \class ProjectExplorer::DebuggerRunConfigurationAspect
109 110
*/

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

123
DebuggerRunConfigurationAspect::DebuggerRunConfigurationAspect(RunConfiguration *runConfiguration,
124
                                                               const DebuggerRunConfigurationAspect *other)
125 126 127 128 129 130 131 132 133
    : 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)
134 135
{}

136
RunConfiguration *DebuggerRunConfigurationAspect::runConfiguration()
137 138 139 140
{
    return m_runConfiguration;
}

141
void DebuggerRunConfigurationAspect::setUseQmlDebugger(bool value)
142 143 144 145 146
{
    m_useQmlDebugger = value ? EnableQmlDebugger : DisableQmlDebugger;
    emit debuggersChanged();
}

147
void DebuggerRunConfigurationAspect::setUseCppDebugger(bool value)
148 149 150 151 152
{
    m_useCppDebugger = value;
    emit debuggersChanged();
}

153
bool DebuggerRunConfigurationAspect::useCppDebugger() const
154 155 156 157
{
    return m_useCppDebugger;
}

158
bool DebuggerRunConfigurationAspect::useQmlDebugger() const
159
{
160
    if (m_useQmlDebugger == DebuggerRunConfigurationAspect::AutoEnableQmlDebugger)
161 162
        return m_runConfiguration->target()->project()->projectLanguages().contains(
                    ProjectExplorer::Constants::LANG_QMLJS);
163
    return m_useQmlDebugger == DebuggerRunConfigurationAspect::EnableQmlDebugger;
164 165
}

166
uint DebuggerRunConfigurationAspect::qmlDebugServerPort() const
167
{
168
    return m_qmlDebugServerPort;
169 170
}

171
void DebuggerRunConfigurationAspect::setQmllDebugServerPort(uint port)
172
{
173
    m_qmlDebugServerPort = port;
174 175
}

176 177 178 179 180 181 182 183 184 185
bool DebuggerRunConfigurationAspect::useMultiProcess() const
{
    return m_useMultiProcess;
}

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

186 187 188 189 190
void DebuggerRunConfigurationAspect::suppressDisplay()
{
    m_suppressDisplay = true;
}

191
void DebuggerRunConfigurationAspect::suppressQmlDebuggingOptions()
192
{
193 194 195
    m_suppressQmlDebuggingOptions = true;
}

196 197 198 199 200
void DebuggerRunConfigurationAspect::suppressCppDebuggingOptions()
{
    m_suppressCppDebuggingOptions = true;
}

201 202 203 204 205
void DebuggerRunConfigurationAspect::suppressQmlDebuggingSpinbox()
{
    m_suppressQmlDebuggingSpinbox = true;
}

206 207 208 209 210
bool DebuggerRunConfigurationAspect::isDisplaySuppressed() const
{
    return m_suppressDisplay;
}

211
bool DebuggerRunConfigurationAspect::areQmlDebuggingOptionsSuppressed() const
212 213
{
    return m_suppressQmlDebuggingOptions;
214 215
}

216 217 218 219 220
bool DebuggerRunConfigurationAspect::areCppDebuggingOptionsSuppressed() const
{
    return m_suppressCppDebuggingOptions;
}

221 222 223 224 225
bool DebuggerRunConfigurationAspect::isQmlDebuggingSpinboxSuppressed() const
{
    return m_suppressQmlDebuggingSpinbox;
}

226
QString DebuggerRunConfigurationAspect::displayName() const
227 228 229 230
{
    return tr("Debugger settings");
}

231
QVariantMap DebuggerRunConfigurationAspect::toMap() const
232 233 234 235 236 237
{
    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);
238
    map.insert(QLatin1String(USE_MULTIPROCESS_KEY), m_useMultiProcess);
239 240 241
    return map;
}

242
void DebuggerRunConfigurationAspect::fromMap(const QVariantMap &map)
243 244 245 246 247 248 249 250
{
    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;
    }
251
    m_useMultiProcess = map.value(QLatin1String(USE_MULTIPROCESS_KEY), false).toBool();
252 253
}

254 255 256 257 258
DebuggerRunConfigurationAspect *DebuggerRunConfigurationAspect::clone(RunConfiguration *parent) const
{
    return new DebuggerRunConfigurationAspect(parent, this);
}

259

260 261 262 263 264 265 266 267 268 269 270 271 272 273
/*!
    \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.
*/

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

Tobias Hunger's avatar
Tobias Hunger committed
282
RunConfiguration::RunConfiguration(Target *target, RunConfiguration *source) :
283
    ProjectConfiguration(target, source),
284
    m_debuggerAspect(source->debuggerAspect()->clone(this))
285
{
Tobias Hunger's avatar
Tobias Hunger committed
286
    Q_ASSERT(target);
287
    foreach (IRunConfigurationAspect *aspect, source->m_aspects) {
288 289 290
        IRunConfigurationAspect *clone = aspect->clone(this);
        if (clone)
            m_aspects.append(clone);
291
    }
con's avatar
con committed
292 293 294 295
}

RunConfiguration::~RunConfiguration()
{
296
    delete m_debuggerAspect;
297 298 299 300 301
    qDeleteAll(m_aspects);
}

void RunConfiguration::addExtraAspects()
{
302
    foreach (IRunControlFactory *factory, ExtensionSystem::PluginManager::getObjects<IRunControlFactory>())
303 304
        if (IRunConfigurationAspect *aspect = factory->createRunConfigurationAspect())
            m_aspects.append(aspect);
con's avatar
con committed
305 306
}

307
/*!
308
    \brief Used to find out whether a runconfiguration is enabled
309 310
*/

311
bool RunConfiguration::isEnabled() const
con's avatar
con committed
312
{
313
    return true;
con's avatar
con committed
314 315
}

dt_'s avatar
dt_ committed
316 317 318 319 320
QString RunConfiguration::disabledReason() const
{
    return QString();
}

Tobias Hunger's avatar
Tobias Hunger committed
321 322 323 324 325
bool RunConfiguration::isConfigured() const
{
    return true;
}

326 327 328 329 330 331 332 333 334 335
bool RunConfiguration::ensureConfigured(QString *errorMessage)
{
    if (isConfigured())
        return true;
    if (errorMessage)
        *errorMessage = tr("Unknown error.");
    return false;
}


336 337 338 339 340 341
/*!
    \fn virtual QWidget *ProjectExplorer::RunConfiguration::createConfigurationWidget()

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

342
BuildConfiguration *RunConfiguration::activeBuildConfiguration() const
con's avatar
con committed
343
{
Tobias Hunger's avatar
Tobias Hunger committed
344
    if (!target())
345
        return 0;
Tobias Hunger's avatar
Tobias Hunger committed
346
    return target()->activeBuildConfiguration();
con's avatar
con committed
347 348
}

Tobias Hunger's avatar
Tobias Hunger committed
349
Target *RunConfiguration::target() const
con's avatar
con committed
350
{
Tobias Hunger's avatar
Tobias Hunger committed
351
    return static_cast<Target *>(parent());
con's avatar
con committed
352 353
}

354 355
QVariantMap RunConfiguration::toMap() const
{
356 357 358
    QVariantMap map = ProjectConfiguration::toMap();

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

360 361 362
    foreach (IRunConfigurationAspect *aspect, m_aspects)
        map.unite(aspect->toMap());

363 364 365
    return map;
}

366 367 368 369 370
ProjectExplorer::Abi RunConfiguration::abi() const
{
    BuildConfiguration *bc = target()->activeBuildConfiguration();
    if (!bc)
        return Abi::hostAbi();
Tobias Hunger's avatar
Tobias Hunger committed
371
    ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit());
372 373 374 375 376
    if (!tc)
        return Abi::hostAbi();
    return tc->targetAbi();
}

377 378
bool RunConfiguration::fromMap(const QVariantMap &map)
{
379
    m_debuggerAspect->fromMap(map);
380

381
    foreach (IRunConfigurationAspect *aspect, m_aspects)
382
        aspect->fromMap(map);
383

384 385 386
    return ProjectConfiguration::fromMap(map);
}

387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
/*!
    \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
*/

403 404 405 406 407
QList<IRunConfigurationAspect *> RunConfiguration::extraAspects() const
{
    return m_aspects;
}

con's avatar
con committed
408
Utils::OutputFormatter *RunConfiguration::createOutputFormatter() const
dt's avatar
dt committed
409
{
con's avatar
con committed
410
    return new Utils::OutputFormatter();
dt's avatar
dt committed
411 412
}

413

414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
/*!
    \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.
*/

439 440
IRunConfigurationFactory::IRunConfigurationFactory(QObject *parent) :
    QObject(parent)
con's avatar
con committed
441 442 443 444 445 446 447
{
}

IRunConfigurationFactory::~IRunConfigurationFactory()
{
}

Tobias Hunger's avatar
Tobias Hunger committed
448
IRunConfigurationFactory *IRunConfigurationFactory::find(Target *parent, const QVariantMap &map)
Tobias Hunger's avatar
Tobias Hunger committed
449
{
Tobias Hunger's avatar
Tobias Hunger committed
450 451 452 453 454 455 456
    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
457 458
}

459 460 461 462 463 464 465 466 467 468 469
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
470
QList<IRunConfigurationFactory *> IRunConfigurationFactory::find(Target *parent)
Tobias Hunger's avatar
Tobias Hunger committed
471
{
Tobias Hunger's avatar
Tobias Hunger committed
472 473 474 475 476 477 478 479
    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
480 481
}

482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
/*!
    \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.
*/

506
IRunControlFactory::IRunControlFactory(QObject *parent)
507
    : QObject(parent)
con's avatar
con committed
508 509 510
{
}

511
IRunControlFactory::~IRunControlFactory()
con's avatar
con committed
512 513 514
{
}

515 516 517 518 519
IRunConfigurationAspect *IRunControlFactory::createRunConfigurationAspect()
{
    return 0;
}

520 521 522 523 524
RunConfigWidget *IRunControlFactory::createConfigurationWidget(RunConfiguration *)
{
    return 0;
}

525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
/*!
    \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.
*/

544
RunControl::RunControl(RunConfiguration *runConfiguration, RunMode mode)
545
    : m_runMode(mode), m_runConfiguration(runConfiguration), m_outputFormatter(0)
con's avatar
con committed
546
{
dt's avatar
dt committed
547
    if (runConfiguration) {
548
        m_displayName  = runConfiguration->displayName();
dt's avatar
dt committed
549 550 551 552
        m_outputFormatter = runConfiguration->createOutputFormatter();
    }
    // We need to ensure that there's always a OutputFormatter
    if (!m_outputFormatter)
con's avatar
con committed
553
        m_outputFormatter = new Utils::OutputFormatter();
con's avatar
con committed
554 555
}

556
RunControl::~RunControl()
con's avatar
con committed
557
{
dt's avatar
dt committed
558 559
    delete m_outputFormatter;
}
560

con's avatar
con committed
561
Utils::OutputFormatter *RunControl::outputFormatter()
dt's avatar
dt committed
562 563
{
    return m_outputFormatter;
con's avatar
con committed
564 565
}

566
RunMode RunControl::runMode() const
dt's avatar
dt committed
567 568 569 570
{
    return m_runMode;
}

571 572 573 574 575
QString RunControl::displayName() const
{
    return m_displayName;
}

576 577 578 579 580 581 582
Abi RunControl::abi() const
{
    if (const RunConfiguration *rc = m_runConfiguration.data())
        return rc->abi();
    return Abi();
}

583 584 585 586 587
RunConfiguration *RunControl::runConfiguration() const
{
    return m_runConfiguration.data();
}

588 589 590 591 592 593 594
ProcessHandle RunControl::applicationProcessHandle() const
{
    return m_applicationProcessHandle;
}

void RunControl::setApplicationProcessHandle(const ProcessHandle &handle)
{
595 596 597 598
    if (m_applicationProcessHandle != handle) {
        m_applicationProcessHandle = handle;
        emit applicationProcessHandleChanged();
    }
599 600
}

601
bool RunControl::promptToStop(bool *optionalPrompt) const
602
{
603
    QTC_ASSERT(isRunning(), return true);
604

605 606 607 608 609 610 611 612 613 614
    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);
}

615 616 617 618
/*!
    \brief Utility to prompt to terminate application with checkable box.
*/

619 620 621 622 623 624
bool RunControl::showPromptToStopDialog(const QString &title,
                                        const QString &text,
                                        const QString &stopButtonText,
                                        const QString &cancelButtonText,
                                        bool *prompt) const
{
625
    QTC_ASSERT(isRunning(), return true);
626 627
    // Show a question message box where user can uncheck this
    // question for this class.
hjk's avatar
hjk committed
628
    Utils::CheckableMessageBox messageBox(Core::ICore::mainWindow());
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
    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;
648 649 650
}

bool RunControl::sameRunConfiguration(const RunControl *other) const
con's avatar
con committed
651
{
652
    return other->m_runConfiguration.data() == m_runConfiguration.data();
con's avatar
con committed
653 654 655 656 657 658 659 660
}

void RunControl::bringApplicationToForeground(qint64 pid)
{
#ifdef Q_OS_MAC
    m_internalPid = pid;
    m_foregroundCount = 0;
    bringApplicationToForegroundInternal();
Friedemann Kleint's avatar
Friedemann Kleint committed
661 662
#else
    Q_UNUSED(pid)
con's avatar
con committed
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
#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
}
681

con's avatar
con committed
682
void RunControl::appendMessage(const QString &msg, Utils::OutputFormat format)
683 684 685
{
    emit appendMessage(this, msg, format);
}