- enhancement: git - restore

This commit is contained in:
Roy Qu 2022-02-15 21:39:17 +08:00
parent d09c101dd6
commit 6177398ce6
16 changed files with 762 additions and 610 deletions

16
NEWS.md
View File

@ -1,15 +1,17 @@
- change: rename "compile log" panel to "tools output"
- fix: debug panel can't be correctly show/hide
- enhancement: redesign tools output's context menu, add "clear" menu item
- enhancement: tools -> git in the options dialog
- enhancement: auto detect git in PATH
- enhancement: basic git commands
Red Panda C++ Version 0.14.3
- fix: wrong code completion font size, when screen dpi changed
- enhancement: replace Files View Panel's path lineedit control with combo box
- enhancement: custome icons for project view
- fix: convert to encoding setting in compiler set option not correctly handled
- change: rename "compile log" panel to "tools output"
- fix: debug panel can't be correctly show/hide
- enhancement: redesign tools output's context menu, add "clear" menu item
- enhancement: tools -> git in the options dialog
- enhancement: auto detect git in PATH
- enhancement: git - create repository
- enhancement: git - add files
- enhancement: git - commit
- enhancement: git - restore
Red Panda C++ Version 0.14.2
- enhancement: file system view mode for project

View File

@ -93,6 +93,7 @@ SOURCES += \
toolsmanager.cpp \
vcs/gitmanager.cpp \
vcs/gitrepository.cpp \
vcs/gitutils.cpp \
widgets/aboutdialog.cpp \
widgets/bookmarkmodel.cpp \
widgets/classbrowser.cpp \
@ -224,6 +225,7 @@ HEADERS += \
toolsmanager.h \
vcs/gitmanager.h \
vcs/gitrepository.h \
vcs/gitutils.h \
widgets/aboutdialog.h \
widgets/bookmarkmodel.h \
widgets/classbrowser.h \

File diff suppressed because it is too large Load Diff

View File

@ -22,6 +22,11 @@ void CustomFileIconProvider::update()
mVCSRepository->update();
}
GitRepository *CustomFileIconProvider::VCSRepository() const
{
return mVCSRepository;
}
QIcon CustomFileIconProvider::icon(IconType type) const
{
if (type == IconType::Folder) {
@ -86,6 +91,15 @@ QIcon CustomFileIconProvider::icon(const QFileInfo &info) const
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_PROJECTFILE_VCS_NOCHANGE);
} else
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_PROJECTFILE);
} else {
if (mVCSRepository->isFileInRepository(info)) {
if (mVCSRepository->isFileStaged(info))
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_FILE_VCS_STAGED);
else if (mVCSRepository->isFileChanged(info))
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_FILE_VCS_CHANGED);
else
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_FILE_VCS_NOCHANGE);
} //use default system icon
}
if (!icon.isNull())
return icon;

View File

@ -17,6 +17,7 @@ private:
public:
QIcon icon(IconType type) const override;
QIcon icon(const QFileInfo &info) const override;
GitRepository *VCSRepository() const;
};
#endif // CUSTOMFILEICONPROVIDER_H

View File

