File indexing completed on 2024-05-05 04:41:03
0001 /* 0002 SPDX-FileCopyrightText: 2010 Aleix Pol Gonzalez <aleixpol@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "vcschangesview.h" 0008 #include <interfaces/icore.h> 0009 #include <interfaces/context.h> 0010 #include <interfaces/iproject.h> 0011 #include <interfaces/idocumentcontroller.h> 0012 #include <interfaces/iplugincontroller.h> 0013 #include <interfaces/iprojectcontroller.h> 0014 #include <interfaces/contextmenuextension.h> 0015 #include <vcs/vcsstatusinfo.h> 0016 #include <project/projectchangesmodel.h> 0017 #include <project/projectmodel.h> 0018 #include <project/projectutils.h> 0019 0020 #include <QIcon> 0021 #include <QMenu> 0022 #include <QPointer> 0023 0024 #include <KActionCollection> 0025 #include <KLocalizedString> 0026 0027 #include "vcschangesviewplugin.h" 0028 0029 using namespace KDevelop; 0030 0031 VcsChangesView::VcsChangesView(VcsProjectIntegrationPlugin* plugin, QWidget* parent) 0032 : QTreeView(parent) 0033 { 0034 setRootIsDecorated(false); 0035 setEditTriggers(QAbstractItemView::NoEditTriggers); 0036 setSelectionMode(ContiguousSelection); 0037 setContextMenuPolicy(Qt::CustomContextMenu); 0038 setTextElideMode(Qt::ElideLeft); 0039 setWordWrap(true); 0040 setWindowIcon(QIcon::fromTheme(QStringLiteral("exchange-positions"), windowIcon())); 0041 0042 connect(this, &VcsChangesView::customContextMenuRequested, this, &VcsChangesView::popupContextMenu); 0043 0044 const auto pluginActions = plugin->actionCollection()->actions(); 0045 for (QAction* action : pluginActions) { 0046 addAction(action); 0047 } 0048 0049 QAction* action = plugin->actionCollection()->action(QStringLiteral("locate_document")); 0050 connect(action, &QAction::triggered, this, &VcsChangesView::selectCurrentDocument); 0051 connect(this, &VcsChangesView::doubleClicked, this, &VcsChangesView::openSelected); 0052 } 0053 0054 static void appendActions(QMenu* menu, const QList<QAction*>& actions) 0055 { 0056 menu->addSeparator(); 0057 menu->addActions(actions); 0058 } 0059 0060 void VcsChangesView::popupContextMenu( const QPoint &pos ) 0061 { 0062 QList<QUrl> urls; 0063 QList<IProject*> projects; 0064 const QModelIndexList selectionIdxs = selectedIndexes(); 0065 if(selectionIdxs.isEmpty()) 0066 return; 0067 0068 for (const QModelIndex& idx : selectionIdxs) { 0069 if(idx.column()==0) { 0070 if(idx.parent().isValid()) 0071 urls += idx.data(KDevelop::VcsFileChangesModel::VcsStatusInfoRole).value<VcsStatusInfo>().url(); 0072 else { 0073 IProject* project = ICore::self()->projectController()->findProjectByName(idx.data(ProjectChangesModel::ProjectNameRole).toString()); 0074 if (project) { 0075 projects += project; 0076 } else { 0077 qWarning() << "Couldn't find a project for project: " << idx.data(ProjectChangesModel::ProjectNameRole).toString(); 0078 } 0079 } 0080 } 0081 } 0082 0083 QPointer<QMenu> menu = new QMenu(this); 0084 QAction* refreshAction = menu->addAction(QIcon::fromTheme(QStringLiteral("view-refresh")), i18nc("@action:inmenu", "Refresh")); 0085 QList<ContextMenuExtension> extensions; 0086 if(!urls.isEmpty()) { 0087 KDevelop::FileContext context(urls); 0088 extensions = ICore::self()->pluginController()->queryPluginsForContextMenuExtensions(&context, menu); 0089 } else { 0090 QList<ProjectBaseItem*> items; 0091 items.reserve(projects.size()); 0092 for (IProject* p : qAsConst(projects)) { 0093 items += p->projectItem(); 0094 } 0095 0096 KDevelop::ProjectItemContextImpl context(items); 0097 extensions = ICore::self()->pluginController()->queryPluginsForContextMenuExtensions(&context, menu); 0098 0099 } 0100 0101 QList<QAction*> buildActions; 0102 QList<QAction*> vcsActions; 0103 QList<QAction*> extActions; 0104 QList<QAction*> projectActions; 0105 QList<QAction*> fileActions; 0106 QList<QAction*> runActions; 0107 for (const ContextMenuExtension& ext : qAsConst(extensions)) { 0108 buildActions += ext.actions(ContextMenuExtension::BuildGroup); 0109 fileActions += ext.actions(ContextMenuExtension::FileGroup); 0110 projectActions += ext.actions(ContextMenuExtension::ProjectGroup); 0111 vcsActions += ext.actions(ContextMenuExtension::VcsGroup); 0112 extActions += ext.actions(ContextMenuExtension::ExtensionGroup); 0113 runActions += ext.actions(ContextMenuExtension::RunGroup); 0114 } 0115 0116 appendActions(menu, buildActions); 0117 appendActions(menu, runActions ); 0118 appendActions(menu, fileActions); 0119 appendActions(menu, vcsActions); 0120 appendActions(menu, extActions); 0121 appendActions(menu, projectActions); 0122 0123 if ( !menu->isEmpty() ) { 0124 QAction* res = menu->exec(viewport()->mapToGlobal(pos)); 0125 if(res == refreshAction) { 0126 if(!urls.isEmpty()) 0127 emit reload(urls); 0128 else 0129 emit reload(projects); 0130 } 0131 } 0132 delete menu; 0133 } 0134 0135 void VcsChangesView::selectCurrentDocument() 0136 { 0137 IDocument* doc = ICore::self()->documentController()->activeDocument(); 0138 if(!doc) 0139 return; 0140 0141 QUrl url = doc->url(); 0142 IProject* p = ICore::self()->projectController()->findProjectForUrl(url); 0143 QModelIndex idx = (p ? 0144 model()->match(model()->index(0, 0), ProjectChangesModel::UrlRole, 0145 url, 1, Qt::MatchExactly).value(0) : 0146 QModelIndex()); 0147 if(idx.isValid()) { 0148 expand(idx.parent()); 0149 setCurrentIndex(idx); 0150 } else 0151 collapseAll(); 0152 } 0153 0154 void VcsChangesView::setModel(QAbstractItemModel* model) 0155 { 0156 connect(model, &QAbstractItemModel::rowsInserted, this, &VcsChangesView::expand); 0157 QTreeView::setModel(model); 0158 } 0159 0160 void VcsChangesView::openSelected(const QModelIndex& index) 0161 { 0162 if(!index.parent().isValid()) //then it's a project 0163 return; 0164 QModelIndex idx = index.sibling(index.row(), 1); 0165 VcsStatusInfo info = idx.data(ProjectChangesModel::VcsStatusInfoRole).value<VcsStatusInfo>(); 0166 QUrl url = info.url(); 0167 0168 ICore::self()->documentController()->openDocument(url); 0169 } 0170 0171 #include "moc_vcschangesview.cpp"