maemoqemumanager.cpp 22.8 KB
Newer Older
1
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).
6
**
7
** Contact: Nokia Corporation (qt-info@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
29
** Nokia at qt-info@nokia.com.
30
31
32
**
**************************************************************************/

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

35
#include "maemoglobal.h"
36
#include "maemoqemuruntimeparser.h"
37
#include "maemosettingspages.h"
38
#include "qt4maemotarget.h"
dt's avatar
dt committed
39
#include "maemoqtversion.h"
40
41
42

#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
43
#include <coreplugin/id.h>
44
45
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
46
#include <coreplugin/icontext.h>
47
48
49
#include <coreplugin/modemanager.h>

#include <projectexplorer/projectexplorer.h>
50
#include <projectexplorer/project.h>
51
#include <projectexplorer/session.h>
52
#include <projectexplorer/buildconfiguration.h>
53
#include <qtsupport/qtversionmanager.h>
54
#include <qt4projectmanager/qt4buildconfiguration.h>
55
#include <remotelinux/linuxdeviceconfiguration.h>
56
#include <remotelinux/remotelinuxrunconfiguration.h>
57
#include <utils/filesystemwatcher.h>
58

59
60
61
62
63
#include <QDebug>
#include <QDir>
#include <QList>
#include <QSet>
#include <QStringBuilder>
64

65
66
67
#include <QAction>
#include <QDesktopServices>
#include <QMessageBox>
68

69
70
#include <limits.h>

71
72
using namespace ProjectExplorer;
using namespace Qt4ProjectManager;
73
using namespace RemoteLinux;
74
75
76

namespace Madde {
namespace Internal {
77

ck's avatar
ck committed
78
MaemoQemuManager *MaemoQemuManager::m_instance = 0;
79
80
81

const QSize iconSize = QSize(24, 20);

ck's avatar
ck committed
82
MaemoQemuManager::MaemoQemuManager(QObject *parent)
83
84
85
    : QObject(parent)
    , m_qemuAction(0)
    , m_qemuProcess(new QProcess(this))
86
    , m_runningQtId(INT_MIN)
87
    , m_userTerminated(false)
88
89
    , m_runtimeRootWatcher(0)
    , m_runtimeFolderWatcher(0)
90
91
92
93
94
{
    m_qemuStarterIcon.addFile(":/qt-maemo/images/qemu-run.png", iconSize);
    m_qemuStarterIcon.addFile(":/qt-maemo/images/qemu-stop.png", iconSize,
        QIcon::Normal, QIcon::On);

95
    m_qemuAction = new QAction("MeeGo Emulator", this);
96
    m_qemuAction->setIcon(m_qemuStarterIcon.pixmap(iconSize));
97
    m_qemuAction->setToolTip(tr("Start MeeGo Emulator"));
98
99
    connect(m_qemuAction, SIGNAL(triggered()), this, SLOT(startRuntime()));

hjk's avatar
hjk committed
100
    Core::ActionManager *actionManager = Core::ICore::actionManager();
101
    Core::Command *qemuCommand = actionManager->registerAction(m_qemuAction,
102
        "MaemoEmulator", Core::Context(Core::Constants::C_GLOBAL));
103
104
105
    qemuCommand->setAttribute(Core::Command::CA_UpdateText);
    qemuCommand->setAttribute(Core::Command::CA_UpdateIcon);

106
    Core::ModeManager::addAction(qemuCommand->action(), 1);
107
108
    m_qemuAction->setEnabled(false);
    m_qemuAction->setVisible(false);
109
110

    // listen to qt version changes to update the start button
111
112
    connect(QtSupport::QtVersionManager::instance(), SIGNAL(qtVersionsChanged(QList<int>,QList<int>,QList<int>)),
        this, SLOT(qtVersionsChanged(QList<int>,QList<int>,QList<int>)));
113
114
115
116
117
118
119
120
121
122
123
124

    // listen to project add, remove and startup changes to udate start button
    SessionManager *session = ProjectExplorerPlugin::instance()->session();
    connect(session, SIGNAL(projectAdded(ProjectExplorer::Project*)), this,
        SLOT(projectAdded(ProjectExplorer::Project*)));
    connect(session, SIGNAL(projectRemoved(ProjectExplorer::Project*)), this,
        SLOT(projectRemoved(ProjectExplorer::Project*)));
    connect(session, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
        this, SLOT(projectChanged(ProjectExplorer::Project*)));

    connect(m_qemuProcess, SIGNAL(error(QProcess::ProcessError)), this,
        SLOT(qemuProcessError(QProcess::ProcessError)));
Robert Loehning's avatar
Robert Loehning committed
125
    connect(m_qemuProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this,
126
        SLOT(qemuProcessFinished()));
ck's avatar
ck committed
127
128
129
130
    connect(m_qemuProcess, SIGNAL(readyReadStandardOutput()), this,
        SLOT(qemuOutput()));
    connect(m_qemuProcess, SIGNAL(readyReadStandardError()), this,
        SLOT(qemuOutput()));
Robert Loehning's avatar
Robert Loehning committed
131
132
    connect(this, SIGNAL(qemuProcessStatus(QemuStatus,QString)),
        this, SLOT(qemuStatusChanged(QemuStatus,QString)));
133
}
134

135
Utils::FileSystemWatcher *MaemoQemuManager::runtimeRootWatcher()
136
137
{
    if (!m_runtimeRootWatcher) {
138
139
        m_runtimeRootWatcher = new Utils::FileSystemWatcher(this);
        m_runtimeRootWatcher->setObjectName(QLatin1String("MaemoQemuRuntimeRootWatcher"));
140
141
142
143
144
145
        connect(m_runtimeRootWatcher, SIGNAL(directoryChanged(QString)), this,
            SLOT(runtimeRootChanged(QString)));
    }
    return m_runtimeRootWatcher;
}

146
Utils::FileSystemWatcher *MaemoQemuManager::runtimeFolderWatcher()
147
148
{
    if (!m_runtimeFolderWatcher) {
149
150
        m_runtimeFolderWatcher = new Utils::FileSystemWatcher(this);
        m_runtimeFolderWatcher->setObjectName(QLatin1String("MaemoQemuRuntimeFolderWatcher"));
151
152
153
154
        connect(m_runtimeFolderWatcher, SIGNAL(directoryChanged(QString)), this,
            SLOT(runtimeFolderChanged(QString)));
    }
    return m_runtimeFolderWatcher;
155
156
}

ck's avatar
ck committed
157
MaemoQemuManager::~MaemoQemuManager()
158
159
{
    terminateRuntime();
160
    m_instance = 0;
161
162
}

ck's avatar
ck committed
163
MaemoQemuManager &MaemoQemuManager::instance(QObject *parent)
164
{
165
    if (m_instance == 0)
ck's avatar
ck committed
166
        m_instance = new MaemoQemuManager(parent);
167
168
169
    return *m_instance;
}

170
bool MaemoQemuManager::runtimeForQtVersion(int uniqueId, MaemoQemuRuntime *rt) const
171
{
172
    *rt = m_runtimes.value(uniqueId, MaemoQemuRuntime());
173
    return rt->isValid();
174
175
}

176
177
178
179
180
bool MaemoQemuManager::qemuIsRunning() const
{
    return m_runningQtId != INT_MIN;
}

181
void MaemoQemuManager::qtVersionsChanged(const QList<int> &added, const QList<int> &removed, const QList<int> &changed)
182
{
183
184
    QList<int> uniqueIds;
    uniqueIds << added << removed << changed;
185
    QtSupport::QtVersionManager *manager = QtSupport::QtVersionManager::instance();
186
187
    foreach (int uniqueId, uniqueIds) {
        if (manager->isValidId(uniqueId)) {
dt's avatar
dt committed
188
189
190
            MaemoQtVersion *version = dynamic_cast<MaemoQtVersion *>(manager->version(uniqueId));

            if (version) {
191
192
                MaemoQemuRuntime runtime
                    = MaemoQemuRuntimeParser::parseRuntime(version);
193
                if (runtime.isValid()) {
194
                    m_runtimes.insert(uniqueId, runtime);
195
196
197
                    if (!runtimeRootWatcher()->watchesDirectory(runtime.m_watchPath))
                        runtimeRootWatcher()->addDirectory(runtime.m_watchPath,
                                                           Utils::FileSystemWatcher::WatchAllChanges);
198
199
200
                } else {
                    m_runtimes.remove(uniqueId);
                }
201
202
203
204
205
206
207
208
209
210
211
212
            }
        } else {
            // this qt version has been removed from the settings
            m_runtimes.remove(uniqueId);
            if (uniqueId == m_runningQtId) {
                terminateRuntime();
                emit qemuProcessStatus(QemuUserReason, tr("Qemu has been shut "
                    "down, because you removed the corresponding Qt version."));
            }
        }
    }

213
    showOrHideQemuButton();
214
215
}

ck's avatar
ck committed
216
void MaemoQemuManager::projectAdded(ProjectExplorer::Project *project)
217
218
219
220
221
222
223
224
225
226
227
228
229
{
    // handle all target related changes, add, remove, etc...
    connect(project, SIGNAL(addedTarget(ProjectExplorer::Target*)), this,
        SLOT(targetAdded(ProjectExplorer::Target*)));
    connect(project, SIGNAL(removedTarget(ProjectExplorer::Target*)), this,
        SLOT(targetRemoved(ProjectExplorer::Target*)));
    connect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
        this, SLOT(targetChanged(ProjectExplorer::Target*)));

    foreach (Target *target, project->targets())
        targetAdded(target);
}

ck's avatar
ck committed
230
void MaemoQemuManager::projectRemoved(ProjectExplorer::Project *project)
231
232
233
234
235
236
237
238
239
240
{
    disconnect(project, SIGNAL(addedTarget(ProjectExplorer::Target*)), this,
        SLOT(targetAdded(ProjectExplorer::Target*)));
    disconnect(project, SIGNAL(removedTarget(ProjectExplorer::Target*)), this,
        SLOT(targetRemoved(ProjectExplorer::Target*)));
    disconnect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
        this, SLOT(targetChanged(ProjectExplorer::Target*)));

    foreach (Target *target, project->targets())
        targetRemoved(target);
241
    showOrHideQemuButton();
242
243
}

ck's avatar
ck committed
244
void MaemoQemuManager::projectChanged(ProjectExplorer::Project *project)
245
{
246
    if (project) {
247
        toggleStarterButton(project->activeTarget());
248
249
        deviceConfigurationChanged(project->activeTarget());
    }
250
251
}

ck's avatar
ck committed
252
void MaemoQemuManager::targetAdded(ProjectExplorer::Target *target)
253
{
254
    if (!target || !MaemoGlobal::isMaemoTargetId(target->id()))
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
        return;

    // handle all run configuration changes, add, remove, etc...
    connect(target, SIGNAL(addedRunConfiguration(ProjectExplorer::RunConfiguration*)),
        this, SLOT(runConfigurationAdded(ProjectExplorer::RunConfiguration*)));
    connect(target, SIGNAL(removedRunConfiguration(ProjectExplorer::RunConfiguration*)),
        this, SLOT(runConfigurationRemoved(ProjectExplorer::RunConfiguration*)));
    connect(target, SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
        this, SLOT(runConfigurationChanged(ProjectExplorer::RunConfiguration*)));

    // handle all build configuration changes, add, remove, etc...
    connect(target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
        this, SLOT(buildConfigurationAdded(ProjectExplorer::BuildConfiguration*)));
    connect(target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
        this, SLOT(buildConfigurationRemoved(ProjectExplorer::BuildConfiguration*)));
    connect(target, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
        this, SLOT(buildConfigurationChanged(ProjectExplorer::BuildConfiguration*)));

    // handle the qt version changes the build configuration uses
    connect(target, SIGNAL(environmentChanged()), this, SLOT(environmentChanged()));

276
    foreach (RunConfiguration *rc, target->runConfigurations())
277
        toggleDeviceConnections(qobject_cast<RemoteLinuxRunConfiguration*> (rc), true);
278
    toggleStarterButton(target);
279
280
}

ck's avatar
ck committed
281
void MaemoQemuManager::targetRemoved(ProjectExplorer::Target *target)
282
{
283
    if (!target || !MaemoGlobal::isMaemoTargetId(target->id()))
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
        return;

    disconnect(target, SIGNAL(addedRunConfiguration(ProjectExplorer::RunConfiguration*)),
        this, SLOT(runConfigurationAdded(ProjectExplorer::RunConfiguration*)));
    disconnect(target, SIGNAL(removedRunConfiguration(ProjectExplorer::RunConfiguration*)),
        this, SLOT(runConfigurationRemoved(ProjectExplorer::RunConfiguration*)));
    disconnect(target, SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
        this, SLOT(runConfigurationChanged(ProjectExplorer::RunConfiguration*)));

    disconnect(target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
        this, SLOT(buildConfigurationAdded(ProjectExplorer::BuildConfiguration*)));
    disconnect(target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
        this, SLOT(buildConfigurationRemoved(ProjectExplorer::BuildConfiguration*)));
    disconnect(target, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
        this, SLOT(buildConfigurationChanged(ProjectExplorer::BuildConfiguration*)));

    disconnect(target, SIGNAL(environmentChanged()), this, SLOT(environmentChanged()));

302
    foreach (RunConfiguration *rc, target->runConfigurations())
303
        toggleDeviceConnections(qobject_cast<RemoteLinuxRunConfiguration*> (rc), false);
304
    showOrHideQemuButton();
305
306
}

ck's avatar
ck committed
307
void MaemoQemuManager::targetChanged(ProjectExplorer::Target *target)
308
{
309
    if (target) {
310
        toggleStarterButton(target);
311
312
        deviceConfigurationChanged(target);
    }
313
314
}

ck's avatar
ck committed
315
void MaemoQemuManager::runConfigurationAdded(ProjectExplorer::RunConfiguration *rc)
316
{
317
    if (!rc || !MaemoGlobal::isMaemoTargetId(rc->target()->id()))
318
        return;
319
    toggleDeviceConnections(qobject_cast<RemoteLinuxRunConfiguration*> (rc), true);
320
321
}

ck's avatar
ck committed
322
void MaemoQemuManager::runConfigurationRemoved(ProjectExplorer::RunConfiguration *rc)
323
{
324
    if (!rc || !MaemoGlobal::isMaemoTargetId(rc->target()->id()))
325
        return;
326
    toggleDeviceConnections(qobject_cast<RemoteLinuxRunConfiguration*> (rc), false);
327
328
}

ck's avatar
ck committed
329
void MaemoQemuManager::runConfigurationChanged(ProjectExplorer::RunConfiguration *rc)
330
331
{
    if (rc)
ck's avatar
ck committed
332
        m_qemuAction->setEnabled(targetUsesMatchingRuntimeConfig(rc->target()));
333
334
}

ck's avatar
ck committed
335
void MaemoQemuManager::buildConfigurationAdded(ProjectExplorer::BuildConfiguration *bc)
336
{
337
    if (!bc || !MaemoGlobal::isMaemoTargetId(bc->target()->id()))
338
339
340
341
342
        return;

    connect(bc, SIGNAL(environmentChanged()), this, SLOT(environmentChanged()));
}

ck's avatar
ck committed
343
void MaemoQemuManager::buildConfigurationRemoved(ProjectExplorer::BuildConfiguration *bc)
344
{
345
    if (!bc || !MaemoGlobal::isMaemoTargetId(bc->target()->id()))
346
347
348
349
350
        return;

    disconnect(bc, SIGNAL(environmentChanged()), this, SLOT(environmentChanged()));
}

ck's avatar
ck committed
351
void MaemoQemuManager::buildConfigurationChanged(ProjectExplorer::BuildConfiguration *bc)
352
353
{
    if (bc)
354
        toggleStarterButton(bc->target());
355
356
}

ck's avatar
ck committed
357
void MaemoQemuManager::environmentChanged()
358
359
360
361
{
    // likely to happen when the qt version changes the build config is using
    if (ProjectExplorerPlugin *explorer = ProjectExplorerPlugin::instance()) {
        if (Project *project = explorer->session()->startupProject())
362
            toggleStarterButton(project->activeTarget());
363
364
365
    }
}

ck's avatar
ck committed
366
void MaemoQemuManager::deviceConfigurationChanged(ProjectExplorer::Target *target)
367
{
ck's avatar
ck committed
368
    m_qemuAction->setEnabled(targetUsesMatchingRuntimeConfig(target));
369
370
}

ck's avatar
ck committed
371
void MaemoQemuManager::startRuntime()
372
373
374
375
376
{
    m_userTerminated = false;
    Project *p = ProjectExplorerPlugin::instance()->session()->startupProject();
    if (!p)
        return;
377
    QtSupport::BaseQtVersion *version;
ck's avatar
ck committed
378
379
    if (!targetUsesMatchingRuntimeConfig(p->activeTarget(), &version)) {
        qWarning("Strange: Qemu button was enabled, but target does not match.");
380
        return;
ck's avatar
ck committed
381
    }
382

ck's avatar
ck committed
383
    m_runningQtId = version->uniqueId();
384
    const MaemoQemuRuntime rt = m_runtimes.value(version->uniqueId());
385
    m_qemuProcess->setProcessEnvironment(rt.environment());
ck's avatar
ck committed
386
    m_qemuProcess->setWorkingDirectory(rt.m_root);
387
    m_qemuProcess->start(rt.m_bin % QLatin1Char(' ') % rt.m_args);
ck's avatar
ck committed
388
389
    if (!m_qemuProcess->waitForStarted())
        return;
390

ck's avatar
ck committed
391
392
393
    emit qemuProcessStatus(QemuStarting);
    connect(m_qemuAction, SIGNAL(triggered()), this, SLOT(terminateRuntime()));
    disconnect(m_qemuAction, SIGNAL(triggered()), this, SLOT(startRuntime()));
394
395
}

ck's avatar
ck committed
396
void MaemoQemuManager::terminateRuntime()
397
398
399
400
401
402
403
404
405
406
407
408
{
    m_userTerminated = true;

    if (m_qemuProcess->state() != QProcess::NotRunning) {
        m_qemuProcess->terminate();
        m_qemuProcess->kill();
    }

    connect(m_qemuAction, SIGNAL(triggered()), this, SLOT(startRuntime()));
    disconnect(m_qemuAction, SIGNAL(triggered()), this, SLOT(terminateRuntime()));
}

ck's avatar
ck committed
409
void MaemoQemuManager::qemuProcessFinished()
410
{
411
    m_runningQtId = INT_MIN;
412
    QemuStatus status = QemuFinished;
ck's avatar
ck committed
413
    QString error;
414
415

    if (!m_userTerminated) {
ck's avatar
ck committed
416
417
418
419
420
421
422
        if (m_qemuProcess->exitStatus() == QProcess::CrashExit) {
            status = QemuCrashed;
            error = m_qemuProcess->errorString();
        } else if (m_qemuProcess->exitCode() != 0) {
            error = tr("Qemu finished with error: Exit code was %1.")
                .arg(m_qemuProcess->exitCode());
        }
423
424
425
    }

    m_userTerminated = false;
ck's avatar
ck committed
426
    emit qemuProcessStatus(status, error);
427
428
}

ck's avatar
ck committed
429
void MaemoQemuManager::qemuProcessError(QProcess::ProcessError error)
430
431
432
433
434
{
    if (error == QProcess::FailedToStart)
        emit qemuProcessStatus(QemuFailedToStart, m_qemuProcess->errorString());
}

ck's avatar
ck committed
435
void MaemoQemuManager::qemuStatusChanged(QemuStatus status, const QString &error)
436
437
438
439
440
441
442
{
    bool running = false;
    switch (status) {
        case QemuStarting:
            running = true;
            break;
        case QemuFailedToStart:
443
444
            QMessageBox::warning(0, tr("Qemu error"),
                tr("Qemu failed to start: %1"));
445
            break;
446
        case QemuCrashed:
447
            MaemoQemuSettingsPage::showQemuCrashDialog();
448
449
450
            break;
        case QemuFinished:
        case QemuUserReason:
451
452
            if (!error.isEmpty())
                QMessageBox::warning(0, tr("Qemu error"), error);
453
454
455
456
457
458
459
460
            break;
        default:
            Q_ASSERT(!"Missing handling of Qemu status");
    }

    updateStarterIcon(running);
}

ck's avatar
ck committed
461
void MaemoQemuManager::qemuOutput()
ck's avatar
ck committed
462
463
464
465
466
{
    qDebug("%s", m_qemuProcess->readAllStandardOutput().data());
    qDebug("%s", m_qemuProcess->readAllStandardError().data());
}

467
468
469
void MaemoQemuManager::runtimeRootChanged(const QString &directory)
{
    QList<int> uniqueIds;
470
    QMap<int, MaemoQemuRuntime>::const_iterator it;
471
472
473
474
475
476
    for (it = m_runtimes.constBegin(); it != m_runtimes.constEnd(); ++it) {
        if (QDir(it.value().m_watchPath) == QDir(directory))
            uniqueIds.append(it.key());
    }

    foreach (int uniqueId, uniqueIds) {
477
        MaemoQemuRuntime runtime = m_runtimes.value(uniqueId, MaemoQemuRuntime());
478
479
480
481
482
483
484
485
486
487
        if (runtime.isValid()) {
            if (QFile::exists(runtime.m_root)) {
                // nothing changed, so we can remove it
                uniqueIds.removeAll(uniqueId);
            }
        } else {
            if (QFile::exists(runtime.m_root)) {
                if (!QFile::exists(runtime.m_root + QLatin1String("/information"))) {
                    // install might be still in progress
                    uniqueIds.removeAll(uniqueId);
488
489
                    runtimeFolderWatcher()->addDirectory(runtime.m_root,
                                                         Utils::FileSystemWatcher::WatchAllChanges);
490
491
492
493
494
495
496
497
498
499
500
                }
            }
        }
    }
    notify(uniqueIds);
}

void MaemoQemuManager::runtimeFolderChanged(const QString &directory)
{
    if (QFile::exists(directory + QLatin1String("/information"))) {
        QList<int> uniqueIds;
501
        QMap<int, MaemoQemuRuntime>::const_iterator it;
502
503
504
505
506
        for (it = m_runtimes.constBegin(); it != m_runtimes.constEnd(); ++it) {
            if (QDir(it.value().m_root) == QDir(directory))
                uniqueIds.append(it.key());
        }
        notify(uniqueIds);
507
        if (m_runtimeFolderWatcher)
508
            m_runtimeFolderWatcher->removeDirectory(directory);
509
510
511
    }
}

512
513
// -- private

ck's avatar
ck committed
514
void MaemoQemuManager::updateStarterIcon(bool running)
515
516
517
518
519
{
    QIcon::State state;
    QString toolTip;
    if (running) {
        state = QIcon::On;
520
        toolTip = tr("Stop MeeGo Emulator");
521
522
    } else {
        state = QIcon::Off;
523
        toolTip = tr("Start MeeGo Emulator");
524
525
526
527
528
529
530
    }

    m_qemuAction->setToolTip(toolTip);
    m_qemuAction->setIcon(m_qemuStarterIcon.pixmap(iconSize, QIcon::Normal,
        state));
}

ck's avatar
ck committed
531
void MaemoQemuManager::toggleStarterButton(Target *target)
532
533
534
{
    int uniqueId = -1;
    if (target) {
535
        if (AbstractQt4MaemoTarget *qt4Target = qobject_cast<AbstractQt4MaemoTarget*>(target)) {
536
            if (Qt4BuildConfiguration *bc = qt4Target->activeQt4BuildConfiguration()) {
537
                if (QtSupport::BaseQtVersion *version = bc->qtVersion())
538
539
540
541
542
                    uniqueId = version->uniqueId();
            }
        }
    }

543
    if (uniqueId >= 0 && (m_runtimes.isEmpty() || !m_runtimes.contains(uniqueId)))
544
        qtVersionsChanged(QList<int>(), QList<int>(), QList<int>() << uniqueId);
545

546
547
548
549
    bool isRunning = m_qemuProcess->state() != QProcess::NotRunning;
    if (m_runningQtId == uniqueId)
        isRunning = false;

550
551
552
553
554
555
556
557
    const Project * const p
        = ProjectExplorerPlugin::instance()->session()->startupProject();
    const bool qemuButtonEnabled
        = p && p->activeTarget() && MaemoGlobal::isMaemoTargetId(p->activeTarget()->id())
            && m_runtimes.value(uniqueId, MaemoQemuRuntime()).isValid()
            && targetUsesMatchingRuntimeConfig(target) && !isRunning;
    m_qemuAction->setEnabled(qemuButtonEnabled);
    showOrHideQemuButton();
558
559
}

ck's avatar
ck committed
560
bool MaemoQemuManager::sessionHasMaemoTarget() const
561
562
563
{
    ProjectExplorerPlugin *explorer = ProjectExplorerPlugin::instance();
    const QList<Project*> &projects = explorer->session()->projects();
564
565
    foreach (const Project *p, projects) {
        foreach (const Target * const target, p->targets()) {
566
            if (MaemoGlobal::isMaemoTargetId(target->id()))
567
568
569
570
                return true;
        }
    }
    return false;
571
572
}

ck's avatar
ck committed
573
bool MaemoQemuManager::targetUsesMatchingRuntimeConfig(Target *target,
574
    QtSupport::BaseQtVersion **qtVersion)
575
576
577
{
    if (!target)
        return false;
578
579
    if (target != target->project()->activeTarget())
        return false;
580

581
582
    RemoteLinuxRunConfiguration *mrc =
        qobject_cast<RemoteLinuxRunConfiguration *> (target->activeRunConfiguration());
ck's avatar
ck committed
583
584
585
586
587
588
    if (!mrc)
        return false;
    Qt4BuildConfiguration *bc
        = qobject_cast<Qt4BuildConfiguration *>(target->activeBuildConfiguration());
    if (!bc)
        return false;
589
    QtSupport::BaseQtVersion *version = bc->qtVersion();
590
    if (!version || !m_runtimes.value(version->uniqueId(), MaemoQemuRuntime()).isValid())
ck's avatar
ck committed
591
592
        return false;

ck's avatar
ck committed
593
594
    if (qtVersion)
        *qtVersion = version;
595
    const LinuxDeviceConfiguration::ConstPtr &config = mrc->deviceConfig();
596
    return config && config->deviceType() == LinuxDeviceConfiguration::Emulator;
597
598
}

599
600
void MaemoQemuManager::notify(const QList<int> uniqueIds)
{
601
    qtVersionsChanged(QList<int>(), QList<int>(), uniqueIds);
602
603
604
    environmentChanged();   // to toggle the start button
}

605
void MaemoQemuManager::toggleDeviceConnections(RemoteLinuxRunConfiguration *mrc,
606
607
608
609
610
611
612
613
614
615
616
617
618
    bool _connect)
{
    if (!mrc)
        return;

    if (_connect) { // handle device configuration changes
        connect(mrc, SIGNAL(deviceConfigurationChanged(ProjectExplorer::Target*)),
            this, SLOT(deviceConfigurationChanged(ProjectExplorer::Target*)));
    } else {
        disconnect(mrc, SIGNAL(deviceConfigurationChanged(ProjectExplorer::Target*)),
            this, SLOT(deviceConfigurationChanged(ProjectExplorer::Target*)));
    }
}
619
620
621
622
623
624
625
626

void MaemoQemuManager::showOrHideQemuButton()
{
    const bool showButton = !m_runtimes.isEmpty() && sessionHasMaemoTarget();
    if (!showButton)
        terminateRuntime();
    m_qemuAction->setVisible(showButton);
}
627
628
629

}   // namespace Internal
}   // namespace Madde