- fix: convert to encoding setting in compiler set option not correctly handled

work save:
  git repository class
This commit is contained in:
Roy Qu 2022-02-15 00:01:50 +08:00
parent de230c63c7
commit 664922a301
23 changed files with 479 additions and 85 deletions

View File

@ -1,11 +1,15 @@
- change: rename "compile log" panel to "tools output" - change: rename "compile log" panel to "tools output"
- fix: debug panel can't be correctly show/hide - fix: debug panel can't be correctly show/hide
- enhancement: redesign tools output's context menu, add "clear" menu item - 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 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
- enhancement: custome icons for project view - enhancement: custome icons for project view
- fix: convert to encoding setting in compiler set option not correctly handled
Red Panda C++ Version 0.14.2 Red Panda C++ Version 0.14.2
- enhancement: file system view mode for project - enhancement: file system view mode for project

View File

@ -292,8 +292,7 @@ QString Compiler::getCharsetArgument(const QByteArray& encoding)
} else { } else {
encodingName = encoding; encodingName = encoding;
} }
if (compilerSetExecCharset == ENCODING_SYSTEM_DEFAULT if (compilerSetExecCharset == ENCODING_SYSTEM_DEFAULT || compilerSetExecCharset.isEmpty()) {
|| compilerSetExecCharset.isEmpty()) {
execEncodingName = systemEncodingName; execEncodingName = systemEncodingName;
} else { } else {
execEncodingName = compilerSetExecCharset; execEncodingName = compilerSetExecCharset;

View File

@ -1,15 +1,25 @@
#include "customfileiconprovider.h" #include "customfileiconprovider.h"
#include "iconsmanager.h" #include "iconsmanager.h"
#include "vcs/gitmanager.h" #include "vcs/gitrepository.h"
CustomFileIconProvider::CustomFileIconProvider() CustomFileIconProvider::CustomFileIconProvider()
{ {
mVCSManager = new GitManager(); mVCSRepository = new GitRepository("");
} }
CustomFileIconProvider::~CustomFileIconProvider() CustomFileIconProvider::~CustomFileIconProvider()
{ {
delete mVCSManager; delete mVCSRepository;
}
void CustomFileIconProvider::setRootFolder(const QString &folder)
{
mVCSRepository->setFolder(folder);
}
void CustomFileIconProvider::update()
{
mVCSRepository->update();
} }
QIcon CustomFileIconProvider::icon(IconType type) const QIcon CustomFileIconProvider::icon(IconType type) const
@ -27,50 +37,50 @@ QIcon CustomFileIconProvider::icon(const QFileInfo &info) const
{ {
QIcon icon; QIcon icon;
if (info.isDir()) { if (info.isDir()) {
if (mVCSManager && mVCSManager->isFileInRepository(info)) { if (mVCSRepository->isFileInRepository(info)) {
if (mVCSManager->isFileInStaged(info)) if (mVCSRepository->isFileStaged(info))
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_FOLDER_VCS_STAGED); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_FOLDER_VCS_STAGED);
else if (mVCSManager->isFileChanged(info)) else if (mVCSRepository->isFileChanged(info))
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_FOLDER_VCS_CHANGED); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_FOLDER_VCS_CHANGED);
else else
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_FOLDER_VCS_NOCHANGE); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_FOLDER_VCS_NOCHANGE);
} else } else
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_FOLDER); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_FOLDER);
} if (isHFile(info.fileName())) { } else if (isHFile(info.fileName())) {
if (mVCSManager && mVCSManager->isFileInRepository(info)) { if (mVCSRepository->isFileInRepository(info)) {
if (mVCSManager->isFileInStaged(info)) if (mVCSRepository->isFileStaged(info))
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_HFILE_VCS_STAGED); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_HFILE_VCS_STAGED);
else if (mVCSManager->isFileChanged(info)) else if (mVCSRepository->isFileChanged(info))
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_HFILE_VCS_CHANGED); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_HFILE_VCS_CHANGED);
else else
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_HFILE_VCS_NOCHANGE); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_HFILE_VCS_NOCHANGE);
} else } else
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_HFILE); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_HFILE);
} else if (isCppFile(info.fileName())) { } else if (isCppFile(info.fileName())) {
if (mVCSManager && mVCSManager->isFileInRepository(info)) { if (mVCSRepository->isFileInRepository(info)) {
if (mVCSManager->isFileInStaged(info)) if (mVCSRepository->isFileStaged(info))
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CPPFILE_VCS_STAGED); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CPPFILE_VCS_STAGED);
else if (mVCSManager->isFileChanged(info)) else if (mVCSRepository->isFileChanged(info))
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CPPFILE_VCS_CHANGED); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CPPFILE_VCS_CHANGED);
else else
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CPPFILE_VCS_NOCHANGE); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CPPFILE_VCS_NOCHANGE);
} else } else
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CPPFILE); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CPPFILE);
} else if (isCFile(info.fileName())) { } else if (isCFile(info.fileName())) {
if (mVCSManager && mVCSManager->isFileInRepository(info)) { if (mVCSRepository->isFileInRepository(info)) {
if (mVCSManager->isFileInStaged(info)) if (mVCSRepository->isFileStaged(info))
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CFILE_VCS_STAGED); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CFILE_VCS_STAGED);
else if (mVCSManager->isFileChanged(info)) else if (mVCSRepository->isFileChanged(info))
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CFILE_VCS_CHANGED); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CFILE_VCS_CHANGED);
else else
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CFILE_VCS_NOCHANGE); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CFILE_VCS_NOCHANGE);
} else } else
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CFILE); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_CFILE);
} else if (info.suffix()=="dev") { } else if (info.suffix()=="dev") {
if (mVCSManager && mVCSManager->isFileInRepository(info)) { if (mVCSRepository->isFileInRepository(info)) {
if (mVCSManager->isFileInStaged(info)) if (mVCSRepository->isFileStaged(info))
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_PROJECTFILE_VCS_STAGED); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_PROJECTFILE_VCS_STAGED);
else if (mVCSManager->isFileChanged(info)) else if (mVCSRepository->isFileChanged(info))
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_PROJECTFILE_VCS_CHANGED); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_PROJECTFILE_VCS_CHANGED);
else else
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_PROJECTFILE_VCS_NOCHANGE); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_PROJECTFILE_VCS_NOCHANGE);

