runconfiguration.cpp 18.8 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/outputformatter.h>
41 42 43
#include <utils/checkablemessagebox.h>

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

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

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

using namespace ProjectExplorer;

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

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

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

65 66
/*!
    \class ProjectExplorer::ProcessHandle
67
    \brief The ProcessHandle class is a helper class to describe a process.
68

69 70
    Encapsulates parameters of a running process, local (PID) or remote (to be done,
    address, port, etc).
71 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
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;
}

106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
///////////////////////////////////////////////////////////////////////
//
// ISettingsAspect
//
///////////////////////////////////////////////////////////////////////

ISettingsAspect *ISettingsAspect::clone() const
{
    ISettingsAspect *other = create();
    QVariantMap data;
    toMap(data);
    other->fromMap(data);
    return other;
}

///////////////////////////////////////////////////////////////////////
//
// IRunConfigurationAspect
//
///////////////////////////////////////////////////////////////////////

IRunConfigurationAspect::IRunConfigurationAspect(RunConfiguration *parent)
{
    m_runConfiguration = parent;
    m_projectSettings = 0;
    m_globalSettings = 0;
    m_useGlobalSettings = false;
    connect(this, SIGNAL(requestRunActionsUpdate()), parent, SIGNAL(requestRunActionsUpdate()));
}

IRunConfigurationAspect::~IRunConfigurationAspect()
{
    delete m_projectSettings;
}
140

141 142 143
/*!
    \brief Returns the widget used to configure this run configuration. Ownership is transferred to the caller
*/
144

145 146 147 148 149
RunConfigWidget *IRunConfigurationAspect::createConfigurationWidget()
{
    return 0;
}

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
void IRunConfigurationAspect::setProjectSettings(ISettingsAspect *settings)
{
    m_projectSettings = settings;
}

void IRunConfigurationAspect::setGlobalSettings(ISettingsAspect *settings)
{
    m_globalSettings = settings;
}

void IRunConfigurationAspect::setUsingGlobalSettings(bool value)
{
    m_useGlobalSettings = value;
}

ISettingsAspect *IRunConfigurationAspect::currentSettings() const
{
   return m_useGlobalSettings ? m_globalSettings : m_projectSettings;
}

void IRunConfigurationAspect::fromMap(const QVariantMap &map)
{
    m_projectSettings->fromMap(map);
    m_useGlobalSettings = map.value(m_id.toString() + QLatin1String(".UseGlobalSettings"), true).toBool();
}

void IRunConfigurationAspect::toMap(QVariantMap &map) const
{
    m_projectSettings->toMap(map);
    map.insert(m_id.toString() + QLatin1String(".UseGlobalSettings"), m_useGlobalSettings);
}

IRunConfigurationAspect *IRunConfigurationAspect::clone(RunConfiguration *parent) const
{
    IRunConfigurationAspect *other = create(parent);
    other->m_projectSettings = m_projectSettings->clone();
    other->m_globalSettings = m_globalSettings;
    other->m_useGlobalSettings = m_useGlobalSettings;
    return other;
}

void IRunConfigurationAspect::resetProjectToGlobalSettings()
{
    QTC_ASSERT(m_globalSettings, return);
    QVariantMap map;
    m_globalSettings->toMap(map);
    m_projectSettings->fromMap(map);
}

199

200 201
/*!
    \class ProjectExplorer::RunConfiguration
202
    \brief The RunConfiguration class is the base class for a run configuration.
203

204 205 206 207 208 209
    A run configuration specifies how a target should be run, while a runner
    does the actual running.

    All RunControls and the target hold a shared pointer to the run
    configuration. That is, the lifetime of the run configuration might exceed
    the life of the target.
210 211 212
    The user might still have a RunControl running (or output tab of that RunControl open)
    and yet unloaded the target.

213 214
    Also, a run configuration might be already removed from the list of run
    configurations
215 216 217
    for a target, but still be runnable via the output tab.
*/

218
RunConfiguration::RunConfiguration(Target *target, const Core::Id id) :
219
    ProjectConfiguration(target, id),
220
    m_aspectsInitialized(false)
con's avatar
con committed
221
{
Tobias Hunger's avatar
Tobias Hunger committed
222
    Q_ASSERT(target);
223
    ctor();
224 225
}

Tobias Hunger's avatar
Tobias Hunger committed
226
RunConfiguration::RunConfiguration(Target *target, RunConfiguration *source) :
227
    ProjectConfiguration(target, source),
