File indexing completed on 2025-01-05 05:14:48

0001 /*
0002 SPDX-FileCopyrightText: 2021 Hamed Masafi <hamed.masfi@gmail.com>
0003 
0004 SPDX-License-Identifier: GPL-3.0-or-later
0005 */
0006 
0007 #include "commitpushdialog.h"
0008 #include "actions/changedfileactions.h"
0009 #include "commands/commandcommit.h"
0010 #include "commands/commandpush.h"
0011 #include "gitmanager.h"
0012 #include "models/changedfilesmodel.h"
0013 #include "runnerdialog.h"
0014 #include <QPainter>
0015 
0016 #include <KSharedConfig>
0017 #include <KWindowConfig>
0018 #include <QWindow>
0019 
0020 namespace
0021 {
0022 static const char myCommitPushDialogGroupName[] = "CommitPushDialog";
0023 }
0024 CommitPushDialog::CommitPushDialog(Git::Manager *git, QWidget *parent)
0025     : AppDialog(git, parent)
0026     , mModel(new ChangedFilesModel(git, true, this))
0027 {
0028     setupUi(this);
0029 
0030     reload();
0031 
0032     mActions = new ChangedFileActions(mGit, this);
0033 
0034     checkBoxIncludeStatus->setCheckState(Qt::PartiallyChecked);
0035 
0036     connect(pushButtonCommit, &QPushButton::clicked, this, &CommitPushDialog::slotPushButtonCommitClicked);
0037     connect(pushButtonPush, &QPushButton::clicked, this, &CommitPushDialog::slotPushButtonPushClicked);
0038     connect(toolButtonAddAll, &QToolButton::clicked, this, &CommitPushDialog::slotToolButtonAddAllClicked);
0039     connect(toolButtonAddNone, &QToolButton::clicked, this, &CommitPushDialog::slotToolButtonAddNoneClicked);
0040     connect(toolButtonAddIndexed, &QToolButton::clicked, this, &CommitPushDialog::slotToolButtonAddIndexedClicked);
0041     connect(toolButtonAddAdded, &QToolButton::clicked, this, &CommitPushDialog::slotToolButtonAddAddedClicked);
0042     connect(toolButtonAddModified, &QToolButton::clicked, this, &CommitPushDialog::slotToolButtonAddModifiedClicked);
0043     connect(toolButtonAddRemoved, &QToolButton::clicked, this, &CommitPushDialog::slotToolButtonAddRemovedClicked);
0044     connect(listView, &QListView::doubleClicked, this, &CommitPushDialog::slotListWidgetItemDoubleClicked);
0045     connect(listView, &QListView::customContextMenuRequested, this, &CommitPushDialog::slotListWidgetCustomContextMenuRequested);
0046     connect(groupBoxMakeCommit, &QGroupBox::toggled, this, &CommitPushDialog::slotGroupBoxMakeCommitToggled);
0047     connect(mModel, &ChangedFilesModel::checkedCountChanged, this, &CommitPushDialog::checkButtonsEnable);
0048     connect(textEditMessage, &QTextEdit::textChanged, this, &CommitPushDialog::checkButtonsEnable);
0049     connect(checkBoxAmend, &QCheckBox::toggled, this, &CommitPushDialog::checkButtonsEnable);
0050     connect(mActions, &ChangedFileActions::reloadNeeded, mModel, &ChangedFilesModel::reload);
0051 
0052     listView->setModel(mModel);
0053     mModel->reload();
0054     readConfig();
0055 }
0056 
0057 CommitPushDialog::~CommitPushDialog()
0058 {
0059     writeConfig();
0060 }
0061 
0062 void CommitPushDialog::readConfig()
0063 {
0064     create(); // ensure a window is created
0065     windowHandle()->resize(QSize(800, 300));
0066     KConfigGroup group(KSharedConfig::openStateConfig(), myCommitPushDialogGroupName);
0067     KWindowConfig::restoreWindowSize(windowHandle(), group);
0068     resize(windowHandle()->size()); // workaround for QTBUG-40584
0069 }
0070 
0071 void CommitPushDialog::writeConfig()
0072 {
0073     KConfigGroup group(KSharedConfig::openStateConfig(), myCommitPushDialogGroupName);
0074     KWindowConfig::saveWindowSize(windowHandle(), group);
0075 }
0076 
0077 void CommitPushDialog::reload()
0078 {
0079     mModel->reload();
0080 
0081     if (!mModel->size()) {
0082         pushButtonCommit->setEnabled(false);
0083         pushButtonPush->setEnabled(true);
0084         groupBoxMakeCommit->setEnabled(false);
0085         pushButtonPush->setText(i18n("Push"));
0086     } else {
0087         pushButtonPush->setText(i18n("Commit and push"));
0088     }
0089 
0090     comboBoxBranch->clear();
0091     comboBoxRemote->clear();
0092     auto branches = mGit->branchesNames(Git::Manager::BranchType::LocalBranch);
0093     auto remotes = mGit->remotes();
0094     comboBoxBranch->addItems(branches);
0095     comboBoxRemote->addItems(remotes);
0096     labelCurrentBranchName->setText(mGit->currentBranch());
0097 
0098     QSet<QString> _words;
0099     for (const auto &b : std::as_const(branches))
0100         _words.insert(b);
0101     for (const auto &r : std::as_const(remotes))
0102         _words.insert(r);
0103     auto data = mModel->data();
0104     for (const auto &row : data) {
0105         const auto parts = row.filePath.split(QLatin1Char('/'));
0106         for (const auto &p : parts)
0107             _words.insert(p);
0108         _words.insert(row.filePath);
0109     }
0110     textEditMessage->addWords(_words.values());
0111     textEditMessage->begin();
0112 }
0113 
0114 void CommitPushDialog::checkButtonsEnable()
0115 {
0116     if (groupBoxMakeCommit->isEnabled() && !groupBoxMakeCommit->isChecked()) {
0117         pushButtonCommit->setEnabled(false);
0118         pushButtonPush->setEnabled(true);
0119         return;
0120     }
0121     bool enable{false};
0122 
0123     if (!mModel->checkedCount()) {
0124         pushButtonCommit->setEnabled(false);
0125         pushButtonPush->setEnabled(false);
0126         return;
0127     }
0128 
0129     enable = checkBoxAmend->isChecked() || !textEditMessage->toPlainText().isEmpty();
0130     pushButtonCommit->setEnabled(enable);
0131     pushButtonPush->setEnabled(enable);
0132 }
0133 
0134 void CommitPushDialog::slotPushButtonCommitClicked()
0135 {
0136     addFiles();
0137     Git::CommandCommit cmd;
0138     cmd.setAmend(checkBoxAmend->isChecked());
0139     cmd.setMessage(textEditMessage->toPlainText());
0140     cmd.setIncludeStatus(Git::checkStateToOptionalBool(checkBoxIncludeStatus->checkState()));
0141 
0142     RunnerDialog d(mGit);
0143     d.run(&cmd);
0144     d.exec();
0145 
0146     accept();
0147 }
0148 
0149 void CommitPushDialog::slotPushButtonPushClicked()
0150 {
0151     addFiles();
0152 
0153     if (groupBoxMakeCommit->isChecked()) {
0154         addFiles();
0155         Git::CommandCommit commitCommand;
0156         commitCommand.setAmend(checkBoxAmend->isChecked());
0157         commitCommand.setMessage(textEditMessage->toPlainText());
0158         commitCommand.setIncludeStatus(Git::checkStateToOptionalBool(checkBoxIncludeStatus->checkState()));
0159 
0160         RunnerDialog d(mGit, this);
0161         d.setAutoClose(true);
0162         d.run(&commitCommand);
0163         auto dd = d.exec();
0164         //        qDebug() << dd;
0165         if (dd != QDialog::Accepted)
0166             return;
0167     }
0168 
0169     Git::CommandPush cmd;
0170     cmd.setRemote(comboBoxRemote->currentText());
0171 
0172     if (radioButtonCurrentBranch->isChecked())
0173         cmd.setLocalBranch(labelCurrentBranchName->text());
0174     else if (radioButtonExistingBranch->isChecked())
0175         cmd.setLocalBranch(comboBoxBranch->currentText());
0176     else
0177         cmd.setLocalBranch(lineEditNewBranchName->text());
0178     cmd.setForce(checkBoxForce->isChecked());
0179 
0180     mGit->commit(textEditMessage->toPlainText());
0181     RunnerDialog d(mGit, this);
0182     d.run(&cmd);
0183     d.exec();
0184     accept();
0185 }
0186 
0187 void CommitPushDialog::addFiles()
0188 {
0189     auto files = mModel->checkedFiles();
0190     for (const auto &file : files) {
0191         mGit->addFile(file);
0192     }
0193 }
0194 
0195 void CommitPushDialog::slotToolButtonAddAllClicked()
0196 {
0197     mModel->toggleCheckAll(true);
0198     checkButtonsEnable();
0199 }
0200 
0201 void CommitPushDialog::slotToolButtonAddNoneClicked()
0202 {
0203     mModel->toggleCheckAll(false);
0204     checkButtonsEnable();
0205 }
0206 
0207 void CommitPushDialog::slotToolButtonAddIndexedClicked()
0208 {
0209     mModel->checkByStatus({Git::ChangeStatus::Removed, Git::ChangeStatus::Modified});
0210     checkButtonsEnable();
0211 }
0212 
0213 void CommitPushDialog::slotToolButtonAddAddedClicked()
0214 {
0215     mModel->checkByStatus(Git::ChangeStatus::Untracked);
0216 }
0217 
0218 void CommitPushDialog::slotToolButtonAddRemovedClicked()
0219 {
0220     mModel->checkByStatus(Git::ChangeStatus::Removed);
0221 }
0222 
0223 void CommitPushDialog::slotToolButtonAddModifiedClicked()
0224 {
0225     mModel->checkByStatus(Git::ChangeStatus::Modified);
0226 }
0227 
0228 void CommitPushDialog::slotListWidgetItemDoubleClicked(const QModelIndex &index)
0229 {
0230     if (!index.isValid())
0231         return;
0232 
0233     auto data = mModel->data(index.row());
0234     if (data->oldFilePath != QString())
0235         mActions->setFilePaths(data->oldFilePath, data->filePath);
0236     else
0237         mActions->setFilePath(data->filePath);
0238     mActions->diff();
0239 }
0240 
0241 void CommitPushDialog::slotGroupBoxMakeCommitToggled(bool checked)
0242 {
0243     checkButtonsEnable();
0244     pushButtonPush->setText(checked ? i18n("Commit and push") : i18n("Push"));
0245 }
0246 
0247 void CommitPushDialog::slotListWidgetCustomContextMenuRequested(const QPoint &pos)
0248 {
0249     Q_UNUSED(pos)
0250     if (!listView->currentIndex().isValid())
0251         return;
0252 
0253     mActions->setFilePath(mModel->filePath(listView->currentIndex().row()));
0254     mActions->popup();
0255 }
0256 
0257 #include "moc_commitpushdialog.cpp"