View File

@ -3,14 +3,16 @@
#include <QFileIconProvider> #include <QFileIconProvider>
class GitManager; class GitRepository;
class CustomFileIconProvider : public QFileIconProvider class CustomFileIconProvider : public QFileIconProvider
{ {
public: public:
CustomFileIconProvider(); CustomFileIconProvider();
~CustomFileIconProvider(); ~CustomFileIconProvider();
void setRootFolder(const QString& folder);
void update();
private: private:
GitManager* mVCSManager; GitRepository* mVCSRepository;
// QFileIconProvider interface // QFileIconProvider interface
public: public:
QIcon icon(IconType type) const override; QIcon icon(IconType type) const override;

View File

@ -68,7 +68,7 @@ const char* SaveException::what() const noexcept {
} }
Editor::Editor(QWidget *parent): Editor::Editor(QWidget *parent):
Editor(parent,QObject::tr("untitled"),ENCODING_SYSTEM_DEFAULT,false,true,nullptr) Editor(parent,QObject::tr("untitled"),ENCODING_AUTO_DETECT,false,true,nullptr)
{ {
} }

View File

@ -162,6 +162,11 @@ int main(int argc, char *argv[])
//set default open folder //set default open folder
QDir::setCurrent(pSettings->environment().defaultOpenFolder()); QDir::setCurrent(pSettings->environment().defaultOpenFolder());
//auto detect git in path
if (!pSettings->vcs().gitOk()) {
pSettings->vcs().detectGitInPath();
}
MainWindow mainWindow; MainWindow mainWindow;
pMainWindow = &mainWindow; pMainWindow = &mainWindow;
if (app.arguments().count()>1) { if (app.arguments().count()>1) {

View File

@ -39,6 +39,7 @@
#include "iconsmanager.h" #include "iconsmanager.h"
#include "widgets/newclassdialog.h" #include "widgets/newclassdialog.h"
#include "widgets/newheaderdialog.h" #include "widgets/newheaderdialog.h"
#include "vcs/gitmanager.h"
#include <QCloseEvent> #include <QCloseEvent>
#include <QComboBox> #include <QComboBox>
@ -287,7 +288,7 @@ MainWindow::MainWindow(QWidget *parent)
//files view //files view
ui->treeFiles->setModel(&mFileSystemModel); ui->treeFiles->setModel(&mFileSystemModel);
mFileSystemModel.setReadOnly(false); mFileSystemModel.setReadOnly(false);
mFileSystemModel.setIconProvider(&mFileIconProvider); mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
setFilesViewRoot(pSettings->environment().currentFolder()); setFilesViewRoot(pSettings->environment().currentFolder());
for (int i=1;i<mFileSystemModel.columnCount();i++) { for (int i=1;i<mFileSystemModel.columnCount();i++) {
ui->treeFiles->hideColumn(i); ui->treeFiles->hideColumn(i);
@ -324,6 +325,9 @@ MainWindow::MainWindow(QWidget *parent)
ui->actionEGE_Manual->setVisible(pSettings->environment().language()=="zh_CN"); ui->actionEGE_Manual->setVisible(pSettings->environment().language()=="zh_CN");
//git menu
connect(ui->menuGit, &QMenu::aboutToShow,
this, &MainWindow::updateVCSActions);
buildContextMenus(); buildContextMenus();
updateAppTitle(); updateAppTitle();
//applySettings(); //applySettings();
@ -425,7 +429,8 @@ void MainWindow::updateEditorActions()
ui->actionAuto_Detect->setEnabled(true); ui->actionAuto_Detect->setEnabled(true);
ui->actionEncode_in_ANSI->setEnabled(true); ui->actionEncode_in_ANSI->setEnabled(true);
ui->actionEncode_in_UTF_8->setEnabled(true); ui->actionEncode_in_UTF_8->setEnabled(true);
ui->actionConvert_to_ANSI->setEnabled(e->encodingOption()!=ENCODING_SYSTEM_DEFAULT && e->fileEncoding()!=ENCODING_SYSTEM_DEFAULT); ui->actionConvert_to_ANSI->setEnabled(e->encodingOption()!=ENCODING_SYSTEM_DEFAULT
&& e->fileEncoding()!=ENCODING_SYSTEM_DEFAULT);
ui->actionConvert_to_UTF_8->setEnabled(e->encodingOption()!=ENCODING_UTF8 && e->fileEncoding()!=ENCODING_UTF8); ui->actionConvert_to_UTF_8->setEnabled(e->encodingOption()!=ENCODING_UTF8 && e->fileEncoding()!=ENCODING_UTF8);
ui->actionCopy->setEnabled(e->selAvail()); ui->actionCopy->setEnabled(e->selAvail());
@ -663,6 +668,8 @@ void MainWindow::applySettings()
// ui->cbFilesPath->setItemIcon(i,pIconsManager->getIcon(IconsManager::FILESYSTEM_GIT)); // ui->cbFilesPath->setItemIcon(i,pIconsManager->getIcon(IconsManager::FILESYSTEM_GIT));
// } // }
ui->menuGit->menuAction()->setVisible(pSettings->vcs().gitOk());
} }
void MainWindow::applyUISettings() void MainWindow::applyUISettings()
@ -2968,7 +2975,12 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos)
onRoot = true; onRoot = true;
} }
} }
GitManager vcsManager;
QString branch;
bool hasRepository = vcsManager.hasRepository(mProject->folder(),branch);
QMenu menu(this); QMenu menu(this);
QMenu vcsMenu(this);
updateProjectActions(); updateProjectActions();
menu.addAction(ui->actionProject_New_File); menu.addAction(ui->actionProject_New_File);
menu.addAction(ui->actionNew_Class); menu.addAction(ui->actionNew_Class);
@ -2981,6 +2993,15 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos)
menu.addAction(mProject_Rename_Unit); menu.addAction(mProject_Rename_Unit);
} }
menu.addSeparator(); menu.addSeparator();
if (pSettings->vcs().gitOk()) {
if (hasRepository) {
menu.addMenu(&vcsMenu);
} else {
ui->actionGit_Create_Repository->setEnabled(true);
menu.addAction(ui->actionGit_Create_Repository);
}
menu.addSeparator();
}
if (onFolder && mProject->modelType()==ProjectModelType::Custom) { if (onFolder && mProject->modelType()==ProjectModelType::Custom) {
menu.addAction(mProject_Add_Folder); menu.addAction(mProject_Add_Folder);
if (!onRoot) { if (!onRoot) {
@ -3001,6 +3022,18 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos)
} }
menu.addAction(ui->actionProject_options); 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.addAction(ui->actionGit_Commit);
vcsMenu.addAction(ui->actionGit_Reset);
vcsMenu.addAction(ui->actionGit_Revert);
ui->actionGit_Commit->setEnabled(true);
ui->actionGit_Reset->setEnabled(true);
ui->actionGit_Revert->setEnabled(true);
}
menu.exec(ui->projectView->mapToGlobal(pos)); menu.exec(ui->projectView->mapToGlobal(pos));
} }
@ -3054,12 +3087,24 @@ void MainWindow::onFileEncodingContextMenu(const QPoint &pos)
void MainWindow::onFilesViewContextMenu(const QPoint &pos) void MainWindow::onFilesViewContextMenu(const QPoint &pos)
{ {
GitManager vcsManager;
QString branch;
bool hasRepository = vcsManager.hasRepository(pSettings->environment().currentFolder(),branch);
QMenu menu(this); QMenu menu(this);
QMenu vcsMenu(this);
menu.addAction(ui->actionOpen_Folder); menu.addAction(ui->actionOpen_Folder);
menu.addSeparator(); menu.addSeparator();
menu.addAction(mFilesView_CreateFolder); menu.addAction(mFilesView_CreateFolder);
menu.addSeparator(); menu.addSeparator();
if (pSettings->vcs().gitOk()) {
if (hasRepository) {
menu.addMenu(&vcsMenu);
} else {
ui->actionGit_Create_Repository->setEnabled(true);
menu.addAction(ui->actionGit_Create_Repository);
}
menu.addSeparator();
}
menu.addAction(mFilesView_Open); menu.addAction(mFilesView_Open);
menu.addAction(mFilesView_OpenWithExternal); menu.addAction(mFilesView_OpenWithExternal);
menu.addSeparator(); menu.addSeparator();
@ -3071,6 +3116,19 @@ void MainWindow::onFilesViewContextMenu(const QPoint &pos)
mFilesView_OpenWithExternal->setEnabled(info.isFile()); mFilesView_OpenWithExternal->setEnabled(info.isFile());
mFilesView_OpenInTerminal->setEnabled(!path.isEmpty()); mFilesView_OpenInTerminal->setEnabled(!path.isEmpty());
mFilesView_OpenInExplorer->setEnabled(!path.isEmpty()); 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.addAction(ui->actionGit_Commit);
vcsMenu.addAction(ui->actionGit_Reset);
vcsMenu.addAction(ui->actionGit_Revert);
ui->actionGit_Commit->setEnabled(true);
ui->actionGit_Reset->setEnabled(true);
ui->actionGit_Revert->setEnabled(true);
}
menu.exec(ui->treeFiles->mapToGlobal(pos)); menu.exec(ui->treeFiles->mapToGlobal(pos));
} }
@ -5501,6 +5559,7 @@ void MainWindow::newProjectUnitFile()
PProjectUnit newUnit = mProject->newUnit( PProjectUnit newUnit = mProject->newUnit(
mProject->pointerToNode(node),newFileName); mProject->pointerToNode(node),newFileName);
idx = mProject->units().count()-1; idx = mProject->units().count()-1;
mProject->rebuildNodes();
mProject->saveUnits(); mProject->saveUnits();
updateProjectView(); updateProjectView();
Editor * editor = mProject->openUnit(idx); Editor * editor = mProject->openUnit(idx);
@ -5528,6 +5587,27 @@ void MainWindow::doFilesViewRemoveFile(const QModelIndex &index)
} }
} }
void MainWindow::updateVCSActions()
{
bool hasRepository = false;
bool shouldEnable = false;
if (ui->projectView->isVisible()) {
GitManager vcsManager;
QString branch;
hasRepository = vcsManager.hasRepository(mProject->folder(),branch);
shouldEnable = true;
} else if (ui->treeFiles->isVisible()) {
GitManager vcsManager;
QString branch;
hasRepository = vcsManager.hasRepository(pSettings->environment().currentFolder(),branch);
shouldEnable = true;
}
ui->actionGit_Create_Repository->setEnabled(!hasRepository && shouldEnable);
ui->actionGit_Commit->setEnabled(hasRepository && shouldEnable);
ui->actionGit_Reset->setEnabled(hasRepository && shouldEnable);
ui->actionGit_Revert->setEnabled(hasRepository && shouldEnable);
}
void MainWindow::invalidateProjectProxyModel() void MainWindow::invalidateProjectProxyModel()
{ {
mProjectProxyModel->invalidate(); mProjectProxyModel->invalidate();
@ -5663,6 +5743,7 @@ void MainWindow::showSearchReplacePanel(bool show)
void MainWindow::setFilesViewRoot(const QString &path) void MainWindow::setFilesViewRoot(const QString &path)
{ {
mFileSystemModelIconProvider.setRootFolder(path);
mFileSystemModel.setRootPath(path); mFileSystemModel.setRootPath(path);
ui->treeFiles->setRootIndex(mFileSystemModel.index(path)); ui->treeFiles->setRootIndex(mFileSystemModel.index(path));
pSettings->environment().setCurrentFolder(path); pSettings->environment().setCurrentFolder(path);
@ -6450,3 +6531,58 @@ void MainWindow::on_actionNew_Class_triggered()
pSettings->ui().setNewHeaderDialogHeight(dialog.height()); pSettings->ui().setNewHeaderDialogHeight(dialog.height());
} }
void MainWindow::on_actionGit_Create_Repository_triggered()
{
if (ui->treeFiles->isVisible()) {
GitManager vcsManager;
vcsManager.createRepository(pSettings->environment().currentFolder());
int pos = ui->cbFilesPath->findText(pSettings->environment().currentFolder());
if (pos>=0) {
ui->cbFilesPath->setItemIcon(pos, pIconsManager->getIcon(IconsManager::FILESYSTEM_GIT));
}
} else if (ui->projectView->isVisible()) {
GitManager vcsManager;
vcsManager.createRepository(mProject->folder());
mProject->model()->beginUpdate();
mProject->model()->endUpdate();
}
}
void MainWindow::on_actionGit_Add_Files_triggered()
{
if (ui->treeFiles->isVisible()) {
GitManager vcsManager;
QModelIndexList indices = ui->treeFiles->selectionModel()->selectedRows();
foreach (const QModelIndex index,indices) {
QFileInfo info = mFileSystemModel.fileInfo(index);
vcsManager.add(info.absolutePath(),info.fileName());
}
//update icons in files view
mFileSystemModelIconProvider.update();
mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
} else if (ui->projectView->isVisible()) {
GitManager vcsManager;
QModelIndexList indices = ui->projectView->selectionModel()->selectedRows();
foreach (const QModelIndex index,indices) {
QModelIndex realIndex = mProjectProxyModel->mapToSource(index);
ProjectModelNode * node = static_cast<ProjectModelNode*>(realIndex.internalPointer());
PProjectModelNode folderNode = mProject->pointerToNode(node);
if (!folderNode)
continue;
if (folderNode->unitIndex>=0) {
PProjectUnit unit = mProject->units()[folderNode->unitIndex];
QFileInfo info(unit->fileName());
vcsManager.add(info.absolutePath(),info.fileName());
}
}
//update icons in project view
mProject->model()->beginUpdate();
mProject->model()->endUpdate();
//update icons in files view too
mFileSystemModelIconProvider.update();
mFileSystemModel.setIconProvider(&mFileSystemModelIconProvider);
}
}

View File

@ -38,6 +38,7 @@
#include "widgets/labelwithmenu.h" #include "widgets/labelwithmenu.h"
#include "widgets/bookmarkmodel.h" #include "widgets/bookmarkmodel.h"
#include "widgets/ojproblemsetmodel.h" #include "widgets/ojproblemsetmodel.h"
#include "widgets/customfilesystemmodel.h"
#include "customfileiconprovider.h" #include "customfileiconprovider.h"
@ -253,6 +254,7 @@ private:
void doFilesViewRemoveFile(const QModelIndex& index); void doFilesViewRemoveFile(const QModelIndex& index);
private slots: private slots:
void updateVCSActions();
void invalidateProjectProxyModel(); void invalidateProjectProxyModel();
void onEditorRenamed(const QString& oldFilename, const QString& newFilename, bool firstSave); void onEditorRenamed(const QString& oldFilename, const QString& newFilename, bool firstSave);
void onAutoSaveTimeout(); void onAutoSaveTimeout();
@ -576,6 +578,10 @@ private slots:
void on_actionNew_Header_triggered(); void on_actionNew_Header_triggered();
void on_actionGit_Create_Repository_triggered();
void on_actionGit_Add_Files_triggered();
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
EditorList *mEditorList; EditorList *mEditorList;
@ -615,8 +621,8 @@ private:
PCodeSnippetManager mCodeSnippetManager; PCodeSnippetManager mCodeSnippetManager;
PTodoParser mTodoParser; PTodoParser mTodoParser;
PToolsManager mToolsManager; PToolsManager mToolsManager;
QFileSystemModel mFileSystemModel; CustomFileSystemModel mFileSystemModel;
CustomFileIconProvider mFileIconProvider; CustomFileIconProvider mFileSystemModelIconProvider;
OJProblemSetModel mOJProblemSetModel; OJProblemSetModel mOJProblemSetModel;
OJProblemModel mOJProblemModel; OJProblemModel mOJProblemModel;
int mOJProblemSetNameCounter; int mOJProblemSetNameCounter;

View File

@ -229,7 +229,7 @@
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>2</number>
</property> </property>
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
@ -2774,6 +2774,11 @@
<string>Reset</string> <string>Reset</string>
</property> </property>
</action> </action>
<action name="actionGit_Add_Files">
<property name="text">
<string>Add Files</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -1910,12 +1910,14 @@ ProjectModel::ProjectModel(Project *project, QObject *parent):
mProject(project) mProject(project)
{ {
mUpdateCount = 0; mUpdateCount = 0;
mVCSManager = new GitManager(); mVCSRepository = new GitRepository("");
mIconProvider = new CustomFileIconProvider();
} }
ProjectModel::~ProjectModel() ProjectModel::~ProjectModel()
{ {
delete mVCSManager; delete mVCSRepository;
delete mIconProvider;
} }
void ProjectModel::beginUpdate() void ProjectModel::beginUpdate()
@ -1930,6 +1932,8 @@ void ProjectModel::endUpdate()
{ {
mUpdateCount--; mUpdateCount--;
if (mUpdateCount==0) { if (mUpdateCount==0) {
mVCSRepository->setFolder(mProject->folder());
mIconProvider->setRootFolder(mProject->folder());
endResetModel(); endResetModel();
} }
} }
@ -1990,21 +1994,20 @@ QVariant ProjectModel::data(const QModelIndex &index, int role) const
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole) {
if (p == mProject->rootNode().get()) { if (p == mProject->rootNode().get()) {
QString branch; QString branch;
if (mVCSManager->hasRepository(mProject->folder(),branch)) if (mVCSRepository->hasRepository(branch))
return QString("%1 [%2]").arg(p->text,branch); return QString("%1 [%2]").arg(p->text,branch);
} }
return p->text; return p->text;
} else if (role==Qt::EditRole) { } else if (role==Qt::EditRole) {
return p->text; return p->text;
} else if (role == Qt::DecorationRole) { } else if (role == Qt::DecorationRole) {
CustomFileIconProvider provider;
QIcon icon; QIcon icon;
if (p->unitIndex>=0) { if (p->unitIndex>=0) {
icon = provider.icon(mProject->units()[p->unitIndex]->fileName()); icon = mIconProvider->icon(mProject->units()[p->unitIndex]->fileName());
} else { } else {
if (p == mProject->rootNode().get()) { if (p == mProject->rootNode().get()) {
QString branch; QString branch;
if (mVCSManager->hasRepository(mProject->folder(),branch)) if (mVCSRepository->hasRepository(branch))
icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_GIT); icon = pIconsManager->getIcon(IconsManager::FILESYSTEM_GIT);
} else { } else {
switch(p->folderNodeType) { switch(p->folderNodeType) {
@ -2019,7 +2022,7 @@ QVariant ProjectModel::data(const QModelIndex &index, int role) const
} }
} }
if (icon.isNull()) if (icon.isNull())
icon = provider.icon(QFileIconProvider::Folder); icon = mIconProvider->icon(QFileIconProvider::Folder);
} }
return icon; return icon;
} }