228
    m_aspectsInitialized(true)
229
{
Tobias Hunger's avatar
Tobias Hunger committed
230
    Q_ASSERT(target);
231
    ctor();
232
    foreach (IRunConfigurationAspect *aspect, source->m_aspects) {
233 234 235
        IRunConfigurationAspect *clone = aspect->clone(this);
        if (clone)
            m_aspects.append(clone);
236
    }
con's avatar
con committed
237 238 239 240
}

RunConfiguration::~RunConfiguration()
{
241 242 243 244 245
    qDeleteAll(m_aspects);
}

void RunConfiguration::addExtraAspects()
{
246 247 248
    if (m_aspectsInitialized)
        return;

249
    foreach (IRunControlFactory *factory, ExtensionSystem::PluginManager::getObjects<IRunControlFactory>())
250
        addExtraAspect(factory->createRunConfigurationAspect(this));
251
    m_aspectsInitialized = true;
con's avatar
con committed
252 253
}

254 255 256 257 258 259
void RunConfiguration::addExtraAspect(IRunConfigurationAspect *aspect)
{
    if (aspect)
        m_aspects += aspect;
}

260 261 262 263 264
void RunConfiguration::ctor()
{
    connect(this, SIGNAL(enabledChanged()), this, SIGNAL(requestRunActionsUpdate()));
}

265
/*!
266
    \brief Used to find out whether a runconfiguration is enabled
267 268
*/

269
bool RunConfiguration::isEnabled() const
con's avatar
con committed
270
{
271
    return true;
con's avatar
con committed
272 273
}

dt_'s avatar
dt_ committed
274 275 276 277 278
QString RunConfiguration::disabledReason() const
{
    return QString();
}

Tobias Hunger's avatar
Tobias Hunger committed
279 280 281 282 283
bool RunConfiguration::isConfigured() const
{
    return true;
}

284 285 286 287 288 289 290 291 292 293
bool RunConfiguration::ensureConfigured(QString *errorMessage)
{
    if (isConfigured())
        return true;
    if (errorMessage)
        *errorMessage = tr("Unknown error.");
    return false;
}


294
BuildConfiguration *RunConfiguration::activeBuildConfiguration() const
con's avatar
con committed
295
{
Tobias Hunger's avatar
Tobias Hunger committed
296
    if (!target())
297
        return 0;
Tobias Hunger's avatar
Tobias Hunger committed
298
    return target()->activeBuildConfiguration();
con's avatar
con committed
299 300
}

Tobias Hunger's avatar
Tobias Hunger committed
301
Target *RunConfiguration::target() const
con's avatar
con committed
302
{
Tobias Hunger's avatar
Tobias Hunger committed
303
    return static_cast<Target *>(parent());
con's avatar
con committed
304 305
}

306 307
QVariantMap RunConfiguration::toMap() const
{
308 309
    QVariantMap map = ProjectConfiguration::toMap();

310
    foreach (IRunConfigurationAspect *aspect, m_aspects)
311
        aspect->toMap(map);
312

313 314 315
    return map;
}

316 317 318 319 320
ProjectExplorer::Abi RunConfiguration::abi() const
{
    BuildConfiguration *bc = target()->activeBuildConfiguration();
    if (!bc)
        return Abi::hostAbi();
Tobias Hunger's avatar
Tobias Hunger committed
321
    ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(target()->kit());
322 323 324 325 326
    if (!tc)
        return Abi::hostAbi();
    return tc->targetAbi();
}

327 328
bool RunConfiguration::fromMap(const QVariantMap &map)
{
329
    addExtraAspects();
330

331
    foreach (IRunConfigurationAspect *aspect, m_aspects)
332
        aspect->fromMap(map);
333

334 335 336
    return ProjectConfiguration::fromMap(map);
}

337 338 339
/*!
    \class ProjectExplorer::IRunConfigurationAspect

340 341
    \brief The IRunConfigurationAspect class provides an additional
    configuration aspect.
342 343 344 345 346 347 348 349 350 351 352 353

    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
*/

354 355
QList<IRunConfigurationAspect *> RunConfiguration::extraAspects() const
{
356
    QTC_ASSERT(m_aspectsInitialized, return QList<IRunConfigurationAspect *>());
357 358
    return m_aspects;
}
359 360 361 362 363 364 365 366
IRunConfigurationAspect *RunConfiguration::extraAspect(Core::Id id) const
{
    QTC_ASSERT(m_aspectsInitialized, return 0);
    foreach (IRunConfigurationAspect *aspect, m_aspects)
        if (aspect->id() == id)
            return aspect;
    return 0;
}
367