@ -747,16 +747,17 @@ void MainWindow::updateDPI()
void MainWindow::onFileSaved(const QString &path, bool inProject)
{
qDebug()<<path<<inProject<<mFileSystemModel.rootPath();
if (inProject && mProject) {
mProject->model()->beginUpdate();
mProject->model()->endUpdate();
}
QModelIndex index = mFileSystemModel.index(path);
if (index.isValid()) {
mFileSystemModelIconProvider.update();
mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
ui->treeFiles->update(index);
if (pSettings->vcs().gitOk()) {
if (inProject && mProject) {
mProject->model()->beginUpdate();
mProject->model()->endUpdate();
}
QModelIndex index = mFileSystemModel.index(path);
if (index.isValid()) {
mFileSystemModelIconProvider.update();
mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
ui->treeFiles->update(index);
}
}
pMainWindow->updateForEncodingInfo();
}
@ -2974,6 +2975,7 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos)
bool onUnit = false;
bool onRoot = false;
bool folderEmpty = false;
bool multiSelection = ui->projectView->selectionModel()->selectedRows().count()>1;
int unitIndex = -1;
QModelIndex current = mProjectProxyModel->mapToSource(ui->projectView->selectionModel()->currentIndex());
if (current.isValid() && mProject) {
@ -3006,7 +3008,7 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos)
if (!onFolder) {
menu.addAction(ui->actionRemove_from_project);
}
if (onUnit) {
if (onUnit && !multiSelection) {
menu.addAction(mProject_Rename_Unit);
}
menu.addSeparator();
@ -3040,16 +3042,41 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos)
menu.addAction(ui->actionProject_options);
if (pSettings->vcs().gitOk() && hasRepository) {
vcsMenu.setTitle(tr("VCS"));
if (ui->projectView->selectionModel()->hasSelection())
vcsMenu.addAction(ui->actionGit_Add_Files);
vcsMenu.setTitle(tr("Version Control"));
if (ui->projectView->selectionModel()->hasSelection()) {
bool shouldAdd = true;
foreach (const QModelIndex& index, ui->projectView->selectionModel()->selectedRows()) {
if (!index.isValid()) {
shouldAdd=false;
break;
}
QModelIndex realIndex = mProjectProxyModel->mapToSource(index);
ProjectModelNode * node = static_cast<ProjectModelNode*>(realIndex.internalPointer());
if (!node || node->unitIndex<0) {
shouldAdd=false;
break;
}
PProjectUnit pUnit=mProject->units()[node->unitIndex];
if (mProject->model()->iconProvider()->VCSRepository()->isFileInRepository(
pUnit->fileName()
)) {
shouldAdd=false;
break;
}
}
if (shouldAdd)
vcsMenu.addAction(ui->actionGit_Add_Files);
}
vcsMenu.addAction(ui->actionGit_Commit);
vcsMenu.addAction(ui->actionGit_Reset);
vcsMenu.addAction(ui->actionGit_Revert);
vcsMenu.addAction(ui->actionGit_Restore);
ui->actionGit_Commit->setEnabled(true);
ui->actionGit_Reset->setEnabled(true);
ui->actionGit_Revert->setEnabled(true);
ui->actionGit_Restore->setEnabled(true);
// vcsMenu.addAction(ui->actionGit_Reset);
// vcsMenu.addAction(ui->actionGit_Revert);
// ui->actionGit_Reset->setEnabled(true);
// ui->actionGit_Revert->setEnabled(true);
}
menu.exec(ui->projectView->mapToGlobal(pos));
}
@ -3135,16 +3162,30 @@ void MainWindow::onFilesViewContextMenu(const QPoint &pos)
mFilesView_OpenInExplorer->setEnabled(!path.isEmpty());
if (pSettings->vcs().gitOk() && hasRepository) {
vcsMenu.setTitle(tr("VCS"));
if (ui->treeFiles->selectionModel()->hasSelection())
vcsMenu.addAction(ui->actionGit_Add_Files);
vcsMenu.setTitle(tr("Version Control"));
if (ui->treeFiles->selectionModel()->hasSelection()) {
bool shouldAdd = true;
foreach (const QModelIndex& index, ui->treeFiles->selectionModel()->selectedRows()) {
if (mFileSystemModelIconProvider.VCSRepository()->isFileInRepository(
mFileSystemModel.fileInfo(index)
)) {
shouldAdd=false;
break;
}
}
if (shouldAdd)
vcsMenu.addAction(ui->actionGit_Add_Files);
}
vcsMenu.addAction(ui->actionGit_Commit);
vcsMenu.addAction(ui->actionGit_Reset);
vcsMenu.addAction(ui->actionGit_Revert);
vcsMenu.addAction(ui->actionGit_Restore);
ui->actionGit_Commit->setEnabled(true);
ui->actionGit_Reset->setEnabled(true);
ui->actionGit_Revert->setEnabled(true);
ui->actionGit_Restore->setEnabled(true);
// vcsMenu.addAction(ui->actionGit_Reset);
// vcsMenu.addAction(ui->actionGit_Revert);
// ui->actionGit_Reset->setEnabled(true);
// ui->actionGit_Revert->setEnabled(true);
}
menu.exec(ui->treeFiles->mapToGlobal(pos));
}
@ -6555,17 +6596,38 @@ void MainWindow::on_actionGit_Create_Repository_triggered()
if (ui->treeFiles->isVisible()) {
GitManager vcsManager;
vcsManager.createRepository(pSettings->environment().currentFolder());
//update files view;
int pos = ui->cbFilesPath->findText(pSettings->environment().currentFolder());
if (pos>=0) {
ui->cbFilesPath->setItemIcon(pos, pIconsManager->getIcon(IconsManager::FILESYSTEM_GIT));
}
mFileSystemModelIconProvider.update();
mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
//update project view
if (mProject && mProject->folder() == mFileSystemModel.rootPath()) {
mProject->addUnit(includeTrailingPathDelimiter(mProject->folder())+".gitignore", mProject->rootNode(), true);
} else if (mProject && mFileSystemModel.index(mProject->folder()).isValid()) {
mProject->model()->beginUpdate();
mProject->model()->endUpdate();
}
} else if (ui->projectView->isVisible() && mProject) {
GitManager vcsManager;
vcsManager.createRepository(mProject->folder());
}
if (mProject) {
mProject->model()->beginUpdate();
mProject->model()->endUpdate();
vcsManager.add(mProject->folder(), extractFileName(mProject->filename()));
//update project view
mProject->addUnit(includeTrailingPathDelimiter(mProject->folder())+".gitignore", mProject->rootNode(), true);
mProject->saveAll();
if (mProject->folder() == mFileSystemModel.rootPath()
|| mFileSystemModel.rootPath().startsWith(includeTrailingPathDelimiter(mProject->folder()), PATH_SENSITIVITY)) {
//update files view;
int pos = ui->cbFilesPath->findText(pSettings->environment().currentFolder());
if (pos>=0) {
ui->cbFilesPath->setItemIcon(pos, pIconsManager->getIcon(IconsManager::FILESYSTEM_GIT));
}
mFileSystemModelIconProvider.update();
mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
}
}
}
@ -6620,10 +6682,39 @@ void MainWindow::on_actionGit_Commit_triggered()
if (folder.isEmpty())
return;
QString message = QInputDialog::getText(this,tr("Commit Message"),"Commit Message:");
if (message.isEmpty())
if (message.isEmpty()) {
QMessageBox::critical(this,
tr("Commit Failed"),
tr("Commit message shouldn't be empty!")
);
return;
GitRepository repository(folder);
repository.commit(message,true);
}
GitManager vcsManager;
vcsManager.commit(folder,message,true);
//update project view
if (mProject) {
mProject->model()->beginUpdate();
mProject->model()->endUpdate();
}
//update files view
mFileSystemModelIconProvider.update();
mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
}
void MainWindow::on_actionGit_Restore_triggered()
{
QString folder;
if (ui->treeFiles->isVisible()) {
folder = pSettings->environment().currentFolder();
} else if (ui->projectView->isVisible() && mProject) {
folder = mProject->folder();
}
if (folder.isEmpty())
return;
GitManager vcsManager;
vcsManager.restore(folder,"");
//update project view
if (mProject) {

View File

@ -584,6 +584,8 @@ private slots:
void on_actionGit_Commit_triggered();
void on_actionGit_Restore_triggered();
private:
Ui::MainWindow *ui;
EditorList *mEditorList;

View File

@ -85,7 +85,7 @@
<enum>QTabWidget::West</enum>
</property>
<property name="currentIndex">
<number>3</number>
<number>0</number>
</property>
<property name="usesScrollButtons">
<bool>true</bool>
@ -126,7 +126,7 @@
<enum>Qt::MoveAction</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
@ -1603,8 +1603,7 @@
<addaction name="actionGit_Create_Repository"/>
<addaction name="separator"/>
<addaction name="actionGit_Commit"/>
<addaction name="actionGit_Revert"/>
<addaction name="actionGit_Reset"/>
<addaction name="actionGit_Restore"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
@ -2756,7 +2755,7 @@
</action>
<action name="actionGit_Create_Repository">
<property name="text">
<string>Create Repository</string>
<string>Create Git Repository</string>
</property>
</action>
<action name="actionGit_Commit">
@ -2779,6 +2778,11 @@
<string>Add Files</string>
</property>
</action>
<action name="actionGit_Restore">
<property name="text">
<string>Restore</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -36,7 +36,7 @@
#include "customfileiconprovider.h"
#include <QMimeData>
#include "settings.h"
#include "vcs/gitmanager.h"
#include "vcs/gitrepository.h"
Project::Project(const QString &filename, const QString &name, QObject *parent) :
QObject(parent),
@ -904,10 +904,6 @@ PProjectUnit Project::addUnit(const QString &inFileName, PProjectModelNode paren
newUnit->setOverrideBuildCmd(false);
newUnit->setBuildCmd("");
if (rebuild) {
mModel.beginUpdate();
auto action = finally([this]{
mModel.endUpdate();
});
rebuildNodes();
}
setModified(true);
@ -1910,13 +1906,11 @@ ProjectModel::ProjectModel(Project *project, QObject *parent):
mProject(project)
{
mUpdateCount = 0;
mVCSRepository = new GitRepository("");
mIconProvider = new CustomFileIconProvider();
}
ProjectModel::~ProjectModel()
{
delete mVCSRepository;
delete mIconProvider;
}
@ -1932,12 +1926,16 @@ void ProjectModel::endUpdate()
{
mUpdateCount--;
if (mUpdateCount==0) {
mVCSRepository->setFolder(mProject->folder());
mIconProvider->setRootFolder(mProject->folder());
endResetModel();
}
}
CustomFileIconProvider *ProjectModel::iconProvider() const
{
return mIconProvider;
}
Project *ProjectModel::project() const
{
return mProject;
@ -1994,7 +1992,7 @@ QVariant ProjectModel::data(const QModelIndex &index, int role) const
if (role == Qt::DisplayRole) {
if (p == mProject->rootNode().get()) {
QString branch;
if (mVCSRepository->hasRepository(branch))
if (mIconProvider->VCSRepository()->hasRepository(branch))
return QString("%1 [%2]").arg(p->text,branch);
}
return p->text;
@ -2007,7 +2005,7 @@ QVariant ProjectModel::data(const QModelIndex &index, int role) const
} else {
if (p == mProject->rootNode().get()) {
QString branch;
if (mVCSRepository->hasRepository(branch))
if (mIconProvider->VCSRepository()->hasRepository(branch))
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_GIT);
} else {
switch(p->folderNodeType) {

View File

@ -112,7 +112,6 @@ public:
void endUpdate();
private:
Project* mProject;
GitRepository *mVCSRepository;
int mUpdateCount;
CustomFileIconProvider* mIconProvider;
@ -136,6 +135,7 @@ public:
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
QMimeData *mimeData(const QModelIndexList &indexes) const override;
Project *project() const;
CustomFileIconProvider *iconProvider() const;
};
class ProjectModelSortFilterProxy : public QSortFilterProxyModel

View File

@ -119,7 +119,10 @@ void GitManager::restore(const QString &folder, const QString &path)
{
QStringList args;
args.append("restore");
args.append(path);
if (path.isEmpty())
args.append(".");
else
args.append(path);
runGit(folder,args);
}
@ -155,10 +158,12 @@ void GitManager::clone(const QString &folder, const QString &url)
runGit(folder,args);
}
void GitManager::commit(const QString &folder, const QString &message)
void GitManager::commit(const QString &folder, const QString &message, bool autoStage)
{
QStringList args;
args.append("commit");
if (autoStage)
args.append("-a");
args.append("-m");
args.append(message);
runGit(folder,args);

View File

@ -5,7 +5,7 @@
#include <QFileInfo>
#include <QSet>
#include "utils.h"
#include "gitrepository.h"
#include "gitutils.h"
class GitError: public BaseError {
public:
@ -32,12 +32,13 @@ public:
void remove(const QString& folder, const QString& path);
void rename(const QString& folder, const QString& oldName, const QString& newName);
void restore(const QString& folder, const QString& path);
QStringList listFiles(const QString& folder);
QStringList listStagedFiles(const QString& folder);
QStringList listChangedFiles(const QString& folder);
void clone(const QString& folder, const QString& url);
void commit(const QString& folder, const QString& message);
void commit(const QString& folder, const QString& message, bool autoStage);
void revert(const QString& folder);
void reset(const QString& folder, const QString& commit, GitResetStrategy strategy);

View File

@ -62,16 +62,9 @@ void GitRepository::clone(const QString &url)
mManager->clone(mFolder,url);
}
void GitRepository::commit(const QString &message, bool autoAdd)
void GitRepository::commit(const QString &message, bool autoStage)
{
if (autoAdd) {
convertFilesListToSet(mManager->listChangedFiles(mRealFolder),mChangedFiles);
foreach(const QString& s, mChangedFiles) {
QFileInfo info(s);
mManager->add(info.absolutePath(),info.fileName());
}
}
mManager->commit(mRealFolder, message);
mManager->commit(mRealFolder, message, autoStage);
}
void GitRepository::revert()

View File

@ -5,14 +5,7 @@
#include <QObject>
#include <QSet>
#include <memory>
enum class GitResetStrategy {
Soft,
Hard,
Merge,
Mixed,
Keep
};
#include "gitutils.h"
class GitManager;
class GitRepository : public QObject
@ -53,7 +46,7 @@ public:
QSet<QString> listFiles(bool refresh);
void clone(const QString& url);
void commit(const QString& message, bool autoAdd=true);
void commit(const QString& message, bool autoStage=true);
void revert();
void reset(const QString& commit, GitResetStrategy strategy);

View File

@ -0,0 +1,2 @@
#include "gitutils.h"

View File

@ -0,0 +1,12 @@
#ifndef GITUTILS_H
#define GITUTILS_H
enum class GitResetStrategy {
Soft,
Hard,
Merge,
Mixed,
Keep
};
#endif // GITUTILS_H