Commit c4e49138 authored by Kai Koehne's avatar Kai Koehne

QmlProject: Add mainFile property

The mainFile property of QmlProject is the default file to run. People
have still the opportunity to override this in their run settings,
though.

The wizard generated code was updated accordingly. Note that this makes
projects generated by the wizard incompatible with QtCreator 2.1!

Task-number: QTCREATORBUG-3249
parent efcac96f
......@@ -6,6 +6,7 @@
<export module="QmlProject" version="1.1" type="Project"/>
</exports>
<property name="sourceDirectory" type="string"/>
<property name="mainFile" type="string"/>
<property name="importPaths" type="string" isList="true"/>
<property name="content" type="QmlProjectItem" isList="true"/>
</type>
......
......@@ -11,6 +11,7 @@ public:
QString sourceDirectory;
QStringList importPaths;
QStringList absoluteImportPaths;
QString mainFile;
QList<QmlFileFilterItem*> qmlFileFilters() const;
......@@ -148,6 +149,21 @@ bool QmlProjectItem::matchesFile(const QString &filePath) const
return false;
}
QString QmlProjectItem::mainFile() const
{
Q_D(const QmlProjectItem);
return d->mainFile;
}
void QmlProjectItem::setMainFile(const QString &mainFilePath)
{
Q_D(QmlProjectItem);
if (mainFilePath == d->mainFile)
return;
d->mainFile = mainFilePath;
emit mainFileChanged();
}
} // namespace QmlProjectManager
#include "qmlprojectitem.moc"
......@@ -25,6 +25,7 @@ class QmlProjectItem : public QObject {
Q_PROPERTY(QDeclarativeListProperty<QmlProjectManager::QmlProjectContentItem> content READ content DESIGNABLE false)
Q_PROPERTY(QString sourceDirectory READ sourceDirectory NOTIFY sourceDirectoryChanged)
Q_PROPERTY(QStringList importPaths READ importPaths WRITE setImportPaths NOTIFY importPathsChanged)
Q_PROPERTY(QString mainFile READ mainFile WRITE setMainFile NOTIFY mainFileChanged)
Q_CLASSINFO("DefaultProperty", "content");
......@@ -43,10 +44,15 @@ public:
QStringList files() const;
bool matchesFile(const QString &filePath) const;
QString mainFile() const;
void setMainFile(const QString &mainFilePath);
signals:
void qmlFilesChanged(const QSet<QString> &, const QSet<QString> &);
void sourceDirectoryChanged();
void importPathsChanged();
void mainFileChanged();
protected:
QmlProjectItemPrivate *d_ptr;
......
......@@ -158,6 +158,13 @@ QStringList QmlProject::files() const
return files;
}
QString QmlProject::mainFile() const
{
if (m_projectItem)
return m_projectItem.data()->mainFile();
return QString();
}
bool QmlProject::validProjectFile() const
{
return !m_projectItem.isNull();
......
......@@ -95,6 +95,7 @@ public:
QDir projectDir() const;
QStringList files() const;
QString mainFile() const;
QStringList importPaths() const;
bool addFiles(const QStringList &filePaths);
......
......@@ -31,6 +31,7 @@
#include "qmlprojectconstants.h"
#include <coreplugin/coreconstants.h>
#include <projectexplorer/customwizard/customwizard.h>
#include <qt4projectmanager/qt4projectmanagerconstants.h>
......@@ -39,6 +40,7 @@
#include <QtGui/QPainter>
#include <QtGui/QPixmap>
#include <QtCore/QDir>
#include <QtCore/QTextStream>
#include <QtCore/QCoreApplication>
......@@ -141,12 +143,16 @@ Core::GeneratedFiles QmlProjectApplicationWizard::generateFiles(const QWizard *w
out
//: Comment added to generated .qmlproject file
<< "/* " << tr("File generated by QtCreator", "qmlproject Template") << " */" << endl
<< "/* "
<< tr("File generated by QtCreator, version %1",
"qmlproject Template").arg(Core::Constants::IDE_VERSION_LONG) << " */" << endl
<< endl
<< "import QmlProject 1.0" << endl
<< "import QmlProject 1.1" << endl
<< endl
<< "Project {" << endl
//: Comment added to generated .qmlproject file
<< " mainFile: \"" << QDir(projectPath).relativeFilePath(mainFileName) << "\"" << endl
<< endl
<< " /* " << tr("Include .qml, .js, and image files from current directory and subdirectories", "qmlproject Template") << " */" << endl
<< " QmlFiles {" << endl
<< " directory: \".\"" << endl
......
......@@ -50,7 +50,7 @@ using namespace QmlProjectManager::Internal;
namespace QmlProjectManager {
const char * const M_CURRENT_FILE = "CurrentFile";
const char * const M_CURRENT_FILE = "CurrentFile";
QmlProjectRunConfiguration::QmlProjectRunConfiguration(QmlProjectTarget *parent) :
ProjectExplorer::RunConfiguration(parent, QLatin1String(Constants::QML_RC_ID)),
......@@ -67,12 +67,13 @@ QmlProjectRunConfiguration::QmlProjectRunConfiguration(QmlProjectTarget *parent,
QmlProjectRunConfiguration *source) :
ProjectExplorer::RunConfiguration(parent, source),
m_qtVersionId(source->m_qtVersionId),
m_scriptFile(source->m_scriptFile),
m_qmlViewerArgs(source->m_qmlViewerArgs),
m_projectTarget(parent),
m_usingCurrentFile(source->m_usingCurrentFile),
m_userEnvironmentChanges(source->m_userEnvironmentChanges)
{
ctor();
setMainScript(source->m_scriptFile);
updateQtVersions();
}
......@@ -191,29 +192,57 @@ ProjectExplorer::OutputFormatter *QmlProjectRunConfiguration::createOutputFormat
return new Qt4ProjectManager::QtOutputFormatter(qmlTarget()->qmlProject());
}
QmlProjectRunConfiguration::MainScriptSource QmlProjectRunConfiguration::mainScriptSource() const
{
if (m_usingCurrentFile) {
return FileInEditor;
}
if (!m_mainScriptFilename.isEmpty()) {
return FileInSettings;
}
return FileInProjectFile;
}
/**
Returns absolute path to main script file.
*/
QString QmlProjectRunConfiguration::mainScript() const
{
if (m_usingCurrentFile)
if (m_usingCurrentFile) {
return m_currentFileFilename;
}
if (!m_mainScriptFilename.isEmpty()) {
return m_mainScriptFilename;
}
return m_mainScriptFilename;
QString path = qmlTarget()->qmlProject()->mainFile();
if (QFileInfo(path).isAbsolute()) {
return path;
} else {
return qmlTarget()->qmlProject()->projectDir().absoluteFilePath(path);
}
}
void QmlProjectRunConfiguration::setMainScript(const QString &scriptFile)
void QmlProjectRunConfiguration::setScriptSource(MainScriptSource source,
const QString &settingsPath)
{
m_scriptFile = scriptFile;
// replace with locale-agnostic string
if (m_scriptFile == CURRENT_FILE)
m_scriptFile = M_CURRENT_FILE;
if (m_scriptFile.isEmpty() || m_scriptFile == M_CURRENT_FILE) {
if (source == FileInEditor) { m_scriptFile.clear();
m_mainScriptFilename.clear();
m_usingCurrentFile = true;
changeCurrentFile(Core::EditorManager::instance()->currentEditor());
} else {
} else if (source == FileInProjectFile) {
m_scriptFile.clear();
m_mainScriptFilename.clear();
m_usingCurrentFile = false;
} else { // FileInSettings
m_scriptFile = settingsPath;
m_mainScriptFilename
= qmlTarget()->qmlProject()->projectDir().absoluteFilePath(m_scriptFile);
m_usingCurrentFile = false;
m_mainScriptFilename = qmlTarget()->qmlProject()->projectDir().absoluteFilePath(scriptFile);
updateEnabled();
}
updateEnabled();
if (m_configurationWidget)
m_configurationWidget.data()->updateFileComboBox();
}
Utils::Environment QmlProjectRunConfiguration::environment() const
......@@ -245,7 +274,13 @@ bool QmlProjectRunConfiguration::fromMap(const QVariantMap &map)
updateQtVersions();
setMainScript(m_scriptFile);
if (m_scriptFile == M_CURRENT_FILE) {
setScriptSource(FileInEditor);
} else if (m_scriptFile.isEmpty()) {
setScriptSource(FileInProjectFile);
} else {
setScriptSource(FileInSettings, m_scriptFile);
}
return RunConfiguration::fromMap(map);
}
......@@ -284,7 +319,7 @@ void QmlProjectRunConfiguration::updateEnabled()
}
}
} else { // use default one
qmlFileFound = !m_mainScriptFilename.isEmpty();
qmlFileFound = !mainScript().isEmpty();
}
bool newValue = (QFileInfo(viewerPath()).exists()
......
......@@ -81,8 +81,15 @@ public:
int qtVersionId() const;
Qt4ProjectManager::QtVersion *qtVersion() const;
enum MainScriptSource {
FileInEditor,
FileInProjectFile,
FileInSettings
};
MainScriptSource mainScriptSource() const;
void setScriptSource(MainScriptSource source, const QString &settingsPath = QString());
QString mainScript() const;
void setMainScript(const QString &scriptFile);
Utils::Environment environment() const;
......
......@@ -44,7 +44,7 @@
#include <QLineEdit>
#include <QFormLayout>
#include <QPushButton>
#include <QStringListModel>
#include <QStandardItemModel>
using Core::ICore;
using Utils::DebuggerLanguageChooser;
......@@ -57,7 +57,7 @@ QmlProjectRunConfigurationWidget::QmlProjectRunConfigurationWidget(QmlProjectRun
m_runConfiguration(rc),
m_qtVersionComboBox(0),
m_fileListCombo(0),
m_fileListModel(new QStringListModel(this))
m_fileListModel(new QStandardItemModel(this))
{
QVBoxLayout *layout = new QVBoxLayout(this);
......@@ -76,7 +76,7 @@ QmlProjectRunConfigurationWidget::QmlProjectRunConfigurationWidget(QmlProjectRun
m_fileListCombo = new QComboBox;
m_fileListCombo->setModel(m_fileListModel);
connect(m_fileListCombo, SIGNAL(activated(QString)), this, SLOT(setMainScript(QString)));
connect(m_fileListCombo, SIGNAL(activated(int)), this, SLOT(setMainScript(int)));
connect(ProjectExplorer::ProjectExplorerPlugin::instance(), SIGNAL(fileListChanged()),
SLOT(updateFileComboBox()));
......@@ -174,35 +174,73 @@ void QmlProjectRunConfigurationWidget::updateFileComboBox()
{
QmlProject *project = m_runConfiguration->qmlTarget()->qmlProject();
QDir projectDir = project->projectDir();
QStringList files;
files.append(CURRENT_FILE);
int currentIndex = -1;
m_fileListModel->clear();
m_fileListModel->appendRow(new QStandardItem(CURRENT_FILE));
QModelIndex currentIndex;
QModelIndex fileInQmlProjectIndex;
const QString mainScriptInFilePath = projectDir.absoluteFilePath(project->mainFile());
QStringList sortedFiles = project->files();
if (!sortedFiles.contains(mainScriptInFilePath))
sortedFiles += mainScriptInFilePath;
// make paths relative to project directory
QStringList relativeFiles;
foreach (const QString &fn, sortedFiles) {
relativeFiles += projectDir.relativeFilePath(fn);
}
sortedFiles = relativeFiles;
qStableSort(sortedFiles.begin(), sortedFiles.end(), caseInsensitiveLessThan);
QString mainScriptPath;
if (m_runConfiguration->mainScriptSource() != QmlProjectRunConfiguration::FileInEditor)
mainScriptPath = projectDir.relativeFilePath(m_runConfiguration->mainScript());
foreach (const QString &fn, sortedFiles) {
QFileInfo fileInfo(fn);
if (fileInfo.suffix() != QLatin1String("qml"))
continue;
QString fileName = projectDir.relativeFilePath(fn);
if (fileName == m_runConfiguration->m_scriptFile)
currentIndex = files.size();
QStandardItem *item = new QStandardItem(fn);
m_fileListModel->appendRow(item);
files.append(fileName);
if (mainScriptPath == fn)
currentIndex = item->index();
if (mainScriptInFilePath == fn)
fileInQmlProjectIndex = item->index();
}
m_fileListModel->setStringList(files);
if (currentIndex != -1)
m_fileListCombo->setCurrentIndex(currentIndex);
else
if (currentIndex.isValid()) {
m_fileListCombo->setCurrentIndex(currentIndex.row());
} else {
m_fileListCombo->setCurrentIndex(0);
}
if (fileInQmlProjectIndex.isValid()) {
QFont font;
font.setBold(true);
m_fileListModel->setData(fileInQmlProjectIndex, font, Qt::FontRole);
}
}
void QmlProjectRunConfigurationWidget::setMainScript(const QString &file)
void QmlProjectRunConfigurationWidget::setMainScript(int index)
{
m_runConfiguration->setMainScript(file);
QmlProject *project = m_runConfiguration->qmlTarget()->qmlProject();
QDir projectDir = project->projectDir();
if (index == 0) {
m_runConfiguration->setScriptSource(QmlProjectRunConfiguration::FileInEditor);
} else {
const QString path = m_fileListModel->data(m_fileListModel->index(index, 0)).toString();
if (projectDir.relativeFilePath(project->mainFile()) == path) {
m_runConfiguration->setScriptSource(QmlProjectRunConfiguration::FileInProjectFile);
} else {
m_runConfiguration->setScriptSource(QmlProjectRunConfiguration::FileInSettings, path);
}
}
}
void QmlProjectRunConfigurationWidget::onQtVersionSelectionChanged()
......
......@@ -33,7 +33,7 @@
#include <QWidget>
QT_FORWARD_DECLARE_CLASS(QComboBox);
QT_FORWARD_DECLARE_CLASS(QStringListModel);
QT_FORWARD_DECLARE_CLASS(QStandardItemModel);
namespace ProjectExplorer {
......@@ -58,11 +58,11 @@ public:
public slots:
void updateQtVersionComboBox();
void userEnvironmentChangesChanged();
void updateFileComboBox();
private slots:
void updateFileComboBox();
void setMainScript(const QString &file);
void setMainScript(int index);
void onQtVersionSelectionChanged();
void onViewerArgsChanged();
void useCppDebuggerToggled(bool toggled);
......@@ -78,7 +78,7 @@ private:
QComboBox *m_qtVersionComboBox;
QComboBox *m_fileListCombo;
QStringListModel *m_fileListModel;
QStandardItemModel *m_fileListModel;
ProjectExplorer::EnvironmentWidget *m_environmentWidget;
};
......
......@@ -20,6 +20,7 @@ private slots:
void testFileFilter();
void testMatchesFile();
void testLibraryPaths();
void testMainFile();
};
tst_FileFormat::tst_FileFormat()
......@@ -334,6 +335,31 @@ void tst_FileFormat::testLibraryPaths()
}
}
void tst_FileFormat::testMainFile()
{
//
// search for qml files in local directory
//
QString projectFile = QLatin1String(
"import QmlProject 1.1\n"
"Project {\n"
" mainFile: \"file1.qml\"\n"
"}\n");
{
QDeclarativeEngine engine;
QDeclarativeComponent component(&engine);
component.setData(projectFile.toUtf8(), QUrl());
if (!component.isReady())
qDebug() << component.errorString();
QVERIFY(component.isReady());
QmlProjectItem *project = qobject_cast<QmlProjectItem*>(component.create());
QVERIFY(project);
QCOMPARE(project->mainFile(), QString("file1.qml"));
}
}
QTEST_MAIN(tst_FileFormat);
#include "tst_fileformat.moc"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment