- enhancement: git - log

This commit is contained in:
Roy Qu 2022-02-21 23:35:28 +08:00
parent adb201b4c1
commit 13993bbc3c
13 changed files with 904 additions and 444 deletions

View File

@ -1,3 +1,6 @@
Red Panda C++ Version 0.14.4
- enhancement: git - log
Red Panda C++ Version 0.14.3 Red Panda C++ Version 0.14.3
- fix: wrong code completion font size, when screen dpi changed - fix: wrong code completion font size, when screen dpi changed
- enhancement: replace Files View Panel's path lineedit control with combo box - enhancement: replace Files View Panel's path lineedit control with combo box

View File

@ -10,7 +10,7 @@ isEmpty(APP_NAME) {
} }
isEmpty(APP_VERSION) { isEmpty(APP_VERSION) {
APP_VERSION=0.14.3 APP_VERSION=0.14.4
} }
isEmpty(PREFIX) { isEmpty(PREFIX) {
@ -92,6 +92,7 @@ SOURCES += \
todoparser.cpp \ todoparser.cpp \
toolsmanager.cpp \ toolsmanager.cpp \
vcs/gitbranchdialog.cpp \ vcs/gitbranchdialog.cpp \
vcs/gitlogdialog.cpp \
vcs/gitmanager.cpp \ vcs/gitmanager.cpp \
vcs/gitmergedialog.cpp \ vcs/gitmergedialog.cpp \
vcs/gitrepository.cpp \ vcs/gitrepository.cpp \
@ -227,6 +228,7 @@ HEADERS += \
todoparser.h \ todoparser.h \
toolsmanager.h \ toolsmanager.h \
vcs/gitbranchdialog.h \ vcs/gitbranchdialog.h \
vcs/gitlogdialog.h \
vcs/gitmanager.h \ vcs/gitmanager.h \
vcs/gitmergedialog.h \ vcs/gitmergedialog.h \
vcs/gitrepository.h \ vcs/gitrepository.h \
@ -326,6 +328,7 @@ FORMS += \
settingsdialog/toolsgeneralwidget.ui \ settingsdialog/toolsgeneralwidget.ui \
settingsdialog/toolsgitwidget.ui \ settingsdialog/toolsgitwidget.ui \
vcs/gitbranchdialog.ui \ vcs/gitbranchdialog.ui \
vcs/gitlogdialog.ui \
vcs/gitmergedialog.ui \ vcs/gitmergedialog.ui \
widgets/aboutdialog.ui \ widgets/aboutdialog.ui \
widgets/cpudialog.ui \ widgets/cpudialog.ui \

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,7 @@
#include "vcs/gitrepository.h" #include "vcs/gitrepository.h"
#include "vcs/gitbranchdialog.h" #include "vcs/gitbranchdialog.h"
#include "vcs/gitmergedialog.h" #include "vcs/gitmergedialog.h"
#include "vcs/gitlogdialog.h"
#include "widgets/infomessagebox.h" #include "widgets/infomessagebox.h"
#include <QCloseEvent> #include <QCloseEvent>
@ -3092,6 +3093,7 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos)
if (shouldAdd) if (shouldAdd)
vcsMenu.addAction(ui->actionGit_Add_Files); vcsMenu.addAction(ui->actionGit_Add_Files);
} }
vcsMenu.addAction(ui->actionGit_Log);
vcsMenu.addAction(ui->actionGit_Branch); vcsMenu.addAction(ui->actionGit_Branch);
vcsMenu.addAction(ui->actionGit_Merge); vcsMenu.addAction(ui->actionGit_Merge);
vcsMenu.addAction(ui->actionGit_Commit); vcsMenu.addAction(ui->actionGit_Commit);
@ -3099,9 +3101,10 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos)
bool canBranch = !mProject->model()->iconProvider()->VCSRepository()->hasChangedFiles() bool canBranch = !mProject->model()->iconProvider()->VCSRepository()->hasChangedFiles()
&& !mProject->model()->iconProvider()->VCSRepository()->hasStagedFiles(); && !mProject->model()->iconProvider()->VCSRepository()->hasStagedFiles();
ui->actionGit_Branch->setEnabled(canBranch);
ui->actionGit_Merge->setEnabled(canBranch); ui->actionGit_Merge->setEnabled(canBranch);
ui->actionGit_Commit->setEnabled(canBranch); ui->actionGit_Commit->setEnabled(true);
ui->actionGit_Branch->setEnabled(true); ui->actionGit_Log->setEnabled(true);
ui->actionGit_Restore->setEnabled(true); ui->actionGit_Restore->setEnabled(true);
// vcsMenu.addAction(ui->actionGit_Reset); // vcsMenu.addAction(ui->actionGit_Reset);
@ -3212,6 +3215,7 @@ void MainWindow::onFilesViewContextMenu(const QPoint &pos)
if (shouldAdd) if (shouldAdd)
vcsMenu.addAction(ui->actionGit_Add_Files); vcsMenu.addAction(ui->actionGit_Add_Files);
} }
vcsMenu.addAction(ui->actionGit_Log);
vcsMenu.addAction(ui->actionGit_Branch); vcsMenu.addAction(ui->actionGit_Branch);
vcsMenu.addAction(ui->actionGit_Merge); vcsMenu.addAction(ui->actionGit_Merge);
vcsMenu.addAction(ui->actionGit_Commit); vcsMenu.addAction(ui->actionGit_Commit);
@ -3221,6 +3225,7 @@ void MainWindow::onFilesViewContextMenu(const QPoint &pos)
&& !mFileSystemModelIconProvider.VCSRepository()->hasStagedFiles(); && !mFileSystemModelIconProvider.VCSRepository()->hasStagedFiles();
ui->actionGit_Branch->setEnabled(canBranch); ui->actionGit_Branch->setEnabled(canBranch);
ui->actionGit_Merge->setEnabled(canBranch); ui->actionGit_Merge->setEnabled(canBranch);
ui->actionGit_Log->setEnabled(true);
ui->actionGit_Commit->setEnabled(true); ui->actionGit_Commit->setEnabled(true);
ui->actionGit_Restore->setEnabled(true); ui->actionGit_Restore->setEnabled(true);
@ -5736,6 +5741,7 @@ void MainWindow::updateVCSActions()
&& !mFileSystemModelIconProvider.VCSRepository()->hasStagedFiles(); && !mFileSystemModelIconProvider.VCSRepository()->hasStagedFiles();
} }
ui->actionGit_Create_Repository->setEnabled(!hasRepository && shouldEnable); ui->actionGit_Create_Repository->setEnabled(!hasRepository && shouldEnable);
ui->actionGit_Log->setEnabled(hasRepository && shouldEnable);
ui->actionGit_Commit->setEnabled(hasRepository && shouldEnable); ui->actionGit_Commit->setEnabled(hasRepository && shouldEnable);
ui->actionGit_Branch->setEnabled(hasRepository && shouldEnable && canBranch); ui->actionGit_Branch->setEnabled(hasRepository && shouldEnable && canBranch);
ui->actionGit_Merge->setEnabled(hasRepository && shouldEnable && canBranch); ui->actionGit_Merge->setEnabled(hasRepository && shouldEnable && canBranch);
@ -6877,3 +6883,27 @@ void MainWindow::on_actionGit_Merge_triggered()
} }
} }
void MainWindow::on_actionGit_Log_triggered()
{
QString folder;
if (ui->treeFiles->isVisible()) {
folder = pSettings->environment().currentFolder();
} else if (ui->projectView->isVisible() && mProject) {
folder = mProject->folder();
}
if (folder.isEmpty())
return;
GitLogDialog dialog(folder);
if (dialog.exec()==QDialog::Accepted) {
//update project view
if (mProject) {
mProject->model()->beginUpdate();
mProject->model()->endUpdate();
}
//update files view
setFilesViewRoot(pSettings->environment().currentFolder());
}
return ;
}

