File indexing completed on 2024-04-28 05:49:05
0001 /* 0002 SPDX-FileCopyrightText: 2023 Waqar Ahmed <waqar.17a@gmail.com> 0003 SPDX-License-Identifier: LGPL-2.0-or-later 0004 */ 0005 #include "currentgitbranchbutton.h" 0006 0007 #include "gitprocess.h" 0008 #include "hostprocess.h" 0009 0010 #include <KAcceleratorManager> 0011 #include <KLocalizedString> 0012 #include <KTextEditor/Document> 0013 #include <KTextEditor/MainWindow> 0014 #include <KTextEditor/View> 0015 #include <QPointer> 0016 0017 #include <QFileInfo> 0018 #include <QProcess> 0019 #include <QtConcurrentRun> 0020 0021 static CurrentGitBranchButton::BranchResult getCurrentBranchName(const QString &workingDir) 0022 { 0023 const QStringList argsList[3] = { 0024 {QStringLiteral("symbolic-ref"), QStringLiteral("--short"), QStringLiteral("HEAD")}, 0025 {QStringLiteral("rev-parse"), QStringLiteral("--short"), QStringLiteral("HEAD")}, 0026 {QStringLiteral("describe"), QStringLiteral("--exact-match"), QStringLiteral("HEAD")}, 0027 }; 0028 0029 for (int i = 0; i < 3; ++i) { 0030 QProcess git; 0031 if (!setupGitProcess(git, workingDir, argsList[i])) { 0032 return {}; 0033 } 0034 0035 startHostProcess(git, QProcess::ReadOnly); 0036 if (git.waitForStarted() && git.waitForFinished(-1)) { 0037 if (git.exitStatus() == QProcess::NormalExit && git.exitCode() == 0) { 0038 return { 0039 QString::fromUtf8(git.readAllStandardOutput().trimmed()), 0040 static_cast<CurrentGitBranchButton::BranchType>(i), 0041 }; 0042 } 0043 } 0044 } 0045 0046 // give up 0047 return {}; 0048 } 0049 0050 CurrentGitBranchButton::CurrentGitBranchButton(KTextEditor::MainWindow *mainWindow, QWidget *parent) 0051 : QToolButton(parent) 0052 { 0053 setVisible(false); 0054 setAutoRaise(true); 0055 setToolButtonStyle(Qt::ToolButtonTextBesideIcon); 0056 m_viewChangedTimer.setSingleShot(true); 0057 m_viewChangedTimer.setInterval(1000); 0058 KAcceleratorManager::setNoAccel(this); 0059 0060 auto mw = QPointer<KTextEditor::MainWindow>(mainWindow); 0061 connect(mainWindow, &KTextEditor::MainWindow::viewChanged, this, [this](KTextEditor::View *v) { 0062 if (!v || v->document()->url().toLocalFile().isEmpty()) { 0063 hideButton(); 0064 m_viewChangedTimer.stop(); 0065 return; 0066 } 0067 m_viewChangedTimer.start(); 0068 }); 0069 m_viewChangedTimer.callOnTimeout(this, [this, mw] { 0070 if (mw) { 0071 onViewChanged(mw->activeView()); 0072 } 0073 }); 0074 0075 connect(&m_watcher, &QFutureWatcher<QString>::finished, this, &CurrentGitBranchButton::onBranchFetched); 0076 onViewChanged(mainWindow->activeView()); 0077 } 0078 0079 CurrentGitBranchButton::~CurrentGitBranchButton() 0080 { 0081 m_viewChangedTimer.stop(); 0082 if (m_watcher.isRunning()) { 0083 disconnect(&m_watcher, &QFutureWatcher<BranchResult>::finished, this, &CurrentGitBranchButton::onBranchFetched); 0084 m_watcher.cancel(); 0085 m_watcher.waitForFinished(); 0086 } 0087 } 0088 0089 void CurrentGitBranchButton::hideButton() 0090 { 0091 setText({}); 0092 setVisible(false); 0093 } 0094 0095 void CurrentGitBranchButton::refresh() 0096 { 0097 m_viewChangedTimer.start(); 0098 } 0099 0100 void CurrentGitBranchButton::onViewChanged(KTextEditor::View *v) 0101 { 0102 if (!v || v->document()->url().toLocalFile().isEmpty()) { 0103 hideButton(); 0104 return; 0105 } 0106 0107 const auto fi = QFileInfo(v->document()->url().toLocalFile()); 0108 const auto workingDir = fi.absolutePath(); 0109 auto future = QtConcurrent::run(&getCurrentBranchName, workingDir); 0110 m_watcher.setFuture(future); 0111 } 0112 0113 void CurrentGitBranchButton::onBranchFetched() 0114 { 0115 const BranchResult branch = m_watcher.result(); 0116 if (branch.branch.isEmpty()) { 0117 hideButton(); 0118 return; 0119 } 0120 0121 setText(branch.branch); 0122 0123 if (branch.type == Commit) { 0124 setToolTip(i18nc("Tooltip text, describing that '%1' commit is checked out", "HEAD at commit %1", branch.branch)); 0125 } else if (branch.type == Tag) { 0126 setToolTip(i18nc("Tooltip text, describing that '%1' tag is checked out", "HEAD is at this tag %1", branch.branch)); 0127 } else if (branch.type == Branch) { 0128 setToolTip(i18nc("Tooltip text, describing that '%1' branch is checked out", "Active branch: %1", branch.branch)); 0129 } 0130 0131 if (!isVisible()) { 0132 setVisible(true); 0133 } 0134 } 0135 0136 #include "moc_currentgitbranchbutton.cpp"