diff --git a/plugins/projectmanagerview/vcsoverlayproxymodel.cpp b/plugins/projectmanagerview/vcsoverlayproxymodel.cpp index 76b3e21c6c..b2009b85eb 100644 --- a/plugins/projectmanagerview/vcsoverlayproxymodel.cpp +++ b/plugins/projectmanagerview/vcsoverlayproxymodel.cpp @@ -1,133 +1,145 @@ /* This file is part of KDevelop Copyright 2013 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 "vcsoverlayproxymodel.h" #include #include #include #include #include #include #include #include #include #include #include #include using namespace KDevelop; using SafeProjectPointer = QPointer; Q_DECLARE_METATYPE(SafeProjectPointer) VcsOverlayProxyModel::VcsOverlayProxyModel(QObject* parent): QIdentityProxyModel(parent) { connect(ICore::self()->projectController(), &IProjectController::projectOpened, this, &VcsOverlayProxyModel::addProject); connect(ICore::self()->projectController(), &IProjectController::projectClosing, this, &VcsOverlayProxyModel::removeProject); foreach (const auto project, ICore::self()->projectController()->projects()) { addProject(project); } } QVariant VcsOverlayProxyModel::data(const QModelIndex& proxyIndex, int role) const { if(role == VcsStatusRole) { if (!proxyIndex.parent().isValid()) { IProject* p = qobject_cast(proxyIndex.data(ProjectModel::ProjectRole).value()); return m_branchName.value(p); } else { ProjectChangesModel* model = ICore::self()->projectController()->changesModel(); const QUrl url = proxyIndex.data(ProjectModel::UrlRole).toUrl(); const auto idx = model->match(model->index(0, 0), ProjectChangesModel::UrlRole, url, 1, Qt::MatchExactly).value(0); return idx.sibling(idx.row(), 1).data(Qt::DisplayRole); } } else return QAbstractProxyModel::data(proxyIndex, role); } void VcsOverlayProxyModel::addProject(IProject* p) { IPlugin* plugin = p->versionControlPlugin(); if(!plugin) return; // TODO: Show revision in case we're in "detached" state IBranchingVersionControl* branchingExtension = plugin->extension(); if(branchingExtension) { const QUrl url = p->path().toUrl(); branchingExtension->registerRepositoryForCurrentBranchChanges(url); //can't use new signal/slot syntax here, IBranchingVersionControl is not a QObject connect(plugin, SIGNAL(repositoryBranchChanged(QUrl)), SLOT(repositoryBranchChanged(QUrl))); repositoryBranchChanged(url); } } void VcsOverlayProxyModel::repositoryBranchChanged(const QUrl& url) { QList allProjects = ICore::self()->projectController()->projects(); foreach(IProject* project, allProjects) { - if( url.isParentOf(project->path().toUrl()) || url.matches(project->path().toUrl(), QUrl::StripTrailingSlash)) { + const bool isExactMatch = url.matches(project->path().toUrl(), QUrl::StripTrailingSlash); + const bool isParentOf = url.isParentOf(project->path().toUrl()); + if (isParentOf || isExactMatch) { + // example projects in KDevelop: + // - /path/to/mygitrepo/: isParentOf=0 isExactMatch=1, + // - /path/to/mygitrepo/myproject: isParentOf=1 isExactMatch=0 + // - /path/to/norepo: isParentOf=0 isExactMatch=0 + // isParentOf=1 isExactMatch=1 is not a valid combination + IPlugin* v = project->versionControlPlugin(); - Q_ASSERT(v); + Q_ASSERT(!isExactMatch || v); // project url == 'change' url => project should be associated with a VCS plugin + if (!v) { + continue; + } + IBranchingVersionControl* branching = v->extension(); Q_ASSERT(branching); VcsJob* job = branching->currentBranch(url); connect(job, &VcsJob::resultsReady, this, &VcsOverlayProxyModel::branchNameReady); job->setProperty("project", QVariant::fromValue(project)); ICore::self()->runController()->registerJob(job); } } } void VcsOverlayProxyModel::branchNameReady(KDevelop::VcsJob* job) { static const QString noBranchStr = i18nc("Version control: Currently not on a branch", "(no branch)"); if(job->status()==VcsJob::JobSucceeded) { SafeProjectPointer p = job->property("project").value(); QModelIndex index = indexFromProject(p); if(index.isValid()) { IProject* project = p.data(); const auto branchName = job->fetchResults().toString(); m_branchName[project] = branchName.isEmpty() ? noBranchStr : branchName; emit dataChanged(index, index); } } } void VcsOverlayProxyModel::removeProject(IProject* p) { m_branchName.remove(p); } QModelIndex VcsOverlayProxyModel::indexFromProject(QObject* project) { for(int i=0; i()==project) { return idx; } } return QModelIndex(); }