1#pragma once
2
3/****************************************************************************************
4 ** GitQlient is an application to manage and operate one or several Git repositories. With
5 ** GitQlient you will be able to add commits, branches and manage all the options Git provides.
6 ** Copyright (C) 2021 Francesc Martinez
7 **
8 ** LinkedIn: www.linkedin.com/in/cescmm/
9 ** Web: www.francescmm.com
10 **
11 ** This program is free software; you can redistribute it and/or
12 ** modify it under the terms of the GNU Lesser General Public
13 ** License as published by the Free Software Foundation; either
14 ** version 2 of the License, or (at your option) any later version.
15 **
16 ** This program is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ** Lesser General Public License for more details.
20 **
21 ** You should have received a copy of the GNU Lesser General Public
22 ** License along with this library; if not, write to the Free Software
23 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 ***************************************************************************************/
25
26#include <QFrame>
27
28class GitCache;
29class GitBase;
30class CommitHistoryModel;
31class CommitHistoryView;
32class QLineEdit;
33class BranchesWidget;
34class QStackedWidget;
35class CommitChangesWidget;
36class CommitInfoWidget;
37class CheckBox;
38class RepositoryViewDelegate;
39class FullDiffWidget;
40class FileDiffWidget;
41class BranchesWidgetMinimal;
42class QPushButton;
43class GitServerCache;
44class QLabel;
45class GitQlientSettings;
46class QSplitter;
47struct GitExecResult;
48
49/*!
50 \brief The HistoryWidget is responsible for showing the history of the repository. It is the first widget shown
51 when a repository is open and manages all the signals from its subwidgets to the GitQlientRepo class. It also creates
52 the layout and acts as a bridge to transfer the signals from one subwidget to the other.
53
54 The layout is formed by four important widgets:
55 - In the left side two different widgets are shown depending on the conditions. If the user selects the Work In
56 Progress (WIP) commit, the WorkInProgressWidget will be shown. In case it's any another commit, the CommitWidgetInfo
57 will be shown.
58 - In the center is located the repository view with the graph tree and the commits information.
59 - In the right side the BranchWidget is shown where the user has control of everything related with branches, tags,
60 stashes and submodules.
61
62*/
63class HistoryWidget : public QFrame
64{
65 Q_OBJECT
66
67signals:
68 void fullReload();
69
70 void referencesReload();
71
72 void logReload();
73
74 /*!
75 \brief Signal triggered when the user wants to see the diff of the selected SHA compared to its first parent.
76
77 \param sha The selected commit SHA.
78 */
79 void signalOpenDiff(const QString &sha);
80 /*!
81 \brief Signal triggered when the user wants to see the diff between two different commits.
82
83 \param sha The list of SHAs to compare.
84 */
85 void signalOpenCompareDiff(const QStringList &sha);
86 /*!
87 \brief Signal triggered when the user opens a new submodule. It is necessary to propagate this signal since is the
88 GitQlient class the responsible of opening a new tab for the submodule.
89
90 \param submodule The submodule to be opened.
91 */
92 void signalOpenSubmodule(const QString &submodule);
93 /*!
94 \brief Signal triggered when the user wants to see the diff of a file between two commits.
95
96 \param sha The base commit SHA.
97 \param parentSha The commit SHA to compare to.
98 \param fileName The file name for the diff.
99 */
100 void signalShowDiff(const QString &sha, const QString &parentSha, const QString &fileName, bool isCached);
101
102 /*!
103 \brief Signal triggered when changes are committed.
104
105 \param commited True if there was no error, false otherwise.
106 */
107 void changesCommitted();
108 /*!
109 \brief Signal triggered when the user wants to see the History & Blame for a specific file.
110
111 \param fileName The file name.
112 */
113 void signalShowFileHistory(const QString &fileName);
114 /*!
115 \brief Signal triggered when toggles the option of seeing all the branches in the repository graph view.
116
117 \param showAll True to show all the branches, false if only the current branch must be shown.
118 */
119 void signalAllBranchesActive(bool showAll);
120 /*!
121 \brief Signal triggered when the user performs a merge and it contains conflicts.
122 */
123 void signalMergeConflicts();
124 /*!
125 * \brief signalConflict Signal triggered when trying to cherry-pick or pull and a conflict happens.
126 */
127 void signalCherryPickConflict(const QStringList &pendingShas);
128 /*!
129 * \brief signalPullConflict Signal triggered when trying to pull and a conflict happens.
130 */
131 void signalPullConflict();
132 /*!
133 \brief Signal triggered when the WIP needs to be updated.
134 */
135 void signalUpdateWip();
136 /**
137 * @brief showPrDetailedView Signal that makes the view change to the Pull Request detailed view
138 * @param pr The pull request number to show.
139 */
140 void showPrDetailedView(int pr);
141
142 /**
143 * @brief panelsVisibilityChanged Signal triggered whenever the visibility of the panels in the BranchesWidget
144 * changes.
145 */
146 void panelsVisibilityChanged();
147
148public:
149 /*!
150 \brief Default constructor.
151
152 \param cache The internal repository cache.
153 \param git The git object to perform Git operations.
154 \param parent The parent widget if needed.
155 */
156 explicit HistoryWidget(const QSharedPointer<GitCache> &cache, const QSharedPointer<GitBase> git,
157 const QSharedPointer<GitServerCache> &gitServerCache,
158 const QSharedPointer<GitQlientSettings> &settings, QWidget *parent = nullptr);
159 /*!
160 \brief Destructor.
161
162 */
163 ~HistoryWidget();
164 /*!
165 \brief Clears all the information in the subwidgets.
166
167 */
168 void clear();
169 /*!
170 \brief Resets the WIP widget.
171
172 */
173 void resetWip();
174
175 /**
176 * @brief loadBranches Loads the information on the branches widget: branches, tags, stashes and submodules.
177 * @brief fullReload Indicates that the information on the panel should be fully reloaded, otherwise only refreshes
178 * the link to the current branch.
179 */
180 void loadBranches(bool fullReload);
181
182 /*!
183 \brief If the current view is the WIP widget, updates it.
184
185 */
186 void updateUiFromWatcher();
187 /*!
188 \brief Focuses on the given commit.
189
190 \param sha The commit SHA to focus the view in.
191 */
192 void focusOnCommit(const QString &sha);
193 /*!
194 \brief Configures the CommitInfoWidget or the WorkInProgress widget depending on the given SHA. It sets the
195 configured widget to visible.
196
197 \param goToSha The SHA to show.
198 */
199 void selectCommit(const QString &goToSha);
200
201 /*!
202 \brief Reloads the history model of the repository graph view when it finishes the loading process.
203
204 \param totalCommits The new total of commits to show in the graph.
205 */
206 void updateGraphView(int totalCommits);
207
208 /**
209 * @brief onCommitTitleMaxLenghtChanged Changes the maximum length of the commit title.
210 */
211 void onCommitTitleMaxLenghtChanged();
212
213 /**
214 * @brief onPanelsVisibilityChaned Reloads the visibility configuration of the panels in the BranchesWidget.
215 */
216 void onPanelsVisibilityChanged();
217
218protected:
219 void keyPressEvent(QKeyEvent *event) override;
220 void keyReleaseEvent(QKeyEvent *event) override;
221
222private:
223 enum class Pages
224 {
225 Graph,
226 FileDiff,
227 FullDiff
228 };
229
230 QSharedPointer<GitBase> mGit;
231 QSharedPointer<GitCache> mCache;
232 QSharedPointer<GitServerCache> mGitServerCache;
233 QSharedPointer<GitQlientSettings> mSettings;
234 CommitHistoryModel *mRepositoryModel = nullptr;
235 CommitHistoryView *mRepositoryView = nullptr;
236 BranchesWidget *mBranchesWidget = nullptr;
237 QLineEdit *mSearchInput = nullptr;
238 QStackedWidget *mCommitStackedWidget = nullptr;
239 QStackedWidget *mCenterStackedWidget = nullptr;
240 CommitChangesWidget *mWipWidget = nullptr;
241 CommitChangesWidget *mAmendWidget = nullptr;
242 CommitInfoWidget *mCommitInfoWidget = nullptr;
243 CheckBox *mChShowAllBranches = nullptr;
244 RepositoryViewDelegate *mItemDelegate = nullptr;
245 QFrame *mGraphFrame = nullptr;
246 FileDiffWidget *mFileDiff = nullptr;
247 FullDiffWidget *mFullDiffWidget = nullptr;
248 QPushButton *mReturnFromFull = nullptr;
249 QLabel *mUserName = nullptr;
250 QLabel *mUserEmail = nullptr;
251 bool mReverseSearch = false;
252 QSplitter *mSplitter = nullptr;
253
254 /*!
255 \brief Performs a search based on the input of the search QLineEdit with the users input.
256
257 */
258 void search();
259 /*!
260 \brief Goes to the selected SHA.
261
262 \param sha The selected SHA.
263 */
264 void goToSha(const QString &sha);
265 /*!
266 \brief Retrieves the SHA from the QModelIndex from the repository graph model when the user clicks over an item.
267 Then, performs the \ref onCommitSelected action.
268
269 \param index The index from the model.
270 */
271 void commitSelected(const QModelIndex &index);
272 /*!
273 \brief Action that stores in the settings the new value for the check box to show all the branches. It also triggers
274 the \ref signalAllBranchesActive signal.
275
276 \param showAll True to show all branches, false to show only the current branch.
277 */
278 void onShowAllUpdated(bool showAll);
279
280 /*!
281 \brief Opens the AmendWidget.
282
283 \param sha The commit SHA to amend.
284 */
285 void onAmendCommit(const QString &sha);
286
287 /*!
288 \brief Tries to perform the git merge operation from \p branchToMerge into the \p current. If there are conflicts
289 the GitQlientRepo class is notified to take actions.
290
291 \param current The current branch.
292 \param branchToMerge The branch to merge from.
293 */
294 void mergeBranch(const QString &current, const QString &branchToMerge);
295
296 /**
297 * @brief mergeSquashBranch Tries to perform the git merge operation squashing all commits from \p branchToMerge into
298 the \p current. If there are conflicts the GitQlientRepo class is notified to take actions.
299 * @param current The current branch
300 * @param branchToMerge The branch to merge from
301 */
302 void mergeSquashBranch(const QString &current, const QString &branchToMerge);
303
304 void processMergeResponse(const GitExecResult &ret);
305
306 /**
307 * @brief endEditFile Closes the file diff view.
308 */
309 void returnToView();
310
311 /**
312 * @brief cherryPickCommit Cherry-picks the commit defined by the SHA in the QLineEdit of the filter.
313 */
314 void cherryPickCommit();
315
316 /**
317 * @brief showFileDiff Shows the file diff.
318 * @param sha The base commit SHA.
319 * @param parentSha The commit SHA to compare with.
320 * @param fileName The file name to diff.
321 */
322 void showFileDiff(const QString &sha, const QString &parentSha, const QString &fileName, bool isCached);
323
324 /**
325 * @brief showFileDiff Shows the file diff.
326 * @param sha The base commit SHA.
327 * @param parentSha The commit SHA to compare with.
328 * @param fileName The file name to diff.
329 */
330 void showFileDiffEdition(const QString &sha, const QString &parentSha, const QString &fileName);
331
332 /**
333 * @brief showFullDiff Shows the full commit diff.
334 * @param sha The base commit SHA.
335 * @param parentSha The commit SHA to compare with.
336 */
337 void onOpenFullDiff(const QString &sha);
338
339 void rearrangeSplittrer(bool minimalActive);
340
341 void cleanCommitPanels();
342
343 void onRevertedChanges();
344};
345