1#include "ConfigWidget.h"
2#include "ui_ConfigWidget.h"
3
4#include <FileEditor.h>
5#include <GitBase.h>
6#include <GitQlientSettings.h>
7#include <QLogger.h>
8
9#include <CredentialsDlg.h>
10#include <GitConfig.h>
11#include <GitCredentials.h>
12#include <QDir>
13#include <QFileInfo>
14#include <QMessageBox>
15#include <QProcess>
16#include <QPushButton>
17#include <QStandardPaths>
18#include <QTimer>
19
20using namespace QLogger;
21
22namespace
23{
24qint64 dirSize(QString dirPath)
25{
26 qint64 size = 0;
27 QDir dir(dirPath);
28
29 auto entryList = dir.entryList(QDir::Files | QDir::System | QDir::Hidden);
30
31 for (const auto &filePath : qAsConst(entryList))
32 {
33 QFileInfo fi(dir, filePath);
34 size += fi.size();
35 }
36
37 entryList = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden);
38
39 for (const auto &childDirPath : qAsConst(entryList))
40 size += dirSize(dirPath + QDir::separator() + childDirPath);
41
42 return size;
43}
44}
45
46ConfigWidget::ConfigWidget(const QSharedPointer<GitBase> &git, QWidget *parent)
47 : QWidget(parent)
48 , ui(new Ui::ConfigWidget)
49 , mGit(git)
50 , mFeedbackTimer(new QTimer())
51 , mSave(new QPushButton())
52{
53 ui->setupUi(this);
54
55 mFeedbackTimer->setInterval(3000);
56
57 mSave->setIcon(QIcon(":/icons/save"));
58 mSave->setToolTip(tr("Save"));
59 connect(mSave, &QPushButton::clicked, this, &ConfigWidget::saveFile);
60 ui->tabWidget->setCornerWidget(mSave);
61
62 ui->mainLayout->setColumnStretch(0, 1);
63 ui->mainLayout->setColumnStretch(1, 3);
64
65 const auto localGitLayout = new QVBoxLayout(ui->localGit);
66 localGitLayout->setContentsMargins(QMargins());
67
68 mLocalGit = new FileEditor(false, this);
69 mLocalGit->editFile(mGit->getGitDir().append("/config"));
70 localGitLayout->addWidget(mLocalGit);
71
72 const auto globalGitLayout = new QVBoxLayout(ui->globalGit);
73 globalGitLayout->setContentsMargins(QMargins());
74
75 mGlobalGit = new FileEditor(false, this);
76 mGlobalGit->editFile(
77 QString("%1/%2").arg(QStandardPaths::writableLocation(QStandardPaths::HomeLocation), ".gitconfig"));
78 globalGitLayout->addWidget(mGlobalGit);
79
80 GitQlientSettings settings(mGit->getGitDir());
81
82 ui->chDevMode->setChecked(settings.localValue("DevMode", false).toBool());
83 enableWidgets();
84
85 // GitQlient configuration
86 ui->chDisableLogs->setChecked(settings.globalValue("logsDisabled", true).toBool());
87 ui->cbLogLevel->setCurrentIndex(settings.globalValue("logsLevel", static_cast<int>(LogLevel::Warning)).toInt());
88 ui->spCommitTitleLength->setValue(settings.globalValue("commitTitleMaxLength", 50).toInt());
89
90 const auto originalStyles = settings.globalValue("colorSchema", "dark").toString();
91 ui->cbStyle->setCurrentText(originalStyles);
92 connect(ui->cbStyle, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged), this,
93 [this, originalStyles]() {
94 mShowResetMsg = ui->cbStyle->currentText() != originalStyles;
95 saveConfig();
96 });
97
98 // Repository configuration
99 mOriginalRepoOrder = settings.localValue("GraphSortingOrder", 0).toInt();
100 ui->cbLogOrder->setCurrentIndex(mOriginalRepoOrder);
101 ui->autoFetch->setValue(settings.localValue("AutoFetch", 5).toInt());
102 ui->pruneOnFetch->setChecked(settings.localValue("PruneOnFetch", true).toBool());
103 ui->clangFormat->setChecked(settings.localValue("ClangFormatOnCommit", false).toBool());
104 ui->updateOnPull->setChecked(settings.localValue("UpdateOnPull", false).toBool());
105 ui->sbMaxCommits->setValue(settings.localValue("MaxCommits", 0).toInt());
106
107 ui->tabWidget->setCurrentIndex(0);
108 connect(ui->pbClearCache, &ButtonLink::clicked, this, &ConfigWidget::clearCache);
109
110 ui->cbPomodoroEnabled->setChecked(settings.localValue("Pomodoro/Enabled", true).toBool());
111
112 ui->cbStash->setChecked(settings.localValue("StashesHeader", true).toBool());
113 ui->cbSubmodule->setChecked(settings.localValue("SubmodulesHeader", true).toBool());
114 ui->cbSubtree->setChecked(settings.localValue("SubtreeHeader", true).toBool());
115
116 // Build System configuration
117 const auto isConfigured = settings.localValue("BuildSystemEnabled", false).toBool();
118 ui->chBoxBuildSystem->setChecked(isConfigured);
119 connect(ui->chBoxBuildSystem, &QCheckBox::stateChanged, this, &ConfigWidget::toggleBsAccesInfo);
120
121 ui->leBsUser->setVisible(isConfigured);
122 ui->leBsUserLabel->setVisible(isConfigured);
123 ui->leBsToken->setVisible(isConfigured);
124 ui->leBsTokenLabel->setVisible(isConfigured);
125 ui->leBsUrl->setVisible(isConfigured);
126 ui->leBsUrlLabel->setVisible(isConfigured);
127
128 if (isConfigured)
129 {
130 const auto url = settings.localValue("BuildSystemUrl", "").toString();
131 const auto user = settings.localValue("BuildSystemUser", "").toString();
132 const auto token = settings.localValue("BuildSystemToken", "").toString();
133
134 ui->leBsUrl->setText(url);
135 ui->leBsUser->setText(user);
136 ui->leBsToken->setText(token);
137 }
138
139 QScopedPointer<GitConfig> gitConfig(new GitConfig(git));
140
141 const auto url = gitConfig->getServerUrl();
142 ui->credentialsFrames->setVisible(url.startsWith("https"));
143
144 connect(ui->buttonGroup, SIGNAL(buttonClicked(QAbstractButton *)), this,
145 SLOT(onCredentialsOptionChanged(QAbstractButton *)));
146 connect(ui->pbAddCredentials, &QPushButton::clicked, this, &ConfigWidget::showCredentialsDlg);
147
148 // Connects for automatic save
149 connect(ui->chDevMode, &CheckBox::stateChanged, this, &ConfigWidget::enableWidgets);
150 connect(ui->chDisableLogs, &CheckBox::stateChanged, this, &ConfigWidget::saveConfig);
151 connect(ui->cbLogLevel, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
152 connect(ui->leGitPath, &QLineEdit::editingFinished, this, &ConfigWidget::saveConfig);
153 connect(ui->spCommitTitleLength, SIGNAL(valueChanged(int)), this, SLOT(saveConfig()));
154 connect(ui->cbTranslations, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
155 connect(ui->sbMaxCommits, SIGNAL(valueChanged(int)), this, SLOT(saveConfig()));
156 connect(ui->cbLogOrder, SIGNAL(currentIndexChanged(int)), this, SLOT(saveConfig()));
157 connect(ui->autoFetch, SIGNAL(valueChanged(int)), this, SLOT(saveConfig()));
158 connect(ui->pruneOnFetch, &QCheckBox::stateChanged, this, &ConfigWidget::saveConfig);
159 connect(ui->updateOnPull, &QCheckBox::stateChanged, this, &ConfigWidget::saveConfig);
160 connect(ui->clangFormat, &QCheckBox::stateChanged, this, &ConfigWidget::saveConfig);
161 connect(ui->cbPomodoroEnabled, &QCheckBox::stateChanged, this, &ConfigWidget::saveConfig);
162 connect(ui->cbStash, &QCheckBox::stateChanged, this, &ConfigWidget::saveConfig);
163 connect(ui->cbSubmodule, &QCheckBox::stateChanged, this, &ConfigWidget::saveConfig);
164 connect(ui->cbSubtree, &QCheckBox::stateChanged, this, &ConfigWidget::saveConfig);
165 connect(ui->leBsUrl, &QLineEdit::editingFinished, this, &ConfigWidget::saveConfig);
166 connect(ui->leBsUser, &QLineEdit::editingFinished, this, &ConfigWidget::saveConfig);
167 connect(ui->leBsToken, &QLineEdit::editingFinished, this, &ConfigWidget::saveConfig);
168
169 calculateCacheSize();
170}
171
172ConfigWidget::~ConfigWidget()
173{
174 delete ui;
175}
176
177void ConfigWidget::onPanelsVisibilityChanged()
178{
179 GitQlientSettings settings(mGit->getGitDir());
180
181 ui->cbStash->setChecked(settings.localValue("StashesHeader", true).toBool());
182 ui->cbSubmodule->setChecked(settings.localValue("SubmodulesHeader", true).toBool());
183 ui->cbSubtree->setChecked(settings.localValue("SubtreeHeader", true).toBool());
184}
185
186void ConfigWidget::onCredentialsOptionChanged(QAbstractButton *button)
187{
188 ui->sbTimeout->setEnabled(button == ui->rbCache);
189}
190
191void ConfigWidget::clearCache()
192{
193 const auto path = QString("%1").arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
194 QProcess p;
195 p.setWorkingDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
196 p.start("rm", { "-rf", path });
197
198 if (p.waitForFinished())
199 calculateCacheSize();
200}
201
202void ConfigWidget::calculateCacheSize()
203{
204 auto size = 0;
205 const auto dirPath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
206 QDir dir(dirPath);
207 QDir::Filters dirFilters = QDir::Dirs | QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::Files;
208 const auto &list = dir.entryInfoList(dirFilters);
209
210 for (const QFileInfo &file : list)
211 {
212 size += file.size();
213 size += dirSize(dirPath + "/" + file.fileName());
214 }
215
216 ui->lCacheSize->setText(QString("%1 KB").arg(size / 1024.0));
217}
218
219void ConfigWidget::toggleBsAccesInfo()
220{
221 const auto visible = ui->chBoxBuildSystem->isChecked();
222 ui->leBsUser->setVisible(visible);
223 ui->leBsUserLabel->setVisible(visible);
224 ui->leBsToken->setVisible(visible);
225 ui->leBsTokenLabel->setVisible(visible);
226 ui->leBsUrl->setVisible(visible);
227 ui->leBsUrlLabel->setVisible(visible);
228}
229
230void ConfigWidget::saveConfig()
231{
232 mFeedbackTimer->stop();
233
234 ui->lFeedback->setText(tr("Changes saved"));
235
236 GitQlientSettings settings(mGit->getGitDir());
237
238 settings.setGlobalValue("logsDisabled", ui->chDisableLogs->isChecked());
239 settings.setGlobalValue("logsLevel", ui->cbLogLevel->currentIndex());
240 settings.setGlobalValue("commitTitleMaxLength", ui->spCommitTitleLength->value());
241 settings.setGlobalValue("colorSchema", ui->cbStyle->currentText());
242 settings.setGlobalValue("gitLocation", ui->leGitPath->text());
243
244 emit commitTitleMaxLenghtChanged();
245
246 if (mShowResetMsg)
247 {
248 QMessageBox::information(this, tr("Reset needed!"),
249 tr("You need to restart GitQlient to see the changes in the styles applid."));
250 }
251
252 const auto logger = QLoggerManager::getInstance();
253 logger->overwriteLogLevel(static_cast<LogLevel>(ui->cbLogLevel->currentIndex()));
254
255 if (ui->chDisableLogs->isChecked())
256 logger->pause();
257 else
258 logger->resume();
259
260 if (mOriginalRepoOrder != ui->cbLogOrder->currentIndex())
261 {
262 settings.setLocalValue("GraphSortingOrder", ui->cbLogOrder->currentIndex());
263 emit reloadView();
264 }
265
266 settings.setLocalValue("AutoFetch", ui->autoFetch->value());
267 settings.setLocalValue("PruneOnFetch", ui->pruneOnFetch->isChecked());
268 settings.setLocalValue("ClangFormatOnCommit", ui->clangFormat->isChecked());
269 settings.setLocalValue("UpdateOnPull", ui->updateOnPull->isChecked());
270 settings.setLocalValue("MaxCommits", ui->sbMaxCommits->value());
271
272 settings.setLocalValue("StashesHeader", ui->cbStash->isChecked());
273 settings.setLocalValue("SubmodulesHeader", ui->cbSubmodule->isChecked());
274 settings.setLocalValue("SubtreeHeader", ui->cbSubtree->isChecked());
275
276 emit panelsVisibilityChaned();
277
278 /* POMODORO CONFIG */
279 settings.setLocalValue("Pomodoro/Enabled", ui->cbPomodoroEnabled->isChecked());
280
281 /* BUILD SYSTEM CONFIG */
282
283 const auto showBs = ui->chBoxBuildSystem->isChecked();
284 const auto bsUser = ui->leBsUser->text();
285 const auto bsToken = ui->leBsToken->text();
286 const auto bsUrl = ui->leBsUrl->text();
287
288 if (showBs && !bsUser.isEmpty() && !bsToken.isEmpty() && !bsUrl.isEmpty())
289 {
290 settings.setLocalValue("BuildSystemEnabled", showBs);
291 settings.setLocalValue("BuildSystemUrl", bsUrl);
292 settings.setLocalValue("BuildSystemUser", bsUser);
293 settings.setLocalValue("BuildSystemToken", bsToken);
294 emit buildSystemConfigured(showBs);
295 }
296 else
297 {
298 settings.setLocalValue("BuildSystemEnabled", false);
299 emit buildSystemConfigured(false);
300 }
301
302 mFeedbackTimer->singleShot(3000, ui->lFeedback, &QLabel::clear);
303}
304
305void ConfigWidget::enableWidgets()
306{
307 const auto enable = ui->chDevMode->isChecked();
308
309 GitQlientSettings settings(mGit->getGitDir());
310 settings.setLocalValue("DevMode", enable);
311
312 ui->tabWidget->setEnabled(enable);
313}
314
315void ConfigWidget::saveFile()
316{
317 const auto id = ui->tabWidget->currentIndex();
318
319 if (id == 0)
320 mLocalGit->saveFile();
321 else
322 mGlobalGit->saveFile();
323}
324
325void ConfigWidget::showCredentialsDlg()
326{
327 // Store credentials if allowed and the user checked the box
328 if (ui->credentialsFrames->isVisible() && ui->chbCredentials->isChecked())
329 {
330 if (ui->rbCache->isChecked())
331 GitCredentials::configureCache(ui->sbTimeout->value(), mGit);
332 else
333 {
334 CredentialsDlg dlg(mGit, this);
335 dlg.exec();
336 }
337 }
338}
339