diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp index 28731fbcc50db3857c9a019735c97ad682506db0..551900778994598ebf07bebc81ff144fd1c72c99 100644 --- a/src/plugins/genericprojectmanager/genericproject.cpp +++ b/src/plugins/genericprojectmanager/genericproject.cpp @@ -130,6 +130,9 @@ void GenericProject::parseProject() _files = convertToAbsoluteFiles(projectInfo.value(QLatin1String("files")).toStringList()); _generated = convertToAbsoluteFiles(projectInfo.value(QLatin1String("generated")).toStringList()); _defines = projectInfo.value(QLatin1String("defines")).toStringList(); + _projectIncludePaths = projectInfo.value(QLatin1String("includePaths")).toStringList(); + + qDebug() << "project include paths:" << _projectIncludePaths; } void GenericProject::refresh() @@ -158,7 +161,7 @@ void GenericProject::refresh() allIncludePaths.append(headerPath.path()); } - allIncludePaths += includePaths(); + allIncludePaths += this->allIncludePaths(); pinfo.frameworkPaths = allFrameworkPaths; pinfo.includePaths = allIncludePaths; @@ -184,6 +187,18 @@ QStringList GenericProject::convertToAbsoluteFiles(const QStringList &paths) con return absolutePaths; } +QStringList GenericProject::allIncludePaths() const +{ + QStringList paths; + paths += _includePaths; + paths += _projectIncludePaths; + paths.removeDuplicates(); + return paths; +} + +QStringList GenericProject::projectIncludePaths() const +{ return _projectIncludePaths; } + QStringList GenericProject::files() const { return _files; } @@ -398,7 +413,11 @@ void GenericProject::restoreSettingsImpl(ProjectExplorer::PersistentSettingsRead toolChainId = QLatin1String("gcc"); setToolChainId(toolChainId.toLower()); // ### move - setIncludePaths(reader.restoreValue(QLatin1String("includePaths")).toStringList()); + + const QStringList userIncludePaths = + reader.restoreValue(QLatin1String("includePaths")).toStringList(); + + setIncludePaths(allIncludePaths()); parseProject(); refresh(); @@ -440,7 +459,8 @@ GenericBuildSettingsWidget::GenericBuildSettingsWidget(GenericProject *project) // include paths QListView *includePathsView = new QListView; _includePathsModel = new ListModel(this); - _includePathsModel->setStringList(_project->includePaths()); + + _includePathsModel->setStringList(_project->allIncludePaths()); includePathsView->setModel(_includePathsModel); fl->addRow(tr("Include paths:"), includePathsView); diff --git a/src/plugins/genericprojectmanager/genericproject.h b/src/plugins/genericprojectmanager/genericproject.h index 2c63d1945f59a795a380a33f501f1b7c94e021ce..5ed588d7f09be819a1fbca7022cd1a09e3f1ac37 100644 --- a/src/plugins/genericprojectmanager/genericproject.h +++ b/src/plugins/genericprojectmanager/genericproject.h @@ -89,6 +89,8 @@ public: QStringList defines() const; void setDefines(const QStringList &defines); + QStringList allIncludePaths() const; + QStringList projectIncludePaths() const; QStringList files() const; QStringList generated() const; QString toolChainId() const; @@ -112,6 +114,7 @@ private: QStringList _files; QStringList _generated; QStringList _includePaths; + QStringList _projectIncludePaths; QStringList _defines; GenericProjectNode* _rootNode; diff --git a/src/plugins/genericprojectmanager/genericprojectnodes.cpp b/src/plugins/genericprojectmanager/genericprojectnodes.cpp index e37f1dd31f3cc7292f2806d3765a3fb59af65302..d96c0d441e461819beff5122724de26e02228c6c 100644 --- a/src/plugins/genericprojectmanager/genericprojectnodes.cpp +++ b/src/plugins/genericprojectmanager/genericprojectnodes.cpp @@ -115,16 +115,21 @@ ProjectExplorer::FolderNode *GenericProjectNode::findOrCreateFolderByName(const folderName += QLatin1Char('/'); // ### FIXME } - FolderNode *folder = _folderByName.value(folderName); - if (! folder) { - folder = new FolderNode(components.at(end - 1)); - _folderByName.insert(folderName, folder); - - FolderNode *parent = findOrCreateFolderByName(components, end - 1); - if (! parent) - parent = this; - addFolderNodes(QList<FolderNode*>() << folder, parent); - } + const QString component = components.at(end - 1); + + if (component.isEmpty()) + return this; + + else if (FolderNode *folder = _folderByName.value(folderName)) + return folder; + + FolderNode *folder = new FolderNode(component); + _folderByName.insert(folderName, folder); + + FolderNode *parent = findOrCreateFolderByName(components, end - 1); + if (! parent) + parent = this; + addFolderNodes(QList<FolderNode*>() << folder, parent); return folder; } diff --git a/src/plugins/genericprojectmanager/genericprojectwizard.cpp b/src/plugins/genericprojectmanager/genericprojectwizard.cpp index fd7007843a501bb7835d871d997593d2b3221317..d24ce1329bd489adff6195f4e87798e72effa27f 100644 --- a/src/plugins/genericprojectmanager/genericprojectwizard.cpp +++ b/src/plugins/genericprojectmanager/genericprojectwizard.cpp @@ -1,25 +1,202 @@ #include "genericprojectwizard.h" + +#include <coreplugin/icore.h> +#include <coreplugin/mimedatabase.h> #include <projectexplorer/projectexplorer.h> #include <utils/pathchooser.h> -#include <QtGui/QWizard> -#include <QtGui/QFormLayout> #include <QtCore/QDir> #include <QtCore/QtDebug> +#include <QtGui/QWizard> +#include <QtGui/QFormLayout> +#include <QtGui/QListView> +#include <QtGui/QTreeView> +#include <QtGui/QDirModel> + using namespace GenericProjectManager::Internal; using namespace Core::Utils; -GenericProjectWizard::GenericProjectWizard() - : Core::BaseFileWizard(parameters()) +namespace { + +class DirModel: public QDirModel +{ +public: + DirModel(QObject *parent) + : QDirModel(parent) + { setFilter(QDir::Dirs | QDir::NoDotAndDotDot); } + + virtual ~DirModel() + { } + +public: + virtual int columnCount(const QModelIndex &) const + { return 1; } + + virtual Qt::ItemFlags flags(const QModelIndex &index) const + { return QDirModel::flags(index) | Qt::ItemIsUserCheckable; } + + virtual QVariant data(const QModelIndex &index, int role) const + { + if (index.column() == 0 && role == Qt::CheckStateRole) { + if (_selectedPaths.contains(index)) + return Qt::Checked; + + return Qt::Unchecked; + } + + return QDirModel::data(index, role); + } + + virtual bool setData(const QModelIndex &index, const QVariant &value, int role) + { + if (index.column() == 0 && role == Qt::CheckStateRole) { + if (value.toBool()) + _selectedPaths.insert(index); + else + _selectedPaths.remove(index); + + return true; + } + + return QDirModel::setData(index, value, role); + } + + void clearSelectedPaths() + { _selectedPaths.clear(); } + + QSet<QString> selectedPaths() const + { + QSet<QString> paths; + + foreach (const QModelIndex &index, _selectedPaths) + paths.insert(filePath(index)); + + return paths; + } + +private: + QSet<QModelIndex> _selectedPaths; +}; + +} // end of anonymous namespace + + +////////////////////////////////////////////////////////////////////////////// +// GenericProjectWizardDialog +////////////////////////////////////////////////////////////////////////////// + + +GenericProjectWizardDialog::GenericProjectWizardDialog(QWidget *parent) + : QWizard(parent) { + setWindowTitle(tr("Import Existing Project")); + + // first page + QWizardPage *firstPage = new QWizardPage; + firstPage->setTitle(tr("Project")); + + QFormLayout *layout = new QFormLayout(firstPage); + _pathChooser = new PathChooser; + layout->addRow(tr("Source Directory:"), _pathChooser); + + _firstPageId = addPage(firstPage); + +#if 0 + // second page + QWizardPage *secondPage = new QWizardPage; + secondPage->setTitle(tr("Second Page Title")); + + QFormLayout *secondPageLayout = new QFormLayout(secondPage); + + _dirView = new QTreeView; + _dirModel = new DirModel(this); + _dirView->setModel(_dirModel); + + Core::ICore *core = Core::ICore::instance(); + Core::MimeDatabase *mimeDatabase = core->mimeDatabase(); + + const QStringList suffixes = mimeDatabase->suffixes(); + + QStringList nameFilters; + foreach (const QString &suffix, suffixes) { + QString nameFilter; + nameFilter.append(QLatin1String("*.")); + nameFilter.append(suffix); + nameFilters.append(nameFilter); + } + + _filesView = new QListView; + _filesModel = new QDirModel(this); + _filesModel->setNameFilters(nameFilters); + _filesModel->setFilter(QDir::Files); + + connect(_dirView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), + this, SLOT(updateFilesView(QModelIndex,QModelIndex))); + + secondPageLayout->addRow(_dirView); + secondPageLayout->addRow(_filesView); + + _secondPageId = addPage(secondPage); +#endif } -GenericProjectWizard::~GenericProjectWizard() +GenericProjectWizardDialog::~GenericProjectWizardDialog() +{ } + +QString GenericProjectWizardDialog::path() const +{ return _pathChooser->path(); } + +void GenericProjectWizardDialog::updateFilesView(const QModelIndex ¤t, + const QModelIndex &) { + if (! current.isValid()) + _filesView->setModel(0); + + else { + const QString selectedPath = _dirModel->filePath(current); + + if (! _filesView->model()) + _filesView->setModel(_filesModel); + + _filesView->setRootIndex(_filesModel->index(selectedPath)); + } +} + +void GenericProjectWizardDialog::initializePage(int id) +{ + if (id == _secondPageId) { + using namespace Core::Utils; + + const QString projectPath = _pathChooser->path(); + + QDirModel *dirModel = qobject_cast<QDirModel *>(_dirView->model()); + _dirView->setRootIndex(dirModel->index(projectPath)); + } +} + +bool GenericProjectWizardDialog::validateCurrentPage() +{ + using namespace Core::Utils; + + if (currentId() == _firstPageId) { + return ! _pathChooser->path().isEmpty(); + + } else if (currentId() == _secondPageId) { + return true; + } + + return QWizard::validateCurrentPage(); } +GenericProjectWizard::GenericProjectWizard() + : Core::BaseFileWizard(parameters()) +{ } + +GenericProjectWizard::~GenericProjectWizard() +{ } + Core::BaseFileWizardParameters GenericProjectWizard::parameters() { static Core::BaseFileWizardParameters parameters(ProjectWizard); @@ -35,42 +212,94 @@ QWizard *GenericProjectWizard::createWizardDialog(QWidget *parent, const QString &defaultPath, const WizardPageList &extensionPages) const { - QWizard *wizard = new QWizard(parent); - wizard->setWindowTitle(tr("Import Existing Project")); + GenericProjectWizardDialog *wizard = new GenericProjectWizardDialog(parent); setupWizard(wizard); - QWizardPage *firstPage = new QWizardPage; - firstPage->setTitle(tr("Project")); + foreach (QWizardPage *p, extensionPages) + wizard->addPage(p); - QFormLayout *layout = new QFormLayout(firstPage); + return wizard; +} - PathChooser *pathChooser = new PathChooser; - pathChooser->setObjectName("pathChooser"); - layout->addRow(tr("Source Directory:"), pathChooser); +void GenericProjectWizard::getFileList(const QDir &dir, const QString &projectRoot, + const QStringList &suffixes, + QStringList *files, QStringList *paths) const +{ + const QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | + QDir::Dirs | + QDir::NoDotAndDotDot | + QDir::NoSymLinks); - wizard->addPage(firstPage); + foreach (const QFileInfo &fileInfo, fileInfoList) { + QString filePath = fileInfo.absoluteFilePath(); + filePath = filePath.mid(projectRoot.length() + 1); - foreach (QWizardPage *p, extensionPages) - wizard->addPage(p); + if (fileInfo.isDir() && isValidDir(fileInfo)) { + getFileList(QDir(fileInfo.absoluteFilePath()), projectRoot, + suffixes, files, paths); - return wizard; + if (! paths->contains(filePath)) + paths->append(filePath); + } + + else if (suffixes.contains(fileInfo.suffix())) + files->append(filePath); + } +} + +bool GenericProjectWizard::isValidDir(const QFileInfo &fileInfo) const +{ + const QString fileName = fileInfo.fileName(); + const QString suffix = fileInfo.suffix(); + + if (fileName.startsWith(QLatin1Char('.'))) + return false; + + else if (fileName == QLatin1String("CVS")) + return false; + + // ### user include/exclude + + return true; } Core::GeneratedFiles GenericProjectWizard::generateFiles(const QWizard *w, QString *errorMessage) const { - PathChooser *pathChooser = w->findChild<PathChooser *>("pathChooser"); - const QString projectName = QFileInfo(pathChooser->path()).baseName() + QLatin1String(".creator"); - const QDir dir(pathChooser->path()); + const GenericProjectWizardDialog *wizard = qobject_cast<const GenericProjectWizardDialog *>(w); + const QString projectPath = wizard->path(); + const QString projectName = QFileInfo(projectPath).baseName() + QLatin1String(".creator"); + const QDir dir(projectPath); + + Core::ICore *core = Core::ICore::instance(); + Core::MimeDatabase *mimeDatabase = core->mimeDatabase(); + + const QStringList suffixes = mimeDatabase->suffixes(); - // ### FIXME: use the mimetype database. - // ### FIXME: import nested folders. - const QStringList sources = dir.entryList(QStringList() << "Makefile" << "*.c" << "*.cpp" << "*.h", QDir::Files); + QStringList sources, paths; + getFileList(dir, projectPath, suffixes, &sources, &paths); + + Core::MimeType headerTy = mimeDatabase->findByType(QLatin1String("text/x-chdr")); + + QStringList nameFilters; + foreach (const QRegExp &rx, headerTy.globPatterns()) + nameFilters.append(rx.pattern()); + + QStringList includePaths; + foreach (const QString &path, paths) { + QFileInfo fileInfo(dir, path); + QDir thisDir(fileInfo.absoluteFilePath()); + + if (! thisDir.entryList(nameFilters, QDir::Files).isEmpty()) + includePaths.append(path); + } QString projectContents; QTextStream stream(&projectContents); stream << "files=" << sources.join(","); stream << endl; + stream << "includePaths=" << includePaths.join(","); + stream << endl; Core::GeneratedFile file(QFileInfo(dir, projectName).absoluteFilePath()); // ### fixme file.setContents(projectContents); diff --git a/src/plugins/genericprojectmanager/genericprojectwizard.h b/src/plugins/genericprojectmanager/genericprojectwizard.h index e5bde8f086eff58be0dd111bc9d4f14aa2482b2f..6c3f87e16a6dd427ece44015689729739e325f32 100644 --- a/src/plugins/genericprojectmanager/genericprojectwizard.h +++ b/src/plugins/genericprojectmanager/genericprojectwizard.h @@ -2,10 +2,53 @@ #define GENERICPROJECTWIZARD_H #include <coreplugin/basefilewizard.h> +#include <utils/pathchooser.h> +#include <QWizard> + +QT_BEGIN_NAMESPACE +class QListView; +class QTreeView; +class QDirModel; +class QModelIndex; +class QDir; +class QStringList; +class QFileInfo; +QT_END_NAMESPACE namespace GenericProjectManager { namespace Internal { +class GenericProjectWizardDialog: public QWizard +{ + Q_OBJECT + +public: + GenericProjectWizardDialog(QWidget *parent = 0); + virtual ~GenericProjectWizardDialog(); + + QString path() const; + +private Q_SLOTS: + void updateFilesView(const QModelIndex ¤t, + const QModelIndex &previous); + +protected: + virtual void initializePage(int id); + virtual bool validateCurrentPage(); + +private: + int _firstPageId; + int _secondPageId; + + Core::Utils::PathChooser *_pathChooser; + + QTreeView *_dirView; + QDirModel *_dirModel; + + QListView *_filesView; + QDirModel *_filesModel; +}; + class GenericProjectWizard : public Core::BaseFileWizard { Q_OBJECT @@ -25,6 +68,13 @@ protected: QString *errorMessage) const; virtual bool postGenerateFiles(const Core::GeneratedFiles &l, QString *errorMessage); + + bool isValidDir(const QFileInfo &fileInfo) const; + + void getFileList(const QDir &dir, const QString &projectRoot, + const QStringList &suffixes, + QStringList *files, + QStringList *paths) const; }; } // end of namespace Internal