OSDN Git Service

4e24959103467d11681b01bc09193a0a75c3c87a
[qt-creator-jp/qt-creator-jp.git] / src / plugins / qt4projectmanager / qt-maemo / maemoqemumanager.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "maemoqemumanager.h"
35
36 #include "maemoglobal.h"
37 #include "maemomanager.h"
38 #include "maemoqemuruntimeparser.h"
39 #include "maemosettingspages.h"
40 #include "maemorunconfiguration.h"
41 #include "qtversionmanager.h"
42 #include "qt4project.h"
43 #include "qt4projectmanagerconstants.h"
44 #include "qt4maemotarget.h"
45
46 #include <coreplugin/actionmanager/actionmanager.h>
47 #include <coreplugin/actionmanager/command.h>
48 #include <coreplugin/uniqueidmanager.h>
49 #include <coreplugin/coreconstants.h>
50 #include <coreplugin/icore.h>
51 #include <coreplugin/icontext.h>
52 #include <coreplugin/modemanager.h>
53
54 #include <projectexplorer/projectexplorer.h>
55 #include <projectexplorer/session.h>
56
57 #include <QtCore/QDebug>
58 #include <QtCore/QDir>
59 #include <QtCore/QList>
60 #include <QtCore/QSet>
61 #include <QtCore/QStringBuilder>
62
63 #include <QtGui/QAction>
64 #include <QtGui/QDesktopServices>
65 #include <QtGui/QMessageBox>
66
67 #include <limits.h>
68
69 using namespace ProjectExplorer;
70 using namespace Qt4ProjectManager;
71 using namespace Qt4ProjectManager::Internal;
72
73 MaemoQemuManager *MaemoQemuManager::m_instance = 0;
74
75 const QSize iconSize = QSize(24, 20);
76
77 MaemoQemuManager::MaemoQemuManager(QObject *parent)
78     : QObject(parent)
79     , m_qemuAction(0)
80     , m_qemuProcess(new QProcess(this))
81     , m_runningQtId(INT_MIN)
82     , m_userTerminated(false)
83 {
84     m_qemuStarterIcon.addFile(":/qt-maemo/images/qemu-run.png", iconSize);
85     m_qemuStarterIcon.addFile(":/qt-maemo/images/qemu-stop.png", iconSize,
86         QIcon::Normal, QIcon::On);
87
88     m_qemuAction = new QAction("Maemo Emulator", this);
89     m_qemuAction->setIcon(m_qemuStarterIcon.pixmap(iconSize));
90     m_qemuAction->setToolTip(tr("Start Maemo Emulator"));
91     connect(m_qemuAction, SIGNAL(triggered()), this, SLOT(startRuntime()));
92
93     Core::ICore *core = Core::ICore::instance();
94     Core::ActionManager *actionManager = core->actionManager();
95     Core::Command *qemuCommand = actionManager->registerAction(m_qemuAction,
96         "MaemoEmulator", Core::Context(Core::Constants::C_GLOBAL));
97     qemuCommand->setAttribute(Core::Command::CA_UpdateText);
98     qemuCommand->setAttribute(Core::Command::CA_UpdateIcon);
99
100     Core::ModeManager *modeManager = core->modeManager();
101     modeManager->addAction(qemuCommand->action(), 1);
102     m_qemuAction->setEnabled(false);
103     m_qemuAction->setVisible(false);
104
105     // listen to qt version changes to update the start button
106     connect(QtVersionManager::instance(), SIGNAL(qtVersionsChanged(QList<int>)),
107         this, SLOT(qtVersionsChanged(QList<int>)));
108
109     // listen to project add, remove and startup changes to udate start button
110     SessionManager *session = ProjectExplorerPlugin::instance()->session();
111     connect(session, SIGNAL(projectAdded(ProjectExplorer::Project*)), this,
112         SLOT(projectAdded(ProjectExplorer::Project*)));
113     connect(session, SIGNAL(projectRemoved(ProjectExplorer::Project*)), this,
114         SLOT(projectRemoved(ProjectExplorer::Project*)));
115     connect(session, SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
116         this, SLOT(projectChanged(ProjectExplorer::Project*)));
117
118     connect(m_qemuProcess, SIGNAL(error(QProcess::ProcessError)), this,
119         SLOT(qemuProcessError(QProcess::ProcessError)));
120     connect(m_qemuProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this,
121         SLOT(qemuProcessFinished()));
122     connect(m_qemuProcess, SIGNAL(readyReadStandardOutput()), this,
123         SLOT(qemuOutput()));
124     connect(m_qemuProcess, SIGNAL(readyReadStandardError()), this,
125         SLOT(qemuOutput()));
126     connect(this, SIGNAL(qemuProcessStatus(QemuStatus, QString)),
127         this, SLOT(qemuStatusChanged(QemuStatus, QString)));
128
129     m_runtimeRootWatcher = new QFileSystemWatcher(this);
130     connect(m_runtimeRootWatcher, SIGNAL(directoryChanged(QString)), this,
131         SLOT(runtimeRootChanged(QString)));
132     m_runtimeFolderWatcher = new QFileSystemWatcher(this);
133     connect(m_runtimeFolderWatcher, SIGNAL(directoryChanged(QString)), this,
134         SLOT(runtimeFolderChanged(QString)));
135 }
136
137 MaemoQemuManager::~MaemoQemuManager()
138 {
139     terminateRuntime();
140     m_instance = 0;
141 }
142
143 MaemoQemuManager &MaemoQemuManager::instance(QObject *parent)
144 {
145     if (m_instance == 0)
146         m_instance = new MaemoQemuManager(parent);
147     return *m_instance;
148 }
149
150 bool MaemoQemuManager::runtimeForQtVersion(int uniqueId, MaemoQemuRuntime *rt) const
151 {
152     *rt = m_runtimes.value(uniqueId, MaemoQemuRuntime());
153     return rt->isValid();
154 }
155
156 bool MaemoQemuManager::qemuIsRunning() const
157 {
158     return m_runningQtId != INT_MIN;
159 }
160
161 void MaemoQemuManager::qtVersionsChanged(const QList<int> &uniqueIds)
162 {
163     QtVersionManager *manager = QtVersionManager::instance();
164     foreach (int uniqueId, uniqueIds) {
165         if (manager->isValidId(uniqueId)) {
166             QtVersion *version = manager->version(uniqueId);
167             if (version->supportsTargetId(Constants::MAEMO5_DEVICE_TARGET_ID)
168                     || version->supportsTargetId(Constants::HARMATTAN_DEVICE_TARGET_ID)
169                     || version->supportsTargetId(Constants::MEEGO_DEVICE_TARGET_ID)) {
170                 MaemoQemuRuntime runtime
171                     = MaemoQemuRuntimeParser::parseRuntime(version);
172                 if (runtime.isValid()) {
173                     m_runtimes.insert(uniqueId, runtime);
174                     if (!m_runtimeRootWatcher->directories().contains(runtime.m_watchPath))
175                         m_runtimeRootWatcher->addPath(runtime.m_watchPath);
176                 } else {
177                     m_runtimes.remove(uniqueId);
178                 }
179             }
180         } else {
181             // this qt version has been removed from the settings
182             m_runtimes.remove(uniqueId);
183             if (uniqueId == m_runningQtId) {
184                 terminateRuntime();
185                 emit qemuProcessStatus(QemuUserReason, tr("Qemu has been shut "
186                     "down, because you removed the corresponding Qt version."));
187             }
188         }
189     }
190
191     showOrHideQemuButton();
192 }
193
194 void MaemoQemuManager::projectAdded(ProjectExplorer::Project *project)
195 {
196     // handle all target related changes, add, remove, etc...
197     connect(project, SIGNAL(addedTarget(ProjectExplorer::Target*)), this,
198         SLOT(targetAdded(ProjectExplorer::Target*)));
199     connect(project, SIGNAL(removedTarget(ProjectExplorer::Target*)), this,
200         SLOT(targetRemoved(ProjectExplorer::Target*)));
201     connect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
202         this, SLOT(targetChanged(ProjectExplorer::Target*)));
203
204     foreach (Target *target, project->targets())
205         targetAdded(target);
206 }
207
208 void MaemoQemuManager::projectRemoved(ProjectExplorer::Project *project)
209 {
210     disconnect(project, SIGNAL(addedTarget(ProjectExplorer::Target*)), this,
211         SLOT(targetAdded(ProjectExplorer::Target*)));
212     disconnect(project, SIGNAL(removedTarget(ProjectExplorer::Target*)), this,
213         SLOT(targetRemoved(ProjectExplorer::Target*)));
214     disconnect(project, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
215         this, SLOT(targetChanged(ProjectExplorer::Target*)));
216
217     foreach (Target *target, project->targets())
218         targetRemoved(target);
219     showOrHideQemuButton();
220 }
221
222 void MaemoQemuManager::projectChanged(ProjectExplorer::Project *project)
223 {
224     if (project) {
225         toggleStarterButton(project->activeTarget());
226         deviceConfigurationChanged(project->activeTarget());
227     }
228 }
229
230 void MaemoQemuManager::targetAdded(ProjectExplorer::Target *target)
231 {
232     if (!target || !MaemoGlobal::isMaemoTargetId(target->id()))
233         return;
234
235     // handle all run configuration changes, add, remove, etc...
236     connect(target, SIGNAL(addedRunConfiguration(ProjectExplorer::RunConfiguration*)),
237         this, SLOT(runConfigurationAdded(ProjectExplorer::RunConfiguration*)));
238     connect(target, SIGNAL(removedRunConfiguration(ProjectExplorer::RunConfiguration*)),
239         this, SLOT(runConfigurationRemoved(ProjectExplorer::RunConfiguration*)));
240     connect(target, SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
241         this, SLOT(runConfigurationChanged(ProjectExplorer::RunConfiguration*)));
242
243     // handle all build configuration changes, add, remove, etc...
244     connect(target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
245         this, SLOT(buildConfigurationAdded(ProjectExplorer::BuildConfiguration*)));
246     connect(target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
247         this, SLOT(buildConfigurationRemoved(ProjectExplorer::BuildConfiguration*)));
248     connect(target, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
249         this, SLOT(buildConfigurationChanged(ProjectExplorer::BuildConfiguration*)));
250
251     // handle the qt version changes the build configuration uses
252     connect(target, SIGNAL(environmentChanged()), this, SLOT(environmentChanged()));
253
254     foreach (RunConfiguration *rc, target->runConfigurations())
255         toggleDeviceConnections(qobject_cast<MaemoRunConfiguration*> (rc), true);
256     toggleStarterButton(target);
257 }
258
259 void MaemoQemuManager::targetRemoved(ProjectExplorer::Target *target)
260 {
261     if (!target || !MaemoGlobal::isMaemoTargetId(target->id()))
262         return;
263
264     disconnect(target, SIGNAL(addedRunConfiguration(ProjectExplorer::RunConfiguration*)),
265         this, SLOT(runConfigurationAdded(ProjectExplorer::RunConfiguration*)));
266     disconnect(target, SIGNAL(removedRunConfiguration(ProjectExplorer::RunConfiguration*)),
267         this, SLOT(runConfigurationRemoved(ProjectExplorer::RunConfiguration*)));
268     disconnect(target, SIGNAL(activeRunConfigurationChanged(ProjectExplorer::RunConfiguration*)),
269         this, SLOT(runConfigurationChanged(ProjectExplorer::RunConfiguration*)));
270
271     disconnect(target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
272         this, SLOT(buildConfigurationAdded(ProjectExplorer::BuildConfiguration*)));
273     disconnect(target, SIGNAL(removedBuildConfiguration(ProjectExplorer::BuildConfiguration*)),
274         this, SLOT(buildConfigurationRemoved(ProjectExplorer::BuildConfiguration*)));
275     disconnect(target, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
276         this, SLOT(buildConfigurationChanged(ProjectExplorer::BuildConfiguration*)));
277
278     disconnect(target, SIGNAL(environmentChanged()), this, SLOT(environmentChanged()));
279
280     foreach (RunConfiguration *rc, target->runConfigurations())
281         toggleDeviceConnections(qobject_cast<MaemoRunConfiguration*> (rc), false);
282     showOrHideQemuButton();
283 }
284
285 void MaemoQemuManager::targetChanged(ProjectExplorer::Target *target)
286 {
287     if (target) {
288         toggleStarterButton(target);
289         deviceConfigurationChanged(target);
290     }
291 }
292
293 void MaemoQemuManager::runConfigurationAdded(ProjectExplorer::RunConfiguration *rc)
294 {
295     if (!rc || !MaemoGlobal::isMaemoTargetId(rc->target()->id()))
296         return;
297     toggleDeviceConnections(qobject_cast<MaemoRunConfiguration*> (rc), true);
298 }
299
300 void MaemoQemuManager::runConfigurationRemoved(ProjectExplorer::RunConfiguration *rc)
301 {
302     if (!rc || !MaemoGlobal::isMaemoTargetId(rc->target()->id()))
303         return;
304     toggleDeviceConnections(qobject_cast<MaemoRunConfiguration*> (rc), false);
305 }
306
307 void MaemoQemuManager::runConfigurationChanged(ProjectExplorer::RunConfiguration *rc)
308 {
309     if (rc)
310         m_qemuAction->setEnabled(targetUsesMatchingRuntimeConfig(rc->target()));
311 }
312
313 void MaemoQemuManager::buildConfigurationAdded(ProjectExplorer::BuildConfiguration *bc)
314 {
315     if (!bc || !MaemoGlobal::isMaemoTargetId(bc->target()->id()))
316         return;
317
318     connect(bc, SIGNAL(environmentChanged()), this, SLOT(environmentChanged()));
319 }
320
321 void MaemoQemuManager::buildConfigurationRemoved(ProjectExplorer::BuildConfiguration *bc)
322 {
323     if (!bc || !MaemoGlobal::isMaemoTargetId(bc->target()->id()))
324         return;
325
326     disconnect(bc, SIGNAL(environmentChanged()), this, SLOT(environmentChanged()));
327 }
328
329 void MaemoQemuManager::buildConfigurationChanged(ProjectExplorer::BuildConfiguration *bc)
330 {
331     if (bc)
332         toggleStarterButton(bc->target());
333 }
334
335 void MaemoQemuManager::environmentChanged()
336 {
337     // likely to happen when the qt version changes the build config is using
338     if (ProjectExplorerPlugin *explorer = ProjectExplorerPlugin::instance()) {
339         if (Project *project = explorer->session()->startupProject())
340             toggleStarterButton(project->activeTarget());
341     }
342 }
343
344 void MaemoQemuManager::deviceConfigurationChanged(ProjectExplorer::Target *target)
345 {
346     m_qemuAction->setEnabled(targetUsesMatchingRuntimeConfig(target));
347 }
348
349 void MaemoQemuManager::startRuntime()
350 {
351     m_userTerminated = false;
352     Project *p = ProjectExplorerPlugin::instance()->session()->startupProject();
353     if (!p)
354         return;
355     QtVersion *version;
356     if (!targetUsesMatchingRuntimeConfig(p->activeTarget(), &version)) {
357         qWarning("Strange: Qemu button was enabled, but target does not match.");
358         return;
359     }
360
361     m_runningQtId = version->uniqueId();
362     const MaemoQemuRuntime rt = m_runtimes.value(version->uniqueId());
363     m_qemuProcess->setProcessEnvironment(rt.environment());
364     m_qemuProcess->setWorkingDirectory(rt.m_root);
365     m_qemuProcess->start(rt.m_bin % QLatin1Char(' ') % rt.m_args);
366     if (!m_qemuProcess->waitForStarted())
367         return;
368
369     emit qemuProcessStatus(QemuStarting);
370     connect(m_qemuAction, SIGNAL(triggered()), this, SLOT(terminateRuntime()));
371     disconnect(m_qemuAction, SIGNAL(triggered()), this, SLOT(startRuntime()));
372 }
373
374 void MaemoQemuManager::terminateRuntime()
375 {
376     m_userTerminated = true;
377
378     if (m_qemuProcess->state() != QProcess::NotRunning) {
379         m_qemuProcess->terminate();
380         m_qemuProcess->kill();
381     }
382
383     connect(m_qemuAction, SIGNAL(triggered()), this, SLOT(startRuntime()));
384     disconnect(m_qemuAction, SIGNAL(triggered()), this, SLOT(terminateRuntime()));
385 }
386
387 void MaemoQemuManager::qemuProcessFinished()
388 {
389     m_runningQtId = INT_MIN;
390     QemuStatus status = QemuFinished;
391     QString error;
392
393     if (!m_userTerminated) {
394         if (m_qemuProcess->exitStatus() == QProcess::CrashExit) {
395             status = QemuCrashed;
396             error = m_qemuProcess->errorString();
397         } else if (m_qemuProcess->exitCode() != 0) {
398             error = tr("Qemu finished with error: Exit code was %1.")
399                 .arg(m_qemuProcess->exitCode());
400         }
401     }
402
403     m_userTerminated = false;
404     emit qemuProcessStatus(status, error);
405 }
406
407 void MaemoQemuManager::qemuProcessError(QProcess::ProcessError error)
408 {
409     if (error == QProcess::FailedToStart)
410         emit qemuProcessStatus(QemuFailedToStart, m_qemuProcess->errorString());
411 }
412
413 void MaemoQemuManager::qemuStatusChanged(QemuStatus status, const QString &error)
414 {
415     bool running = false;
416     switch (status) {
417         case QemuStarting:
418             running = true;
419             break;
420         case QemuFailedToStart:
421             QMessageBox::warning(0, tr("Qemu error"),
422                 tr("Qemu failed to start: %1"));
423             break;
424         case QemuCrashed:
425             MaemoManager::instance().qemuSettingsPage()->showQemuCrashDialog();
426             break;
427         case QemuFinished:
428         case QemuUserReason:
429             if (!error.isEmpty())
430                 QMessageBox::warning(0, tr("Qemu error"), error);
431             break;
432         default:
433             Q_ASSERT(!"Missing handling of Qemu status");
434     }
435
436     updateStarterIcon(running);
437 }
438
439 void MaemoQemuManager::qemuOutput()
440 {
441     qDebug("%s", m_qemuProcess->readAllStandardOutput().data());
442     qDebug("%s", m_qemuProcess->readAllStandardError().data());
443 }
444
445 void MaemoQemuManager::runtimeRootChanged(const QString &directory)
446 {
447     QList<int> uniqueIds;
448     QMap<int, MaemoQemuRuntime>::const_iterator it;
449     for (it = m_runtimes.constBegin(); it != m_runtimes.constEnd(); ++it) {
450         if (QDir(it.value().m_watchPath) == QDir(directory))
451             uniqueIds.append(it.key());
452     }
453
454     foreach (int uniqueId, uniqueIds) {
455         MaemoQemuRuntime runtime = m_runtimes.value(uniqueId, MaemoQemuRuntime());
456         if (runtime.isValid()) {
457             if (QFile::exists(runtime.m_root)) {
458                 // nothing changed, so we can remove it
459                 uniqueIds.removeAll(uniqueId);
460             }
461         } else {
462             if (QFile::exists(runtime.m_root)) {
463                 if (!QFile::exists(runtime.m_root + QLatin1String("/information"))) {
464                     // install might be still in progress
465                     uniqueIds.removeAll(uniqueId);
466                     m_runtimeFolderWatcher->addPath(runtime.m_root);
467                 }
468             }
469         }
470     }
471     notify(uniqueIds);
472 }
473
474 void MaemoQemuManager::runtimeFolderChanged(const QString &directory)
475 {
476     if (QFile::exists(directory + QLatin1String("/information"))) {
477         QList<int> uniqueIds;
478         QMap<int, MaemoQemuRuntime>::const_iterator it;
479         for (it = m_runtimes.constBegin(); it != m_runtimes.constEnd(); ++it) {
480             if (QDir(it.value().m_root) == QDir(directory))
481                 uniqueIds.append(it.key());
482         }
483         notify(uniqueIds);
484         m_runtimeFolderWatcher->removePath(directory);
485     }
486 }
487
488 // -- private
489
490 void MaemoQemuManager::updateStarterIcon(bool running)
491 {
492     QIcon::State state;
493     QString toolTip;
494     if (running) {
495         state = QIcon::On;
496         toolTip = tr("Stop Maemo Emulator");
497     } else {
498         state = QIcon::Off;
499         toolTip = tr("Start Maemo Emulator");
500     }
501
502     m_qemuAction->setToolTip(toolTip);
503     m_qemuAction->setIcon(m_qemuStarterIcon.pixmap(iconSize, QIcon::Normal,
504         state));
505 }
506
507 void MaemoQemuManager::toggleStarterButton(Target *target)
508 {
509     int uniqueId = -1;
510     if (target) {
511         if (AbstractQt4MaemoTarget *qt4Target = qobject_cast<AbstractQt4MaemoTarget*>(target)) {
512             if (Qt4BuildConfiguration *bc = qt4Target->activeBuildConfiguration()) {
513                 if (QtVersion *version = bc->qtVersion())
514                     uniqueId = version->uniqueId();
515             }
516         }
517     }
518
519     if (uniqueId >= 0 && (m_runtimes.isEmpty() || !m_runtimes.contains(uniqueId)))
520         qtVersionsChanged(QList<int>() << uniqueId);
521
522     bool isRunning = m_qemuProcess->state() != QProcess::NotRunning;
523     if (m_runningQtId == uniqueId)
524         isRunning = false;
525
526     const Project * const p
527         = ProjectExplorerPlugin::instance()->session()->startupProject();
528     const bool qemuButtonEnabled
529         = p && p->activeTarget() && MaemoGlobal::isMaemoTargetId(p->activeTarget()->id())
530             && m_runtimes.value(uniqueId, MaemoQemuRuntime()).isValid()
531             && targetUsesMatchingRuntimeConfig(target) && !isRunning;
532     m_qemuAction->setEnabled(qemuButtonEnabled);
533     showOrHideQemuButton();
534 }
535
536 bool MaemoQemuManager::sessionHasMaemoTarget() const
537 {
538     ProjectExplorerPlugin *explorer = ProjectExplorerPlugin::instance();
539     const QList<Project*> &projects = explorer->session()->projects();
540     foreach (const Project *p, projects) {
541         foreach (const Target * const target, p->targets()) {
542             if (MaemoGlobal::isMaemoTargetId(target->id()))
543                 return true;
544         }
545     }
546     return false;
547 }
548
549 bool MaemoQemuManager::targetUsesMatchingRuntimeConfig(Target *target,
550     QtVersion **qtVersion)
551 {
552     if (!target)
553         return false;
554
555     MaemoRunConfiguration *mrc =
556         qobject_cast<MaemoRunConfiguration *> (target->activeRunConfiguration());
557     if (!mrc)
558         return false;
559     Qt4BuildConfiguration *bc
560         = qobject_cast<Qt4BuildConfiguration *>(target->activeBuildConfiguration());
561     if (!bc)
562         return false;
563     QtVersion *version = bc->qtVersion();
564     if (!version || !m_runtimes.value(version->uniqueId(), MaemoQemuRuntime()).isValid())
565         return false;
566
567     if (qtVersion)
568         *qtVersion = version;
569     const MaemoDeviceConfig::ConstPtr &config = mrc->deviceConfig();
570     return config && config->type() == MaemoDeviceConfig::Emulator;
571 }
572
573 void MaemoQemuManager::notify(const QList<int> uniqueIds)
574 {
575     qtVersionsChanged(uniqueIds);
576     environmentChanged();   // to toggle the start button
577 }
578
579 void MaemoQemuManager::toggleDeviceConnections(MaemoRunConfiguration *mrc,
580     bool _connect)
581 {
582     if (!mrc)
583         return;
584
585     if (_connect) { // handle device configuration changes
586         connect(mrc, SIGNAL(deviceConfigurationChanged(ProjectExplorer::Target*)),
587             this, SLOT(deviceConfigurationChanged(ProjectExplorer::Target*)));
588     } else {
589         disconnect(mrc, SIGNAL(deviceConfigurationChanged(ProjectExplorer::Target*)),
590             this, SLOT(deviceConfigurationChanged(ProjectExplorer::Target*)));
591     }
592 }
593
594 void MaemoQemuManager::showOrHideQemuButton()
595 {
596     const bool showButton = !m_runtimes.isEmpty() && sessionHasMaemoTarget();
597     if (!showButton)
598         terminateRuntime();
599     m_qemuAction->setVisible(showButton);
600 }