View File

@ -594,6 +594,8 @@ private slots:
void on_actionGit_Merge_triggered(); void on_actionGit_Merge_triggered();
void on_actionGit_Log_triggered();
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
EditorList *mEditorList; EditorList *mEditorList;

View File

@ -542,7 +542,7 @@
<enum>QTabWidget::South</enum> <enum>QTabWidget::South</enum>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>2</number> <number>6</number>
</property> </property>
<property name="iconSize"> <property name="iconSize">
<size> <size>
@ -1603,6 +1603,7 @@
</property> </property>
<addaction name="actionGit_Create_Repository"/> <addaction name="actionGit_Create_Repository"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionGit_Log"/>
<addaction name="actionGit_Branch"/> <addaction name="actionGit_Branch"/>
<addaction name="actionGit_Merge"/> <addaction name="actionGit_Merge"/>
<addaction name="separator"/> <addaction name="separator"/>
@ -2802,6 +2803,14 @@
<string>Merge</string> <string>Merge</string>
</property> </property>
</action> </action>
<action name="actionGit_Log">
<property name="text">
<string>Show Log</string>
</property>
<property name="toolTip">
<string>Show Log</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -0,0 +1,107 @@
#include "gitlogdialog.h"
#include "ui_gitlogdialog.h"
#include "gitmanager.h"
#include <QMenu>
GitLogDialog::GitLogDialog(const QString& folder, QWidget *parent) :
QDialog(parent),
ui(new Ui::GitLogDialog),
mModel(folder)
{
ui->setupUi(this);
ui->tblLogs->setModel(&mModel);
ui->tblLogs->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
connect(ui->tblLogs,&QTableView::customContextMenuRequested,
this, &GitLogDialog::onLogsContextMenu);
}
GitLogDialog::~GitLogDialog()
{
delete ui;
}
GitLogModel::GitLogModel(const QString &folder, QObject *parent):
QAbstractTableModel(parent),mFolder(folder)
{
GitManager manager;
mCount = manager.logCounts(folder);
}
int GitLogModel::rowCount(const QModelIndex &parent) const
{
return mCount;
}
int GitLogModel::columnCount(const QModelIndex &parent) const
{
return 3;
}
QVariant GitLogModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role == Qt::DisplayRole) {
int row = index.row();
GitManager manager;
QList<PGitCommitInfo> listCommitInfos =
manager.log(mFolder,row,1);
if (listCommitInfos.isEmpty()) {
return QVariant();
}
switch(index.column()) {
case 0:
return listCommitInfos[0]->authorDate;
case 1:
return listCommitInfos[0]->author;
case 2:
return listCommitInfos[0]->title;
}
}
return QVariant();
}
QVariant GitLogModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation==Qt::Horizontal && role == Qt::DisplayRole) {
switch(section) {
case 0:
return tr("Date");
case 1:
return tr("Author");
case 2:
return tr("Title");
}
}
return QVariant();
}
const QString &GitLogModel::folder() const
{
return mFolder;
}
void GitLogDialog::on_btnClose_clicked()
{
reject();
}
void GitLogDialog::onLogsContextMenu(const QPoint &pos)
{
QMenu menu(this);
QString branch;
GitManager manager;
if (!manager.hasRepository(mModel.folder(), branch))
return;
menu.addAction(ui->actionRevert);
menu.addAction(ui->actionReset);
menu.addAction(ui->actionBranch);
menu.addAction(ui->actionTag);
ui->actionReset->setText(tr("Reset \"%1\" to this...").arg(branch));
ui->actionRevert->setText(tr("Revert \"%1\" to this...").arg(branch));
ui->actionBranch->setText(tr("Create Branch at this version..."));
ui->actionTag->setText(tr("Create Tag at this version..."));
menu.exec(ui->tblLogs->mapToGlobal(pos));
}

