diff --git a/plugins/projectmanagerview/projectmanagerview.cpp b/plugins/projectmanagerview/projectmanagerview.cpp index 5968b37ba4..ba82d4e300 100644 --- a/plugins/projectmanagerview/projectmanagerview.cpp +++ b/plugins/projectmanagerview/projectmanagerview.cpp @@ -1,284 +1,316 @@ /* 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 #include #include #include #include #include #include #include #include #include #include #include #include "../openwith/iopenwith.h" #include #include #include "tests/modeltest.h" #include #include "projectmanagerviewplugin.h" #include "ui_projectmanagerview.h" using namespace KDevelop; //BEGIN ProjectManagerFilterAction ProjectManagerFilterAction::ProjectManagerFilterAction( const QString &initialFilter, QObject* parent ) : KAction( parent ) , m_intialFilter(initialFilter) { setIcon(KIcon("view-filter")); setText(i18n("Filter...")); setToolTip(i18n("Insert wildcard patterns to filter the project view" " for files and targets for matching items.")); } QWidget* ProjectManagerFilterAction::createWidget( QWidget* parent ) { KLineEdit* edit = new KLineEdit(parent); edit->setClickMessage(i18n("Filter...")); edit->setClearButtonShown(true); connect(edit, SIGNAL(textChanged(QString)), this, SIGNAL(filterChanged(QString))); if (!m_intialFilter.isEmpty()) { edit->setText(m_intialFilter); } return edit; } //END ProjectManagerFilterAction static const char* sessionConfigGroup = "ProjectManagerView"; static const char* splitterStateConfigKey = "splitterState"; static const char* filterConfigKey = "filter"; 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( SmallIcon( "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(KIcon("dirsync")); m_syncAction->setShortcut(Qt::ControlModifier + Qt::Key_Less); connect(m_syncAction, SIGNAL(triggered(bool)), this, SLOT(locateCurrentDocument())); addAction(m_syncAction); updateSyncAction(); addAction(plugin->actionCollection()->action("project_build")); addAction(plugin->actionCollection()->action("project_install")); addAction(plugin->actionCollection()->action("project_clean")); connect(m_ui->projectTreeView, SIGNAL(activateUrl(KUrl)), this, SLOT(openUrl(KUrl))); // m_filters = new KLineEdit(this); // m_filters->setClearButtonShown(true); // connect(d->m_filters, SIGNAL(returnPressed()), this, SLOT(filtersChanged())); // vbox->addWidget( m_filters ); m_ui->buildSetView->setProjectView( this ); m_modelFilter = new ProjectProxyModel( this ); m_modelFilter->setDynamicSortFilter( true ); m_modelFilter->setSourceModel(ICore::self()->projectController()->projectModel()); m_ui->projectTreeView->setModel( m_modelFilter ); QString filterText; if (pmviewConfig.hasKey(filterConfigKey)) { filterText = pmviewConfig.readEntry(filterConfigKey, QString()); } ProjectManagerFilterAction* filterAction = new ProjectManagerFilterAction(filterText, this); connect(filterAction, SIGNAL(filterChanged(QString)), this, SLOT(filterChanged(QString))); addAction(filterAction); + connect( m_ui->projectTreeView, SIGNAL(clicked(QModelIndex)), this, SLOT(itemClicked(QModelIndex))); connect( m_ui->projectTreeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged()) ); connect( KDevelop::ICore::self()->documentController(), SIGNAL(documentClosed(KDevelop::IDocument*)), SLOT(updateSyncAction())); connect( KDevelop::ICore::self()->documentController(), SIGNAL(documentActivated(KDevelop::IDocument*)), SLOT(updateSyncAction())); connect( qobject_cast(KDevelop::ICore::self()->uiController()->activeMainWindow()), SIGNAL(areaChanged(Sublime::Area*)), SLOT(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()->setResizeMode( 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) { m_plugin->removeItems(selectedItems()); return true; } else if (keyEvent->key() == Qt::Key_F2) { m_plugin->renameItems(selectedItems()); 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 << m_modelFilter->itemFromProxyIndex( idx ); } + selected.removeAll(0); KDevelop::ICore::self()->selectionController()->updateSelection( new ProjectItemContext( selected ) ); } 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.writeEntry(filterConfigKey, m_filterString); pmviewConfig.sync(); } QList ProjectManagerView::selectedItems() const { QList items; foreach( const QModelIndex &idx, m_ui->projectTreeView->selectionModel()->selectedIndexes() ) { KDevelop::ProjectBaseItem* item = ICore::self()->projectController()->projectModel()->itemFromIndex( m_modelFilter->mapToSource(idx) ); if( item ) items << item; else kDebug(9511) << "adding an unknown item"; } return items; } 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->filesForUrl(doc->url())) { QModelIndex index = m_modelFilter->proxyIndexFromItem(item); 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::openUrl( const KUrl& url ) { IOpenWith::openFiles(KUrl::List() << url); } +void ProjectManagerView::itemClicked(QModelIndex index) +{ + m_modelFilter->itemClicked(index); +} + void ProjectManagerView::filterChanged(const QString &text) { m_filterString = text; m_modelFilter->setFilterString(text); + + // Auto-expand to fill the view + if(text.size()) + { + int depth = 0; + while(m_ui->projectTreeView->sizeHint().height() < m_ui->projectTreeView->height() && depth < 10) + { + depth += 1; + m_ui->projectTreeView->expandToDepth(depth); + } + } + + // Auto-expand if only exactly one folder survived filtering +// QModelIndex parent = QModelIndex(); +// while(m_modelFilter->rowCount(parent)) +// { +// kDebug() << "row-count " << m_modelFilter->rowCount(parent); +// m_ui->projectTreeView->expand(parent); +// if(m_modelFilter->rowCount(parent) == 1) +// { +// parent = m_modelFilter->index(0, 0, parent); +// }else{ +// break; +// } +// } } #include "projectmanagerview.moc" diff --git a/plugins/projectmanagerview/projectmanagerview.h b/plugins/projectmanagerview/projectmanagerview.h index 624dfb82b0..9da4df883a 100644 --- a/plugins/projectmanagerview/projectmanagerview.h +++ b/plugins/projectmanagerview/projectmanagerview.h @@ -1,89 +1,90 @@ /* 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 KDEVPROJECTMANAGERVIEW_H #define KDEVPROJECTMANAGERVIEW_H #include #include class QModelIndex; class KUrl; namespace Ui { class ProjectManagerView; } class ProjectProxyModel; namespace KDevelop { class ProjectBaseItem; } class ProjectManagerViewPlugin; class ProjectManagerFilterAction : public KAction { Q_OBJECT public: explicit ProjectManagerFilterAction( const QString &initialFilter, QObject* parent ); signals: void filterChanged(const QString& filter); protected: virtual QWidget* createWidget( QWidget* parent ); QString m_intialFilter; }; class ProjectManagerView: public QWidget { Q_OBJECT public: ProjectManagerView( ProjectManagerViewPlugin*, QWidget *parent ); virtual ~ProjectManagerView(); ProjectManagerViewPlugin* plugin() const { return m_plugin; } QList selectedItems() const; protected: virtual bool eventFilter(QObject* obj, QEvent* event); private slots: void selectionChanged(); void locateCurrentDocument(); void updateSyncAction(); void openUrl( const KUrl& ); void filterChanged(const QString&); + void itemClicked( QModelIndex ); private: QAction* m_syncAction; Ui::ProjectManagerView* m_ui; QStringList m_cachedFileList; ProjectProxyModel* m_modelFilter; ProjectManagerViewPlugin* m_plugin; QString m_filterString; }; #endif // KDEVPROJECTMANAGER_H