Commit 92a224f1 authored by Waqar Ahmed's avatar Waqar Ahmed
Browse files

Implement branch comparing and Compare branches tree



This add a new feature, comparing branches. Implementation is as follows:
- Move everything inside the GitWidget into a QStackedWidget
- Whenever the user wants to compare branches, create a new CompareBranchesView
and switch to it
- After the user is done, the compare view is deleted.
Signed-off-by: Waqar Ahmed's avatarWaqar Ahmed <waqar.17a@gmail.com>
parent 53bbdd0e
......@@ -68,6 +68,7 @@ target_sources(
filehistorywidget.cpp
quickdialog.cpp
pushpulldialog.cpp
comarebranchesview.cpp
tools/kateprojectcodeanalysistoolcppcheck.cpp
tools/kateprojectcodeanalysistoolflake8.cpp
......
#include "comarebranchesview.h"
#include "kateprojectpluginview.h"
#include "kateprojectworker.h"
#include <QVBoxLayout>
#include <KLocalizedString>
#include <QProcess>
static QVariantMap createMap(const QStringList &files)
{
QVariantMap cnf, filesMap;
filesMap[QStringLiteral("list")] = (files);
cnf[QStringLiteral("name")] = QStringLiteral("ComparingBranches");
cnf[QStringLiteral("files")] = (QVariantList() << filesMap);
return cnf;
}
CompareBranchesView::CompareBranchesView(QWidget *parent, const QString &gitPath, const QString fromB, const QString &toBr, QStringList files)
: QWidget(parent)
, m_files(std::move(files))
, m_gitDir(gitPath)
, m_fromBr(fromB)
, m_toBr(toBr)
{
setLayout(new QVBoxLayout);
KateProjectWorker *w = new KateProjectWorker(m_gitDir, QString(), createMap(m_files), true);
connect(w, &KateProjectWorker::loadDone, this, &CompareBranchesView::loadFilesDone, Qt::QueuedConnection);
w->run();
m_backBtn.setText(i18n("Back"));
m_backBtn.setIcon(QIcon::fromTheme(QStringLiteral("draw-arrow-back.svg")));
connect(&m_backBtn, &QPushButton::clicked, this, &CompareBranchesView::backClicked);
layout()->addWidget(&m_backBtn);
m_tree.setModel(&m_model);
layout()->addWidget(&m_tree);
m_tree.setHeaderHidden(true);
connect(&m_tree, &QTreeView::clicked, this, &CompareBranchesView::showDiff);
}
void CompareBranchesView::loadFilesDone(const KateProjectSharedQStandardItem &topLevel, KateProjectSharedQHashStringItem)
{
m_model.clear();
m_model.invisibleRootItem()->appendColumn(topLevel->takeColumn(0));
m_tree.expandAll();
}
void CompareBranchesView::showDiff(const QModelIndex &idx)
{
auto file = idx.data(Qt::UserRole).toString().remove(m_gitDir + QLatin1Char('/'));
QProcess git;
git.setWorkingDirectory(m_gitDir);
QStringList args{QStringLiteral("diff"), QStringLiteral("%1...%2").arg(m_fromBr).arg(m_toBr), QStringLiteral("--"), file};
git.start(QStringLiteral("git"), args, QProcess::ReadOnly);
if (git.waitForStarted() && git.waitForFinished(-1)) {
if (git.exitStatus() != QProcess::NormalExit || git.exitCode() != 0) {
return;
}
}
m_pluginView->showDiffInFixedView(git.readAllStandardOutput());
}
#ifndef COMAREBRANCHESVIEW_H
#define COMAREBRANCHESVIEW_H
#include <QPushButton>
#include <QStandardItemModel>
#include <QTreeView>
#include <QWidget>
#include <kateproject.h>
class KateProjectPluginView;
class CompareBranchesView : public QWidget
{
Q_OBJECT
public:
explicit CompareBranchesView(QWidget *parent, const QString &gitPath, const QString fromB, const QString &toBr, QStringList files);
void setPluginView(KateProjectPluginView *pv)
{
m_pluginView = pv;
}
Q_SIGNAL void backClicked();
private Q_SLOTS:
void loadFilesDone(const KateProjectSharedQStandardItem &topLevel, KateProjectSharedQHashStringItem file2Item);
void showDiff(const QModelIndex &idx);
private:
QPushButton m_backBtn;
QTreeView m_tree;
QStringList m_files;
QStandardItemModel m_model;
QString m_gitDir;
QString m_fromBr;
QString m_toBr;
KateProjectPluginView *m_pluginView;
};
#endif // COMAREBRANCHESVIEW_H
......@@ -4,7 +4,9 @@
SPDX-License-Identifier: LGPL-2.0-or-later
*/
#include "gitwidget.h"
#include "branchcheckoutdialog.h"
#include "branchesdialog.h"
#include "comarebranchesview.h"
#include "git/gitdiff.h"
#include "gitcommitdialog.h"
#include "gitstatusmodel.h"
......@@ -145,6 +147,8 @@ GitWidget::GitWidget(KateProject *project, KTextEditor::MainWindow *mainWindow,
: m_project(project)
, m_mainWin(mainWindow)
, m_pluginView(pluginView)
, m_mainView(new QWidget(this))
, m_stackWid(new QStackedWidget(this))
{
setDotGitPath();
......@@ -222,7 +226,8 @@ GitWidget::GitWidget(KateProject *project, KTextEditor::MainWindow *mainWindow,
m_treeView->setItemDelegateForColumn(1, new NumStatStyle(this, m_pluginView->plugin()));
setLayout(layout);
// our main view - status view + btns
m_mainView->setLayout(layout);
connect(&m_gitStatusWatcher, &QFutureWatcher<GitUtils::GitParsedStatus>::finished, this, &GitWidget::parseStatusReady);
connect(m_commitBtn, &QPushButton::clicked, this, &GitWidget::opencommitChangesDialog);
......@@ -230,6 +235,12 @@ GitWidget::GitWidget(KateProject *project, KTextEditor::MainWindow *mainWindow,
// single / double click
connect(m_treeView, &QTreeView::clicked, this, &GitWidget::treeViewSingleClicked);
connect(m_treeView, &QTreeView::doubleClicked, this, &GitWidget::treeViewDoubleClicked);
m_stackWid->addWidget(m_mainView);
// This Widget's layout
setLayout(new QVBoxLayout);
this->layout()->addWidget(m_stackWid);
}
GitWidget::~GitWidget()
......@@ -724,6 +735,38 @@ void GitWidget::numStatForStatus(QVector<GitUtils::StatusItem> &list, bool modif
GitUtils::parseDiffNumStat(list, git.readAllStandardOutput());
}
void GitWidget::branchCompareFiles(const QString &from, const QString &to)
{
// git diff br...br2 --name-only -z
const auto args = QStringList{QStringLiteral("diff"), QStringLiteral("%1...%2").arg(from).arg(to), QStringLiteral("--name-only"), QStringLiteral("-z")};
QProcess git;
git.setWorkingDirectory(m_gitPath);
git.start(QStringLiteral("git"), args, QProcess::ReadOnly);
if (git.waitForStarted() && git.waitForFinished(-1)) {
if (git.exitStatus() != QProcess::NormalExit || git.exitCode() != 0) {
return;
}
}
QList<QByteArray> files = git.readAllStandardOutput().split(0x00);
QStringList filesList;
std::transform(files.cbegin(), files.cend(), std::back_inserter(filesList), [](const QByteArray &a) {
return QString::fromUtf8(a);
});
CompareBranchesView *w = new CompareBranchesView(this, m_gitPath, from, to, filesList);
w->setPluginView(m_pluginView);
connect(w, &CompareBranchesView::backClicked, this, [this] {
auto x = m_stackWid->currentWidget();
if (x) {
m_stackWid->setCurrentWidget(m_mainView);
x->deleteLater();
}
});
m_stackWid->addWidget(w);
m_stackWid->setCurrentWidget(w);
}
bool GitWidget::eventFilter(QObject *o, QEvent *e)
{
if (e->type() == QEvent::ContextMenu) {
......@@ -747,6 +790,16 @@ void GitWidget::buildMenu()
BranchCheckoutDialog bd(m_mainWin->window(), m_pluginView, m_project->baseDir());
bd.openDialog();
});
m_gitMenu->addAction(i18n("Compare Branches"), this, [this] {
BranchesDialog bd(m_mainWin->window(), m_pluginView, m_project->baseDir());
bd.openDialog(GitUtils::RefType::Head);
QString frombr = bd.branch();
bd.openDialog(GitUtils::RefType::Head);
QString tobr = bd.branch();
branchCompareFiles(frombr, tobr);
});
m_gitMenu->addAction(i18n("Stash"))->setMenu(stashMenu());
}
......
......@@ -25,6 +25,7 @@ class QToolButton;
class QTemporaryFile;
class KateProjectPluginView;
class GitWidgetTreeView;
class QStackedWidget;
namespace KTextEditor
{
......@@ -67,6 +68,9 @@ private:
QMenu *m_gitMenu;
KateProjectPluginView *m_pluginView;
QWidget *m_mainView;
QStackedWidget *m_stackWid;
using CancelHandle = QPointer<QProcess>;
CancelHandle m_cancelHandle;
......@@ -86,6 +90,7 @@ private:
void commitChanges(const QString &msg, const QString &desc, bool signOff);
void applyDiff(const QString &fileName, bool staged, bool hunk, KTextEditor::View *v);
void numStatForStatus(QVector<GitUtils::StatusItem> &list, bool modified);
void branchCompareFiles(const QString &from, const QString &to);
QMenu *stashMenu();
void hideEmptyTreeNodes();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment