remotelinuxrunconfiguration.cpp 17.7 KB
Newer Older
ck's avatar
ck committed
1
2
3
4
/**************************************************************************
**
** This file is part of Qt Creator
**
con's avatar
con committed
5
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
ck's avatar
ck committed
6
**
hjk's avatar
hjk committed
7
** Contact: Nokia Corporation (info@qt.nokia.com)
ck's avatar
ck committed
8
9
10
11
**
**
** GNU Lesser General Public License Usage
**
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.
ck's avatar
ck committed
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
** If you have questions regarding the use of this file, please contact
Tobias Hunger's avatar
Tobias Hunger committed
29
** Nokia at info@qt.nokia.com.
ck's avatar
ck committed
30
31
**
**************************************************************************/
32

33
#include "remotelinuxrunconfiguration.h"
ck's avatar
ck committed
34

35
#include "abstractlinuxdevicedeploystep.h"
36
#include "maemodeployables.h"
ck's avatar
ck committed
37
#include "maemoglobal.h"
ck's avatar
ck committed
38
#include "maemoqemumanager.h"
39
#include "maemoremotemountsmodel.h"
40
#include "maemorunconfigurationwidget.h"
ck's avatar
ck committed
41
#include "maemotoolchain.h"
42
#include "qt4maemodeployconfiguration.h"
43
#include "qt4maemotarget.h"
dt's avatar
dt committed
44
#include "maemoqtversion.h"
ck's avatar
ck committed
45
46
47

#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
48

49
50
#include <debugger/debuggerconstants.h>

51
#include <projectexplorer/projectexplorer.h>
52
#include <projectexplorer/projectexplorerconstants.h>
53
#include <projectexplorer/session.h>
54

55
#include <qtsupport/qtoutputformatter.h>
56
#include <qt4projectmanager/qt4buildconfiguration.h>
57
#include <qt4projectmanager/qt4nodes.h>
58
#include <qt4projectmanager/qt4project.h>
Christian Kandeler's avatar
Christian Kandeler committed
59
#include <qt4projectmanager/qt4target.h>
60

ck's avatar
ck committed
61
#include <utils/qtcassert.h>
62
#include <utils/qtcprocess.h>
ck's avatar
ck committed
63

ck's avatar
ck committed
64
#include <QtCore/QStringBuilder>
ck's avatar
ck committed
65

66
67
68
69
using namespace ProjectExplorer;
using namespace Qt4ProjectManager;

namespace RemoteLinux {
ck's avatar
ck committed
70

71
namespace {
72
const bool DefaultUseRemoteGdbValue = false;
73
} // anonymous namespace
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
107
108
namespace Internal {
class RemoteLinuxRunConfigurationPrivate {
public:
    RemoteLinuxRunConfigurationPrivate(const QString &proFilePath, const Qt4BaseTarget *target)
        : proFilePath(proFilePath), useRemoteGdb(DefaultUseRemoteGdbValue),
          baseEnvironmentType(RemoteLinuxRunConfiguration::SystemBaseEnvironment),
          validParse(target->qt4Project()->validParse(proFilePath))
    {
    }

    RemoteLinuxRunConfigurationPrivate(const RemoteLinuxRunConfigurationPrivate *other)
        : proFilePath(other->proFilePath), gdbPath(other->gdbPath), arguments(other->arguments),
          useRemoteGdb(other->useRemoteGdb), baseEnvironmentType(other->baseEnvironmentType),
          systemEnvironment(other->systemEnvironment),
          userEnvironmentChanges(other->userEnvironmentChanges), validParse(other->validParse)
    {
    }

