diff options
author | Eike Ziller <eike.ziller@qt.io> | 2018-03-29 14:56:24 +0200 |
---|---|---|
committer | Eike Ziller <eike.ziller@qt.io> | 2018-04-11 06:51:48 +0000 |
commit | d44ed66a9f32d91ee62748f095f222faa5a7b875 (patch) | |
tree | e7c99aa96321753e4c2cfd3ae2af103bf75dbed3 /src/plugins/projectexplorer/foldernavigationwidget.cpp | |
parent | 99bcc001990846329f9d430ae23998d8de183e35 (diff) | |
download | qt-creator-d44ed66a9f32d91ee62748f095f222faa5a7b875.tar.gz |
File System View: Add option to show folders on top
Task-number: QTCREATORBUG-7818
Change-Id: I37a36a03c9baf6fba7b3eedcb52ee5912a57a47a
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
Diffstat (limited to 'src/plugins/projectexplorer/foldernavigationwidget.cpp')
-rw-r--r-- | src/plugins/projectexplorer/foldernavigationwidget.cpp | 97 |
1 files changed, 83 insertions, 14 deletions
diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp index f358c82dfd..7601ab6de6 100644 --- a/src/plugins/projectexplorer/foldernavigationwidget.cpp +++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp @@ -70,6 +70,7 @@ #include <QMessageBox> #include <QScrollBar> #include <QSize> +#include <QSortFilterProxyModel> #include <QTimer> #include <QToolButton> #include <QVBoxLayout> @@ -128,6 +129,10 @@ private: class FolderNavigationModel : public QFileSystemModel { public: + enum Roles { + IsFolderRole = Qt::UserRole + 50 // leave some gap for the custom roles in QFileSystemModel + }; + explicit FolderNavigationModel(QObject *parent = nullptr); QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const final; Qt::DropActions supportedDragActions() const final; @@ -135,6 +140,37 @@ public: bool setData(const QModelIndex &index, const QVariant &value, int role) final; }; +// Sorts folders on top if wanted +class FolderSortProxyModel : public QSortFilterProxyModel +{ +public: + FolderSortProxyModel(QObject *parent = nullptr); + +protected: + bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const; +}; + +FolderSortProxyModel::FolderSortProxyModel(QObject *parent) + : QSortFilterProxyModel(parent) +{ +} + +bool FolderSortProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const +{ + const QAbstractItemModel *src = sourceModel(); + if (sortRole() == FolderNavigationModel::IsFolderRole) { + const bool leftIsFolder = src->data(source_left, FolderNavigationModel::IsFolderRole) + .toBool(); + const bool rightIsFolder = src->data(source_right, FolderNavigationModel::IsFolderRole) + .toBool(); + if (leftIsFolder != rightIsFolder) + return leftIsFolder; + } + const QString leftName = src->data(source_left, QFileSystemModel::FileNameRole).toString(); + const QString rightName = src->data(source_right, QFileSystemModel::FileNameRole).toString(); + return Utils::FileName::fromString(leftName) < Utils::FileName::fromString(rightName); +} + FolderNavigationModel::FolderNavigationModel(QObject *parent) : QFileSystemModel(parent) { } @@ -142,6 +178,8 @@ QVariant FolderNavigationModel::data(const QModelIndex &index, int role) const { if (role == Qt::ToolTipRole) return QDir::toNativeSeparators(QDir::cleanPath(filePath(index))); + else if (role == IsFolderRole) + return isDir(index); else return QFileSystemModel::data(index, role); } @@ -250,8 +288,10 @@ static bool isChildOf(const QModelIndex &index, const QModelIndex &parent) FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent), m_listView(new Utils::NavigationTreeView(this)), m_fileSystemModel(new FolderNavigationModel(this)), + m_sortProxyModel(new FolderSortProxyModel(m_fileSystemModel)), m_filterHiddenFilesAction(new QAction(tr("Show Hidden Files"), this)), m_showBreadCrumbsAction(new QAction(tr("Show Bread Crumbs"), this)), + m_showFoldersOnTopAction(new QAction(tr("Show Folders on Top"), this)), m_toggleSync(new QToolButton(this)), m_toggleRootSync(new QToolButton(this)), m_rootSelector(new QComboBox), @@ -264,6 +304,9 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent setBackgroundRole(QPalette::Base); setAutoFillBackground(true); + m_sortProxyModel->setSourceModel(m_fileSystemModel); + m_sortProxyModel->setSortRole(FolderNavigationModel::IsFolderRole); + m_sortProxyModel->sort(0); m_fileSystemModel->setResolveSymlinks(false); m_fileSystemModel->setIconProvider(Core::FileIconProvider::iconProvider()); QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot; @@ -275,9 +318,11 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent setHiddenFilesFilter(false); m_showBreadCrumbsAction->setCheckable(true); setShowBreadCrumbs(true); + m_showFoldersOnTopAction->setCheckable(true); + setShowFoldersOnTop(true); m_listView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); m_listView->setIconSize(QSize(16,16)); - m_listView->setModel(m_fileSystemModel); + m_listView->setModel(m_sortProxyModel); m_listView->setEditTriggers(QAbstractItemView::NoEditTriggers); m_listView->setDragEnabled(true); m_listView->setDragDropMode(QAbstractItemView::DragOnly); @@ -319,17 +364,21 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent // connections connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged, this, &FolderNavigationWidget::handleCurrentEditorChanged); - connect(m_listView, &QAbstractItemView::activated, - this, [this](const QModelIndex &index) { openItem(index); }); + connect(m_listView, &QAbstractItemView::activated, this, [this](const QModelIndex &index) { + openItem(m_sortProxyModel->mapToSource(index)); + }); // use QueuedConnection for updating crumble path, because that can scroll, which doesn't // work well when done directly in currentChanged (the wrong item can get highlighted) connect(m_listView->selectionModel(), &QItemSelectionModel::currentChanged, this, - &FolderNavigationWidget::setCrumblePath, + [this](const QModelIndex ¤t, const QModelIndex &previous) { + setCrumblePath(m_sortProxyModel->mapToSource(current), + m_sortProxyModel->mapToSource(previous)); + }, Qt::QueuedConnection); connect(m_crumbLabel, &Utils::FileCrumbLabel::pathClicked, [this](const Utils::FileName &path) { - const QModelIndex rootIndex = m_listView->rootIndex(); + const QModelIndex rootIndex = m_sortProxyModel->mapToSource(m_listView->rootIndex()); const QModelIndex fileIndex = m_fileSystemModel->index(path.toString()); if (!isChildOf(fileIndex, rootIndex)) selectBestRootForFile(path); @@ -343,6 +392,10 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent &QAction::toggled, this, &FolderNavigationWidget::setShowBreadCrumbs); + connect(m_showFoldersOnTopAction, + &QAction::toggled, + this, + &FolderNavigationWidget::setShowFoldersOnTop); connect(m_toggleSync, &QAbstractButton::clicked, this, @@ -356,8 +409,8 @@ FolderNavigationWidget::FolderNavigationWidget(QWidget *parent) : QWidget(parent const auto directory = m_rootSelector->itemData(index).value<Utils::FileName>(); m_rootSelector->setToolTip(directory.toString()); setRootDirectory(directory); - const QModelIndex rootIndex = m_listView->rootIndex(); - const QModelIndex fileIndex = m_listView->currentIndex(); + const QModelIndex rootIndex = m_sortProxyModel->mapToSource(m_listView->rootIndex()); + const QModelIndex fileIndex = m_sortProxyModel->mapToSource(m_listView->currentIndex()); if (!isChildOf(fileIndex, rootIndex)) selectFile(directory); }); @@ -382,6 +435,13 @@ void FolderNavigationWidget::setShowBreadCrumbs(bool show) m_crumbLabel->setVisible(show); } +void FolderNavigationWidget::setShowFoldersOnTop(bool onTop) +{ + m_showFoldersOnTopAction->setChecked(onTop); + m_sortProxyModel->setSortRole(onTop ? FolderNavigationModel::IsFolderRole + : QFileSystemModel::FileNameRole); +} + static bool itemLessThan(QComboBox *combo, int index, const FolderNavigationWidgetFactory::RootDirectory &directory) @@ -433,7 +493,7 @@ void FolderNavigationWidget::removeRootDirectory(const QString &id) void FolderNavigationWidget::addNewItem() { - const QModelIndex current = m_listView->currentIndex(); + const QModelIndex current = m_sortProxyModel->mapToSource(m_listView->currentIndex()); if (!current.isValid()) return; const auto filePath = Utils::FileName::fromString(m_fileSystemModel->filePath(current)); @@ -448,7 +508,7 @@ void FolderNavigationWidget::addNewItem() void FolderNavigationWidget::editCurrentItem() { const QModelIndex current = m_listView->currentIndex(); - if (m_fileSystemModel->flags(current) & Qt::ItemIsEditable) + if (m_listView->model()->flags(current) & Qt::ItemIsEditable) m_listView->edit(current); } @@ -467,7 +527,7 @@ static QVector<FolderNode *> removableFolderNodes(const Utils::FileName &filePat void FolderNavigationWidget::removeCurrentItem() { - const QModelIndex current = m_listView->currentIndex(); + const QModelIndex current = m_sortProxyModel->mapToSource(m_listView->currentIndex()); if (!current.isValid() || m_fileSystemModel->isDir(current)) return; const QString filePath = m_fileSystemModel->filePath(current); @@ -543,7 +603,8 @@ void FolderNavigationWidget::selectBestRootForFile(const Utils::FileName &filePa void FolderNavigationWidget::selectFile(const Utils::FileName &filePath) { - const QModelIndex fileIndex = m_fileSystemModel->index(filePath.toString()); + const QModelIndex fileIndex = m_sortProxyModel->mapFromSource( + m_fileSystemModel->index(filePath.toString())); if (fileIndex.isValid() || filePath.isEmpty() /* Computer root */) { // TODO This only scrolls to the right position if all directory contents are loaded. // Unfortunately listening to directoryLoaded was still not enough (there might also @@ -564,7 +625,8 @@ void FolderNavigationWidget::selectFile(const Utils::FileName &filePath) void FolderNavigationWidget::setRootDirectory(const Utils::FileName &directory) { - const QModelIndex index = m_fileSystemModel->setRootPath(directory.toString()); + const QModelIndex index = m_sortProxyModel->mapFromSource( + m_fileSystemModel->setRootPath(directory.toString())); m_listView->setRootIndex(index); } @@ -624,7 +686,8 @@ void FolderNavigationWidget::createNewFolder(const QModelIndex &parent) const Utils::FileName name = Utils::makeUniquelyNumbered(Utils::FileName::fromString(baseName), existingItems); // create directory and edit - const QModelIndex index = m_fileSystemModel->mkdir(parent, name.toString()); + const QModelIndex index = m_sortProxyModel->mapFromSource( + m_fileSystemModel->mkdir(parent, name.toString())); if (!index.isValid()) return; m_listView->setCurrentIndex(index); @@ -662,7 +725,7 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev) { QMenu menu; // Open current item - const QModelIndex current = m_listView->currentIndex(); + const QModelIndex current = m_sortProxyModel->mapToSource(m_listView->currentIndex()); const bool hasCurrentItem = current.isValid(); QAction *actionOpenFile = nullptr; QAction *actionOpenProjects = nullptr; @@ -753,6 +816,11 @@ bool FolderNavigationWidget::isShowingBreadCrumbs() const return m_showBreadCrumbsAction->isChecked(); } +bool FolderNavigationWidget::isShowingFoldersOnTop() const +{ + return m_showFoldersOnTopAction->isChecked(); +} + QStringList FolderNavigationWidget::projectFilesInDirectory(const QString &path) { QDir dir(path); @@ -812,6 +880,7 @@ Core::NavigationView FolderNavigationWidgetFactory::createWidget() auto filterMenu = new QMenu(filter); filterMenu->addAction(fnw->m_filterHiddenFilesAction); filterMenu->addAction(fnw->m_showBreadCrumbsAction); + filterMenu->addAction(fnw->m_showFoldersOnTopAction); filter->setMenu(filterMenu); n.dockToolBarWidgets << filter << fnw->m_toggleSync; return n; |