diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp index 77f55f1f17f3cbba35b09ca9e9151c0935f32dcc..3a766b2b374b40705c86ddb75149472c89b7f933 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.cpp +++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp @@ -36,31 +36,52 @@ #include <coreplugin/editormanager/editormanager.h> #include <utils/pathchooser.h> +#include <utils/qtcassert.h> #include <QtCore/QDebug> -#include <QtGui/QDirModel> +#include <QtGui/QFileSystemModel> #include <QtGui/QVBoxLayout> #include <QtGui/QToolButton> #include <QtGui/QLabel> #include <QtGui/QListView> #include <QtGui/QSortFilterProxyModel> +#include <QtGui/QAction> +#include <QtGui/QMenu> +#include <QtGui/QFileDialog> +#include <QtGui/QContextMenuEvent> enum { debug = 0 }; namespace ProjectExplorer { namespace Internal { -class FirstRowFilter : public QSortFilterProxyModel +// Hide the '.' entry. +class DotRemovalFilter : public QSortFilterProxyModel { Q_OBJECT public: - FirstRowFilter(QObject *parent = 0) : QSortFilterProxyModel(parent) {} + explicit DotRemovalFilter(QObject *parent = 0); protected: - bool filterAcceptsRow(int source_row, const QModelIndex &) const { - return source_row != 0; - } + virtual bool filterAcceptsRow(int source_row, const QModelIndex &parent) const; +private: + const QString m_dot; }; +DotRemovalFilter::DotRemovalFilter(QObject *parent) : + QSortFilterProxyModel(parent), + m_dot(QString(QLatin1Char('.'))) +{ +} + +bool DotRemovalFilter::filterAcceptsRow(int source_row, const QModelIndex &parent) const +{ + // Check for first entry unless we are at '/'. + if (source_row || !parent.isValid()) + return true; + const QString fileName = sourceModel()->data(parent.child(source_row, 0)).toString(); + return fileName != m_dot; +} + /*! /class FolderNavigationWidget @@ -68,34 +89,38 @@ protected: */ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent), - m_explorer(ProjectExplorerPlugin::instance()), - m_view(new QListView(this)), - m_dirModel(new QDirModel(this)), - m_filter(new FirstRowFilter(this)), + m_listView(new QListView(this)), + m_fileSystemModel(new QFileSystemModel(this)), + m_filterModel(new DotRemovalFilter(this)), m_title(new QLabel(this)), m_autoSync(false) { - m_dirModel->setResolveSymlinks(false); - m_dirModel->setFilter(QDir::Dirs | QDir::Files | QDir::Drives | QDir::Readable | QDir::Writable - | QDir::Executable | QDir::Hidden); - m_dirModel->setSorting(QDir::Name | QDir::DirsFirst); - m_filter->setSourceModel(m_dirModel); - m_view->setModel(m_filter); - m_view->setFrameStyle(QFrame::NoFrame); - m_view->setAttribute(Qt::WA_MacShowFocusRect, false); - setFocusProxy(m_view); + m_fileSystemModel->setResolveSymlinks(false); + QDir::Filters filters = QDir::AllDirs | QDir::Files | QDir::Drives + | QDir::Readable| QDir::Writable + | QDir::Executable | QDir::Hidden; +#ifdef Q_OS_WIN // Symlinked directories can cause file watcher warnings on Win32. + filters |= QDir::NoSymLinks; +#endif + m_fileSystemModel->setFilter(filters); + m_fileSystemModel->setRootPath(QDir::rootPath()); + m_filterModel->setSourceModel(m_fileSystemModel); + m_listView->setModel(m_filterModel); + m_listView->setFrameStyle(QFrame::NoFrame); + m_listView->setAttribute(Qt::WA_MacShowFocusRect, false); + setFocusProxy(m_listView); QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(m_title); - layout->addWidget(m_view); + layout->addWidget(m_listView); m_title->setMargin(5); layout->setSpacing(0); layout->setContentsMargins(0, 0, 0, 0); setLayout(layout); // connections - connect(m_view, SIGNAL(activated(const QModelIndex&)), - this, SLOT(openItem(const QModelIndex&))); + connect(m_listView, SIGNAL(activated(const QModelIndex&)), + this, SLOT(slotOpenItem(const QModelIndex&))); setAutoSynchronization(true); } @@ -130,53 +155,136 @@ void FolderNavigationWidget::setAutoSynchronization(bool sync) void FolderNavigationWidget::setCurrentFile(const QString &filePath) { - if (debug) - qDebug() << "FolderNavigationWidget::setCurrentFile(" << filePath << ")"; - - QString dir = QFileInfo(filePath).path(); - if (dir.isEmpty()) - dir = Utils::PathChooser::homePath(); - - QModelIndex dirIndex = m_dirModel->index(dir); - QModelIndex fileIndex = m_dirModel->index(filePath); + // Try to find directory of current file + bool pathOpened = false; + if (!filePath.isEmpty()) { + const QFileInfo fi(filePath); + if (fi.exists()) + pathOpened = setCurrentDirectory(fi.absolutePath()); + } + if (!pathOpened) // Default to home. + setCurrentDirectory(Utils::PathChooser::homePath()); - m_view->setRootIndex(m_filter->mapFromSource(dirIndex)); - if (dirIndex.isValid()) { - setCurrentTitle(QDir(m_dirModel->filePath(dirIndex))); + // Select the current file. + if (pathOpened) { + const QModelIndex fileIndex = m_fileSystemModel->index(filePath); if (fileIndex.isValid()) { - QItemSelectionModel *selections = m_view->selectionModel(); - QModelIndex mainIndex = m_filter->mapFromSource(fileIndex); + QItemSelectionModel *selections = m_listView->selectionModel(); + const QModelIndex mainIndex = m_filterModel->mapFromSource(fileIndex); selections->setCurrentIndex(mainIndex, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Clear); - m_view->scrollTo(mainIndex); + m_listView->scrollTo(mainIndex); } + } +} + +bool FolderNavigationWidget::setCurrentDirectory(const QString &directory) +{ + return !directory.isEmpty() && setCurrentDirectory(m_fileSystemModel->index(directory)); +} + +bool FolderNavigationWidget::setCurrentDirectory(const QModelIndex &dirIndex) +{ + const bool valid = dirIndex.isValid(); + if (valid) { + // position view root on directory index. + m_listView->setRootIndex(m_filterModel->mapFromSource(dirIndex)); + const QDir currentDir(m_fileSystemModel->filePath(dirIndex)); + setCurrentTitle(currentDir.dirName(), currentDir.absolutePath()); } else { - setCurrentTitle(QDir()); + m_listView->setRootIndex(QModelIndex()); + setCurrentTitle(QString(), QString()); } + return valid; } -void FolderNavigationWidget::openItem(const QModelIndex &index) +QString FolderNavigationWidget::currentDirectory() const { - if (index.isValid()) { - const QModelIndex srcIndex = m_filter->mapToSource(index); - if (m_dirModel->isDir(srcIndex)) { - m_view->setRootIndex(index); - setCurrentTitle(QDir(m_dirModel->filePath(srcIndex))); - } else { - const QString filePath = m_dirModel->filePath(srcIndex); - Core::EditorManager *editorManager = Core::EditorManager::instance(); - editorManager->openEditor(filePath); - editorManager->ensureEditorManagerVisible(); - } + const QModelIndex rootIndex = m_listView->rootIndex(); + if (rootIndex.isValid()) + return m_fileSystemModel->filePath(m_filterModel->mapToSource(rootIndex)); + return QString(); +} + +void FolderNavigationWidget::slotOpenItem(const QModelIndex &viewIndex) +{ + if (viewIndex.isValid()) + openItem(m_filterModel->mapToSource(viewIndex)); +} + +void FolderNavigationWidget::openItem(const QModelIndex &srcIndex) +{ + const QString fileName = m_fileSystemModel->fileName(srcIndex); + if (fileName == QLatin1String(".")) + return; + if (fileName == QLatin1String("..")) { // cd up. + setCurrentDirectory(srcIndex.parent().parent()); + return; + } + if (m_fileSystemModel->isDir(srcIndex)) { // Change to directory + setCurrentDirectory(srcIndex); + return; } + // Open file. + Core::EditorManager *editorManager = Core::EditorManager::instance(); + editorManager->openEditor(m_fileSystemModel->filePath(srcIndex)); + editorManager->ensureEditorManagerVisible(); } -void FolderNavigationWidget::setCurrentTitle(const QDir &dir) +void FolderNavigationWidget::setCurrentTitle(const QString &dirName, const QString &fullPath) { - m_title->setText(dir.dirName()); - m_title->setToolTip(dir.absolutePath()); + m_title->setText(dirName); + m_title->setToolTip(fullPath); +} + +QModelIndex FolderNavigationWidget::currentItem() const +{ + const QModelIndex current = m_listView->currentIndex(); + if (current.isValid()) + return m_filterModel->mapToSource(current); + return QModelIndex(); +} + +// Format the text for the "open" action of the context menu according +// to the selectect entry +static inline QString actionOpenText(const QFileSystemModel *model, + const QModelIndex &index) +{ + if (!index.isValid()) + return FolderNavigationWidget::tr("Open"); + const QString fileName = model->fileName(index); + if (fileName == QLatin1String("..")) + return FolderNavigationWidget::tr("Open parent folder"); + return FolderNavigationWidget::tr("Open \"%1\"").arg(fileName); +} + +void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev) +{ + QMenu menu; + // Open current item + const QModelIndex current = currentItem(); + QAction *actionOpen = menu.addAction(actionOpenText(m_fileSystemModel, current)); + actionOpen->setEnabled(current.isValid()); + // Open file dialog to choose a path starting from current + QAction *actionChooseFolder = menu.addAction(tr("Choose folder...")); + + QAction *action = menu.exec(ev->globalPos()); + if (!action) + return; + + ev->accept(); + if (action == actionOpen) { // Handle open file. + openItem(current); + return; + } + if (action == actionChooseFolder) { // Open file dialog + const QString newPath = QFileDialog::getExistingDirectory(this, tr("Choose folder"), currentDirectory()); + if (!newPath.isEmpty()) + setCurrentDirectory(newPath); + } } +// --------------------FolderNavigationWidgetFactory FolderNavigationWidgetFactory::FolderNavigationWidgetFactory() { } diff --git a/src/plugins/projectexplorer/foldernavigationwidget.h b/src/plugins/projectexplorer/foldernavigationwidget.h index cc405cac494ba74f26dd918be1767b91bca655ba..07b3f558de93770443b82cd6c50ad239685af510 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.h +++ b/src/plugins/projectexplorer/foldernavigationwidget.h @@ -39,7 +39,7 @@ class QLabel; class QListView; class QSortFilterProxyModel; class QModelIndex; -class QDirModel; +class QFileSystemModel; class QDir; QT_END_NAMESPACE @@ -66,16 +66,23 @@ public slots: void toggleAutoSynchronization(); private slots: - void openItem(const QModelIndex &mainIndex); void setCurrentFile(const QString &filePath); + void slotOpenItem(const QModelIndex &viewIndex); -private: - void setCurrentTitle(const QDir &directory); +protected: + virtual void contextMenuEvent(QContextMenuEvent *ev); - ProjectExplorerPlugin *m_explorer; - QListView *m_view; - QDirModel *m_dirModel; - QSortFilterProxyModel *m_filter; +private: + void setCurrentTitle(const QString &dirName, const QString &fullPath); + bool setCurrentDirectory(const QString &directory); + bool setCurrentDirectory(const QModelIndex &dirIndex); + void openItem(const QModelIndex &srcIndex); + QModelIndex currentItem() const; + QString currentDirectory() const; + + QListView *m_listView; + QFileSystemModel *m_fileSystemModel; + QSortFilterProxyModel *m_filterModel; QLabel *m_title; bool m_autoSync; }; diff --git a/src/plugins/qmlprojectmanager/qmlprojectwizard.h b/src/plugins/qmlprojectmanager/qmlprojectwizard.h index 3dfc00d4090f558f9a13d1217c2021a5b3eeb150..865a69512a8b133e226ee94c6157c5bcc8358bd5 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectwizard.h +++ b/src/plugins/qmlprojectmanager/qmlprojectwizard.h @@ -36,12 +36,9 @@ QT_BEGIN_NAMESPACE class QDir; -class QDirModel; class QFileInfo; -class QListView; class QModelIndex; class QStringList; -class QTreeView; QT_END_NAMESPACE namespace Utils { @@ -65,15 +62,7 @@ public: QString projectName() const; private: - int m_secondPageId; - Utils::FileWizardPage *m_firstPage; - - QTreeView *m_dirView; - QDirModel *m_dirModel; - - QListView *m_filesView; - QDirModel *m_filesModel; }; class QmlProjectWizard : public Core::BaseFileWizard