    QString proFilePath;
    QString gdbPath;
    MaemoRemoteMountsModel *remoteMounts;
    QString arguments;
    bool useRemoteGdb;
    RemoteLinuxRunConfiguration::BaseEnvironmentType baseEnvironmentType;
    Utils::Environment systemEnvironment;
    QList<Utils::EnvironmentItem> userEnvironmentChanges;
    bool validParse;
    QString disabledReason;
};
} // namespace Internal

using namespace Internal;

RemoteLinuxRunConfiguration::RemoteLinuxRunConfiguration(Qt4BaseTarget *parent,
ck's avatar
ck committed
109
        const QString &proFilePath)
110
111
    : RunConfiguration(parent, QLatin1String(MAEMO_RC_ID)),
      m_d(new RemoteLinuxRunConfigurationPrivate(proFilePath, parent))
112
{
ck's avatar
ck committed
113
    init();
114
115
}

116
117
118
119
RemoteLinuxRunConfiguration::RemoteLinuxRunConfiguration(Qt4BaseTarget *parent,
        RemoteLinuxRunConfiguration *source)
    : RunConfiguration(parent, source),
      m_d(new RemoteLinuxRunConfigurationPrivate(source->m_d))
120
{
ck's avatar
ck committed
121
    init();
122
123
}

124
void RemoteLinuxRunConfiguration::init()
ck's avatar
ck committed
125
{
126
    setDefaultDisplayName(defaultDisplayName());
127
128
    setUseCppDebugger(true);
    setUseQmlDebugger(false);
129
    m_d->remoteMounts = new MaemoRemoteMountsModel(this);
ck's avatar
ck committed
130

131
132
133
134
    connect(target(),
        SIGNAL(activeDeployConfigurationChanged(ProjectExplorer::DeployConfiguration*)),
        this, SLOT(handleDeployConfigChanged()));
    handleDeployConfigChanged();
ck's avatar
ck committed
135

Christian Kandeler's avatar
Christian Kandeler committed
136
    Qt4Project *pro = qt4Target()->qt4Project();
137
138
139
140
    connect(pro, SIGNAL(proFileUpdated(Qt4ProjectManager::Qt4ProFileNode*,bool)),
            this, SLOT(proFileUpdate(Qt4ProjectManager::Qt4ProFileNode*,bool)));
    connect(pro, SIGNAL(proFileInvalidated(Qt4ProjectManager::Qt4ProFileNode *)),
            this, SLOT(proFileInvalidated(Qt4ProjectManager::Qt4ProFileNode*)));
141
142
143
144
145
146
147
148
    connect(this, SIGNAL(debuggersChanged()), SLOT(updateEnabledState()));
    connect(m_d->remoteMounts, SIGNAL(rowsInserted(QModelIndex, int, int)), this,
        SLOT(handleRemoteMountsChanged()));
    connect(m_d->remoteMounts, SIGNAL(rowsRemoved(QModelIndex, int, int)), this,
        SLOT(handleRemoteMountsChanged()));
    connect(m_d->remoteMounts, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this,
        SLOT(handleRemoteMountsChanged()));
    connect(m_d->remoteMounts, SIGNAL(modelReset()), SLOT(handleRemoteMountsChanged()));
149
150
    connect(target(), SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
        SLOT(updateEnabledState()));
ck's avatar
ck committed
151
152
}

153
RemoteLinuxRunConfiguration::~RemoteLinuxRunConfiguration()
ck's avatar
ck committed
154
155
156
{
}

157
Qt4BaseTarget *RemoteLinuxRunConfiguration::qt4Target() const
ck's avatar
ck committed
158
{
Christian Kandeler's avatar
Christian Kandeler committed
159
    return static_cast<Qt4BaseTarget *>(target());
Tobias Hunger's avatar
Tobias Hunger committed
160
161
}

162
Qt4BuildConfiguration *RemoteLinuxRunConfiguration::activeQt4BuildConfiguration() const
Tobias Hunger's avatar
Tobias Hunger committed
163
164
{
    return static_cast<Qt4BuildConfiguration *>(activeBuildConfiguration());
ck's avatar
ck committed
165
166
}

167
bool RemoteLinuxRunConfiguration::isEnabled() const
ck's avatar
ck committed
168
{
169
170
    if (!m_d->validParse) {
        m_d->disabledReason = tr("The .pro file could not be parsed/");
171
172
173
        return false;
    }
    if (!deviceConfig()) {
174
        m_d->disabledReason = tr("No device configuration set.");
175
176
177
        return false;
    }
    if (!activeQt4BuildConfiguration()) {
178
        m_d->disabledReason = tr("No active build configuration.");
179
180
181
        return false;
    }
    if (remoteExecutableFilePath().isEmpty()) {
182
        m_d->disabledReason = tr("Don't know what to run.");
183
184
185
        return false;
    }
    if (!hasEnoughFreePorts(ProjectExplorer::Constants::RUNMODE)) {
186
        m_d->disabledReason = tr("Not enough free ports on the device.");
187
188
        return false;
    }
189
    m_d->disabledReason.clear();
190
    return true;
ck's avatar
ck committed
191
192
}

193
QString RemoteLinuxRunConfiguration::disabledReason() const
dt_'s avatar
dt_ committed
194
{
195
    return m_d->disabledReason;
dt_'s avatar
dt_ committed
196
197
}

198
QWidget *RemoteLinuxRunConfiguration::createConfigurationWidget()
ck's avatar
ck committed
199
200
201
202
{
    return new MaemoRunConfigurationWidget(this);
}

203
Utils::OutputFormatter *RemoteLinuxRunConfiguration::createOutputFormatter() const
dt's avatar
dt committed
204
{
205
    return new QtSupport::QtOutputFormatter(qt4Target()->qt4Project());
dt's avatar
dt committed
206
207
}

208
void RemoteLinuxRunConfiguration::handleParseState(bool success)
209
{
210
    bool enabled = isEnabled();
211
    m_d->validParse = success;
212
213
    if (enabled != isEnabled())
        updateEnabledState();
214
215
}

216
void RemoteLinuxRunConfiguration::proFileInvalidated(Qt4ProjectManager::Qt4ProFileNode *pro)
217
{
218
    if (m_d->proFilePath != pro->path())
219
220
221
222
        return;
    handleParseState(false);
}

223
void RemoteLinuxRunConfiguration::proFileUpdate(Qt4ProjectManager::Qt4ProFileNode *pro, bool success)
224
{
225
    if (m_d->proFilePath == pro->path()) {
226
        handleParseState(success);
dt's avatar
dt committed
227
        emit targetInformationChanged();
228
    }
229
230
}

231
QVariantMap RemoteLinuxRunConfiguration::toMap() const
ck's avatar
ck committed
232
{
233
    QVariantMap map(RunConfiguration::toMap());
234
    map.insert(ArgumentsKey, m_d->arguments);
235
    const QDir dir = QDir(target()->project()->projectDirectory());
236
    map.insert(ProFileKey, dir.relativeFilePath(m_d->proFilePath));
237
    map.insert(UseRemoteGdbKey, useRemoteGdb());
238
    map.insert(BaseEnvironmentBaseKey, m_d->baseEnvironmentType);
239
    map.insert(UserEnvironmentChangesKey,
240
241
        Utils::EnvironmentItem::toStringList(m_d->userEnvironmentChanges));
    map.unite(m_d->remoteMounts->toMap());
242
    return map;
ck's avatar
ck committed
243
244
}

245
bool RemoteLinuxRunConfiguration::fromMap(const QVariantMap &map)
ck's avatar
ck committed
246
{
247
248
249
    if (!RunConfiguration::fromMap(map))
        return false;

250
    m_d->arguments = map.value(ArgumentsKey).toString();
251
    const QDir dir = QDir(target()->project()->projectDirectory());
252
253
254
    m_d->proFilePath = dir.filePath(map.value(ProFileKey).toString());
    m_d->useRemoteGdb = map.value(UseRemoteGdbKey, DefaultUseRemoteGdbValue).toBool();
    m_d->userEnvironmentChanges =
255
        Utils::EnvironmentItem::fromStringList(map.value(UserEnvironmentChangesKey)
256
        .toStringList());
257
258
259
    m_d->baseEnvironmentType = static_cast<BaseEnvironmentType> (map.value(BaseEnvironmentBaseKey,
        SystemBaseEnvironment).toInt());
    m_d->remoteMounts->fromMap(map);
260

261
    m_d->validParse = qt4Target()->qt4Project()->validParse(m_d->proFilePath);
262

263
264
    setDefaultDisplayName(defaultDisplayName());

265
    return true;
ck's avatar
ck committed
266
267
}

268
QString RemoteLinuxRunConfiguration::defaultDisplayName()
269
{
270
271
272
    if (!m_d->proFilePath.isEmpty())
        return (QFileInfo(m_d->proFilePath).completeBaseName()) + QLatin1String(" (remote)");
    //: Remote Linux run configuration default display name
Christian Kandeler's avatar
Christian Kandeler committed
273
    return tr("Run on remote device");
274
275
}

276
LinuxDeviceConfiguration::ConstPtr RemoteLinuxRunConfiguration::deviceConfig() const
277
{
278
    const AbstractLinuxDeviceDeployStep * const step = deployStep();
279
    return step ? step->helper().deviceConfig() : LinuxDeviceConfiguration::ConstPtr();
ck's avatar
ck committed
280
281
}

282
QString RemoteLinuxRunConfiguration::gdbCmd() const
ck's avatar
ck committed
283
{
284
    return QDir::toNativeSeparators(activeBuildConfiguration()->toolChain()->debuggerCommand());
ck's avatar
ck committed
285
286
}

287
Qt4MaemoDeployConfiguration *RemoteLinuxRunConfiguration::deployConfig() const
288
{
289
290
291
    return qobject_cast<Qt4MaemoDeployConfiguration *>(target()->activeDeployConfiguration());
}

292
293
294
295
296
297
MaemoRemoteMountsModel *RemoteLinuxRunConfiguration::remoteMounts() const
{
    return m_d->remoteMounts;
}

AbstractLinuxDeviceDeployStep *RemoteLinuxRunConfiguration::deployStep() const
298
{
299
    return MaemoGlobal::earlierBuildStep<AbstractLinuxDeviceDeployStep>(deployConfig(), 0);
300
301
}

302
QString RemoteLinuxRunConfiguration::arguments() const
303
{
304
    return m_d->arguments;
305
306
}

307
QString RemoteLinuxRunConfiguration::commandPrefix() const
308
{
309
310
311
312
    if (!deviceConfig())
        return QString();

    return QString::fromLocal8Bit("%1 %2")
313
        .arg(MaemoGlobal::remoteCommandPrefix(deviceConfig()->osType()))
314
        .arg(MaemoGlobal::remoteEnvironment(userEnvironmentChanges()));
315
316
}

317
QString RemoteLinuxRunConfiguration::localDirToMountForRemoteGdb() const
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
{
    const QString projectDir
        = QDir::fromNativeSeparators(QDir::cleanPath(activeBuildConfiguration()
            ->target()->project()->projectDirectory()));
    const QString execDir
        = QDir::fromNativeSeparators(QFileInfo(localExecutableFilePath()).path());
    const int length = qMin(projectDir.length(), execDir.length());
    int lastSeparatorPos = 0;
    for (int i = 0; i < length; ++i) {
        if (projectDir.at(i) != execDir.at(i))
            return projectDir.left(lastSeparatorPos);
        if (projectDir.at(i) == QLatin1Char('/'))
            lastSeparatorPos = i;
    }
    return projectDir.length() == execDir.length()
        ? projectDir : projectDir.left(lastSeparatorPos);
}

336
QString RemoteLinuxRunConfiguration::remoteProjectSourcesMountPoint() const
337
{
338
    return MaemoGlobal::homeDirOnDevice(deviceConfig()->sshParameters().userName)
339
340
341
342
        + QLatin1String("/gdbSourcesDir_")
        + QFileInfo(localExecutableFilePath()).fileName();
}

343
QString RemoteLinuxRunConfiguration::localExecutableFilePath() const
ck's avatar
ck committed
344
{
Christian Kandeler's avatar
Christian Kandeler committed
345
    TargetInformation ti = qt4Target()->qt4Project()->rootProjectNode()
346
        ->targetInformation(m_d->proFilePath);
dt's avatar
dt committed
347
348
349
    if (!ti.valid)
        return QString();

350
    return QDir::cleanPath(ti.workingDir + QLatin1Char('/') + ti.target);
ck's avatar
ck committed
351
352
}

353
QString RemoteLinuxRunConfiguration::remoteExecutableFilePath() const
354
{
355
    return deployConfig()->deployables()->remoteExecutableFilePath(localExecutableFilePath());
356
357
}

358
PortList RemoteLinuxRunConfiguration::freePorts() const
ck's avatar
ck committed
359
{
360
    const Qt4BuildConfiguration * const bc = activeQt4BuildConfiguration();
361
362
363
    const AbstractLinuxDeviceDeployStep * const step = deployStep();
    return bc && step
        ? MaemoGlobal::freePorts(deployStep()->helper().deviceConfig(), bc->qtVersion())
364
        : PortList();
ck's avatar
ck committed
365
366
}

367
bool RemoteLinuxRunConfiguration::useRemoteGdb() const
368
{
369
    if (!m_d->useRemoteGdb)
Christian Kandeler's avatar
Christian Kandeler committed
370
371
372
373
        return false;
    const AbstractQt4MaemoTarget * const maemoTarget
        = qobject_cast<AbstractQt4MaemoTarget *>(target());
    return maemoTarget && maemoTarget->allowsRemoteMounts();
374
375
}

376
void RemoteLinuxRunConfiguration::setUseRemoteGdb(bool useRemoteGdb)
ck's avatar
ck committed
377
{
378
    m_d->useRemoteGdb = useRemoteGdb;
ck's avatar
ck committed
379
380
}

381
382
383
384
385
386
void RemoteLinuxRunConfiguration::setArguments(const QString &args)
{
    m_d->arguments = args;
}

RemoteLinuxRunConfiguration::DebuggingType RemoteLinuxRunConfiguration::debuggingType() const
387
{
Christian Kandeler's avatar
Christian Kandeler committed
388
389
390
    const AbstractQt4MaemoTarget * const maemoTarget
        = qobject_cast<AbstractQt4MaemoTarget *>(target());
    if (!maemoTarget || !maemoTarget->allowsQmlDebugging())
391
392
393
394
395
396
397
398
399
        return DebugCppOnly;
    if (useCppDebugger()) {
        if (useQmlDebugger())
            return DebugCppAndQml;
        return DebugCppOnly;
    }
    return DebugQmlOnly;
}

400
int RemoteLinuxRunConfiguration::portsUsedByDebuggers() const
401
402
403
404
405
406
407
408
409
410
411
{
    switch (debuggingType()) {
    case DebugCppOnly:
    case DebugQmlOnly:
        return 1;
    case DebugCppAndQml:
    default:
        return 2;
    }
}

412
bool RemoteLinuxRunConfiguration::hasEnoughFreePorts(const QString &mode) const
413
414
415
416
417
418
419
420
421
{
    const int freePortCount = freePorts().count();
    const AbstractQt4MaemoTarget * const maemoTarget
        = qobject_cast<AbstractQt4MaemoTarget *>(target());
    const bool remoteMountsAllowed = maemoTarget && maemoTarget->allowsRemoteMounts();
    const int mountDirCount = remoteMountsAllowed
        ? remoteMounts()->validMountSpecificationCount() : 0;
    if (mode == Debugger::Constants::DEBUGMODE)
        return freePortCount >= mountDirCount + portsUsedByDebuggers();
422
    if (mode == ProjectExplorer::Constants::RUNMODE)
423
424
425
426
        return freePortCount >= mountDirCount;
    return false;
}

427
void RemoteLinuxRunConfiguration::updateDeviceConfigurations()
ck's avatar
ck committed
428
{
429
    emit deviceConfigurationChanged(target());
430
    updateEnabledState();
ck's avatar
ck committed
431
432
}

433
void RemoteLinuxRunConfiguration::handleDeployConfigChanged()
434
{
435
    Qt4MaemoDeployConfiguration * const activeDeployConf = deployConfig();
436
    if (activeDeployConf) {
437
438
        connect(activeDeployConf->deployables().data(), SIGNAL(modelReset()),
            SLOT(handleDeployablesUpdated()), Qt::UniqueConnection);
439
440
441
442
443
444
445
446
        connect(activeDeployConf->stepList(), SIGNAL(stepInserted(int)),
            SLOT(handleDeployConfigChanged()), Qt::UniqueConnection);
        connect(activeDeployConf->stepList(), SIGNAL(stepInserted(int)),
            SLOT(handleDeployConfigChanged()), Qt::UniqueConnection);
        connect(activeDeployConf->stepList(), SIGNAL(stepMoved(int,int)),
            SLOT(handleDeployConfigChanged()), Qt::UniqueConnection);
        connect(activeDeployConf->stepList(), SIGNAL(stepRemoved(int)),
            SLOT(handleDeployConfigChanged()), Qt::UniqueConnection);
447
448
        AbstractLinuxDeviceDeployStep * const step
            = MaemoGlobal::earlierBuildStep<AbstractLinuxDeviceDeployStep>(activeDeployConf, 0);
449
        if (step) {
450
            connect(&step->helper(), SIGNAL(deviceConfigChanged()),
451
                SLOT(updateDeviceConfigurations()), Qt::UniqueConnection);
452
453
        }
    }
454

455
    updateDeviceConfigurations();
456
457
458
459
460
461
462
463
464
465
466
467
468
    updateEnabledState();
}

void RemoteLinuxRunConfiguration::handleDeployablesUpdated()
{
    emit deploySpecsChanged();
    updateEnabledState();
}

void RemoteLinuxRunConfiguration::handleRemoteMountsChanged()
{
    emit remoteMountsChanged();
    updateEnabledState();
469
470
}

471
QString RemoteLinuxRunConfiguration::baseEnvironmentText() const
472
{
473
    if (m_d->baseEnvironmentType == CleanBaseEnvironment)
474
        return tr("Clean Environment");
475
    else  if (m_d->baseEnvironmentType == SystemBaseEnvironment)
476
477
478
479
        return tr("System Environment");
    return QString();
}

480
RemoteLinuxRunConfiguration::BaseEnvironmentType RemoteLinuxRunConfiguration::baseEnvironmentType() const
481
{
482
    return m_d->baseEnvironmentType;
483
484
}

485
void RemoteLinuxRunConfiguration::setBaseEnvironmentType(BaseEnvironmentType env)
486
{
487
488
    if (m_d->baseEnvironmentType != env) {
        m_d->baseEnvironmentType = env;
489
490
491
492
        emit baseEnvironmentChanged();
    }
}

493
Utils::Environment RemoteLinuxRunConfiguration::environment() const
494
{
495
    Utils::Environment env = baseEnvironment();
496
497
498
499
    env.modify(userEnvironmentChanges());
    return env;
}

500
Utils::Environment RemoteLinuxRunConfiguration::baseEnvironment() const
501
{
502
    return (m_d->baseEnvironmentType == SystemBaseEnvironment ? systemEnvironment()
503
        : Utils::Environment());
504
505
}

506
QList<Utils::EnvironmentItem> RemoteLinuxRunConfiguration::userEnvironmentChanges() const
507
{
508
    return m_d->userEnvironmentChanges;
509
510
}

511
void RemoteLinuxRunConfiguration::setUserEnvironmentChanges(
512
    const QList<Utils::EnvironmentItem> &diff)
513
{
514
515
    if (m_d->userEnvironmentChanges != diff) {
        m_d->userEnvironmentChanges = diff;
516
517
518
519
        emit userEnvironmentChangesChanged(diff);
    }
}

520
Utils::Environment RemoteLinuxRunConfiguration::systemEnvironment() const
521
{
522
    return m_d->systemEnvironment;
523
524
}

525
void RemoteLinuxRunConfiguration::setSystemEnvironment(const Utils::Environment &environment)
526
{
527
528
    if (m_d->systemEnvironment.size() == 0 || m_d->systemEnvironment != environment) {
        m_d->systemEnvironment = environment;
529
530
531
532
        emit systemEnvironmentChanged();
    }
}

533
QString RemoteLinuxRunConfiguration::proFilePath() const
534
{
535
    return m_d->proFilePath;
536
537
}

538
} // namespace RemoteLinux