maemoglobal.cpp 15.2 KB
Newer Older
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).
6
**
hjk's avatar
hjk committed
7
** Contact: Nokia Corporation (info@qt.nokia.com)
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.
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.
30
31
32
33
**
**************************************************************************/
#include "maemoglobal.h"

34
#include "maemoconstants.h"
35
#include "maemoqemumanager.h"
36

Friedemann Kleint's avatar
Friedemann Kleint committed
37
38
#include <projectexplorer/projectexplorerconstants.h>

39
#include <coreplugin/filemanager.h>
40
#include <utils/ssh/sshconnection.h>
41
#include <qt4projectmanager/qt4projectmanagerconstants.h>
42
#include <qtsupport/qtversionmanager.h>
Christian Kandeler's avatar
Christian Kandeler committed
43
#include <qt4projectmanager/qt4target.h>
44
45
#include <utils/environment.h>

46
#include <QtCore/QDateTime>
47
#include <QtCore/QDir>
48
#include <QtCore/QFileInfo>
49
#include <QtCore/QProcess>
ck's avatar
ck committed
50
#include <QtCore/QString>
51
#include <QtGui/QDesktopServices>
ck's avatar
ck committed
52

53
54
55
56
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Constants;

namespace RemoteLinux {
57
namespace Internal {
58
59
60
namespace {
static const QLatin1String binQmake("/bin/qmake" EXEC_SUFFIX);
}
61

62
63
bool MaemoGlobal::isMaemoTargetId(const QString &id)
{
64
65
66
67
68
69
    return isFremantleTargetId(id) || isHarmattanTargetId(id)
        || isMeegoTargetId(id);
}

bool MaemoGlobal::isFremantleTargetId(const QString &id)
{
70
    return id == QLatin1String(MAEMO5_DEVICE_TARGET_ID);
71
72
73
74
}

bool MaemoGlobal::isHarmattanTargetId(const QString &id)
{
75
    return id == QLatin1String(HARMATTAN_DEVICE_TARGET_ID);
76
77
78
79
}

bool MaemoGlobal::isMeegoTargetId(const QString &id)
{
80
    return id == QLatin1String(MEEGO_DEVICE_TARGET_ID);
81
82
}

dt's avatar
dt committed
83
bool MaemoGlobal::isValidMaemo5QtVersion(const QString &qmakePath)
84
{
85
    return isValidMaemoQtVersion(qmakePath, LinuxDeviceConfiguration::Maemo5OsType);
86
87
}

dt's avatar
dt committed
88
bool MaemoGlobal::isValidHarmattanQtVersion(const QString &qmakePath)
89
{
90
    return isValidMaemoQtVersion(qmakePath, LinuxDeviceConfiguration::HarmattanOsType);
91
92
}

dt's avatar
dt committed
93
bool MaemoGlobal::isValidMeegoQtVersion(const QString &qmakePath)
Christian Kandeler's avatar
Christian Kandeler committed
94
{
95
    return isValidMaemoQtVersion(qmakePath, LinuxDeviceConfiguration::MeeGoOsType);
Christian Kandeler's avatar
Christian Kandeler committed
96
97
}

98
bool MaemoGlobal::isLinuxQt(const QtSupport::BaseQtVersion *qtVersion)
Christian Kandeler's avatar
Christian Kandeler committed
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
{
    if (!qtVersion)
        return false;
    const QList<ProjectExplorer::Abi> &abis = qtVersion->qtAbis();
    foreach (const ProjectExplorer::Abi &abi, abis) {
        if (abi.os() == ProjectExplorer::Abi::LinuxOS)
            return true;
    }
    return false;
}

bool MaemoGlobal::hasLinuxQt(const ProjectExplorer::Target *target)
{
    const Qt4BaseTarget * const qtTarget
        = qobject_cast<const Qt4BaseTarget *>(target);
    if (!qtTarget)
        return false;
    const Qt4BuildConfiguration * const bc
        = qtTarget->activeBuildConfiguration();
    return bc && isLinuxQt(bc->qtVersion());
}

121
bool MaemoGlobal::isValidMaemoQtVersion(const QString &qmakePath, const QString &osType)
122
{
123
    if (MaemoGlobal::osType(qmakePath) != osType)
124
125
126
        return false;
    QProcess madAdminProc;
    const QStringList arguments(QLatin1String("list"));
dt's avatar
dt committed
127
    if (!callMadAdmin(madAdminProc, arguments, qmakePath, false))
128
129
130
131
132
        return false;
    if (!madAdminProc.waitForStarted() || !madAdminProc.waitForFinished())
        return false;

    madAdminProc.setReadChannel(QProcess::StandardOutput);
dt's avatar
dt committed
133
    const QByteArray tgtName = targetName(qmakePath).toAscii();
134
135
136
137
138
139
140
141
142
143
    while (madAdminProc.canReadLine()) {
        const QByteArray &line = madAdminProc.readLine();
        if (line.contains(tgtName)
            && (line.contains("(installed)") || line.contains("(default)")))
            return true;
    }
    return false;
}


144
145
146
147
148
149
150
QString MaemoGlobal::homeDirOnDevice(const QString &uname)
{
    return uname == QLatin1String("root")
        ? QString::fromLatin1("/root")
        : QLatin1String("/home/") + uname;
}

151
QString MaemoGlobal::devrootshPath()
152
153
154
155
{
    return QLatin1String("/usr/lib/mad-developer/devrootsh");
}

156
int MaemoGlobal::applicationIconSize(const QString &osType)
157
{
158
    return osType == LinuxDeviceConfiguration::HarmattanOsType ? 80 : 64;
159
160
}

161
QString MaemoGlobal::remoteSudo(const QString &osType, const QString &uname)
162
{
163
164
    if (uname == QLatin1String("root"))
        return QString();
165
166
167
    if (osType == LinuxDeviceConfiguration::Maemo5OsType
            || osType == LinuxDeviceConfiguration::HarmattanOsType
            || osType == LinuxDeviceConfiguration::MeeGoOsType) {
168
169
        return devrootshPath();
    }
170
    return QString(); // Using sudo would open a can of worms.
171
172
}

173
QString MaemoGlobal::remoteCommandPrefix(const QString &osType)
ck's avatar
ck committed
174
{
175
    QString prefix = QString::fromLocal8Bit("%1; ").arg(remoteSourceProfilesCommand());
176
177
    if (osType != LinuxDeviceConfiguration::Maemo5OsType
            && osType != LinuxDeviceConfiguration::HarmattanOsType) {
178
        prefix += QLatin1String("DISPLAY=:0.0 ");
179
    }
180
    return prefix;
181
182
183
184
185
186
187
188
189
190
}

QString MaemoGlobal::remoteSourceProfilesCommand()
{
    const QList<QByteArray> profiles = QList<QByteArray>() << "/etc/profile"
        << "/home/user/.profile" << "~/.profile";
    QByteArray remoteCall(":");
    foreach (const QByteArray &profile, profiles)
        remoteCall += "; test -f " + profile + " && source " + profile;
    return QString::fromAscii(remoteCall);
ck's avatar
ck committed
191
192
}

193
QString MaemoGlobal::remoteEnvironment(const QList<Utils::EnvironmentItem> &list)
194
195
196
{
    QString env;
    QString placeHolder = QLatin1String("%1=%2 ");
197
    foreach (const Utils::EnvironmentItem &item, list)
198
199
200
201
        env.append(placeHolder.arg(item.name).arg(item.value));
    return env.mid(0, env.size() - 1);
}

202
QString MaemoGlobal::failedToConnectToServerMessage(const Utils::SshConnection::Ptr &connection,
203
    const LinuxDeviceConfiguration::ConstPtr &deviceConfig)
204
{
Friedemann Kleint's avatar
Friedemann Kleint committed
205
    QString errorMsg = tr("Could not connect to host: %1")
206
207
        .arg(connection->errorString());

208
    if (deviceConfig->type() == LinuxDeviceConfiguration::Emulator) {
209
210
        if (connection->errorState() == Utils::SshTimeoutError
                || connection->errorState() == Utils::SshSocketError) {
Friedemann Kleint's avatar
Friedemann Kleint committed
211
            errorMsg += tr("\nDid you start Qemu?");
212
        }
213
   } else if (connection->errorState() == Utils::SshTimeoutError) {
Friedemann Kleint's avatar
Friedemann Kleint committed
214
        errorMsg += tr("\nIs the device connected and set up for network access?");
215
216
217
218
    }
    return errorMsg;
}

219
QString MaemoGlobal::deviceConfigurationName(const LinuxDeviceConfiguration::ConstPtr &devConf)
220
{
Friedemann Kleint's avatar
Friedemann Kleint committed
221
    return devConf ? devConf->name() : tr("(No device)");
222
223
}

224
PortList MaemoGlobal::freePorts(const LinuxDeviceConfiguration::ConstPtr &devConf,
225
    const QtSupport::BaseQtVersion *qtVersion)
226
{
dt's avatar
dt committed
227
    if (!devConf || !qtVersion)
228
229
        return PortList();
    if (devConf->type() == LinuxDeviceConfiguration::Emulator) {
230
231
232
233
234
235
236
237
        MaemoQemuRuntime rt;
        const int id = qtVersion->uniqueId();
        if (MaemoQemuManager::instance().runtimeForQtVersion(id, &rt))
            return rt.m_freePorts;
    }
    return devConf->freePorts();
}

dt's avatar
dt committed
238
QString MaemoGlobal::maddeRoot(const QString &qmakePath)
239
{
dt's avatar
dt committed
240
    QDir dir(targetRoot(qmakePath));
241
242
243
244
    dir.cdUp(); dir.cdUp();
    return dir.absolutePath();
}

dt's avatar
dt committed
245
QString MaemoGlobal::targetRoot(const QString &qmakePath)
246
{
dt's avatar
dt committed
247
    return QDir::cleanPath(qmakePath).remove(binQmake);
248
249
}

dt's avatar
dt committed
250
QString MaemoGlobal::targetName(const QString &qmakePath)
251
{
dt's avatar
dt committed
252
    return QDir(targetRoot(qmakePath)).dirName();
253
254
}

dt's avatar
dt committed
255
QString MaemoGlobal::madAdminCommand(const QString &qmakePath)
256
{
dt's avatar
dt committed
257
    return maddeRoot(qmakePath) + QLatin1String("/bin/mad-admin");
258
259
}

dt's avatar
dt committed
260
QString MaemoGlobal::madCommand(const QString &qmakePath)
261
{
dt's avatar
dt committed
262
    return maddeRoot(qmakePath) + QLatin1String("/bin/mad");
263
264
}

265
QString MaemoGlobal::madDeveloperUiName(const QString &osType)
266
{
267
    return osType == LinuxDeviceConfiguration::HarmattanOsType
268
269
270
        ? tr("SDK Connectivity") : tr("Mad Developer");
}

271
QString MaemoGlobal::osType(const QString &qmakePath)
272
{
dt's avatar
dt committed
273
    const QString &name = targetName(qmakePath);
274
    if (name.startsWith(QLatin1String("fremantle")))
275
        return LinuxDeviceConfiguration::Maemo5OsType;
276
    if (name.startsWith(QLatin1String("harmattan")))
277
        return LinuxDeviceConfiguration::HarmattanOsType;
Christian Kandeler's avatar
Christian Kandeler committed
278
    if (name.startsWith(QLatin1String("meego")))
279
280
        return LinuxDeviceConfiguration::MeeGoOsType;
    return LinuxDeviceConfiguration::GenericLinuxOsType;
281
282
}

dt's avatar
dt committed
283
QString MaemoGlobal::architecture(const QString &qmakePath)
Christian Kandeler's avatar
Christian Kandeler committed
284
285
{
    QProcess proc;
286
    const QStringList args = QStringList() << QLatin1String("uname")
Christian Kandeler's avatar
Christian Kandeler committed
287
        << QLatin1String("-m");
dt's avatar
dt committed
288
    if (!callMad(proc, args, qmakePath, true))
Christian Kandeler's avatar
Christian Kandeler committed
289
290
291
292
293
294
295
296
        return QString();
    if (!proc.waitForFinished())
        return QString();
    QString arch = QString::fromUtf8(proc.readAllStandardOutput());
    arch.chop(1); // Newline
    return arch;
}

297
298
bool MaemoGlobal::removeRecursively(const QString &filePath, QString &error)
{
299
    error.clear();
300
    QFileInfo fileInfo(filePath);
301
302
    if (!fileInfo.exists())
        return true;
303
    QFile::setPermissions(filePath, fileInfo.permissions() | QFile::WriteUser);
304
305
306
307
308
309
310
311
312
313
    if (fileInfo.isDir()) {
        QDir dir(filePath);
        QStringList fileNames = dir.entryList(QDir::Files | QDir::Hidden
            | QDir::System | QDir::Dirs | QDir::NoDotAndDotDot);
        foreach (const QString &fileName, fileNames) {
            if (!removeRecursively(filePath + QLatin1Char('/') + fileName, error))
                return false;
        }
        dir.cdUp();
        if (!dir.rmdir(fileInfo.fileName())) {
Friedemann Kleint's avatar
Friedemann Kleint committed
314
            error = tr("Failed to remove directory '%1'.")
315
316
317
318
319
                .arg(QDir::toNativeSeparators(filePath));
            return false;
        }
    } else {
        if (!QFile::remove(filePath)) {
Friedemann Kleint's avatar
Friedemann Kleint committed
320
            error = tr("Failed to remove file '%1'.")
321
322
323
324
325
326
327
                .arg(QDir::toNativeSeparators(filePath));
            return false;
        }
    }
    return true;
}

328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
bool MaemoGlobal::copyRecursively(const QString &srcFilePath,
    const QString &tgtFilePath, QString *error)
{
    QFileInfo srcFileInfo(srcFilePath);
    if (srcFileInfo.isDir()) {
        QDir targetDir(tgtFilePath);
        targetDir.cdUp();
        if (!targetDir.mkdir(QFileInfo(tgtFilePath).fileName())) {
            if (error) {
                *error = tr("Failed to create directory '%1'.")
                    .arg(QDir::toNativeSeparators(tgtFilePath));
                return false;
            }
        }
        QDir sourceDir(srcFilePath);
        QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
        foreach (const QString &fileName, fileNames) {
            const QString newSrcFilePath
                = srcFilePath + QLatin1Char('/') + fileName;
            const QString newTgtFilePath
                = tgtFilePath + QLatin1Char('/') + fileName;
            if (!copyRecursively(newSrcFilePath, newTgtFilePath))
                return false;
        }
    } else {
        if (!QFile::copy(srcFilePath, tgtFilePath)) {
            if (error) {
                *error = tr("Could not copy file '%1' to '%2'.")
                    .arg(QDir::toNativeSeparators(srcFilePath),
                         QDir::toNativeSeparators(tgtFilePath));
            }
            return false;
        }
    }
    return true;
}

365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
bool MaemoGlobal::isFileNewerThan(const QString &filePath,
    const QDateTime &timeStamp)
{
    QFileInfo fileInfo(filePath);
    if (!fileInfo.exists() || fileInfo.lastModified() >= timeStamp)
        return true;
    if (fileInfo.isDir()) {
        const QStringList dirContents = QDir(filePath)
            .entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
        foreach (const QString &curFileName, dirContents) {
            const QString curFilePath
                = filePath + QLatin1Char('/') + curFileName;
            if (isFileNewerThan(curFilePath, timeStamp))
                return true;
        }
    }
    return false;
}

384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
void MaemoGlobal::addMaddeEnvironment(Utils::Environment &env, const QString &qmakePath)
{
    Utils::Environment maddeEnv;
#ifdef Q_OS_WIN
    const QString root = maddeRoot(qmakePath);
    env.prependOrSetPath(root + QLatin1String("/bin"));
    env.prependOrSet(QLatin1String("HOME"),
        QDesktopServices::storageLocation(QDesktopServices::HomeLocation));
#else
    Q_UNUSED(qmakePath);
#endif
    for (Utils::Environment::const_iterator it = maddeEnv.constBegin(); it != maddeEnv.constEnd(); ++it)
        env.prependOrSet(it.key(), it.value());
}

void MaemoGlobal::transformMaddeCall(QString &command, QStringList &args, const QString &qmakePath)
{
#ifdef Q_OS_WIN
    const QString root = maddeRoot(qmakePath);
    args.prepend(command);
    command = root + QLatin1String("/bin/sh.exe");
#else
    Q_UNUSED(command);
    Q_UNUSED(args);
    Q_UNUSED(qmakePath);
#endif
}

412
bool MaemoGlobal::callMad(QProcess &proc, const QStringList &args,
dt's avatar
dt committed
413
    const QString &qmakePath, bool useTarget)
414
{
dt's avatar
dt committed
415
    return callMaddeShellScript(proc, qmakePath, madCommand(qmakePath), args,
416
        useTarget);
417
418
419
}

bool MaemoGlobal::callMadAdmin(QProcess &proc, const QStringList &args,
dt's avatar
dt committed
420
    const QString &qmakePath, bool useTarget)
421
{
dt's avatar
dt committed
422
    return callMaddeShellScript(proc, qmakePath, madAdminCommand(qmakePath),
423
        args, useTarget);
424
425
}

426
bool MaemoGlobal::callMaddeShellScript(QProcess &proc,
dt's avatar
dt committed
427
    const QString &qmakePath, const QString &command, const QStringList &args,
428
    bool useTarget)
429
{
430
431
    if (!QFileInfo(command).exists())
        return false;
432
    QString actualCommand = command;
dt's avatar
dt committed
433
    QStringList actualArgs = targetArgs(qmakePath, useTarget) + args;
434
    Utils::Environment env(proc.systemEnvironment());
435
    addMaddeEnvironment(env, qmakePath);
436
    proc.setEnvironment(env.toStringList());
437
    transformMaddeCall(actualCommand, actualArgs, qmakePath);
438
    proc.start(actualCommand, actualArgs);
439
    return true;
440
441
}

dt's avatar
dt committed
442
QStringList MaemoGlobal::targetArgs(const QString &qmakePath, bool useTarget)
443
444
445
{
    QStringList args;
    if (useTarget) {
dt's avatar
dt committed
446
        args << QLatin1String("-t") << targetName(qmakePath);
447
448
449
450
    }
    return args;
}

451
QString MaemoGlobal::osTypeToString(const QString &osType)
452
{
453
454
455
456
457
458
459
    if (osType == LinuxDeviceConfiguration::Maemo5OsType)
        return QLatin1String("Maemo5/Fremantle");
    if (osType == LinuxDeviceConfiguration::HarmattanOsType)
        return QLatin1String("Harmattan");
    if (osType == LinuxDeviceConfiguration::MeeGoOsType)
        return QLatin1String("MeeGo");
    return QLatin1String("Other Linux");
460
461
}

462
MaemoGlobal::PackagingSystem MaemoGlobal::packagingSystem(const QString &osType)
463
{
464
465
466
    if (osType == LinuxDeviceConfiguration::Maemo5OsType
           || osType == LinuxDeviceConfiguration::HarmattanOsType) {
        return Dpkg;
467
    }
468
469
470
    if (osType == LinuxDeviceConfiguration::MeeGoOsType)
        return Rpm;
    return Tar;
471
}
472

473
} // namespace Internal
474
} // namespace RemoteLinux