con's avatar
con committed
368
Utils::OutputFormatter *RunConfiguration::createOutputFormatter() const
dt's avatar
dt committed
369
{
con's avatar
con committed
370
    return new Utils::OutputFormatter();
dt's avatar
dt committed
371 372
}

373

374 375 376
/*!
    \class ProjectExplorer::IRunConfigurationFactory

377 378
    \brief The IRunConfigurationFactory class restores run configurations from
    settings.
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395

    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.
*/

/*!
396
    \fn QString ProjectExplorer::IRunConfigurationFactory::displayNameForId(const Core::Id id) const
397 398 399
    \brief Used to translate the types to names to display to the user.
*/

400 401
IRunConfigurationFactory::IRunConfigurationFactory(QObject *parent) :
    QObject(parent)
con's avatar
con committed
402 403 404 405 406 407 408
{
}

IRunConfigurationFactory::~IRunConfigurationFactory()
{
}

409 410 411 412 413 414 415 416 417 418 419
RunConfiguration *IRunConfigurationFactory::create(Target *parent, const Core::Id id)
{
    if (!canCreate(parent, id))
        return 0;
    RunConfiguration *rc = doCreate(parent, id);
    if (!rc)
        return 0;
    rc->addExtraAspects();
    return rc;
}

420 421 422 423 424 425 426 427 428 429 430 431
RunConfiguration *IRunConfigurationFactory::restore(Target *parent, const QVariantMap &map)
{
    if (!canRestore(parent, map))
        return 0;
    RunConfiguration *rc = doRestore(parent, map);
    if (!rc->fromMap(map)) {
        delete rc;
        rc = 0;
    }
    return rc;
}

Tobias Hunger's avatar
Tobias Hunger committed
432
IRunConfigurationFactory *IRunConfigurationFactory::find(Target *parent, const QVariantMap &map)
Tobias Hunger's avatar
Tobias Hunger committed
433
{
Tobias Hunger's avatar
Tobias Hunger committed
434
    QList<IRunConfigurationFactory *> factories
435
            = ExtensionSystem::PluginManager::getObjects<IRunConfigurationFactory>();
Tobias Hunger's avatar
Tobias Hunger committed
436 437 438 439 440
    foreach (IRunConfigurationFactory *factory, factories) {
        if (factory->canRestore(parent, map))
            return factory;
    }
    return 0;
Tobias Hunger's avatar
Tobias Hunger committed
441 442
}

443 444 445
IRunConfigurationFactory *IRunConfigurationFactory::find(Target *parent, RunConfiguration *rc)
{
    QList<IRunConfigurationFactory *> factories
446
            = ExtensionSystem::PluginManager::getObjects<IRunConfigurationFactory>();
447 448 449 450 451 452 453
    foreach (IRunConfigurationFactory *factory, factories) {
        if (factory->canClone(parent, rc))
            return factory;
    }
    return 0;
}

Tobias Hunger's avatar
Tobias Hunger committed
454
QList<IRunConfigurationFactory *> IRunConfigurationFactory::find(Target *parent)
Tobias Hunger's avatar
Tobias Hunger committed
455
{
Tobias Hunger's avatar
Tobias Hunger committed
456
    QList<IRunConfigurationFactory *> factories
457
            = ExtensionSystem::PluginManager::getObjects<IRunConfigurationFactory>();
Tobias Hunger's avatar
Tobias Hunger committed
458 459 460 461 462 463
    QList<IRunConfigurationFactory *> result;
    foreach (IRunConfigurationFactory *factory, factories) {
        if (!factory->availableCreationIds(parent).isEmpty())
            result << factory;
    }
    return result;
Tobias Hunger's avatar
Tobias Hunger committed
464 465
}

466 467 468
/*!
    \class ProjectExplorer::IRunControlFactory

469 470
    \brief The IRunControlFactory class creates RunControl objects matching a
    run configuration.
471 472 473
*/

/*!
474
    \fn IRunConfigurationAspect *ProjectExplorer::IRunControlFactory::createRunConfigurationAspect(RunConfiguration *rc)
475 476 477 478 479 480 481 482
    \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.
*/

