From 80963107c637121e53b71722b1af7eaf70607183 Mon Sep 17 00:00:00 2001
From: Kai Koehne <kai.koehne@nokia.com>
Date: Wed, 16 Dec 2009 16:39:39 +0100
Subject: [PATCH] Fix various crashes for QmlProject

QmlProject used LocalApplicationRunCOnfiguration, but didn't provide
e.g. an associated BuildConfiguration. Fix this by implementing it's
own QmlRunControlFactory, QmlRunControl.
---
 src/plugins/qmlprojectmanager/qmlproject.cpp  | 128 ++++++++++++++----
 src/plugins/qmlprojectmanager/qmlproject.h    |  56 ++++++--
 .../qmlprojectmanager/qmlprojectplugin.cpp    |   1 +
 3 files changed, 141 insertions(+), 44 deletions(-)

diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index 89ebeaf584c..b63bc16b5e0 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -56,6 +56,7 @@
 #include <QtGui/QComboBox>
 #include <QtGui/QMessageBox>
 #include <QtGui/QLineEdit>
+#include <QtGui/QLabel>
 
 using namespace QmlProjectManager;
 using namespace QmlProjectManager::Internal;
@@ -299,7 +300,7 @@ void QmlProjectFile::modified(ReloadBehavior *)
 }
 
 QmlRunConfiguration::QmlRunConfiguration(QmlProject *pro)
-    : ProjectExplorer::LocalApplicationRunConfiguration(pro),
+    : ProjectExplorer::RunConfiguration(pro),
       m_project(pro),
       m_type(Constants::QMLRUNCONFIGURATION)
 {
@@ -322,25 +323,14 @@ QString QmlRunConfiguration::type() const
     return m_type;
 }
 
-QString QmlRunConfiguration::executable() const
+QString QmlRunConfiguration::viewerPath() const
 {
     if (!m_qmlViewerCustomPath.isEmpty())
         return m_qmlViewerCustomPath;
     return m_qmlViewerDefaultPath;
 }
 
-QmlRunConfiguration::RunMode QmlRunConfiguration::runMode() const
-{
-    return Gui;
-}
-
-QString QmlRunConfiguration::workingDirectory() const
-{
-    QFileInfo projectFile(m_project->file()->fileName());
-    return projectFile.absolutePath();
-}
-
-QStringList QmlRunConfiguration::commandLineArguments() const
+QStringList QmlRunConfiguration::viewerArguments() const
 {
     QStringList args;
 
@@ -350,23 +340,13 @@ QStringList QmlRunConfiguration::commandLineArguments() const
     const QString s = mainScript();
     if (! s.isEmpty())
         args.append(s);
-
     return args;
 }
 
-ProjectExplorer::Environment QmlRunConfiguration::environment() const
-{
-    return ProjectExplorer::Environment::systemEnvironment();
-}
-
-QString QmlRunConfiguration::dumperLibrary() const
-{
-    return QString();
-}
-
-QStringList QmlRunConfiguration::dumperLibraryLocations() const
+QString QmlRunConfiguration::workingDirectory() const
 {
-    return QStringList();
+    QFileInfo projectFile(m_project->file()->fileName());
+    return projectFile.absolutePath();
 }
 
 QWidget *QmlRunConfiguration::configurationWidget()
@@ -403,7 +383,7 @@ QWidget *QmlRunConfiguration::configurationWidget()
 
     Utils::PathChooser *qmlViewer = new Utils::PathChooser;
     qmlViewer->setExpectedKind(Utils::PathChooser::Command);
-    qmlViewer->setPath(executable());
+    qmlViewer->setPath(viewerPath());
     connect(qmlViewer, SIGNAL(changed(QString)), this, SLOT(onQmlViewerChanged()));
 
     QLineEdit *qmlViewerArgs = new QLineEdit;
