forked from qt-creator/qt-creator
Initial import
This commit is contained in:
443
src/plugins/qt4projectmanager/qt4runconfiguration.cpp
Normal file
443
src/plugins/qt4projectmanager/qt4runconfiguration.cpp
Normal file
@@ -0,0 +1,443 @@
|
||||
/***************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Qt Software Information (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** Non-Open Source Usage
|
||||
**
|
||||
** Licensees may use this file in accordance with the Qt Beta Version
|
||||
** License Agreement, Agreement version 2.2 provided with the Software or,
|
||||
** alternatively, in accordance with the terms contained in a written
|
||||
** agreement between you and Nokia.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License versions 2.0 or 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the packaging
|
||||
** of this file. Please review the following information to ensure GNU
|
||||
** General Public Licensing requirements will be met:
|
||||
**
|
||||
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt GPL Exception version
|
||||
** 1.2, included in the file GPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
***************************************************************************/
|
||||
#include "qt4runconfiguration.h"
|
||||
#include "qt4project.h"
|
||||
#include "profilereader.h"
|
||||
#include "qt4nodes.h"
|
||||
#include "makestep.h"
|
||||
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/messagemanager.h>
|
||||
#include <coreplugin/variablemanager.h>
|
||||
#include <projectexplorer/buildstep.h>
|
||||
|
||||
#include <QtGui/QFormLayout>
|
||||
#include <QtGui/QInputDialog>
|
||||
|
||||
using namespace Qt4ProjectManager::Internal;
|
||||
using namespace Qt4ProjectManager;
|
||||
using ProjectExplorer::ApplicationRunConfiguration;
|
||||
using ProjectExplorer::PersistentSettingsReader;
|
||||
using ProjectExplorer::PersistentSettingsWriter;
|
||||
|
||||
Qt4RunConfiguration::Qt4RunConfiguration(Qt4Project *pro, QString proFilePath)
|
||||
: ApplicationRunConfiguration(pro), m_proFilePath(proFilePath), m_userSetName(false)
|
||||
{
|
||||
setName(tr("Qt4RunConfiguration"));
|
||||
if (!m_proFilePath.isEmpty()) {
|
||||
updateCachedValues();
|
||||
setName(QFileInfo(m_proFilePath).baseName());
|
||||
}
|
||||
}
|
||||
|
||||
Qt4RunConfiguration::~Qt4RunConfiguration()
|
||||
{
|
||||
}
|
||||
|
||||
QString Qt4RunConfiguration::type() const
|
||||
{
|
||||
return "Qt4ProjectManager.Qt4RunConfiguration";
|
||||
}
|
||||
|
||||
QWidget *Qt4RunConfiguration::configurationWidget()
|
||||
{
|
||||
QWidget *configWidget = new QWidget;
|
||||
QFormLayout *toplayout = new QFormLayout(configWidget);
|
||||
toplayout->setMargin(0);
|
||||
|
||||
QLabel *nameLabel = new QLabel(tr("Name:"));
|
||||
QLineEdit *nameLineEdit = new QLineEdit(name());
|
||||
nameLabel->setBuddy(nameLineEdit);
|
||||
toplayout->addRow(nameLabel, nameLineEdit);
|
||||
|
||||
QLabel *executableLabel = new QLabel(tr("Executable:"));
|
||||
QLabel *executableLabel2 = new QLabel(executable());
|
||||
toplayout->addRow(executableLabel, executableLabel2);
|
||||
|
||||
QLabel *workingDirectoryLabel = new QLabel(tr("Working Directory:"));
|
||||
QLabel *workingDirectoryLabel2 = new QLabel(workingDirectory());
|
||||
toplayout->addRow(workingDirectoryLabel, workingDirectoryLabel2);
|
||||
|
||||
QLabel *argumentsLabel = new QLabel(tr("&Arguments:"));
|
||||
QLineEdit *argumentsLineEdit = new QLineEdit(ProjectExplorer::Environment::joinArgumentList(commandLineArguments()));
|
||||
argumentsLabel->setBuddy(argumentsLineEdit);
|
||||
toplayout->addRow(argumentsLabel, argumentsLineEdit);
|
||||
|
||||
connect(argumentsLineEdit, SIGNAL(textEdited(const QString&)),
|
||||
this, SLOT(setCommandLineArguments(const QString&)));
|
||||
|
||||
connect(nameLineEdit, SIGNAL(textEdited(const QString&)),
|
||||
this, SLOT(nameEdited(const QString&)));
|
||||
|
||||
return configWidget;
|
||||
}
|
||||
|
||||
void Qt4RunConfiguration::save(PersistentSettingsWriter &writer) const
|
||||
{
|
||||
writer.saveValue("CommandLineArguments", m_commandLineArguments);
|
||||
writer.saveValue("ProFile", m_proFilePath);
|
||||
writer.saveValue("UserSetName", m_userSetName);
|
||||
ApplicationRunConfiguration::save(writer);
|
||||
}
|
||||
|
||||
void Qt4RunConfiguration::restore(const PersistentSettingsReader &reader)
|
||||
{
|
||||
ApplicationRunConfiguration::restore(reader);
|
||||
m_commandLineArguments = reader.restoreValue("CommandLineArguments").toStringList();
|
||||
m_proFilePath = reader.restoreValue("ProFile").toString();
|
||||
m_userSetName = reader.restoreValue("UserSetName").toBool();
|
||||
if (!m_proFilePath.isEmpty()) {
|
||||
updateCachedValues();
|
||||
if (!m_userSetName)
|
||||
setName(QFileInfo(m_proFilePath).baseName());
|
||||
}
|
||||
}
|
||||
|
||||
QString Qt4RunConfiguration::executable() const
|
||||
{
|
||||
return resolveVariables(project()->activeBuildConfiguration(), m_executable);
|
||||
}
|
||||
|
||||
ApplicationRunConfiguration::RunMode Qt4RunConfiguration::runMode() const
|
||||
{
|
||||
return m_runMode;
|
||||
}
|
||||
|
||||
QString Qt4RunConfiguration::workingDirectory() const
|
||||
{
|
||||
return resolveVariables(project()->activeBuildConfiguration(), m_workingDir);
|
||||
}
|
||||
|
||||
QStringList Qt4RunConfiguration::commandLineArguments() const
|
||||
{
|
||||
return m_commandLineArguments;
|
||||
}
|
||||
|
||||
ProjectExplorer::Environment Qt4RunConfiguration::environment() const
|
||||
{
|
||||
Qt4Project *pro = qobject_cast<Qt4Project *>(project());
|
||||
Q_ASSERT(pro);
|
||||
return pro->environment(pro->activeBuildConfiguration());
|
||||
}
|
||||
|
||||
void Qt4RunConfiguration::setCommandLineArguments(const QString &argumentsString)
|
||||
{
|
||||
m_commandLineArguments = ProjectExplorer::Environment::parseCombinedArgString(argumentsString);
|
||||
}
|
||||
|
||||
void Qt4RunConfiguration::nameEdited(const QString &name)
|
||||
{
|
||||
if (name == "") {
|
||||
setName(tr("Qt4RunConfiguration"));
|
||||
m_userSetName = false;
|
||||
} else {
|
||||
setName(name);
|
||||
m_userSetName = true;
|
||||
}
|
||||
}
|
||||
|
||||
QString Qt4RunConfiguration::proFilePath() const
|
||||
{
|
||||
return m_proFilePath;
|
||||
}
|
||||
|
||||
// and needs to be reloaded.
|
||||
// Check wheter it is
|
||||
void Qt4RunConfiguration::updateCachedValues()
|
||||
{
|
||||
ProFileReader *reader = static_cast<Qt4Project *>(project())->createProFileReader();
|
||||
if (!reader->readProFile(m_proFilePath)) {
|
||||
delete reader;
|
||||
Core::ICore *core = ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>();
|
||||
core->messageManager()->printToOutputPane(QString("Could not parse %1. The Qt4 run configuration %2 can not be started.").arg(m_proFilePath).arg(name()));
|
||||
return;
|
||||
}
|
||||
|
||||
QString destDir;
|
||||
|
||||
if (reader->contains("DESTDIR")) {
|
||||
// TODO Can return different destdirs for different scopes!
|
||||
destDir = reader->value("DESTDIR");
|
||||
if (QDir::isRelativePath(destDir)) {
|
||||
destDir = "${BASEDIR}" + QLatin1Char('/') + destDir;
|
||||
}
|
||||
} else {
|
||||
destDir = "${BASEDIR}";
|
||||
#if defined(Q_OS_WIN)
|
||||
if (!reader->contains("DESTDIR"))
|
||||
destDir += QLatin1Char('/') + "${QMAKE_BUILDCONFIG}";
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (Q_OS_MAC)
|
||||
if (!reader->values("-CONFIG").contains("app_bundle")) {
|
||||
destDir += QLatin1Char('/')
|
||||
+ "${QMAKE_TARGET}"
|
||||
+ QLatin1String(".app/Contents/MacOS");
|
||||
}
|
||||
#endif
|
||||
m_workingDir = destDir;
|
||||
m_executable = destDir + QLatin1Char('/') + "${QMAKE_TARGET}";
|
||||
|
||||
#if defined (Q_OS_WIN)
|
||||
m_executable += QLatin1String(".exe");
|
||||
#endif
|
||||
|
||||
m_targets = reader->values(QLatin1String("TARGET"));
|
||||
|
||||
m_srcDir = QFileInfo(m_proFilePath).path();
|
||||
const QStringList config = reader->values(QLatin1String("CONFIG"));
|
||||
m_runMode = ProjectExplorer::ApplicationRunConfiguration::Gui;
|
||||
|
||||
delete reader;
|
||||
}
|
||||
|
||||
QString Qt4RunConfiguration::resolveVariables(const QString &buildConfiguration, const QString& in) const
|
||||
{
|
||||
detectQtShadowBuild(buildConfiguration);
|
||||
|
||||
QString relSubDir = QFileInfo(project()->file()->fileName()).absoluteDir().relativeFilePath(m_srcDir);
|
||||
QString baseDir = QDir(project()->buildDirectory(buildConfiguration)).absoluteFilePath(relSubDir);
|
||||
|
||||
Core::VariableManager *vm = ExtensionSystem::PluginManager::instance()->getObject<Core::ICore>()->variableManager();
|
||||
if (!vm)
|
||||
return QString();
|
||||
QString dest;
|
||||
bool found = false;
|
||||
vm->insert("QMAKE_BUILDCONFIG", qmakeBuildConfigFromBuildConfiguration(buildConfiguration));
|
||||
vm->insert("BASEDIR", baseDir);
|
||||
|
||||
|
||||
/*
|
||||
TODO This is a hack to detect correct target (there might be different targets in
|
||||
different scopes)
|
||||
*/
|
||||
|
||||
// This code also works for workingDirectory,
|
||||
// since directories are executable.
|
||||
foreach (const QString &target, m_targets) {
|
||||
dest = in;
|
||||
vm->insert("QMAKE_TARGET", target);
|
||||
dest = QDir::cleanPath(vm->resolve(dest));
|
||||
vm->remove("QMAKE_TARGET");
|
||||
QFileInfo fi(dest);
|
||||
if (fi.exists() && (fi.isExecutable() || dest.endsWith(".js"))) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
vm->remove("BASEDIR");
|
||||
vm->remove("QMAKE_BUILDCONFIG");
|
||||
if (found)
|
||||
return dest;
|
||||
else
|
||||
return QString();
|
||||
}
|
||||
|
||||
/* This function tries to find out wheter qmake/make will put the binary in "/debug/" or in "/release/"
|
||||
That is this function is strictly only for windows.
|
||||
We look wheter make gets an explicit parameter "debug" or "release"
|
||||
That works because if we have either debug or release there then it is surely a
|
||||
debug_and_release buildconfiguration and thus we are put in a subdirectory.
|
||||
|
||||
Now if there is no explicit debug or release parameter, then we need to look at what qmake's CONFIG
|
||||
value is, if it is not debug_and_release, we don't care and return ""
|
||||
otherwise we look at wheter the default is debug or not
|
||||
|
||||
Note: When fixing this function consider those cases
|
||||
qmake CONFIG+=debug_and_release CONFIG+=debug
|
||||
make release
|
||||
=> we should return release
|
||||
|
||||
qmake CONFIG+=debug_and_release CONFIG+=debug
|
||||
make
|
||||
=> we should return debug
|
||||
|
||||
qmake CONFIG-=debug_and_release CONFIG+=debug
|
||||
make
|
||||
=> we should return "", since the executable is not put in a subdirectory
|
||||
|
||||
Not a function to be proud of
|
||||
*/
|
||||
QString Qt4RunConfiguration::qmakeBuildConfigFromBuildConfiguration(const QString &buildConfigurationName) const
|
||||
{
|
||||
MakeStep *ms = qobject_cast<Qt4Project *>(project())->makeStep();
|
||||
QStringList makeargs = ms->value(buildConfigurationName, "makeargs").toStringList();
|
||||
if (makeargs.contains("debug"))
|
||||
return "debug";
|
||||
else if(makeargs.contains("release"))
|
||||
return "release";
|
||||
|
||||
// Oh we don't have an explicit make argument
|
||||
QMakeStep *qs = qobject_cast<Qt4Project *>(project())->qmakeStep();
|
||||
QVariant qmakeBuildConfiguration = qs->value(buildConfigurationName, "buildConfiguration");
|
||||
if (qmakeBuildConfiguration.isValid()) {
|
||||
QtVersion::QmakeBuildConfig projectBuildConfiguration = QtVersion::QmakeBuildConfig(qmakeBuildConfiguration.toInt());
|
||||
if (projectBuildConfiguration & QtVersion::BuildAll) {
|
||||
if (projectBuildConfiguration & QtVersion::DebugBuild)
|
||||
return "debug";
|
||||
else
|
||||
return "release";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
// Old sytle always CONFIG+=debug_and_release
|
||||
if (qobject_cast<Qt4Project *>(project())->qtVersion(buildConfigurationName)->defaultBuildConfig() & QtVersion::DebugBuild)
|
||||
return "debug";
|
||||
else
|
||||
return "release";
|
||||
}
|
||||
|
||||
// enable us to infer the right string
|
||||
return "";
|
||||
}
|
||||
|
||||
/*!
|
||||
Handle special case were a subproject of the qt directory is opened, and
|
||||
qt was configured to be built as a shadow build -> also build in the sub-
|
||||
project in the correct shadow build directory.
|
||||
*/
|
||||
void Qt4RunConfiguration::detectQtShadowBuild(const QString &buildConfiguration) const
|
||||
{
|
||||
if (project()->activeBuildConfiguration() == buildConfiguration)
|
||||
return;
|
||||
|
||||
const QString currentQtDir = static_cast<Qt4Project *>(project())->qtDir(buildConfiguration);
|
||||
const QString qtSourceDir = static_cast<Qt4Project *>(project())->qtVersion(buildConfiguration)->sourcePath();
|
||||
|
||||
// if the project is a sub-project of Qt and Qt was shadow-built then automatically
|
||||
// adjust the build directory of the sub-project.
|
||||
if (project()->file()->fileName().startsWith(qtSourceDir) && qtSourceDir != currentQtDir) {
|
||||
project()->setValue(buildConfiguration, "useShadowBuild", true);
|
||||
QString buildDir = QFileInfo(project()->file()->fileName()).absolutePath();
|
||||
buildDir.replace(qtSourceDir, currentQtDir);
|
||||
project()->setValue(buildConfiguration, "buildDirectory", buildDir);
|
||||
project()->setValue(buildConfiguration, "autoShadowBuild", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Qt4RunConfigurationFactory
|
||||
/// This class is used to restore run settings (saved in .user files)
|
||||
///
|
||||
|
||||
Qt4RunConfigurationFactory::Qt4RunConfigurationFactory()
|
||||
{
|
||||
}
|
||||
|
||||
Qt4RunConfigurationFactory::~Qt4RunConfigurationFactory()
|
||||
{
|
||||
}
|
||||
|
||||
// used to recreate the runConfigurations when restoring settings
|
||||
bool Qt4RunConfigurationFactory::canCreate(const QString &type) const
|
||||
{
|
||||
return type == "Qt4ProjectManager.Qt4RunConfiguration";
|
||||
}
|
||||
|
||||
QSharedPointer<ProjectExplorer::RunConfiguration> Qt4RunConfigurationFactory::create(ProjectExplorer::Project *project, const QString &type)
|
||||
{
|
||||
Qt4Project *p = qobject_cast<Qt4Project *>(project);
|
||||
Q_ASSERT(p);
|
||||
Q_ASSERT(type == "Qt4ProjectManager.Qt4RunConfiguration");
|
||||
// The right path is set in restoreSettings
|
||||
QSharedPointer<ProjectExplorer::RunConfiguration> rc(new Qt4RunConfiguration(p, QString::null));
|
||||
return rc;
|
||||
}
|
||||
|
||||
QStringList Qt4RunConfigurationFactory::canCreate(ProjectExplorer::Project *pro) const
|
||||
{
|
||||
Qt4Project *qt4project = qobject_cast<Qt4Project *>(pro);
|
||||
if (qt4project)
|
||||
return QStringList();
|
||||
else
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QString Qt4RunConfigurationFactory::nameForType(const QString &type) const
|
||||
{
|
||||
Q_UNUSED(type);
|
||||
return "Run Qt4 application";
|
||||
}
|
||||
|
||||
///
|
||||
/// Qt4RunConfigurationFactoryUser
|
||||
/// This class is used to create new RunConfiguration from the runsettings page
|
||||
///
|
||||
|
||||
Qt4RunConfigurationFactoryUser::Qt4RunConfigurationFactoryUser()
|
||||
{
|
||||
}
|
||||
|
||||
Qt4RunConfigurationFactoryUser::~Qt4RunConfigurationFactoryUser()
|
||||
{
|
||||
}
|
||||
|
||||
bool Qt4RunConfigurationFactoryUser::canCreate(const QString &type) const
|
||||
{
|
||||
Q_UNUSED(type);
|
||||
return false;
|
||||
}
|
||||
|
||||
QSharedPointer<ProjectExplorer::RunConfiguration> Qt4RunConfigurationFactoryUser::create(ProjectExplorer::Project *project, const QString &type)
|
||||
{
|
||||
Qt4Project *p = qobject_cast<Qt4Project *>(project);
|
||||
Q_ASSERT(p);
|
||||
|
||||
QString fileName = type.mid(QString("Qt4RunConfiguration.").size());
|
||||
return QSharedPointer<ProjectExplorer::RunConfiguration>(new Qt4RunConfiguration(p, fileName));
|
||||
}
|
||||
|
||||
QStringList Qt4RunConfigurationFactoryUser::canCreate(ProjectExplorer::Project *pro) const
|
||||
{
|
||||
Qt4Project *qt4project = qobject_cast<Qt4Project *>(pro);
|
||||
if (qt4project) {
|
||||
QStringList applicationProFiles;
|
||||
QList<Qt4ProFileNode *> list = qt4project->applicationProFiles();
|
||||
foreach(Qt4ProFileNode * node, list) {
|
||||
applicationProFiles.append("Qt4RunConfiguration." + node->path());
|
||||
}
|
||||
return applicationProFiles;
|
||||
} else {
|
||||
return QStringList();
|
||||
}
|
||||
}
|
||||
|
||||
QString Qt4RunConfigurationFactoryUser::nameForType(const QString &type) const
|
||||
{
|
||||
QString fileName = type.mid(QString("Qt4RunConfiguration.").size());
|
||||
return QFileInfo(fileName).baseName();
|
||||
}
|
||||
Reference in New Issue
Block a user