File indexing completed on 2024-04-28 04:38:49
0001 /* 0002 SPDX-FileCopyrightText: 2020 Jonathan L. Verner <jonathan.verner@matfyz.cz> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #ifndef KDEVPLATFORM_PLUGIN_COMMIT_TOOLVIEW_H 0008 #define KDEVPLATFORM_PLUGIN_COMMIT_TOOLVIEW_H 0009 0010 #include "repostatusmodel.h" 0011 0012 #include <interfaces/iuicontroller.h> 0013 0014 #include <KTextEditor/Attribute> 0015 0016 #include <QWidget> 0017 0018 class ActiveStyledDelegate; 0019 class DiffViewsCtrl; 0020 class FilterEmptyItemsProxyModel; 0021 class RepoStatusModel; 0022 class SimpleCommitForm; 0023 0024 class QAction; 0025 class QMenu; 0026 class QModelIndex; 0027 class QLineEdit; 0028 class QTreeView; 0029 class QAbstractProxyModel; 0030 class QUrl; 0031 0032 namespace KDevelop { 0033 class IBasicVersionControl; 0034 class IDocument; 0035 class IProject; 0036 class VcsJob; 0037 } 0038 0039 namespace KTextEditor { 0040 class View; 0041 class Document; 0042 } 0043 0044 /** 0045 * This implements the git-cola like toolview for preparing commits. 0046 * 0047 * The view contains a list of projects. Each project contains four 0048 * lists: 0049 * 0050 * - the staged changes list lists all files in the project which 0051 * have changes staged for commit; 0052 * - the unstaged changes list lists all files in the project which 0053 * have changes which are not currently staged for commit; 0054 * - the conflicts list lists all files which have unresolved (merge) 0055 * conflicts; and 0056 * - the untracked list which lists all files not tracked in the VCS 0057 * 0058 * Clicking on a file in one of the staged/unstaged lists opens a document 0059 * tab with the diff showing the changes. The user can then select lines/hunks 0060 * from the diff and remove/add them from the staged changes using the context menu. 0061 * 0062 * Double clicking on a file will, instead, stage/unstage all changes in the file 0063 * or mark the conflicts as resolved or add the file to be tracked in VCS. 0064 * 0065 * Above these lists a lineedit and a textedit may be used to prepare a 0066 * commit message. The commit button will commit the staged changes to the 0067 * repo. If several projects are listed, the one which is expanded will be 0068 * used (only one project is allowed to be expaned to show the lists at a time, 0069 * an expaned project is automatically collapsed when a different one is expanded). 0070 * 0071 * @author Jonathan L. Verner <jonathan.verner@matfyz.cz> 0072 */ 0073 0074 class CommitToolView : public QWidget 0075 { 0076 Q_OBJECT 0077 0078 public: 0079 enum ShowDiffParams { Activate, NoActivate }; 0080 0081 /** 0082 * @note: m_statusmodel remains the property of the caller whose 0083 * responsibility is to delete it (and care must be taken not 0084 * to delete it before the CommitToolView is deleted) 0085 */ 0086 CommitToolView(QWidget* parent, RepoStatusModel* m_statusmodel); 0087 ~CommitToolView() override; 0088 0089 /** 0090 * @returns the currently active project (i.e. the one that 0091 * is expanded in the treeview) 0092 */ 0093 KDevelop::IProject* activeProject() const; 0094 0095 /** 0096 * @returns the index of the currently active project (i.e. the one that 0097 * is expanded in the treeview) 0098 */ 0099 QStandardItem* activeProjectItem() const; 0100 0101 /** 0102 * @returns true if the item pointed to by the repostatusmodel index 0103 * idx is the root item of the currently active project. 0104 */ 0105 bool isActiveProject(const QModelIndex& idx) const; 0106 0107 Q_SIGNALS: 0108 0109 /** 0110 * This signal is emitted when the view wants to show a diff 0111 * 0112 * @param url the url to display the changes for 0113 * @param area the type of changes to display 0114 */ 0115 void showDiff(const QUrl& url, const RepoStatusModel::Areas area); 0116 0117 /** 0118 * This signal is emitted when the view wants to show a file 0119 * 0120 * @param url the url of the file to show 0121 */ 0122 void showSource(const QUrl& url); 0123 0124 /** 0125 * This signal is emitted when the diff showing changes of type @param area 0126 * to the file @param url needs to be updated. 0127 */ 0128 void updateDiff(const QUrl& url, const RepoStatusModel::Areas area); 0129 0130 /** 0131 * This signal is emitted when all diffs showing changes to files in 0132 * project @param project need to be updated. 0133 */ 0134 void updateProjectDiffs(KDevelop::IProject* project); 0135 0136 /** 0137 * This signal is emitted when all diffs showing changes to the file 0138 * @param url need to be updated. 0139 * 0140 * @note: In contrast to the updateDiff signal, this also includes diffs 0141 * showing all changes to the owning project (staged/unstaged) 0142 */ 0143 void updateUrlDiffs(const QUrl& url); 0144 0145 public Q_SLOTS: 0146 /** 0147 * Shows the toolview context menu 0148 */ 0149 void popupContextMenu(const QPoint& pos); 0150 0151 /** 0152 * A handler called when the user double clicks 0153 * an item in the treeview. 0154 */ 0155 void dblClicked(const QModelIndex& idx); 0156 0157 /** 0158 * A handler called when the user clicks an item 0159 * in the treeview. 0160 */ 0161 void clicked(const QModelIndex& idx); 0162 0163 /** 0164 * A handler called when a user expands an item 0165 * in the treeview. 0166 */ 0167 void activateProject(const QModelIndex& idx); 0168 0169 /** 0170 * Stages the staged changes in the given files. 0171 * 0172 * @param urls the list of files whose changes to stage 0173 */ 0174 void stageSelectedFiles(const QList<QUrl>& urls); 0175 0176 /** 0177 * Unstages the staged changes in the given files. 0178 * 0179 * @param urls the list of files whose changes to unstage 0180 */ 0181 void unstageSelectedFiles(const QList<QUrl>& urls); 0182 0183 /** 0184 * Reverts the uncommited changes in the given files. 0185 * 0186 * @param urls the list of files whose changes to revert 0187 * 0188 * @note: This is an irreversible and dangerous action, 0189 * a confirmation dialog is shown before it is applied 0190 */ 0191 void revertSelectedFiles(const QList<QUrl>& urls); 0192 0193 /** 0194 * Runs git commit on the staged changes. The commit message 0195 * is constructed from the data in the commit form. 0196 * 0197 * @note This function assumes that there are some staged changes. 0198 * @note The extended description of the commit is wrapped at 70 columns 0199 */ 0200 void commitActiveProject(); 0201 0202 private: 0203 0204 /* Describes an action on selected lines/hunk in a diff */ 0205 enum ApplyAction { 0206 Stage, 0207 Unstage, 0208 Revert, 0209 }; 0210 0211 /** 0212 * Updates the toolview layout based on the dock area position: 0213 * 0214 * When the toolview is placed on the left/right, all the widgets 0215 * sit on top of each other; when it is placed on the top/bottom, 0216 * the commit area (commit header, button, description textedit) 0217 * will sit to the left of the changes view with the search filter. 0218 */ 0219 0220 void doLayOut(const Qt::DockWidgetArea area); 0221 0222 /** 0223 * A helper function which return the VCS plugin which 0224 * handles `url`. 0225 * 0226 * @param url the url for which the plugin is returned 0227 * 0228 * @note: Returns nullptr if no project/VCS plugin for the 0229 * given url exists. 0230 */ 0231 KDevelop::IBasicVersionControl* vcsPluginForUrl(const QUrl& url) const; 0232 0233 /** 0234 * The model which lists the projects and staged/modified/... files 0235 * which are shown in the treeview. 0236 */ 0237 RepoStatusModel* m_statusmodel; 0238 0239 /** 0240 * The filtered repostatus model 0241 */ 0242 FilterEmptyItemsProxyModel* m_proxymodel; 0243 0244 /** The form for composing the commit message and doing the commit. */ 0245 SimpleCommitForm* m_commitForm = nullptr; 0246 0247 /** The treeview listing the projects & their staged/modified/... files */ 0248 QTreeView* m_view = nullptr; 0249 0250 /** The lineedit for filtering the treeview */ 0251 QLineEdit* m_filter = nullptr; 0252 0253 /**************************************** 0254 * Various contextmenus & their actions * 0255 ****************************************/ 0256 0257 QMenu 0258 /** Menu with a single "Refresh" action (shown for projects in the toolview) */ 0259 *m_refreshMenu 0260 /** Menu with stage/unstage/revert actions (shown for files in the toolview) */ 0261 , *m_toolviewMenu 0262 ; 0263 QAction *m_refreshModelAct 0264 , *m_stageFilesAct 0265 , *m_unstageFilesAct 0266 , *m_revertFilesAct 0267 ; 0268 0269 /** A style delegate for showing the currently selected project in bold */ 0270 ActiveStyledDelegate* m_styleDelegate; 0271 }; 0272 0273 /** 0274 * A factory for creating CommitToolViews. 0275 */ 0276 class CommitToolViewFactory : public KDevelop::IToolViewFactory 0277 { 0278 public: 0279 explicit CommitToolViewFactory(RepoStatusModel* statusModel); 0280 ~CommitToolViewFactory(); 0281 QWidget* create(QWidget* parent = nullptr) override; 0282 Qt::DockWidgetArea defaultPosition() const override; 0283 QString id() const override; 0284 0285 private: 0286 RepoStatusModel* m_statusmodel; 0287 DiffViewsCtrl* m_diffViewsCtrl; 0288 }; 0289 0290 #endif