@@ -449,7 +429,7 @@ void QmlRunConfiguration::onQmlViewerArgsChanged()
 
 void QmlRunConfiguration::save(ProjectExplorer::PersistentSettingsWriter &writer) const
 {
-    ProjectExplorer::LocalApplicationRunConfiguration::save(writer);
+    ProjectExplorer::RunConfiguration::save(writer);
 
     writer.saveValue(QLatin1String("qmlviewer"), m_qmlViewerCustomPath);
     writer.saveValue(QLatin1String("qmlviewerargs"), m_qmlViewerArgs);
@@ -458,7 +438,7 @@ void QmlRunConfiguration::save(ProjectExplorer::PersistentSettingsWriter &writer
 
 void QmlRunConfiguration::restore(const ProjectExplorer::PersistentSettingsReader &reader)
 {
-    ProjectExplorer::LocalApplicationRunConfiguration::restore(reader);
+    ProjectExplorer::RunConfiguration::restore(reader);
 
     m_qmlViewerCustomPath = reader.restoreValue(QLatin1String("qmlviewer")).toString();
     m_qmlViewerArgs = reader.restoreValue(QLatin1String("qmlviewerargs")).toString();
@@ -502,4 +482,92 @@ ProjectExplorer::RunConfiguration *QmlRunConfigurationFactory::create(ProjectExp
     return new QmlRunConfiguration(pro);
 }
 
+QmlRunControl::QmlRunControl(QmlRunConfiguration *runConfiguration)
+    : RunControl(runConfiguration)
+{
+    m_applicationLauncher.setEnvironment(ProjectExplorer::Environment::systemEnvironment().toStringList());
+    m_applicationLauncher.setWorkingDirectory(runConfiguration->workingDirectory());
+
+    m_executable = runConfiguration->viewerPath();
+    m_commandLineArguments = runConfiguration->viewerArguments();
+
+    connect(&m_applicationLauncher, SIGNAL(applicationError(QString)),
+            this, SLOT(slotError(QString)));
+    connect(&m_applicationLauncher, SIGNAL(appendOutput(QString)),
+            this, SLOT(slotAddToOutputWindow(QString)));
+    connect(&m_applicationLauncher, SIGNAL(processExited(int)),
+            this, SLOT(processExited(int)));
+    connect(&m_applicationLauncher, SIGNAL(bringToForegroundRequested(qint64)),
+            this, SLOT(bringApplicationToForeground(qint64)));
+}
+
+QmlRunControl::~QmlRunControl()
+{
+}
+
+void QmlRunControl::start()
+{
+    m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable, m_commandLineArguments);
+    emit started();
+    emit addToOutputWindow(this, tr("Starting %1...").arg(QDir::toNativeSeparators(m_executable)));
+}
+
+void QmlRunControl::stop()
+{
+    m_applicationLauncher.stop();
+}
+
+bool QmlRunControl::isRunning() const
+{
+    return m_applicationLauncher.isRunning();
+}
+
+void QmlRunControl::slotError(const QString &err)
+{
+    emit error(this, err);
+    emit finished();
+}
+
+void QmlRunControl::slotAddToOutputWindow(const QString &line)
+{
+    emit addToOutputWindowInline(this, line);
+}
+
+void QmlRunControl::processExited(int exitCode)
+{
+    emit addToOutputWindow(this, tr("%1 exited with code %2").arg(QDir::toNativeSeparators(m_executable)).arg(exitCode));
+    emit finished();
+}
+
+QmlRunControlFactory::QmlRunControlFactory(QObject *parent)
+    : IRunControlFactory::IRunControlFactory(parent)
+{
+}
+
+QmlRunControlFactory::~QmlRunControlFactory()
+{
+
+}
+
+bool QmlRunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const
+{
+    return (mode == ProjectExplorer::Constants::RUNMODE)
+            && (qobject_cast<QmlRunConfiguration*>(runConfiguration) != 0);
+}
 
+RunControl *QmlRunControlFactory::create(RunConfiguration *runConfiguration, const QString &mode)
+{
+    QTC_ASSERT(canRun(runConfiguration, mode), return 0);
+    return new QmlRunControl(qobject_cast<QmlRunConfiguration *>(runConfiguration));
+}
+
+QString QmlRunControlFactory::displayName() const
+{
+    return tr("Run");
+}
+
+QWidget *QmlRunControlFactory::configurationWidget(RunConfiguration *runConfiguration)
+{
+    Q_UNUSED(runConfiguration)
+    return new QLabel("TODO add Configuration widget");
+}
diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h
index 9cbb23a37eb..0101a26b6ca 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.h
+++ b/src/plugins/qmlprojectmanager/qmlproject.h
@@ -136,37 +136,30 @@ private:
     QString m_fileName;
 };
 
-class QmlRunConfiguration : public ProjectExplorer::LocalApplicationRunConfiguration
+class QmlRunConfiguration : public ProjectExplorer::RunConfiguration
 {
     Q_OBJECT
 public:
     QmlRunConfiguration(QmlProject *pro);
     virtual ~QmlRunConfiguration();
 
+    QString viewerPath() const;
+    QStringList viewerArguments() const;
+    QString workingDirectory() const;
+
+    // RunConfiguration
     virtual QString type() const;
-    virtual QString executable() const;
-    virtual RunMode runMode() const;
-    virtual QString workingDirectory() const;
-    virtual QStringList commandLineArguments() const;
-    virtual ProjectExplorer::Environment environment() const;
-    virtual QString dumperLibrary() const;
-    virtual QStringList dumperLibraryLocations() const;
     virtual QWidget *configurationWidget();
 
-    ProjectExplorer::ToolChain::ToolChainType toolChainType() const { return ProjectExplorer::ToolChain::OTHER; }
-
     virtual void save(ProjectExplorer::PersistentSettingsWriter &writer) const;
     virtual void restore(const ProjectExplorer::PersistentSettingsReader &reader);
 
 private Q_SLOTS:
+    QString mainScript() const;
     void setMainScript(const QString &scriptFile);
     void onQmlViewerChanged();
     void onQmlViewerArgsChanged();
 
-
-private:
-    QString mainScript() const;
-
 private:
     QmlProject *m_project;
     QString m_scriptFile;
@@ -200,6 +193,41 @@ private:
     QLatin1String m_type;
 };
 
+class QmlRunControl : public ProjectExplorer::RunControl {
+    Q_OBJECT
+public:
+    explicit QmlRunControl(QmlRunConfiguration *runConfiguration);
+    virtual ~QmlRunControl ();
+
+    // RunControl
+    virtual void start();
+    virtual void stop();
+    virtual bool isRunning() const;
+
+private slots:
+    void processExited(int exitCode);
+    void slotAddToOutputWindow(const QString &line);
+    void slotError(const QString & error);
+
+private:
+    ProjectExplorer::ApplicationLauncher m_applicationLauncher;
+
+    QString m_executable;
+    QStringList m_commandLineArguments;
+};
+
+class QmlRunControlFactory : public ProjectExplorer::IRunControlFactory {
+    Q_OBJECT
+public:
+    explicit QmlRunControlFactory(QObject *parent = 0);
+    virtual ~QmlRunControlFactory();
+
+    // IRunControlFactory
+    virtual bool canRun(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode) const;
+    virtual ProjectExplorer::RunControl *create(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode);
+    virtual QString displayName() const;
+    virtual QWidget *configurationWidget(ProjectExplorer::RunConfiguration *runConfiguration);
+};
 
 } // namespace Internal
 } // namespace QmlProjectManager
diff --git a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
index 72543e8111b..afc0dc81aab 100644
--- a/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
+++ b/src/plugins/qmlprojectmanager/qmlprojectplugin.cpp
@@ -86,6 +86,7 @@ bool QmlProjectPlugin::initialize(const QStringList &, QString *errorMessage)
 
     addAutoReleasedObject(manager);
     addAutoReleasedObject(new QmlRunConfigurationFactory);
+    addAutoReleasedObject(new QmlRunControlFactory);
     addAutoReleasedObject(new QmlNewProjectWizard);
     addAutoReleasedObject(new QmlProjectWizard);
     return true;
-- 
GitLab