View File

@ -101,7 +101,8 @@ private:
using PProjectUnit = std::shared_ptr<ProjectUnit>; using PProjectUnit = std::shared_ptr<ProjectUnit>;
class GitManager; class GitRepository;
class CustomFileIconProvider;
class ProjectModel : public QAbstractItemModel { class ProjectModel : public QAbstractItemModel {
Q_OBJECT Q_OBJECT
public: public:
@ -111,8 +112,9 @@ public:
void endUpdate(); void endUpdate();
private: private:
Project* mProject; Project* mProject;
GitManager *mVCSManager; GitRepository *mVCSRepository;
int mUpdateCount; int mUpdateCount;
CustomFileIconProvider* mIconProvider;
// QAbstractItemModel interface // QAbstractItemModel interface

View File

@ -5083,9 +5083,9 @@ void Settings::UI::doLoad()
mNewHeaderDialogHeight = intValue("new_header_dialog_height", 300*qApp->desktop()->height()/1080); mNewHeaderDialogHeight = intValue("new_header_dialog_height", 300*qApp->desktop()->height()/1080);
} }
Settings::VCS::VCS(Settings *settings):_Base(settings,SETTING_VCS) Settings::VCS::VCS(Settings *settings):_Base(settings,SETTING_VCS),
mGitOk(false)
{ {
} }
void Settings::VCS::doSave() void Settings::VCS::doSave()
@ -5095,7 +5095,7 @@ void Settings::VCS::doSave()
void Settings::VCS::doLoad() void Settings::VCS::doLoad()
{ {
mGitPath = stringValue("git_path", ""); setGitPath(stringValue("git_path", ""));
} }
const QString &Settings::VCS::gitPath() const const QString &Settings::VCS::gitPath() const
@ -5105,5 +5105,54 @@ const QString &Settings::VCS::gitPath() const
void Settings::VCS::setGitPath(const QString &newGitPath) void Settings::VCS::setGitPath(const QString &newGitPath)
{ {
mGitPath = newGitPath; if (mGitPath!=newGitPath) {
mGitPath = newGitPath;
validateGit();
}
}
void Settings::VCS::validateGit()
{
mGitOk = false;
QFileInfo fileInfo(mGitPath);
if (!fileInfo.exists()) {
return;
}
QStringList args;
args.append("--version");
QString output = runAndGetOutput(
fileInfo.fileName(),
fileInfo.absolutePath(),
args);
mGitOk = output.startsWith("git version");
}
bool Settings::VCS::gitOk() const
{
return mGitOk;
}
void Settings::VCS::detectGitInPath()
{
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
QString path = env.value("PATH");
QStringList pathList = path.split(PATH_SEPARATOR);
QSet<QString> searched;
foreach (const QString& s, pathList){
if (searched.contains(s))
continue;;
searched.insert(s);
QDir dir(s);
if (dir.exists(GIT_PROGRAM)) {
QString oldPath = mGitPath;
setGitPath(dir.filePath(GIT_PROGRAM));
if (mGitOk) {
doSave();
return;
} else {
mGitPath = oldPath;
}
}
}
} }

View File

@ -887,8 +887,13 @@ public:
explicit VCS(Settings *settings); explicit VCS(Settings *settings);
const QString &gitPath() const; const QString &gitPath() const;
void setGitPath(const QString &newGitPath); void setGitPath(const QString &newGitPath);
bool gitOk() const;
void detectGitInPath();
private:
void validateGit();
private: private:
QString mGitPath; QString mGitPath;
bool mGitOk;
protected: protected:
void doSave() override; void doSave() override;
void doLoad() override; void doLoad() override;

View File

@ -246,7 +246,7 @@ void CompilerSetOptionWidget::saveCurrentCompilerSet()
if (ui->cbEncodingDetails->isVisible()) { if (ui->cbEncodingDetails->isVisible()) {
pSet->setExecCharset(ui->cbEncodingDetails->currentText()); pSet->setExecCharset(ui->cbEncodingDetails->currentText());
} else { } else {
pSet->setExecCharset(ui->cbEncoding->currentText()); pSet->setExecCharset(ui->cbEncoding->currentData().toString());
} }
//read values in the options widget //read values in the options widget

View File

@ -4,6 +4,7 @@
#include "../settings.h" #include "../settings.h"
#include "../systemconsts.h" #include "../systemconsts.h"
#include "../utils.h" #include "../utils.h"
#include "../mainwindow.h"
#include <QFileDialog> #include <QFileDialog>
@ -29,6 +30,7 @@ void ToolsGitWidget::doSave()
{ {
pSettings->vcs().setGitPath(ui->txtGitPath->text()); pSettings->vcs().setGitPath(ui->txtGitPath->text());
pSettings->vcs().save(); pSettings->vcs().save();
pMainWindow->applySettings();
} }
void ToolsGitWidget::updateIcons(const QSize &size) void ToolsGitWidget::updateIcons(const QSize &size)

View File

@ -31,6 +31,7 @@
#define GPROF_PROGRAM "gprof.exe" #define GPROF_PROGRAM "gprof.exe"
#define CLEAN_PROGRAM "del /q /f" #define CLEAN_PROGRAM "del /q /f"
#define CPP_PROGRAM "cpp.exe" #define CPP_PROGRAM "cpp.exe"
#define GIT_PROGRAM "git.exe"
#elif defined(Q_OS_LINUX) #elif defined(Q_OS_LINUX)
#define GCC_PROGRAM "gcc" #define GCC_PROGRAM "gcc"
#define GPP_PROGRAM "g++" #define GPP_PROGRAM "g++"
@ -42,6 +43,7 @@
#define GPROF_PROGRAM "gprof" #define GPROF_PROGRAM "gprof"
#define CLEAN_PROGRAM "rm -rf" #define CLEAN_PROGRAM "rm -rf"
#define CPP_PROGRAM "cpp" #define CPP_PROGRAM "cpp"
#define GIT_PROGRAM "git"
#else #else
#error "Only support windows and linux now!" #error "Only support windows and linux now!"
#endif #endif

View File

@ -1140,3 +1140,5 @@ void copyFolder(const QString &fromDir, const QString &toDir)
} }
} }
} }

View File

@ -2,6 +2,7 @@
#include "../utils.h" #include "../utils.h"
#include "../settings.h" #include "../settings.h"
#include <QDir>
#include <QFileInfo> #include <QFileInfo>
GitManager::GitManager(QObject *parent) : QObject(parent) GitManager::GitManager(QObject *parent) : QObject(parent)
@ -16,6 +17,16 @@ void GitManager::createRepository(const QString &folder)
QStringList args; QStringList args;
args.append("init"); args.append("init");
runGit(folder,args); runGit(folder,args);
QStringList contents;
contents.append(".git");
contents.append("*.o");
contents.append("*.exe");
contents.append("*.");
QDir dir(folder);
stringsToFile(contents,dir.filePath(".gitignore"));
add(folder,".gitignore");
} }
bool GitManager::hasRepository(const QString &folder, QString& currentBranch) bool GitManager::hasRepository(const QString &folder, QString& currentBranch)
@ -50,7 +61,7 @@ bool GitManager::isFileInRepository(const QFileInfo& fileInfo)
return output.trimmed() == fileInfo.fileName(); return output.trimmed() == fileInfo.fileName();
} }
bool GitManager::isFileInStaged(const QFileInfo &fileInfo) bool GitManager::isFileStaged(const QFileInfo &fileInfo)
{ {
QStringList args; QStringList args;
args.append("diff"); args.append("diff");
@ -111,6 +122,23 @@ QStringList GitManager::listFiles(const QString &folder)
return textToLines(runGit(folder,args)); return textToLines(runGit(folder,args));
} }
QStringList GitManager::listStagedFiles(const QString &folder)
{
QStringList args;
args.append("diff");
args.append("--staged");
args.append("--name-only");
return textToLines(runGit(folder,args));
}
QStringList GitManager::listChangedFiles(const QString &folder)
{
QStringList args;
args.append("diff");
args.append("--name-only");
return textToLines(runGit(folder,args));
}
void GitManager::clone(const QString &folder, const QString &url) void GitManager::clone(const QString &folder, const QString &url)
{ {
QStringList args; QStringList args;
@ -161,8 +189,15 @@ void GitManager::reset(const QString &folder, const QString &commit, GitResetStr
runGit(folder,args); runGit(folder,args);
} }
bool GitManager::isValid()
{
return pSettings->vcs().gitOk();
}
QString GitManager::runGit(const QString& workingFolder, const QStringList &args) QString GitManager::runGit(const QString& workingFolder, const QStringList &args)
{ {
if (!isValid())
return "";
QFileInfo fileInfo(pSettings->vcs().gitPath()); QFileInfo fileInfo(pSettings->vcs().gitPath());
if (!fileInfo.exists()) if (!fileInfo.exists())
return "fatal: git doesn't exist"; return "fatal: git doesn't exist";
@ -174,12 +209,98 @@ QString GitManager::runGit(const QString& workingFolder, const QStringList &args
fileInfo.absoluteFilePath(), fileInfo.absoluteFilePath(),
workingFolder, workingFolder,
args); args);
output = escapeUTF8String(output.toUtf8());
emit gitCmdFinished(output); emit gitCmdFinished(output);
// if (output.startsWith("fatal:")) // if (output.startsWith("fatal:"))
// throw GitError(output); // throw GitError(output);
return output; return output;
} }
QString GitManager::escapeUTF8String(const QByteArray &rawString)
{
QByteArray stringValue;
int p = 0;
while (p<rawString.length()) {
char ch = rawString[p];
if (ch =='\\' && p+1 < rawString.length()) {
p++;
ch = rawString[p];
switch (ch) {
case '\'':
stringValue+=0x27;
p++;
break;
case '"':
stringValue+=0x22;
p++;
break;
case '?':
stringValue+=0x3f;
p++;
break;
case '\\':
stringValue+=0x5c;
p++;
break;
case 'a':
stringValue+=0x07;
p++;
break;
case 'b':
stringValue+=0x08;
p++;
break;
case 'f':
stringValue+=0x0c;
p++;
break;
case 'n':
stringValue+=0x0a;
p++;
break;
case 'r':
stringValue+=0x0d;
p++;
break;
case 't':
stringValue+=0x09;
p++;
break;
case 'v':
stringValue+=0x0b;
p++;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
{
int i=0;
for (i=0;i<3;i++) {
if (p+i>=rawString.length() ||
rawString[p+i]<'0' || rawString[p+i]>'7')
break;
}
bool ok;
unsigned char ch = rawString.mid(p,i).toInt(&ok,8);
stringValue+=ch;
p+=i;
break;
}
}
} else {
if (ch!='\"')
stringValue+=ch;
p++;
}
}
return QString::fromUtf8(stringValue);
}
GitError::GitError(const QString &reason):BaseError(reason) GitError::GitError(const QString &reason):BaseError(reason)
{ {

View File

@ -3,6 +3,7 @@
#include <QObject> #include <QObject>
#include <QFileInfo> #include <QFileInfo>
#include <QSet>
#include "utils.h" #include "utils.h"
#include "gitrepository.h" #include "gitrepository.h"
@ -22,7 +23,7 @@ public:
bool hasRepository(const QString& folder, QString& currentBranch); bool hasRepository(const QString& folder, QString& currentBranch);
bool isFileInRepository(const QFileInfo& fileInfo); bool isFileInRepository(const QFileInfo& fileInfo);
bool isFileInStaged(const QFileInfo& fileInfo); bool isFileStaged(const QFileInfo& fileInfo);
bool isFileChanged(const QFileInfo& fileInfo); bool isFileChanged(const QFileInfo& fileInfo);
void add(const QString& folder, const QString& path); void add(const QString& folder, const QString& path);
@ -30,17 +31,23 @@ 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);
QStringList listFiles(const QString& folder); QStringList listFiles(const QString& folder);
QStringList listStagedFiles(const QString& folder);
QStringList listChangedFiles(const QString& folder);
void clone(const QString& folder, const QString& url); void clone(const QString& folder, const QString& url);
void commit(const QString& folder, const QString& message); void commit(const QString& folder, const QString& message);
void revert(const QString& folder); void revert(const QString& folder);
void reset(const QString& folder, const QString& commit, GitResetStrategy strategy); void reset(const QString& folder, const QString& commit, GitResetStrategy strategy);
bool isValid();
signals: signals:
void gitCmdRunning(const QString& gitCmd); void gitCmdRunning(const QString& gitCmd);
void gitCmdFinished(const QString& message); void gitCmdFinished(const QString& message);
private: private:
QString runGit(const QString& workingFolder, const QStringList& args); QString runGit(const QString& workingFolder, const QStringList& args);
QString escapeUTF8String(const QByteArray& rawString);
private: private:
}; };

View File

@ -1,12 +1,17 @@
#include "gitrepository.h" #include "gitrepository.h"
#include "gitmanager.h" #include "gitmanager.h"
GitRepository::GitRepository(const QString& folder, GitManager *manager, QObject *parent) GitRepository::GitRepository(const QString& folder, QObject *parent)
: QObject{parent}, : QObject{parent},
mFolder(folder), mInRepository(false)
mManager(manager)
{ {
Q_ASSERT(manager!=nullptr); mManager = new GitManager();
setFolder(folder);
}
GitRepository::~GitRepository()
{
delete mManager;
} }
const QString &GitRepository::folder() const const QString &GitRepository::folder() const
@ -21,7 +26,8 @@ void GitRepository::createRepository()
bool GitRepository::hasRepository(QString& currentBranch) bool GitRepository::hasRepository(QString& currentBranch)
{ {
return mManager->hasRepository(mFolder, currentBranch); currentBranch = mBranch;
return mInRepository;
} }
void GitRepository::add(const QString &path) void GitRepository::add(const QString &path)
@ -44,12 +50,11 @@ void GitRepository::restore(const QString &path)
mManager->restore(mFolder, path); mManager->restore(mFolder, path);
} }
QStringList GitRepository::listFiles(bool refresh) QSet<QString> GitRepository::listFiles(bool refresh)
{ {
if (refresh || mFiles.isEmpty()) { if (refresh)
mFiles = mManager->listFiles(mFolder); update();
} return mFilesInRepositories;
return mFiles;
} }
void GitRepository::clone(const QString &url) void GitRepository::clone(const QString &url)
@ -72,18 +77,33 @@ void GitRepository::reset(const QString &commit, GitResetStrategy strategy)
mManager->reset(mFolder,commit,strategy); mManager->reset(mFolder,commit,strategy);
} }
GitManager *GitRepository::manager() const
{
return mManager;
}
void GitRepository::setManager(GitManager *newManager)
{
Q_ASSERT(newManager!=nullptr);
mManager = newManager;
}
void GitRepository::setFolder(const QString &newFolder) void GitRepository::setFolder(const QString &newFolder)
{ {
mFolder = newFolder; mFolder = newFolder;
update();
} }
void GitRepository::update()
{
if (!mManager->isValid()) {
mInRepository = false;
mBranch = "";
mFilesInRepositories.clear();
mChangedFiles.clear();
mStagedFiles.clear();
} else {
mInRepository = mManager->hasRepository(mFolder,mBranch);
convertFilesListToSet(mManager->listFiles(mFolder),mFilesInRepositories);
convertFilesListToSet(mManager->listChangedFiles(mFolder),mChangedFiles);
convertFilesListToSet(mManager->listStagedFiles(mFolder),mStagedFiles);
}
}
void GitRepository::convertFilesListToSet(const QStringList &filesList, QSet<QString> &set)
{
set.clear();
foreach (const QString& s, filesList) {
set.insert(includeTrailingPathDelimiter(mFolder)+s);
}
}

View File

@ -1,7 +1,9 @@
#ifndef GITREPOSITORY_H #ifndef GITREPOSITORY_H
#define GITREPOSITORY_H #define GITREPOSITORY_H
#include <QFileInfo>
#include <QObject> #include <QObject>
#include <QSet>
#include <memory> #include <memory>
enum class GitResetStrategy { enum class GitResetStrategy {
@ -17,34 +19,59 @@ class GitRepository : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit GitRepository(const QString& folder, GitManager* manager, QObject *parent = nullptr); explicit GitRepository(const QString& folder, QObject *parent = nullptr);
~GitRepository();
const QString &folder() const; const QString &folder() const;
void createRepository(); void createRepository();
bool hasRepository(QString& currentBranch); bool hasRepository(QString& currentBranch);
bool isFileInRepository(const QFileInfo& fileInfo) {
return isFileInRepository(fileInfo.absoluteFilePath());
}
bool isFileInRepository(const QString& filePath) {
return mFilesInRepositories.contains(filePath);
}
bool isFileStaged(const QFileInfo& fileInfo) {
return isFileStaged(fileInfo.absoluteFilePath());
}
bool isFileStaged(const QString& filePath) {
return mStagedFiles.contains(filePath);
}
bool isFileChanged(const QFileInfo& fileInfo) {
return isFileChanged(fileInfo.absoluteFilePath());
}
bool isFileChanged(const QString& filePath) {
return mChangedFiles.contains(filePath);
}
void add(const QString& path); void add(const QString& path);
void remove(const QString& path); void remove(const QString& path);
void rename(const QString& oldName, const QString& newName); void rename(const QString& oldName, const QString& newName);
void restore(const QString& path); void restore(const QString& path);
QStringList listFiles(bool refresh); QSet<QString> listFiles(bool refresh);
void clone(const QString& url); void clone(const QString& url);
void commit(const QString& message); void commit(const QString& message);
void revert(); void revert();
void reset(const QString& commit, GitResetStrategy strategy); void reset(const QString& commit, GitResetStrategy strategy);
GitManager *manager() const;
void setManager(GitManager *newManager);
void setFolder(const QString &newFolder); void setFolder(const QString &newFolder);
void update();
signals: signals:
private: private:
QString mFolder; QString mFolder;
bool mInRepository;
QString mBranch;
GitManager* mManager; GitManager* mManager;
QStringList mFiles; QSet<QString> mFilesInRepositories;
QSet<QString> mChangedFiles;
QSet<QString> mStagedFiles;
private:
void convertFilesListToSet(const QStringList& filesList,QSet<QString>& set);
}; };
#endif // GITREPOSITORY_H #endif // GITREPOSITORY_H

