qmlprojectruncontrol.cpp 8.47 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
Kai Koehne's avatar
Kai Koehne committed
2
**
hjk's avatar
hjk committed
3 4
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
Kai Koehne's avatar
Kai Koehne committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
Kai Koehne's avatar
Kai Koehne committed
7
**
hjk's avatar
hjk committed
8 9 10 11 12 13 14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
Kai Koehne's avatar
Kai Koehne committed
15 16
**
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17 18 19 20 21 22 23 24 25
** Alternatively, 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26 27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
Kai Koehne's avatar
Kai Koehne committed
29 30 31 32 33

#include "qmlprojectruncontrol.h"
#include "qmlprojectrunconfiguration.h"
#include <coreplugin/icore.h>
#include <projectexplorer/projectexplorerconstants.h>
34
#include <projectexplorer/target.h>
Tobias Hunger's avatar
Tobias Hunger committed
35
#include <projectexplorer/kit.h>
36
#include <projectexplorer/project.h>
37
#include <projectexplorer/projectexplorer.h>
Kai Koehne's avatar
Kai Koehne committed
38 39
#include <utils/qtcassert.h>

Lasse Holmstedt's avatar
Lasse Holmstedt committed
40 41
#include <debugger/debuggerrunner.h>
#include <debugger/debuggerplugin.h>
42
#include <debugger/debuggerconstants.h>
Friedemann Kleint's avatar
Friedemann Kleint committed
43
#include <debugger/debuggerstartparameters.h>
hjk's avatar
hjk committed
44
#include <debugger/debuggerruncontrolfactory.h>
Daniel Teske's avatar
Daniel Teske committed
45
#include <qtsupport/baseqtversion.h>
46
#include <qtsupport/qmlobservertool.h>
47

48
#include <qmlprojectmanager/qmlprojectplugin.h>
49

50
using namespace ProjectExplorer;
Kai Koehne's avatar
Kai Koehne committed
51 52

