1 | #include "InitScreen.h" |
2 | |
3 | #include <GeneralConfigDlg.h> |
4 | #include <CreateRepoDlg.h> |
5 | #include <ProgressDlg.h> |
6 | #include <GitQlientSettings.h> |
7 | #include <GitBase.h> |
8 | #include <GitConfig.h> |
9 | #include <ButtonLink.hpp> |
10 | |
11 | #include <QPushButton> |
12 | #include <QGridLayout> |
13 | #include <QFileDialog> |
14 | #include <QButtonGroup> |
15 | #include <QStackedWidget> |
16 | #include <QStyle> |
17 | #include <QLabel> |
18 | #include <QApplication> |
19 | #include <QMessageBox> |
20 | #include <QtGlobal> |
21 | #include <QDesktopServices> |
22 | #include <GitQlientStyles.h> |
23 | |
24 | #include <QLogger.h> |
25 | |
26 | using namespace QLogger; |
27 | |
28 | InitScreen::InitScreen(QWidget *parent) |
29 | : QFrame(parent) |
30 | , mOpenRepo(new QPushButton(tr("OPEN" ))) |
31 | , mCloneRepo(new QPushButton(tr("CLONE" ))) |
32 | , mInitRepo(new QPushButton(tr("NEW" ))) |
33 | { |
34 | setAttribute(Qt::WA_DeleteOnClose); |
35 | |
36 | setStyleSheet(GitQlientStyles::getStyles()); |
37 | |
38 | mOpenRepo->setObjectName("bigButton" ); |
39 | mCloneRepo->setObjectName("bigButton" ); |
40 | mInitRepo->setObjectName("bigButton" ); |
41 | |
42 | // Adding buttons to open or init repos |
43 | const auto repoOptionsFrame = new QFrame(); |
44 | const auto repoOptionsLayout = new QHBoxLayout(repoOptionsFrame); |
45 | repoOptionsLayout->setSpacing(0); |
46 | repoOptionsLayout->setContentsMargins(QMargins()); |
47 | repoOptionsLayout->addWidget(mOpenRepo); |
48 | repoOptionsLayout->addStretch(); |
49 | repoOptionsLayout->addWidget(mCloneRepo); |
50 | repoOptionsLayout->addStretch(); |
51 | repoOptionsLayout->addWidget(mInitRepo); |
52 | |
53 | const auto projectsFrame = new QFrame(); |
54 | mRecentProjectsLayout = new QVBoxLayout(projectsFrame); |
55 | mRecentProjectsLayout->setContentsMargins(QMargins()); |
56 | mRecentProjectsLayout->addWidget(createRecentProjectsPage()); |
57 | |
58 | const auto mostUsedProjectsFrame = new QFrame(); |
59 | mUsedProjectsLayout = new QVBoxLayout(mostUsedProjectsFrame); |
60 | mUsedProjectsLayout->setContentsMargins(QMargins()); |
61 | mUsedProjectsLayout->addWidget(createUsedProjectsPage()); |
62 | |
63 | const auto widgetsLayout = new QHBoxLayout(); |
64 | widgetsLayout->setSpacing(10); |
65 | widgetsLayout->setContentsMargins(0, 10, 0, 10); |
66 | widgetsLayout->addWidget(projectsFrame); |
67 | widgetsLayout->addStretch(); |
68 | widgetsLayout->addWidget(mostUsedProjectsFrame); |
69 | |
70 | const auto title = new QLabel(tr("GitQlient %1" ).arg(VER)); |
71 | title->setObjectName("title" ); |
72 | |
73 | const auto gitqlientIcon = new QLabel(); |
74 | QIcon stagedIcon(":/icons/GitQlientLogoSVG" ); |
75 | gitqlientIcon->setPixmap(stagedIcon.pixmap(96, 96)); |
76 | |
77 | const auto configBtn = new QPushButton(); |
78 | configBtn->setIcon(QIcon(":/icons/config" )); |
79 | connect(configBtn, &QPushButton::clicked, this, &InitScreen::openConfigDlg); |
80 | |
81 | const auto titleLayout = new QHBoxLayout(); |
82 | titleLayout->setContentsMargins(QMargins()); |
83 | titleLayout->setSpacing(10); |
84 | titleLayout->addStretch(); |
85 | titleLayout->addWidget(gitqlientIcon); |
86 | titleLayout->addWidget(title); |
87 | titleLayout->addStretch(); |
88 | titleLayout->addWidget(configBtn); |
89 | |
90 | const auto lineTitle = new QFrame(); |
91 | lineTitle->setObjectName("orangeHSeparator" ); |
92 | |
93 | const auto lineTitle2 = new QFrame(); |
94 | lineTitle2->setObjectName("orangeHSeparator" ); |
95 | |
96 | const auto version = new ButtonLink(tr("About GitQlient..." )); |
97 | connect(version, &ButtonLink::clicked, this, &InitScreen::showAbout); |
98 | version->setToolTip(QString("%1" ).arg(SHA_VER)); |
99 | |
100 | const auto goToRepo = new ButtonLink(tr("Source code" )); |
101 | connect(goToRepo, &ButtonLink::clicked, this, |
102 | []() { QDesktopServices::openUrl(QUrl("https://www.github.com/francescmm/GitQlient" )); }); |
103 | goToRepo->setToolTip(tr("Get the source code in GitHub" )); |
104 | |
105 | const auto goToBlog = new ButtonLink(tr("Report an issue" )); |
106 | connect(goToBlog, &ButtonLink::clicked, this, |
107 | []() { QDesktopServices::openUrl(QUrl("https://github.com/francescmm/GitQlient/issues/new/choose" )); }); |
108 | goToBlog->setToolTip(tr("Report an issue in GitHub" )); |
109 | |
110 | const auto promoLayout = new QHBoxLayout(); |
111 | promoLayout->setContentsMargins(QMargins()); |
112 | promoLayout->setSpacing(0); |
113 | promoLayout->addWidget(version); |
114 | promoLayout->addStretch(); |
115 | promoLayout->addWidget(goToRepo); |
116 | promoLayout->addStretch(); |
117 | promoLayout->addWidget(goToBlog); |
118 | |
119 | const auto centerFrame = new QFrame(); |
120 | centerFrame->setObjectName("InitWidget" ); |
121 | const auto centerLayout = new QVBoxLayout(centerFrame); |
122 | centerLayout->setSpacing(10); |
123 | centerLayout->setContentsMargins(QMargins()); |
124 | centerLayout->addLayout(titleLayout); |
125 | centerLayout->addWidget(lineTitle); |
126 | centerLayout->addWidget(repoOptionsFrame); |
127 | centerLayout->addLayout(widgetsLayout); |
128 | centerLayout->addWidget(lineTitle2); |
129 | centerLayout->addLayout(promoLayout); |
130 | centerLayout->addStretch(); |
131 | |
132 | const auto layout = new QGridLayout(this); |
133 | layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding), 0, 0); |
134 | layout->addWidget(centerFrame, 1, 1); |
135 | layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding), 2, 2); |
136 | |
137 | connect(mOpenRepo, &QPushButton::clicked, this, &InitScreen::openRepo); |
138 | connect(mCloneRepo, &QPushButton::clicked, this, &InitScreen::cloneRepo); |
139 | connect(mInitRepo, &QPushButton::clicked, this, &InitScreen::initRepo); |
140 | |
141 | const auto gitBase(QSharedPointer<GitBase>::create("" )); |
142 | mGit = QSharedPointer<GitConfig>::create(gitBase); |
143 | |
144 | connect(mGit.data(), &GitConfig::signalCloningProgress, this, &InitScreen::updateProgressDialog, |
145 | Qt::DirectConnection); |
146 | connect(mGit.data(), &GitConfig::signalCloningFailure, this, &InitScreen::showError, Qt::DirectConnection); |
147 | } |
148 | |
149 | void InitScreen::openRepo() |
150 | { |
151 | const QString dirName(QFileDialog::getExistingDirectory(this, "Choose the directory of a Git project" )); |
152 | |
153 | if (!dirName.isEmpty()) |
154 | { |
155 | QDir d(dirName); |
156 | emit signalOpenRepo(d.absolutePath()); |
157 | } |
158 | } |
159 | |
160 | void InitScreen::cloneRepo() |
161 | { |
162 | CreateRepoDlg cloneDlg(CreateRepoDlgType::CLONE, mGit, this); |
163 | connect(&cloneDlg, &CreateRepoDlg::signalOpenWhenFinish, this, [this](const QString &path) { mPathToOpen = path; }); |
164 | |
165 | if (cloneDlg.exec() == QDialog::Accepted) |
166 | { |
167 | mProgressDlg = new ProgressDlg(tr("Loading repository..." ), QString(), 100, false); |
168 | connect(mProgressDlg, &ProgressDlg::destroyed, this, [this]() { mProgressDlg = nullptr; }); |
169 | mProgressDlg->show(); |
170 | } |
171 | } |
172 | |
173 | void InitScreen::initRepo() |
174 | { |
175 | CreateRepoDlg cloneDlg(CreateRepoDlgType::INIT, mGit, this); |
176 | connect(&cloneDlg, &CreateRepoDlg::signalOpenWhenFinish, this, &InitScreen::signalOpenRepo); |
177 | cloneDlg.exec(); |
178 | } |
179 | |
180 | QWidget *InitScreen::createRecentProjectsPage() |
181 | { |
182 | delete mInnerWidget; |
183 | mInnerWidget = new QFrame(); |
184 | |
185 | auto title = new QLabel(tr("Recent" )); |
186 | title->setStyleSheet("font-size: 14pt;" ); |
187 | |
188 | const auto innerLayout = new QVBoxLayout(mInnerWidget); |
189 | innerLayout->setContentsMargins(QMargins()); |
190 | innerLayout->setSpacing(10); |
191 | innerLayout->addWidget(title); |
192 | |
193 | const auto projects = GitQlientSettings().getRecentProjects(); |
194 | |
195 | for (auto project : projects) |
196 | { |
197 | const auto projectName = project.mid(project.lastIndexOf("/" ) + 1); |
198 | const auto labelText = QString("%1<br><em>%2</em>" ).arg(projectName, project); |
199 | const auto clickableFrame = new ButtonLink(labelText, this); |
200 | connect(clickableFrame, &ButtonLink::clicked, this, [this, project]() { emit signalOpenRepo(project); }); |
201 | innerLayout->addWidget(clickableFrame); |
202 | } |
203 | |
204 | innerLayout->addStretch(); |
205 | |
206 | const auto clear = new ButtonLink(tr("Clear list" )); |
207 | clear->setVisible(!projects.isEmpty()); |
208 | connect(clear, &ButtonLink::clicked, this, [this]() { |
209 | GitQlientSettings().clearRecentProjects(); |
210 | |
211 | mRecentProjectsLayout->addWidget(createRecentProjectsPage()); |
212 | }); |
213 | |
214 | const auto lineTitle = new QFrame(); |
215 | lineTitle->setObjectName("separator" ); |
216 | |
217 | innerLayout->addWidget(lineTitle); |
218 | innerLayout->addWidget(clear); |
219 | |
220 | return mInnerWidget; |
221 | } |
222 | |
223 | QWidget *InitScreen::createUsedProjectsPage() |
224 | { |
225 | delete mMostUsedInnerWidget; |
226 | mMostUsedInnerWidget = new QFrame(); |
227 | |
228 | auto title = new QLabel(tr("Most used" )); |
229 | title->setStyleSheet("font-size: 14pt;" ); |
230 | |
231 | const auto innerLayout = new QVBoxLayout(mMostUsedInnerWidget); |
232 | innerLayout->setContentsMargins(QMargins()); |
233 | innerLayout->setSpacing(10); |
234 | innerLayout->addWidget(title); |
235 | |
236 | const auto projects = GitQlientSettings().getMostUsedProjects(); |
237 | |
238 | for (auto project : projects) |
239 | { |
240 | const auto projectName = project.mid(project.lastIndexOf("/" ) + 1); |
241 | const auto labelText = QString("%1<br><em>%2</em>" ).arg(projectName, project); |
242 | const auto clickableFrame = new ButtonLink(labelText); |
243 | connect(clickableFrame, &ButtonLink::clicked, this, [this, project]() { emit signalOpenRepo(project); }); |
244 | innerLayout->addWidget(clickableFrame); |
245 | } |
246 | |
247 | innerLayout->addStretch(); |
248 | |
249 | const auto clear = new ButtonLink(tr("Clear list" )); |
250 | clear->setVisible(!projects.isEmpty()); |
251 | connect(clear, &ButtonLink::clicked, this, [this]() { |
252 | GitQlientSettings().clearMostUsedProjects(); |
253 | |
254 | mUsedProjectsLayout->addWidget(createUsedProjectsPage()); |
255 | }); |
256 | |
257 | const auto lineTitle = new QFrame(); |
258 | lineTitle->setObjectName("separator" ); |
259 | |
260 | innerLayout->addWidget(lineTitle); |
261 | innerLayout->addWidget(clear); |
262 | |
263 | return mMostUsedInnerWidget; |
264 | } |
265 | |
266 | void InitScreen::updateProgressDialog(QString stepDescription, int value) |
267 | { |
268 | if (value >= 0) |
269 | { |
270 | mProgressDlg->setValue(value); |
271 | |
272 | if (stepDescription.contains("done" , Qt::CaseInsensitive)) |
273 | { |
274 | mProgressDlg->close(); |
275 | emit signalOpenRepo(mPathToOpen); |
276 | |
277 | mPathToOpen = "" ; |
278 | } |
279 | } |
280 | |
281 | mProgressDlg->setLabelText(stepDescription); |
282 | mProgressDlg->repaint(); |
283 | } |
284 | |
285 | void InitScreen::showError(int, QString description) |
286 | { |
287 | if (mProgressDlg) |
288 | mProgressDlg->deleteLater(); |
289 | |
290 | QMessageBox::critical(this, tr("Error!" ), description); |
291 | } |
292 | |
293 | void InitScreen::showAbout() |
294 | { |
295 | const QString aboutMsg = tr( |
296 | "GitQlient, pronounced as git+client (/gɪtˈklaɪənt/) is a multi-platform Git client. " |
297 | "With GitQlient you will be able to add commits, branches and manage all the options Git provides. <br><br>" |
298 | "Once a fork of QGit, GitQlient has followed is own path. " |
299 | "You can download the code from <a href='https://github.com/francescmm/GitQlient'>GitHub</a>. If you find any " |
300 | "bug or problem, please report it in <a href='https://github.com/francescmm/GitQlient/issues'>the issues " |
301 | "page</a> so I can fix it as soon as possible.<br><br>" |
302 | "If you want to integrate GitQlient into QtCreator, I also provide a plugin that you can download from " |
303 | "<a href='https://github.com/francescmm/GitQlient/releases'>here</a>. Just make sure you pick the right " |
304 | "version and follow the instructions in the main page of the repo.<br><br>" |
305 | "GitQlient can be compiled from Qt 5.12 on.<br><br>" |
306 | "Copyright © 2019 - 2020 GitQlient (Francesc Martínez)" ); |
307 | |
308 | QMessageBox::about(this, tr("About GitQlient v%1" ).arg(VER), aboutMsg); |
309 | } |
310 | |
311 | void InitScreen::openConfigDlg() |
312 | { |
313 | GeneralConfigDlg dlg; |
314 | dlg.exec(); |
315 | } |
316 | |
317 | void InitScreen::onRepoOpened() |
318 | { |
319 | mRecentProjectsLayout->addWidget(createRecentProjectsPage()); |
320 | mUsedProjectsLayout->addWidget(createUsedProjectsPage()); |
321 | } |
322 | |