View File

@ -0,0 +1,48 @@
#ifndef GITLOGDIALOG_H
#define GITLOGDIALOG_H
#include <QDialog>
#include <QAbstractTableModel>
#include <QMap>
#include "gitutils.h"
namespace Ui {
class GitLogDialog;
}
class GitLogModel: public QAbstractTableModel {
public:
explicit GitLogModel(const QString& folder,QObject *parent = nullptr);
// QAbstractItemModel interface
public:
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
const QString &folder() const;
private:
QString mFolder;
int mCount;
QMap<int,PGitCommitInfo> mGitCommitInfos;
};
class GitLogDialog : public QDialog
{
Q_OBJECT
public:
explicit GitLogDialog(const QString& folder, QWidget *parent = nullptr);
~GitLogDialog();
private slots:
void on_btnClose_clicked();
void onLogsContextMenu(const QPoint &pos);
private:
Ui::GitLogDialog *ui;
GitLogModel mModel;
};
#endif // GITLOGDIALOG_H

View File

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GitLogDialog</class>
<widget class="QDialog" name="GitLogDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>922</width>
<height>613</height>
</rect>
</property>
<property name="windowTitle">
<string>Git Log</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTableView" name="tblLogs">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>250</number>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
</widget>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>795</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnClose">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
<action name="actionReset">
<property name="text">
<string>Reset</string>
</property>
</action>
<action name="actionRevert">
<property name="text">
<string>Revert</string>
</property>
</action>
<action name="actionBranch">
<property name="text">
<string>branch</string>
</property>
</action>
<action name="actionTag">
<property name="text">
<string>Tag</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -126,6 +126,65 @@ void GitManager::restore(const QString &folder, const QString &path)
runGit(folder,args); runGit(folder,args);
} }
int GitManager::logCounts(const QString &folder, const QString &branch)
{
QStringList args;
args.append("rev-list");
args.append("--count");
if (branch.isEmpty())
args.append("HEAD");
else
args.append(branch);
QString s = runGit(folder,args).trimmed();
bool ok;
int result = s.toInt(&ok);
if (!ok)
result = 0;
return result;
}
QList<PGitCommitInfo> GitManager::log(const QString &folder, int start, int count, const QString &branch)
{
QStringList args;
args.append("log");
args.append("--skip");
args.append(QString("%1").arg(start-1));
args.append("-n");
args.append(QString("%1").arg(count));
args.append("--format=medium");
args.append("--date=iso-strict");
if (branch.isEmpty())
args.append("HEAD");
else
args.append(branch);
QString output = runGit(folder,args);
QStringList lines = textToLines(output);
QList<PGitCommitInfo> result;
int pos = 0;
PGitCommitInfo commitInfo;
while (pos<lines.length()) {
if (lines[pos].startsWith("commit ")) {
commitInfo = std::make_shared<GitCommitInfo>();
commitInfo->commitHash=lines[pos].mid(QString("commit ").length()).trimmed();
result.append(commitInfo);
} else if(!commitInfo) {
break;
} else if (lines[pos].startsWith("Author:")) {
commitInfo->author=lines[pos].mid(QString("Author:").length()).trimmed();
} else if (lines[pos].startsWith("Date:")) {
commitInfo->authorDate=QDateTime::fromString(lines[pos].mid(QString("Date:").length()).trimmed(),Qt::ISODate);
} else if (!lines[pos].trimmed().isEmpty()) {
if (commitInfo->title.isEmpty()) {
commitInfo->title = lines[pos].trimmed();
} else {
commitInfo->fullCommitMessage.append(lines[pos].trimmed()+"\n");
}
}
pos++;
}
return result;
}
QStringList GitManager::listFiles(const QString &folder) QStringList GitManager::listFiles(const QString &folder)
{ {
QStringList args; QStringList args;

View File

@ -33,6 +33,9 @@ public:
void rename(const QString& folder, const QString& oldName, const QString& newName); void rename(const QString& folder, const QString& oldName, const QString& newName);
void restore(const QString& folder, const QString& path); void restore(const QString& folder, const QString& path);
int logCounts(const QString& folder, const QString& branch=QString());
QList<PGitCommitInfo> log(const QString& folder, int start, int count, const QString& branch=QString());
QStringList listFiles(const QString& folder); QStringList listFiles(const QString& folder);
QStringList listStagedFiles(const QString& folder); QStringList listStagedFiles(const QString& folder);
QStringList listChangedFiles(const QString& folder); QStringList listChangedFiles(const QString& folder);

View File

@ -1,6 +1,11 @@
#ifndef GITUTILS_H #ifndef GITUTILS_H
#define GITUTILS_H #define GITUTILS_H
#include <QDateTime>
#include <QString>
#include <memory>
enum class GitResetStrategy { enum class GitResetStrategy {
Soft, Soft,
Hard, Hard,
@ -30,4 +35,14 @@ enum class GitMergeStrategyOption {
Subtree Subtree
}; };
struct GitCommitInfo {
QString commitHash;
QString author;
QDateTime authorDate;
QString title;
QString fullCommitMessage;
};
using PGitCommitInfo = std::shared_ptr<GitCommitInfo>;
#endif // GITUTILS_H #endif // GITUTILS_H

View File

@ -7,7 +7,7 @@ SUBDIRS += \
APP_NAME = RedPandaCPP APP_NAME = RedPandaCPP
APP_VERSION = 0.14.3 APP_VERSION = 0.14.4
linux: { linux: {