namespace QmlProjectManager {
53

Kai Koehne's avatar
Kai Koehne committed
54 55
namespace Internal {

56
QmlProjectRunControl::QmlProjectRunControl(QmlProjectRunConfiguration *runConfiguration, RunMode mode)
dt's avatar
dt committed
57
    : RunControl(runConfiguration, mode)
Kai Koehne's avatar
Kai Koehne committed
58
{
59
    m_applicationLauncher.setEnvironment(runConfiguration->environment());
Kai Koehne's avatar
Kai Koehne committed
60 61
    m_applicationLauncher.setWorkingDirectory(runConfiguration->workingDirectory());

62
    if (mode == NormalRunMode) {
63 64 65 66
        m_executable = runConfiguration->viewerPath();
    } else {
        m_executable = runConfiguration->observerPath();
    }
Kai Koehne's avatar
Kai Koehne committed
67
    m_commandLineArguments = runConfiguration->viewerArguments();
68
    m_mainQmlFile = runConfiguration->mainScript();
Kai Koehne's avatar
Kai Koehne committed
69

con's avatar
con committed
70
    connect(&m_applicationLauncher, SIGNAL(appendMessage(QString,Utils::OutputFormat)),
Robert Loehning's avatar
Robert Loehning committed
71
            this, SLOT(slotAppendMessage(QString,Utils::OutputFormat)));
Kai Koehne's avatar
Kai Koehne committed
72 73 74 75 76 77
    connect(&m_applicationLauncher, SIGNAL(processExited(int)),
            this, SLOT(processExited(int)));
    connect(&m_applicationLauncher, SIGNAL(bringToForegroundRequested(qint64)),
            this, SLOT(slotBringApplicationToForeground(qint64)));
}

78
QmlProjectRunControl::~QmlProjectRunControl()
Kai Koehne's avatar
Kai Koehne committed
79
{
80
    stop();
Kai Koehne's avatar
Kai Koehne committed
81 82
}

83
void QmlProjectRunControl::start()
Kai Koehne's avatar
Kai Koehne committed
84
{
85
    m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable,
Kai Koehne's avatar
Kai Koehne committed
86
                                m_commandLineArguments);
87
    setApplicationProcessHandle(ProcessHandle(m_applicationLauncher.applicationPID()));
Kai Koehne's avatar
Kai Koehne committed
88
    emit started();
dt's avatar
dt committed
89
    QString msg = tr("Starting %1 %2\n")
90
        .arg(QDir::toNativeSeparators(m_executable), m_commandLineArguments);
con's avatar
con committed
91
    appendMessage(msg, Utils::NormalMessageFormat);
Kai Koehne's avatar
Kai Koehne committed
92 93
}

94
RunControl::StopResult QmlProjectRunControl::stop()
Kai Koehne's avatar
Kai Koehne committed
95 96
{
    m_applicationLauncher.stop();
97
    return StoppedSynchronously;
Kai Koehne's avatar
Kai Koehne committed
98 99
}

100
bool QmlProjectRunControl::isRunning() const
Kai Koehne's avatar
Kai Koehne committed
101 102 103 104
{
    return m_applicationLauncher.isRunning();
}

105
QIcon QmlProjectRunControl::icon() const
106
{
107
    return QIcon(QLatin1String(ProjectExplorer::Constants::ICON_RUN_SMALL));
108 109
}

110
void QmlProjectRunControl::slotBringApplicationToForeground(qint64 pid)
Kai Koehne's avatar
Kai Koehne committed
111 112 113 114
{
    bringApplicationToForeground(pid);
}

115
void QmlProjectRunControl::slotAppendMessage(const QString &line, Utils::OutputFormat format)
Kai Koehne's avatar
Kai Koehne committed
116
{
117
    appendMessage(line, format);
Kai Koehne's avatar
Kai Koehne committed
118 119
}

120
void QmlProjectRunControl::processExited(int exitCode)
Kai Koehne's avatar
Kai Koehne committed
121
{
dt's avatar
dt committed
122
    QString msg = tr("%1 exited with code %2\n")
123
        .arg(QDir::toNativeSeparators(m_executable)).arg(exitCode);
con's avatar
con committed
124
    appendMessage(msg, exitCode ? Utils::ErrorMessageFormat : Utils::NormalMessageFormat);
Kai Koehne's avatar
Kai Koehne committed
125 126 127
    emit finished();
}

128 129 130 131 132
QString QmlProjectRunControl::mainQmlFile() const
{
    return m_mainQmlFile;
}

133
QmlProjectRunControlFactory::QmlProjectRunControlFactory(QObject *parent)
Kai Koehne's avatar
Kai Koehne committed
134 135 136 137
    : IRunControlFactory(parent)
{
}

138
QmlProjectRunControlFactory::~QmlProjectRunControlFactory()
Kai Koehne's avatar
Kai Koehne committed
139 140 141
{
}

142
bool QmlProjectRunControlFactory::canRun(RunConfiguration *runConfiguration,
143
                                         RunMode mode) const
Kai Koehne's avatar
Kai Koehne committed
144
{
145 146
    QmlProjectRunConfiguration *config =
        qobject_cast<QmlProjectRunConfiguration*>(runConfiguration);
147 148
    if (!config)
        return false;
149
    if (mode == NormalRunMode)
150
        return !config->viewerPath().isEmpty();
151
    if (mode != DebugRunMode)
152
        return false;
153

154 155
    if (!Debugger::DebuggerPlugin::isActiveDebugLanguage(Debugger::QmlLanguage))
        return false;
Lasse Holmstedt's avatar
Lasse Holmstedt committed
156

157 158 159 160 161 162 163 164
    if (!config->observerPath().isEmpty())
        return true;
    if (!config->qtVersion())
        return false;
    if (!config->qtVersion()->needsQmlDebuggingLibrary())
        return true;
    if (QtSupport::QmlObserverTool::canBuild(config->qtVersion()))
        return true;
Lasse Holmstedt's avatar
Lasse Holmstedt committed
165
    return false;
Kai Koehne's avatar
Kai Koehne committed
166 167
}

168
RunControl *QmlProjectRunControlFactory::create(RunConfiguration *runConfiguration,
169
                                                RunMode mode, QString *errorMessage)
Kai Koehne's avatar
Kai Koehne committed
170 171
{
    QTC_ASSERT(canRun(runConfiguration, mode), return 0);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
172
    QmlProjectRunConfiguration *config = qobject_cast<QmlProjectRunConfiguration *>(runConfiguration);
173 174 175 176 177 178 179 180 181 182 183 184

    QList<ProjectExplorer::RunControl *> runcontrols =
            ProjectExplorer::ProjectExplorerPlugin::instance()->runControls();
    foreach (ProjectExplorer::RunControl *rc, runcontrols) {
        if (QmlProjectRunControl *qrc = qobject_cast<QmlProjectRunControl *>(rc)) {
            if (qrc->mainQmlFile() == config->mainScript())
                // Asking the user defeats the purpose
                // Making it configureable might be worth it
                qrc->stop();
        }
    }

Lasse Holmstedt's avatar
Lasse Holmstedt committed
185
    RunControl *runControl = 0;
186
    if (mode == NormalRunMode)
187
        runControl = new QmlProjectRunControl(config, mode);
188
    else if (mode == DebugRunMode)
189
        runControl = createDebugRunControl(config, errorMessage);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
190
    return runControl;
Kai Koehne's avatar
Kai Koehne committed
191 192
}

193
QString QmlProjectRunControlFactory::displayName() const
Kai Koehne's avatar
Kai Koehne committed
194 195 196 197
{
    return tr("Run");
}

198
RunControl *QmlProjectRunControlFactory::createDebugRunControl(QmlProjectRunConfiguration *runConfig, QString *errorMessage)
Lasse Holmstedt's avatar
Lasse Holmstedt committed
199 200 201
{
    Debugger::DebuggerStartParameters params;
    params.startMode = Debugger::StartInternal;
202
    params.executable = runConfig->observerPath();
203
    params.qmlServerAddress = QLatin1String("127.0.0.1");
204
    params.qmlServerPort = runConfig->debuggerAspect()->qmlDebugServerPort();
205
    params.processArgs = QString::fromLatin1("-qmljsdebugger=port:%1,block").arg(params.qmlServerPort);
206
    params.processArgs += QLatin1Char(' ') + runConfig->viewerArguments();
Lasse Holmstedt's avatar
Lasse Holmstedt committed
207
    params.workingDirectory = runConfig->workingDirectory();
208
    params.environment = runConfig->environment();
Lasse Holmstedt's avatar
Lasse Holmstedt committed
209
    params.displayName = runConfig->displayName();
210 211
    params.projectSourceDirectory = runConfig->target()->project()->projectDirectory();
    params.projectSourceFiles = runConfig->target()->project()->files(Project::ExcludeGeneratedFiles);
212
    if (runConfig->debuggerAspect()->useQmlDebugger())
Kai Koehne's avatar
Kai Koehne committed
213
        params.languages |= Debugger::QmlLanguage;
214
    if (runConfig->debuggerAspect()->useCppDebugger())
Kai Koehne's avatar
Kai Koehne committed
215 216
        params.languages |= Debugger::CppLanguage;

217 218 219 220 221 222 223
    // Makes sure that all bindings go through the JavaScript engine, so that
    // breakpoints are actually hit!
    const QString optimizerKey = QLatin1String("QML_DISABLE_OPTIMIZER");
    if (!params.environment.hasKey(optimizerKey)) {
        params.environment.set(optimizerKey, QLatin1String("1"));
    }

224
    if (params.executable.isEmpty()) {
225
        QmlProjectPlugin::showQmlObserverToolWarning();
226
        errorMessage->clear(); // hack, we already showed a error message
227 228 229
        return 0;
    }

230
    return Debugger::DebuggerPlugin::createDebugger(params, runConfig, errorMessage);
Lasse Holmstedt's avatar
Lasse Holmstedt committed
231 232
}

Kai Koehne's avatar
Kai Koehne committed
233 234
} // namespace Internal
} // namespace QmlProjectManager