Commit c8513df2 authored by Pawel Faron's avatar Pawel Faron Committed by Daniel Teske
Browse files

Implemented "Add Existing Directory..." feature.



This feature lets add files from selected directory and its
subdirectories to project. Files to add are selected based on filter
supplied by a user.

Task-number: QTCREATORBUG-9081
Change-Id: I978e87c24c5aeffc4eb74160cd6f4f20096de017
Reviewed-by: default avatarDaniel Teske <daniel.teske@digia.com>
parent 0ddb6cac
......@@ -31,10 +31,10 @@
#include "genericprojectwizard.h"
#include "genericprojectconstants.h"
#include "selectablefilesmodel.h"
#include <coreplugin/mimedatabase.h>
#include <coreplugin/icore.h>
#include <projectexplorer/selectablefilesmodel.h>
#include <QVBoxLayout>
#include <QLineEdit>
......@@ -117,12 +117,12 @@ void FilesSelectionWizardPage::initializePage()
{
m_view->setModel(0);
delete m_model;
m_model = new SelectableFilesModel(m_genericProjectWizardDialog->path(), this);
m_model = new ProjectExplorer::SelectableFilesModel(this);
connect(m_model, SIGNAL(parsingProgress(QString)),
this, SLOT(parsingProgress(QString)));
connect(m_model, SIGNAL(parsingFinished()),
this, SLOT(parsingFinished()));
m_model->startParsing();
m_model->startParsing(m_genericProjectWizardDialog->path());
m_hideFilesFilterLabel->setVisible(false);
m_hideFilesfilterLineEdit->setVisible(false);
......@@ -139,7 +139,6 @@ void FilesSelectionWizardPage::initializePage()
void FilesSelectionWizardPage::cleanupPage()
{
m_model->cancel();
m_model->waitForFinished();
}
void FilesSelectionWizardPage::parsingProgress(const QString &text)
......
......@@ -39,11 +39,14 @@ class QTreeView;
class QLineEdit;
QT_END_NAMESPACE
namespace ProjectExplorer {
class SelectableFilesModel;
}
namespace GenericProjectManager {
namespace Internal {
class GenericProjectWizardDialog;
class SelectableFilesModel;
class FilesSelectionWizardPage : public QWizardPage
{
......@@ -68,7 +71,7 @@ private:
void createApplyButton(QVBoxLayout *layout);
GenericProjectWizardDialog *m_genericProjectWizardDialog;
SelectableFilesModel *m_model;
ProjectExplorer::SelectableFilesModel *m_model;
QLabel *m_hideFilesFilterLabel;
QLineEdit *m_hideFilesfilterLineEdit;
......
......@@ -10,7 +10,6 @@ HEADERS = genericproject.h \
pkgconfigtool.h \
genericmakestep.h \
genericbuildconfiguration.h \
selectablefilesmodel.h \
filesselectionwizardpage.h
SOURCES = genericproject.cpp \
genericprojectplugin.cpp \
......@@ -21,7 +20,6 @@ SOURCES = genericproject.cpp \
pkgconfigtool.cpp \
genericmakestep.cpp \
genericbuildconfiguration.cpp \
selectablefilesmodel.cpp \
filesselectionwizardpage.cpp
RESOURCES += genericproject.qrc
FORMS += genericmakestep.ui
......@@ -39,7 +39,5 @@ QtcPlugin {
"genericprojectwizard.h",
"pkgconfigtool.cpp",
"pkgconfigtool.h",
"selectablefilesmodel.cpp",
"selectablefilesmodel.h",
]
}
......@@ -237,6 +237,7 @@ QList<ProjectNode::ProjectAction> GenericProjectNode::supportedActions(Node *nod
return QList<ProjectAction>()
<< AddNewFile
<< AddExistingFile
<< AddExistingDirectory
<< RemoveFile
<< Rename;
}
......
......@@ -36,7 +36,6 @@
#include "genericprojectfileseditor.h"
#include "genericmakestep.h"
#include "genericproject.h"
#include "selectablefilesmodel.h"
#include <coreplugin/icore.h>
#include <coreplugin/mimedatabase.h>
......@@ -45,7 +44,7 @@
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/selectablefilesmodel.h>
#include <texteditor/texteditoractionhandler.h>
......@@ -115,7 +114,7 @@ void GenericProjectPlugin::updateContextMenu(ProjectExplorer::Project *project,
void GenericProjectPlugin::editFiles()
{
GenericProject *genericProject = static_cast<GenericProject *>(m_contextMenuProject);
SelectableFilesDialog sfd(QFileInfo(genericProject->projectFilePath()).path(), genericProject->files(),
ProjectExplorer::SelectableFilesDialogEditFiles sfd(QFileInfo(genericProject->projectFilePath()).path(), genericProject->files(),
Core::ICore::mainWindow());
if (sfd.exec() == QDialog::Accepted)
genericProject->setFiles(sfd.selectedFiles());
......
......@@ -76,6 +76,7 @@
#include "miniprojecttargetselector.h"
#include "taskhub.h"
#include "customtoolchain.h"
#include <selectablefilesmodel.h>
#include <projectexplorer/customwizard/customwizard.h>
#include "devicesupport/desktopdevice.h"
#include "devicesupport/desktopdevicefactory.h"
......@@ -198,6 +199,7 @@ struct ProjectExplorerPluginPrivate {
QAction *m_cancelBuildAction;
QAction *m_addNewFileAction;
QAction *m_addExistingFilesAction;
QAction *m_addExistingDirectoryAction;
QAction *m_addNewSubprojectAction;
QAction *m_removeFileAction;
QAction *m_removeProjectAction;
......@@ -795,6 +797,15 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
// add existing directory action
d->m_addExistingDirectoryAction = new QAction(tr("Add Existing Directory..."), this);
cmd = Core::ActionManager::registerAction(d->m_addExistingDirectoryAction,
ProjectExplorer::Constants::ADDEXISTINGDIRECTORY,
projecTreeContext);
mprojectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
msubProjectContextMenu->addAction(cmd, Constants::G_PROJECT_FILES);
mfolderContextMenu->addAction(cmd, Constants::G_FOLDER_FILES);
// new subproject action
d->m_addNewSubprojectAction = new QAction(tr("New Subproject..."), this);
cmd = ActionManager::registerAction(d->m_addNewSubprojectAction, ProjectExplorer::Constants::ADDNEWSUBPROJECT,
......@@ -962,6 +973,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
connect(d->m_closeAllProjects, SIGNAL(triggered()), this, SLOT(closeAllProjects()));
connect(d->m_addNewFileAction, SIGNAL(triggered()), this, SLOT(addNewFile()));
connect(d->m_addExistingFilesAction, SIGNAL(triggered()), this, SLOT(addExistingFiles()));
connect(d->m_addExistingDirectoryAction, SIGNAL(triggered()), this, SLOT(addExistingDirectory()));
connect(d->m_addNewSubprojectAction, SIGNAL(triggered()), this, SLOT(addNewSubproject()));
connect(d->m_removeProjectAction, SIGNAL(triggered()), this, SLOT(removeProject()));
connect(d->m_openFileAction, SIGNAL(triggered()), this, SLOT(openFile()));
......@@ -2619,6 +2631,7 @@ void ProjectExplorerPlugin::invalidateProject(Project *project)
void ProjectExplorerPlugin::updateContextMenuActions()
{
d->m_addExistingFilesAction->setEnabled(false);
d->m_addExistingDirectoryAction->setEnabled(false);
d->m_addNewFileAction->setEnabled(false);
d->m_addNewSubprojectAction->setEnabled(false);
d->m_removeFileAction->setEnabled(false);
......@@ -2626,6 +2639,7 @@ void ProjectExplorerPlugin::updateContextMenuActions()
d->m_renameFileAction->setEnabled(false);
d->m_addExistingFilesAction->setVisible(true);
d->m_addExistingDirectoryAction->setVisible(true);
d->m_removeFileAction->setVisible(true);
d->m_deleteFileAction->setVisible(true);
d->m_runActionContextMenu->setVisible(false);
......@@ -2663,6 +2677,7 @@ void ProjectExplorerPlugin::updateContextMenuActions()
d->m_addNewSubprojectAction->setEnabled(d->m_currentNode->nodeType() == ProjectNodeType
&& actions.contains(ProjectNode::AddSubProject));
d->m_addExistingFilesAction->setEnabled(actions.contains(ProjectNode::AddExistingFile));
d->m_addExistingDirectoryAction->setEnabled(actions.contains(ProjectNode::AddExistingDirectory));
d->m_renameFileAction->setEnabled(actions.contains(ProjectNode::Rename));
} else if (qobject_cast<FileNode*>(d->m_currentNode)) {
// Enable and show remove / delete in magic ways:
......@@ -2772,6 +2787,17 @@ void ProjectExplorerPlugin::addExistingFiles()
addExistingFiles(fileNames);
}
void ProjectExplorerPlugin::addExistingDirectory()
{
QTC_ASSERT(d->m_currentNode, return);
const QString path = QFileInfo(d->m_currentNode->path()).absolutePath();
SelectableFilesDialogAddDirectory dialog(path, QStringList(), Core::ICore::mainWindow());
if (dialog.exec() == QDialog::Accepted)
addExistingFiles(dialog.selectedFiles());
}
void ProjectExplorerPlugin::addExistingFiles(const QStringList &filePaths)
{
ProjectNode *projectNode = qobject_cast<ProjectNode*>(d->m_currentNode->projectNode());
......
......@@ -186,6 +186,7 @@ private slots:
void addNewFile();
void addExistingFiles();
void addExistingDirectory();
void addNewSubproject();
void removeProject();
void openFile();
......
......@@ -141,7 +141,8 @@ HEADERS += projectexplorer.h \
projectmacroexpander.h \
customparser.h \
customparserconfigdialog.h \
ipotentialkit.h
ipotentialkit.h \
selectablefilesmodel.h
SOURCES += projectexplorer.cpp \
abi.cpp \
......@@ -269,7 +270,8 @@ SOURCES += projectexplorer.cpp \
projectmacroexpander.cpp \
customparser.cpp \
customparserconfigdialog.cpp \
ipotentialkit.cpp
ipotentialkit.cpp \
selectablefilesmodel.cpp
FORMS += processstep.ui \
editorsettingspropertiespage.ui \
......
......@@ -121,6 +121,7 @@ QtcPlugin {
"runconfiguration.cpp", "runconfiguration.h",
"runconfigurationmodel.cpp", "runconfigurationmodel.h",
"runsettingspropertiespage.cpp", "runsettingspropertiespage.h",
"selectablefilesmodel.cpp", "selectablefilesmodel.h"
"session.cpp", "session.h",
"sessiondialog.cpp", "sessiondialog.h", "sessiondialog.ui",
"settingsaccessor.cpp", "settingsaccessor.h",
......@@ -141,7 +142,7 @@ QtcPlugin {
"toolchainmanager.cpp", "toolchainmanager.h",
"toolchainoptionspage.cpp", "toolchainoptionspage.h",
"unconfiguredprojectpanel.cpp", "unconfiguredprojectpanel.h",
"vcsannotatetaskhandler.cpp", "vcsannotatetaskhandler.h",
"vcsannotatetaskhandler.cpp", "vcsannotatetaskhandler.h"
]
}
......
......@@ -69,6 +69,7 @@ const char RUNCONTEXTMENU[] = "ProjectExplorer.RunContextMenu";
const char STOP[] = "ProjectExplorer.Stop";
const char ADDNEWFILE[] = "ProjectExplorer.AddNewFile";
const char ADDEXISTINGFILES[] = "ProjectExplorer.AddExistingFiles";
const char ADDEXISTINGDIRECTORY[] = "ProjectExplorer.AddExistingDirectory";
const char ADDNEWSUBPROJECT[] = "ProjectExplorer.AddNewSubproject";
const char REMOVEPROJECT[] = "ProjectExplorer.RemoveProject";
const char OPENFILE[] = "ProjectExplorer.OpenFile";
......@@ -246,6 +247,12 @@ const char VAR_CURRENTKIT_ID[] = "CurrentKit:Id";
const char VAR_CURRENTBUILD_NAME[] = "CurrentBuild:Name";
const char VAR_CURRENTBUILD_TYPE[] = "CurrentBuild:Type";
const char HIDE_FILE_FILTER_SETTING[] = "GenericProject/FileFilter";
const char HIDE_FILE_FILTER_DEFAULT[] = "Makefile*; *.o; *.obj; *~; *.files; *.config; *.creator; *.user; *.includes; *.autosave";
const char SHOW_FILE_FILTER_SETTING[] = "GenericProject/ShowFileFilter";
const char SHOW_FILE_FILTER_DEFAULT[] = "*.c; *.cc; *.cpp; *.cp; *.cxx; *.c++; *.h; *.hh; *.hpp; *.hxx;";
// Unconfigured Panel
const char UNCONFIGURED_PANEL_PAGE_ID[] = "UnconfiguredPanel";
......
......@@ -184,6 +184,9 @@ public:
// the file is added
AddNewFile,
AddExistingFile,
// Add files, which match user defined filters,
// from an existing directory and its subdirectories
AddExistingDirectory,
// Removes a file from the project, optionally also
// delete it on disc
RemoveFile,
......
......@@ -28,7 +28,7 @@
****************************************************************************/
#include "selectablefilesmodel.h"
#include "genericprojectconstants.h"
#include <projectexplorerconstants.h>
#include <coreplugin/fileiconprovider.h>
#include <coreplugin/icore.h>
......@@ -41,19 +41,14 @@
#include <QPushButton>
#include <QTreeView>
#include <QDir>
#include <utils/pathchooser.h>
namespace GenericProjectManager {
namespace Internal {
namespace ProjectExplorer {
SelectableFilesModel::SelectableFilesModel(const QString &baseDir, QObject *parent)
: QAbstractItemModel(parent), m_root(0), m_baseDir(baseDir), m_allFiles(true)
SelectableFilesModel::SelectableFilesModel(QObject *parent)
: QAbstractItemModel(parent), m_root(0), m_allFiles(true)
{
// Dummy tree
m_root = new Tree;
m_root->name = QLatin1String("/");
m_root->parent = 0;
m_root->fullPath = m_baseDir;
m_root->isDir = true;
connect(&m_watcher, SIGNAL(finished()), this, SLOT(buildTreeFinished()));
}
void SelectableFilesModel::setInitialMarkedFiles(const QStringList &files)
......@@ -68,20 +63,19 @@ void SelectableFilesModel::setInitialMarkedFiles(const QStringList &files)
m_allFiles = false;
}
void SelectableFilesModel::init()
void SelectableFilesModel::startParsing(const QString &baseDir)
{
}
m_watcher.cancel();
m_watcher.waitForFinished();
void SelectableFilesModel::startParsing()
{
m_baseDir = baseDir;
// Build a tree in a future
m_rootForFuture = new Tree;
m_rootForFuture->name = QLatin1String("/");
m_rootForFuture->parent = 0;
m_rootForFuture->fullPath = m_baseDir;
m_rootForFuture->fullPath = baseDir;
m_rootForFuture->isDir = true;
connect(&m_watcher, SIGNAL(finished()), this, SLOT(buildTreeFinished()));
m_watcher.setFuture(QtConcurrent::run(&SelectableFilesModel::run, this));
}
......@@ -101,14 +95,10 @@ void SelectableFilesModel::buildTreeFinished()
emit parsingFinished();
}
void SelectableFilesModel::waitForFinished()
{
m_watcher.waitForFinished();
}
void SelectableFilesModel::cancel()
{
m_watcher.cancel();
m_watcher.waitForFinished();
}
bool SelectableFilesModel::filter(Tree *t)
......@@ -193,11 +183,15 @@ void SelectableFilesModel::buildTree(const QString &baseDir, Tree *tree, QFuture
SelectableFilesModel::~SelectableFilesModel()
{
m_watcher.cancel();
m_watcher.waitForFinished();
deleteTree(m_root);
}
void SelectableFilesModel::deleteTree(Tree *tree)
{
if (!tree)
return;
foreach (Tree *t, tree->childDirectories)
deleteTree(t);
foreach (Tree *t, tree->files)
......@@ -234,6 +228,8 @@ QModelIndex SelectableFilesModel::parent(const QModelIndex &child) const
{
if (!child.isValid())
return QModelIndex();
if (!child.internalPointer())
return QModelIndex();
Tree *parent = static_cast<Tree *>(child.internalPointer())->parent;
if (!parent)
return QModelIndex();
......@@ -398,6 +394,22 @@ void SelectableFilesModel::applyFilter(const QString &showFilesfilter, const QSt
applyFilter(createIndex(0, 0, m_root));
}
void SelectableFilesModel::selectAllFiles()
{
selectAllFiles(m_root);
}
void SelectableFilesModel::selectAllFiles(Tree *root)
{
root->checked = Qt::Checked;
foreach (Tree *t, root->childDirectories)
selectAllFiles(t);
foreach (Tree *t, root->visibleFiles)
t->checked = Qt::Checked;
}
Qt::CheckState SelectableFilesModel::applyFilter(const QModelIndex &index)
{
bool allChecked = true;
......@@ -511,10 +523,10 @@ Qt::CheckState SelectableFilesModel::applyFilter(const QModelIndex &index)
}
//////////
// SelectableFilesDialog
// SelectableFilesDialogs
//////////
SelectableFilesDialog::SelectableFilesDialog(const QString &path, const QStringList files, QWidget *parent)
SelectableFilesDialogEditFiles::SelectableFilesDialogEditFiles(const QString &path, const QStringList files, QWidget *parent)
: QDialog(parent)
{
QVBoxLayout *layout = new QVBoxLayout();
......@@ -527,7 +539,7 @@ SelectableFilesDialog::SelectableFilesDialog(const QString &path, const QStringL
createHideFileFilterControls(layout);
createApplyButton(layout);
m_selectableFilesModel = new SelectableFilesModel(path, this);
m_selectableFilesModel = new SelectableFilesModel(this);
m_selectableFilesModel->setInitialMarkedFiles(files);
m_view->setModel(m_selectableFilesModel);
m_view->setMinimumSize(500, 400);
......@@ -556,10 +568,10 @@ SelectableFilesDialog::SelectableFilesDialog(const QString &path, const QStringL
connect(m_selectableFilesModel, SIGNAL(parsingFinished()),
this, SLOT(parsingFinished()));
m_selectableFilesModel->startParsing();
m_selectableFilesModel->startParsing(path);
}
void SelectableFilesDialog::createHideFileFilterControls(QVBoxLayout *layout)
void SelectableFilesDialogEditFiles::createHideFileFilterControls(QVBoxLayout *layout)
{
QHBoxLayout *hbox = new QHBoxLayout;
m_hideFilesFilterLabel = new QLabel;
......@@ -576,7 +588,7 @@ void SelectableFilesDialog::createHideFileFilterControls(QVBoxLayout *layout)
layout->addLayout(hbox);
}
void SelectableFilesDialog::createShowFileFilterControls(QVBoxLayout *layout)
void SelectableFilesDialogEditFiles::createShowFileFilterControls(QVBoxLayout *layout)
{
QHBoxLayout *hbox = new QHBoxLayout;
m_showFilesFilterLabel = new QLabel;
......@@ -593,7 +605,7 @@ void SelectableFilesDialog::createShowFileFilterControls(QVBoxLayout *layout)
layout->addLayout(hbox);
}
void SelectableFilesDialog::createApplyButton(QVBoxLayout *layout)
void SelectableFilesDialogEditFiles::createApplyButton(QVBoxLayout *layout)
{
QHBoxLayout *hbox = new QHBoxLayout;
......@@ -608,18 +620,17 @@ void SelectableFilesDialog::createApplyButton(QVBoxLayout *layout)
connect(m_applyFilterButton, SIGNAL(clicked()), this, SLOT(applyFilter()));
}
SelectableFilesDialog::~SelectableFilesDialog()
SelectableFilesDialogEditFiles::~SelectableFilesDialogEditFiles()
{
m_selectableFilesModel->cancel();
m_selectableFilesModel->waitForFinished();
}
void SelectableFilesDialog::parsingProgress(const QString &fileName)
void SelectableFilesDialogEditFiles::parsingProgress(const QString &fileName)
{
m_progressLabel->setText(tr("Generating file list...\n\n%1").arg(fileName));
}
void SelectableFilesDialog::parsingFinished()
void SelectableFilesDialogEditFiles::parsingFinished()
{
m_hideFilesFilterLabel->show();
m_hideFilesfilterLineEdit->show();
......@@ -642,7 +653,7 @@ void SelectableFilesDialog::parsingFinished()
}
}
void SelectableFilesDialog::smartExpand(const QModelIndex &index)
void SelectableFilesDialogEditFiles::smartExpand(const QModelIndex &index)
{
if (m_view->model()->data(index, Qt::CheckStateRole) == Qt::PartiallyChecked) {
m_view->expand(index);
......@@ -652,12 +663,12 @@ void SelectableFilesDialog::smartExpand(const QModelIndex &index)
}
}
QStringList SelectableFilesDialog::selectedFiles() const
QStringList SelectableFilesDialogEditFiles::selectedFiles() const
{
return m_selectableFilesModel->selectedFiles();
}
void SelectableFilesDialog::applyFilter()
void SelectableFilesDialogEditFiles::applyFilter()
{
const QString showFilesFilter = m_showFilesfilterLineEdit->text();
Core::ICore::settings()->setValue(QLatin1String(Constants::SHOW_FILE_FILTER_SETTING), showFilesFilter);
......@@ -668,7 +679,70 @@ void SelectableFilesDialog::applyFilter()
m_selectableFilesModel->applyFilter(showFilesFilter, hideFilesFilter);
}
} // namespace Internal
} // namespace GenericProjectManager
SelectableFilesDialogAddDirectory::SelectableFilesDialogAddDirectory(const QString &path,
const QStringList files, QWidget *parent) :
SelectableFilesDialogEditFiles(path, files, parent)
{
setWindowTitle(tr("Add Existing Directory"));
connect(m_selectableFilesModel, SIGNAL(parsingFinished()), this, SLOT(parsingFinished()));
createPathChooser(static_cast<QVBoxLayout*>(layout()), path);
}
void SelectableFilesDialogAddDirectory::createPathChooser(QVBoxLayout *layout, const QString &path)
{
QHBoxLayout *hbox = new QHBoxLayout;
m_pathChooser = new Utils::PathChooser;
m_pathChooser->setPath(path);
m_sourceDirectoryLabel = new QLabel(tr("Source directory:"));
hbox->addWidget(m_sourceDirectoryLabel);
hbox->addWidget(m_pathChooser);
layout->insertLayout(0, hbox);
m_startParsingButton = new QPushButton(tr("Start Parsing"));
hbox->addWidget(m_startParsingButton);
connect(m_pathChooser, SIGNAL(validChanged(bool)), this, SLOT(validityOfDirectoryChanged(bool)));
connect(m_startParsingButton, SIGNAL(clicked()), this, SLOT(startParsing()));
}
void SelectableFilesDialogAddDirectory::validityOfDirectoryChanged(bool validState)
{
m_startParsingButton->setEnabled(validState);
}
void SelectableFilesDialogAddDirectory::parsingFinished()
{
m_selectableFilesModel->selectAllFiles();
m_selectableFilesModel->applyFilter(m_showFilesfilterLineEdit->text(),
m_hideFilesfilterLineEdit->text());
setWidgetsEnabled(true);
}
void SelectableFilesDialogAddDirectory::startParsing()
{
setWidgetsEnabled(false);
m_selectableFilesModel->startParsing(m_pathChooser->path());
}
void SelectableFilesDialogAddDirectory::setWidgetsEnabled(bool enabled)
{
m_hideFilesfilterLineEdit->setEnabled(enabled);
m_showFilesfilterLineEdit->setEnabled(enabled);
m_applyFilterButton->setEnabled(enabled);
m_view->setEnabled(enabled);
m_pathChooser->setEnabled(enabled);
m_startParsingButton->setVisible(enabled);
m_progressLabel->setVisible(!enabled);
}
} // namespace ProjectExplorer
......@@ -37,13 +37,15 @@
#include <QDialog>
#include <QTreeView>
#include <QLabel>
#include "projectexplorer_export.h"
namespace Utils { class PathChooser; }
QT_BEGIN_NAMESPACE
class QVBoxLayout;
QT_END_NAMESPACE
namespace GenericProjectManager {
namespace Internal {
namespace ProjectExplorer {
struct Tree
{
......@@ -81,12 +83,12 @@ struct Glob
}
};
class SelectableFilesModel : public QAbstractItemModel
class PROJECTEXPLORER_EXPORT SelectableFilesModel : public QAbstractItemModel
{
Q_OBJECT
public:
SelectableFilesModel(const QString &baseDir, QObject *parent);
SelectableFilesModel(QObject *parent);
~SelectableFilesModel();