| 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 | |
| 20 | using namespace QLogger; |
| 21 | |
| 22 | namespace |
| 23 | { |
| 24 | qint64 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 | |
| 46 | ConfigWidget::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 | |
| 172 | ConfigWidget::~ConfigWidget() |
| 173 | { |
| 174 | delete ui; |
| 175 | } |
| 176 | |
| 177 | void 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 | |
| 186 | void ConfigWidget::onCredentialsOptionChanged(QAbstractButton *button) |
| 187 | { |
| 188 | ui->sbTimeout->setEnabled(button == ui->rbCache); |
| 189 | } |
| 190 | |
| 191 | void 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 | |
| 202 | void 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 | |
| 219 | void 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 | |
| 230 | void 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 | |
| 305 | void 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 | |
| 315 | void 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 | |
| 325 | void 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 | |