View File

@ -4,10 +4,6 @@
CustomFileSystemModel::CustomFileSystemModel(QObject *parent) : QFileSystemModel(parent) CustomFileSystemModel::CustomFileSystemModel(QObject *parent) : QFileSystemModel(parent)
{ {
mGitManager = new GitManager(this);
mGitRepository = new GitRepository("",mGitManager,mGitManager);
connect(this,&QFileSystemModel::rootPathChanged,
this, &CustomFileSystemModel::onRootPathChanged);
} }
QVariant CustomFileSystemModel::data(const QModelIndex &index, int role) const QVariant CustomFileSystemModel::data(const QModelIndex &index, int role) const
@ -15,7 +11,3 @@ QVariant CustomFileSystemModel::data(const QModelIndex &index, int role) const
return QFileSystemModel::data(index,role); return QFileSystemModel::data(index,role);
} }
void CustomFileSystemModel::onRootPathChanged(const QString &folder)
{
mGitRepository->setFolder(folder);
}

View File

@ -15,11 +15,6 @@ public:
// QAbstractItemModel interface // QAbstractItemModel interface
public: public:
QVariant data(const QModelIndex &index, int role) const override; QVariant data(const QModelIndex &index, int role) const override;
private slots:
void onRootPathChanged(const QString& folder);
private:
GitRepository *mGitRepository;
GitManager *mGitManager;
}; };
#endif // CUSTOMFILESYSTEMMODEL_H #endif // CUSTOMFILESYSTEMMODEL_H