diff --git a/plugins/projectmanagerview/projectmanagerview.cpp b/plugins/projectmanagerview/projectmanagerview.cpp index dcf4d34ba1..fd8bc02c88 100644 --- a/plugins/projectmanagerview/projectmanagerview.cpp +++ b/plugins/projectmanagerview/projectmanagerview.cpp @@ -1,267 +1,283 @@ /* This file is part of KDevelop Copyright 2005 Roberto Raggi Copyright 2007 Andreas Pakulat Copyright 2008 Aleix Pol This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "projectmanagerview.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../openwith/iopenwith.h" #include #include #include "projectmanagerviewplugin.h" #include "vcsoverlayproxymodel.h" #include "ui_projectmanagerview.h" #include "debug.h" using namespace KDevelop; ProjectManagerViewItemContext::ProjectManagerViewItemContext(const QList< ProjectBaseItem* >& items, ProjectManagerView* view) : ProjectItemContextImpl(items), m_view(view) { } ProjectManagerView *ProjectManagerViewItemContext::view() const { return m_view; } static const char sessionConfigGroup[] = "ProjectManagerView"; static const char splitterStateConfigKey[] = "splitterState"; +static const char targetsVisibleConfigKey[] = "targetsVisible"; static const int projectTreeViewStrechFactor = 75; // % static const int projectBuildSetStrechFactor = 25; // % ProjectManagerView::ProjectManagerView( ProjectManagerViewPlugin* plugin, QWidget *parent ) : QWidget( parent ), m_ui(new Ui::ProjectManagerView), m_plugin(plugin) { m_ui->setupUi( this ); m_ui->projectTreeView->installEventFilter(this); setWindowIcon( QIcon::fromTheme( "project-development" ) ); KConfigGroup pmviewConfig(ICore::self()->activeSession()->config(), sessionConfigGroup); if (pmviewConfig.hasKey(splitterStateConfigKey)) { QByteArray geometry = pmviewConfig.readEntry(splitterStateConfigKey, QByteArray()); m_ui->splitter->restoreState(geometry); } else { m_ui->splitter->setStretchFactor(0, projectTreeViewStrechFactor); m_ui->splitter->setStretchFactor(1, projectBuildSetStrechFactor); } m_syncAction = plugin->actionCollection()->action("locate_document"); Q_ASSERT(m_syncAction); m_syncAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); m_syncAction->setText(i18n("Locate Current Document")); m_syncAction->setToolTip(i18n("Locates the current document in the project tree and selects it.")); m_syncAction->setIcon(QIcon::fromTheme("dirsync")); m_syncAction->setShortcut(Qt::ControlModifier + Qt::Key_Less); connect(m_syncAction, &QAction::triggered, this, &ProjectManagerView::locateCurrentDocument); addAction(m_syncAction); updateSyncAction(); + m_toggleTargetsAction = new QAction(i18n("Show Targets"), this); + m_toggleTargetsAction->setCheckable(true); + m_toggleTargetsAction->setChecked(pmviewConfig.readEntry(targetsVisibleConfigKey, true)); + m_toggleTargetsAction->setIcon(QIcon::fromTheme("system-run")); + connect(m_toggleTargetsAction, &QAction::triggered, this, &ProjectManagerView::toggleHideTargets); + addAction(m_toggleTargetsAction); + addAction(plugin->actionCollection()->action("project_build")); addAction(plugin->actionCollection()->action("project_install")); addAction(plugin->actionCollection()->action("project_clean")); connect(m_ui->projectTreeView, &ProjectTreeView::activate, this, &ProjectManagerView::open); m_ui->buildSetView->setProjectView( this ); m_modelFilter = new ProjectProxyModel( this ); + m_modelFilter->showTargets(m_toggleTargetsAction->isChecked()); m_modelFilter->setSourceModel(ICore::self()->projectController()->projectModel()); m_overlayProxy = new VcsOverlayProxyModel( this ); m_overlayProxy->setSourceModel(m_modelFilter); m_ui->projectTreeView->setModel( m_overlayProxy ); connect( m_ui->projectTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ProjectManagerView::selectionChanged ); connect( KDevelop::ICore::self()->documentController(), &IDocumentController::documentClosed, this, &ProjectManagerView::updateSyncAction); connect( KDevelop::ICore::self()->documentController(), &IDocumentController::documentActivated, this, &ProjectManagerView::updateSyncAction); connect( qobject_cast(KDevelop::ICore::self()->uiController()->activeMainWindow()), &Sublime::MainWindow::areaChanged, this, &ProjectManagerView::updateSyncAction); selectionChanged(); //Update the "sync" button after the initialization has completed, to see whether there already is some open documents QMetaObject::invokeMethod(this, "updateSyncAction", Qt::QueuedConnection); // Need to set this to get horizontal scrollbar. Also needs to be done after // the setModel call m_ui->projectTreeView->header()->setSectionResizeMode( QHeaderView::ResizeToContents ); } bool ProjectManagerView::eventFilter(QObject* obj, QEvent* event) { if (obj == m_ui->projectTreeView) { if (event->type() == QEvent::KeyRelease) { QKeyEvent* keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Delete && keyEvent->modifiers() == Qt::NoModifier) { m_plugin->removeItems(selectedItems()); return true; } else if (keyEvent->key() == Qt::Key_F2 && keyEvent->modifiers() == Qt::NoModifier) { m_plugin->renameItems(selectedItems()); return true; } else if (keyEvent->key() == Qt::Key_C && keyEvent->modifiers() == Qt::ControlModifier) { m_plugin->copyFromContextMenu(); return true; } else if (keyEvent->key() == Qt::Key_V && keyEvent->modifiers() == Qt::ControlModifier) { m_plugin->pasteFromContextMenu(); return true; } } } return QObject::eventFilter(obj, event); } void ProjectManagerView::selectionChanged() { m_ui->buildSetView->selectionChanged(); QList selected; foreach( const QModelIndex& idx, m_ui->projectTreeView->selectionModel()->selectedRows() ) { selected << ICore::self()->projectController()->projectModel()->itemFromIndex(indexFromView( idx )); } selected.removeAll(0); KDevelop::ICore::self()->selectionController()->updateSelection( new ProjectManagerViewItemContext( selected, this ) ); } void ProjectManagerView::updateSyncAction() { m_syncAction->setEnabled( KDevelop::ICore::self()->documentController()->activeDocument() ); } ProjectManagerView::~ProjectManagerView() { KConfigGroup pmviewConfig(ICore::self()->activeSession()->config(), sessionConfigGroup); pmviewConfig.writeEntry(splitterStateConfigKey, m_ui->splitter->saveState()); pmviewConfig.sync(); delete m_ui; } QList ProjectManagerView::selectedItems() const { QList items; foreach( const QModelIndex &idx, m_ui->projectTreeView->selectionModel()->selectedIndexes() ) { KDevelop::ProjectBaseItem* item = ICore::self()->projectController()->projectModel()->itemFromIndex(indexFromView(idx)); if( item ) items << item; else qCDebug(PLUGIN_PROJECTMANAGERVIEW) << "adding an unknown item"; } return items; } void ProjectManagerView::selectItems(const QList< ProjectBaseItem* >& items) { QItemSelection selection; foreach (ProjectBaseItem *item, items) { QModelIndex indx = indexToView(item->index()); selection.append(QItemSelectionRange(indx, indx)); m_ui->projectTreeView->setCurrentIndex(indx); } m_ui->projectTreeView->selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect); } void ProjectManagerView::expandItem(ProjectBaseItem* item) { m_ui->projectTreeView->expand( indexToView(item->index())); } +void ProjectManagerView::toggleHideTargets(bool visible) +{ + KConfigGroup pmviewConfig(ICore::self()->activeSession()->config(), sessionConfigGroup); + pmviewConfig.writeEntry(targetsVisibleConfigKey, visible); + m_modelFilter->showTargets(visible); +} + void ProjectManagerView::locateCurrentDocument() { ICore::self()->uiController()->raiseToolView(this); KDevelop::IDocument *doc = ICore::self()->documentController()->activeDocument(); if (!doc) { // in theory we should never get a null pointer as the action is only enabled // when there is an active document. // but: in practice it can happen that you close the last document and press // the shortcut to locate a doc or vice versa... so just do the failsafe thing here... return; } QModelIndex bestMatch; foreach (IProject* proj, ICore::self()->projectController()->projects()) { foreach (KDevelop::ProjectFileItem* item, proj->filesForPath(IndexedString(doc->url()))) { QModelIndex index = indexToView(item->index()); if (index.isValid()) { if (!bestMatch.isValid()) { bestMatch = index; } else if (KDevelop::ProjectBaseItem* parent = item->parent()) { // prefer files in their real folders over the 'copies' in the target folders if (!parent->target()) { bestMatch = index; break; } } } } } if (bestMatch.isValid()) { m_ui->projectTreeView->clearSelection(); m_ui->projectTreeView->setCurrentIndex(bestMatch); m_ui->projectTreeView->expand(bestMatch); m_ui->projectTreeView->scrollTo(bestMatch); } } void ProjectManagerView::open( const Path& path ) { IOpenWith::openFiles(QList() << path.toUrl()); } QModelIndex ProjectManagerView::indexFromView(const QModelIndex& index) const { return m_modelFilter->mapToSource( m_overlayProxy->mapToSource(index) ); } QModelIndex ProjectManagerView::indexToView(const QModelIndex& index) const { return m_overlayProxy->mapFromSource( m_modelFilter->mapFromSource(index) ); } diff --git a/plugins/projectmanagerview/projectmanagerview.h b/plugins/projectmanagerview/projectmanagerview.h index 57774ffac0..07e24d6894 100644 --- a/plugins/projectmanagerview/projectmanagerview.h +++ b/plugins/projectmanagerview/projectmanagerview.h @@ -1,93 +1,95 @@ /* This file is part of KDevelop Copyright 2005 Roberto Raggi Copyright 2007 Andreas Pakulat This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_PLUGIN_PROJECTMANAGERVIEW_H #define KDEVPLATFORM_PLUGIN_PROJECTMANAGERVIEW_H #include #include #include #include class QModelIndex; namespace Ui { class ProjectManagerView; } class ProjectProxyModel; class VcsOverlayProxyModel; namespace KDevelop { class ProjectBaseItem; class Path; } class ProjectManagerView; class ProjectManagerViewPlugin; //own subclass to the current view can be passed from ProjectManagetView to ProjectManagerViewPlugin class ProjectManagerViewItemContext : public KDevelop::ProjectItemContextImpl { public: ProjectManagerViewItemContext(const QList< KDevelop::ProjectBaseItem* >& items, ProjectManagerView *view); ProjectManagerView *view() const; private: ProjectManagerView *m_view; }; class ProjectManagerView: public QWidget { Q_OBJECT public: ProjectManagerView( ProjectManagerViewPlugin*, QWidget *parent ); virtual ~ProjectManagerView(); ProjectManagerViewPlugin* plugin() const { return m_plugin; } QList selectedItems() const; void selectItems(const QList &items); void expandItem(KDevelop::ProjectBaseItem *item); protected: virtual bool eventFilter(QObject* obj, QEvent* event) override; private slots: void selectionChanged(); void locateCurrentDocument(); void updateSyncAction(); void open( const KDevelop::Path& ); + void toggleHideTargets(bool hidden); private: QModelIndex indexFromView(const QModelIndex& index) const; QModelIndex indexToView(const QModelIndex& index) const; QAction* m_syncAction; + QAction* m_toggleTargetsAction; Ui::ProjectManagerView* m_ui; QStringList m_cachedFileList; ProjectProxyModel* m_modelFilter; VcsOverlayProxyModel* m_overlayProxy; ProjectManagerViewPlugin* m_plugin; }; #endif // KDEVPLATFORM_PLUGIN_PROJECTMANAGERVIEW_H diff --git a/project/projectproxymodel.cpp b/project/projectproxymodel.cpp index 995c29b200..9e98e83f3a 100644 --- a/project/projectproxymodel.cpp +++ b/project/projectproxymodel.cpp @@ -1,51 +1,77 @@ /* This file is part of KDevelop Copyright 2008 Aleix Pol This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "projectproxymodel.h" #include +#include ProjectProxyModel::ProjectProxyModel(QObject * parent) : QSortFilterProxyModel(parent) + , m_showTargets(true) { setDynamicSortFilter(true); sort(0); //initiate sorting regardless of the view } KDevelop::ProjectModel * ProjectProxyModel::projectModel() const { return qobject_cast( sourceModel() ); } bool ProjectProxyModel::lessThan(const QModelIndex & left, const QModelIndex & right) const { KDevelop::ProjectBaseItem *iLeft=projectModel()->itemFromIndex(left), *iRight=projectModel()->itemFromIndex(right); if(!iLeft || !iRight) return false; return( iLeft->lessThan( iRight ) ); } +void ProjectProxyModel::showTargets(bool visible) +{ + if (visible != m_showTargets) { + m_showTargets = visible; + invalidateFilter(); + } +} + +bool ProjectProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + if (m_showTargets) { + return true; + } + else { + // Get the base item for the associated parent and row. + QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + auto *item = projectModel()->itemFromIndex(index); + // If it's a target, return false, otherwise true. + return item->type() != KDevelop::ProjectBaseItem::Target + && item->type() != KDevelop::ProjectBaseItem::LibraryTarget + && item->type() != KDevelop::ProjectBaseItem::ExecutableTarget; + } +} + QModelIndex ProjectProxyModel::proxyIndexFromItem(KDevelop::ProjectBaseItem* item) const { return mapFromSource(projectModel()->indexFromItem(item)); } KDevelop::ProjectBaseItem* ProjectProxyModel::itemFromProxyIndex( const QModelIndex& idx ) const { return static_cast( projectModel()->itemFromIndex( mapToSource( idx ) ) ); } diff --git a/project/projectproxymodel.h b/project/projectproxymodel.h index 51ae1680a4..f3c09f8ed3 100644 --- a/project/projectproxymodel.h +++ b/project/projectproxymodel.h @@ -1,51 +1,57 @@ /* This file is part of KDevelop Copyright 2008 Aleix Pol This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_PROJECTPROXYMODEL_H #define KDEVPLATFORM_PROJECTPROXYMODEL_H #include #include "projectexport.h" #include #include #include #include namespace KDevelop { class ProjectModel; class ProjectBaseItem; } class KDEVPLATFORMPROJECT_EXPORT ProjectProxyModel : public QSortFilterProxyModel { Q_OBJECT public: explicit ProjectProxyModel(QObject *parent); bool lessThan (const QModelIndex & left, const QModelIndex & right) const override; QModelIndex proxyIndexFromItem(KDevelop::ProjectBaseItem* item) const; KDevelop::ProjectBaseItem* itemFromProxyIndex(const QModelIndex&) const; + void showTargets(bool visible); + + protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE; + private: KDevelop::ProjectModel* projectModel() const; + bool m_showTargets; }; #endif