/*!
483
    \fn RunConfigWidget *ProjectExplorer::IRunConfigurationAspect::createConfigurationWidget()
484 485 486 487 488 489 490

    \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.
*/

491
IRunControlFactory::IRunControlFactory(QObject *parent)
492
    : QObject(parent)
con's avatar
con committed
493 494 495
{
}

496
IRunControlFactory::~IRunControlFactory()
con's avatar
con committed
497 498 499
{
}

500
IRunConfigurationAspect *IRunControlFactory::createRunConfigurationAspect(RunConfiguration *rc)
501
{
502
    Q_UNUSED(rc);
503 504 505
    return 0;
}

506 507
/*!
    \class ProjectExplorer::RunControl
508
    \brief The RunControl class instances represent one item that is run.
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
*/

/*!
    \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.
*/

525
RunControl::RunControl(RunConfiguration *runConfiguration, RunMode mode)
526
    : m_runMode(mode), m_runConfiguration(runConfiguration), m_outputFormatter(0)
con's avatar
con committed
527
{
dt's avatar
dt committed
528
    if (runConfiguration) {
529
        m_displayName  = runConfiguration->displayName();
dt's avatar
dt committed
530 531 532 533
        m_outputFormatter = runConfiguration->createOutputFormatter();
    }
    // We need to ensure that there's always a OutputFormatter
    if (!m_outputFormatter)
con's avatar
con committed
534
        m_outputFormatter = new Utils::OutputFormatter();
con's avatar
con committed
535 536
}

537
RunControl::~RunControl()
con's avatar
con committed
538
{
dt's avatar
dt committed
539 540
    delete m_outputFormatter;
}
541

con's avatar
con committed
542
Utils::OutputFormatter *RunControl::outputFormatter()
dt's avatar
dt committed
543 544
{
    return m_outputFormatter;
con's avatar
con committed
545 546
}

547
RunMode RunControl::runMode() const
dt's avatar
dt committed
548 549 550 551
{
    return m_runMode;
}

552 553 554 555 556
QString RunControl::displayName() const
{
    return m_displayName;
}

557 558 559 560 561 562 563
Abi RunControl::abi() const
{
    if (const RunConfiguration *rc = m_runConfiguration.data())
        return rc->abi();
    return Abi();
}

564 565 566 567 568
RunConfiguration *RunControl::runConfiguration() const
{
    return m_runConfiguration.data();
}

569 570 571 572 573 574 575
ProcessHandle RunControl::applicationProcessHandle() const
{
    return m_applicationProcessHandle;
}

void RunControl::setApplicationProcessHandle(const ProcessHandle &handle)
{
576 577 578 579
    if (m_applicationProcessHandle != handle) {
        m_applicationProcessHandle = handle;
        emit applicationProcessHandleChanged();
    }
580 581
}

582
bool RunControl::promptToStop(bool *optionalPrompt) const
583
{
584
    QTC_ASSERT(isRunning(), return true);
585

586 587 588 589 590 591 592 593 594 595
    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);
}

596 597 598 599
/*!
    \brief Utility to prompt to terminate application with checkable box.
*/

600 601 602 603 604 605
bool RunControl::showPromptToStopDialog(const QString &title,
                                        const QString &text,
                                        const QString &stopButtonText,
                                        const QString &cancelButtonText,
                                        bool *prompt) const
{
606
    QTC_ASSERT(isRunning(), return true);
607 608
    // Show a question message box where user can uncheck this
    // question for this class.
hjk's avatar
hjk committed
609
    Utils::CheckableMessageBox messageBox(Core::ICore::mainWindow());
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
    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;
629 630 631
}

bool RunControl::sameRunConfiguration(const RunControl *other) const
con's avatar
con committed
632
{
633
    return other->m_runConfiguration.data() == m_runConfiguration.data();
con's avatar
con committed
634 635 636 637 638 639 640 641
}

void RunControl::bringApplicationToForeground(qint64 pid)
{
#ifdef Q_OS_MAC
    m_internalPid = pid;
    m_foregroundCount = 0;
    bringApplicationToForegroundInternal();
Friedemann Kleint's avatar
Friedemann Kleint committed
642 643
#else
    Q_UNUSED(pid)
con's avatar
con committed
644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661
#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
}
662

con's avatar
con committed
663
void RunControl::appendMessage(const QString &msg, Utils::OutputFormat format)
664 665 666
{
    emit appendMessage(this, msg, format);
}