1 | #include "BranchContextMenu.h" |
2 | |
3 | #include <BranchDlg.h> |
4 | #include <GitBase.h> |
5 | #include <GitBranches.h> |
6 | #include <GitCache.h> |
7 | #include <GitConfig.h> |
8 | #include <GitQlientStyles.h> |
9 | #include <GitRemote.h> |
10 | |
11 | #include <QApplication> |
12 | #include <QClipboard> |
13 | #include <QMessageBox> |
14 | |
15 | #include <utility> |
16 | |
17 | BranchContextMenu::(BranchContextMenuConfig config, QWidget *parent) |
18 | : QMenu(parent) |
19 | , mConfig(std::move(config)) |
20 | { |
21 | setAttribute(Qt::WA_DeleteOnClose); |
22 | |
23 | connect(addAction(tr("Copy name" )), &QAction::triggered, this, |
24 | [this] { QApplication::clipboard()->setText(mConfig.branchSelected); }); |
25 | |
26 | addSeparator(); |
27 | |
28 | if (mConfig.isLocal) |
29 | { |
30 | connect(addAction(tr("Pull" )), &QAction::triggered, this, &BranchContextMenu::pull); |
31 | connect(addAction(tr("Fetch" )), &QAction::triggered, this, &BranchContextMenu::fetch); |
32 | connect(addAction(tr("Push" )), &QAction::triggered, this, &BranchContextMenu::push); |
33 | } |
34 | |
35 | if (mConfig.currentBranch == mConfig.branchSelected) |
36 | connect(addAction(tr("Push force" )), &QAction::triggered, this, &BranchContextMenu::pushForce); |
37 | |
38 | addSeparator(); |
39 | |
40 | connect(addAction(tr("Create branch" )), &QAction::triggered, this, &BranchContextMenu::createBranch); |
41 | connect(addAction(tr("Create && checkout branch" )), &QAction::triggered, this, |
42 | &BranchContextMenu::createCheckoutBranch); |
43 | connect(addAction(tr("Checkout branch" )), &QAction::triggered, this, &BranchContextMenu::signalCheckoutBranch); |
44 | |
45 | if (mConfig.currentBranch != mConfig.branchSelected) |
46 | { |
47 | const auto actionName = tr("Merge %1 into %2" ).arg(mConfig.branchSelected, mConfig.currentBranch); |
48 | connect(addAction(actionName), &QAction::triggered, this, &BranchContextMenu::merge); |
49 | |
50 | const auto mergeSquashAction = tr("Squash-merge %1 into %2" ).arg(mConfig.branchSelected, mConfig.currentBranch); |
51 | connect(addAction(mergeSquashAction), &QAction::triggered, this, &BranchContextMenu::mergeSquash); |
52 | } |
53 | |
54 | addSeparator(); |
55 | |
56 | connect(addAction(tr("Rename" )), &QAction::triggered, this, &BranchContextMenu::rename); |
57 | connect(addAction(tr("Delete" )), &QAction::triggered, this, &BranchContextMenu::deleteBranch); |
58 | } |
59 | |
60 | void BranchContextMenu::() |
61 | { |
62 | QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); |
63 | QScopedPointer<GitRemote> git(new GitRemote(mConfig.mGit)); |
64 | const auto ret = git->pull(); |
65 | QApplication::restoreOverrideCursor(); |
66 | |
67 | if (ret.success) |
68 | emit fullReload(); |
69 | else |
70 | { |
71 | const auto errorMsg = ret.output; |
72 | |
73 | if (errorMsg.contains("error: could not apply" , Qt::CaseInsensitive) |
74 | && errorMsg.contains("causing a conflict" , Qt::CaseInsensitive)) |
75 | { |
76 | emit signalPullConflict(); |
77 | } |
78 | else |
79 | { |
80 | QMessageBox msgBox(QMessageBox::Critical, tr("Error while pulling" ), |
81 | tr("There were problems during the pull operation. Please, see the detailed " |
82 | "description for more information." ), |
83 | QMessageBox::Ok, this); |
84 | msgBox.setDetailedText(errorMsg); |
85 | msgBox.setStyleSheet(GitQlientStyles::getStyles()); |
86 | msgBox.exec(); |
87 | } |
88 | } |
89 | } |
90 | |
91 | void BranchContextMenu::() |
92 | { |
93 | QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); |
94 | QScopedPointer<GitRemote> git(new GitRemote(mConfig.mGit)); |
95 | const auto ret = git->fetch(); |
96 | QApplication::restoreOverrideCursor(); |
97 | |
98 | if (ret) |
99 | { |
100 | emit signalFetchPerformed(); |
101 | emit fullReload(); |
102 | } |
103 | else |
104 | QMessageBox::critical(this, tr("Fetch failed" ), tr("There were some problems while fetching. Please try again." )); |
105 | } |
106 | |
107 | void BranchContextMenu::() |
108 | { |
109 | QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); |
110 | QScopedPointer<GitRemote> git(new GitRemote(mConfig.mGit)); |
111 | const auto ret |
112 | = mConfig.currentBranch == mConfig.branchSelected ? git->push() : git->pushBranch(mConfig.branchSelected); |
113 | QApplication::restoreOverrideCursor(); |
114 | |
115 | if (ret.output.contains("has no upstream branch" )) |
116 | { |
117 | BranchDlg dlg({ mConfig.branchSelected, BranchDlgMode::PUSH_UPSTREAM, mConfig.mCache, mConfig.mGit }); |
118 | dlg.exec(); |
119 | } |
120 | else if (ret.success) |
121 | { |
122 | QScopedPointer<GitConfig> git(new GitConfig(mConfig.mGit)); |
123 | const auto remote = git->getRemoteForBranch(mConfig.branchSelected); |
124 | |
125 | if (remote.success) |
126 | { |
127 | const auto oldSha = mConfig.mCache->getShaOfReference( |
128 | QString("%1/%2" ).arg(remote.output, mConfig.branchSelected), References::Type::RemoteBranches); |
129 | const auto sha = mConfig.mCache->getShaOfReference(mConfig.branchSelected, References::Type::LocalBranch); |
130 | mConfig.mCache->deleteReference(oldSha, References::Type::RemoteBranches, |
131 | QString("%1/%2" ).arg(remote.output, mConfig.branchSelected)); |
132 | mConfig.mCache->insertReference(sha, References::Type::RemoteBranches, |
133 | QString("%1/%2" ).arg(remote.output, mConfig.branchSelected)); |
134 | emit mConfig.mCache->signalCacheUpdated(); |
135 | emit logReload(); |
136 | } |
137 | } |
138 | else |
139 | { |
140 | QMessageBox msgBox(QMessageBox::Critical, tr("Error while pushing" ), |
141 | tr("There were problems during the push operation. Please, see the detailed description " |
142 | "for more information." ), |
143 | QMessageBox::Ok, this); |
144 | msgBox.setDetailedText(ret.output); |
145 | msgBox.setStyleSheet(GitQlientStyles::getStyles()); |
146 | msgBox.exec(); |
147 | } |
148 | } |
149 | |
150 | void BranchContextMenu::() |
151 | { |
152 | QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); |
153 | QScopedPointer<GitRemote> git(new GitRemote(mConfig.mGit)); |
154 | const auto ret = git->push(true); |
155 | QApplication::restoreOverrideCursor(); |
156 | |
157 | if (ret.success) |
158 | { |
159 | emit signalRefreshPRsCache(); |
160 | emit fullReload(); |
161 | } |
162 | else |
163 | { |
164 | QMessageBox msgBox(QMessageBox::Critical, tr("Error while pulling" ), |
165 | tr("There were problems during the pull operation. Please, see the detailed description " |
166 | "for more information." ), |
167 | QMessageBox::Ok, this); |
168 | msgBox.setDetailedText(ret.output); |
169 | msgBox.setStyleSheet(GitQlientStyles::getStyles()); |
170 | msgBox.exec(); |
171 | } |
172 | } |
173 | |
174 | void BranchContextMenu::() |
175 | { |
176 | BranchDlg dlg({ mConfig.branchSelected, BranchDlgMode::CREATE, mConfig.mCache, mConfig.mGit }); |
177 | dlg.exec(); |
178 | } |
179 | |
180 | void BranchContextMenu::() |
181 | { |
182 | BranchDlg dlg({ mConfig.branchSelected, BranchDlgMode::CREATE_CHECKOUT, mConfig.mCache, mConfig.mGit }); |
183 | dlg.exec(); |
184 | } |
185 | |
186 | void BranchContextMenu::() |
187 | { |
188 | emit signalMergeRequired(mConfig.currentBranch, mConfig.branchSelected); |
189 | } |
190 | |
191 | void BranchContextMenu::() |
192 | { |
193 | emit mergeSqushRequested(mConfig.currentBranch, mConfig.branchSelected); |
194 | } |
195 | |
196 | void BranchContextMenu::() |
197 | { |
198 | BranchDlg dlg({ mConfig.branchSelected, BranchDlgMode::RENAME, mConfig.mCache, mConfig.mGit }); |
199 | dlg.exec(); |
200 | } |
201 | |
202 | void BranchContextMenu::() |
203 | { |
204 | if (!mConfig.isLocal && mConfig.branchSelected == "master" ) |
205 | QMessageBox::critical(this, tr("Delete master?!" ), tr("You are not allowed to delete remote master." ), |
206 | QMessageBox::Ok); |
207 | else |
208 | { |
209 | auto ret = QMessageBox::warning(this, tr("Delete branch!" ), tr("Are you sure you want to delete the branch?" ), |
210 | QMessageBox::Ok, QMessageBox::Cancel); |
211 | |
212 | if (ret == QMessageBox::Ok) |
213 | { |
214 | const auto type = mConfig.isLocal ? References::Type::LocalBranch : References::Type::RemoteBranches; |
215 | const auto sha = mConfig.mCache->getShaOfReference(mConfig.branchSelected, type); |
216 | QScopedPointer<GitBranches> git(new GitBranches(mConfig.mGit)); |
217 | QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); |
218 | const auto ret2 = mConfig.isLocal ? git->removeLocalBranch(mConfig.branchSelected) |
219 | : git->removeRemoteBranch(mConfig.branchSelected); |
220 | QApplication::restoreOverrideCursor(); |
221 | |
222 | if (ret2.success) |
223 | { |
224 | mConfig.mCache->deleteReference(sha, type, mConfig.branchSelected); |
225 | emit mConfig.mCache->signalCacheUpdated(); |
226 | emit logReload(); |
227 | } |
228 | else |
229 | QMessageBox::critical( |
230 | this, tr("Delete a branch failed" ), |
231 | tr("There were some problems while deleting the branch:<br><br> %1" ).arg(ret2.output)); |
232 | } |
233 | } |
234 | } |
235 | |