diff --git a/NEWS.md b/NEWS.md
index 0fec4332..f160bd88 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -9,6 +9,7 @@ Red Panda C++ Version 0.14.4
- enhancement: git - remotes
- enhancement: rename "open folder" to "choose working folder"
- enhancement: let user choose app theme when first run
+ - enhancement: git - pull / push / fetch
Red Panda C++ Version 0.14.3
- fix: wrong code completion font size, when screen dpi changed
diff --git a/RedPandaIDE/icons.qrc b/RedPandaIDE/icons.qrc
index 8080f3dd..678cb5e7 100644
--- a/RedPandaIDE/icons.qrc
+++ b/RedPandaIDE/icons.qrc
@@ -111,8 +111,6 @@
images/demos/dark.png
- images/demos/dark-zh_CN.png
images/demos/light.png
- images/demos/light-zh_CN.png
diff --git a/RedPandaIDE/images/demos/dark.png b/RedPandaIDE/images/demos/dark.png
new file mode 100644
index 00000000..78a7cbbe
Binary files /dev/null and b/RedPandaIDE/images/demos/dark.png differ
diff --git a/RedPandaIDE/images/demos/light.png b/RedPandaIDE/images/demos/light.png
new file mode 100644
index 00000000..ad864361
Binary files /dev/null and b/RedPandaIDE/images/demos/light.png differ
diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp
index 1ce94f4a..07ddef7d 100644
--- a/RedPandaIDE/mainwindow.cpp
+++ b/RedPandaIDE/mainwindow.cpp
@@ -6943,3 +6943,92 @@ void MainWindow::on_actionGit_Remotes_triggered()
dialog.exec();
}
+
+void MainWindow::on_actionGit_Fetch_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 manager;
+ QString output;
+ if (!manager.fetch(folder,output)) {
+ InfoMessageBox infoBox;
+ infoBox.showMessage(output);
+ }
+}
+
+
+void MainWindow::on_actionGit_Pull_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 manager;
+ QString branch;
+ if (!manager.hasRepository(folder,branch))
+ return;
+ QString remote = manager.getBranchRemote(folder,branch);
+ QString output;
+ if (remote.isEmpty()) {
+ GitRemoteDialog dialog(folder);
+ QString remote = dialog.chooseRemote();
+ if (remote.trimmed().isEmpty())
+ return;
+ if (!manager.setBranchUpstream(folder,branch,remote,output)) {
+ InfoMessageBox infoBox;
+ infoBox.showMessage(output);
+ return;
+ }
+ }
+ manager.pull(folder,output);
+ if (!output.isEmpty()) {
+ InfoMessageBox infoBox;
+ infoBox.showMessage(output);
+ }
+}
+
+
+void MainWindow::on_actionGit_Push_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 manager;
+ QString branch;
+ if (!manager.hasRepository(folder,branch))
+ return;
+ QString remote = manager.getBranchRemote(folder,branch);
+ QString output;
+ if (remote.isEmpty()) {
+ GitRemoteDialog dialog(folder);
+ QString remote = dialog.chooseRemote();
+ if (remote.trimmed().isEmpty())
+ return;
+ manager.push(folder,remote,branch,output);
+ if (!output.isEmpty()) {
+ InfoMessageBox infoBox;
+ infoBox.showMessage(output);
+ }
+ } else {
+ if (!output.isEmpty()) {
+ InfoMessageBox infoBox;
+ infoBox.showMessage(output);
+ }
+ }
+}
+
diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h
index 8b69daa9..fb20b1f7 100644
--- a/RedPandaIDE/mainwindow.h
+++ b/RedPandaIDE/mainwindow.h
@@ -598,6 +598,12 @@ private slots:
void on_actionGit_Remotes_triggered();
+ void on_actionGit_Fetch_triggered();
+
+ void on_actionGit_Pull_triggered();
+
+ void on_actionGit_Push_triggered();
+
private:
Ui::MainWindow *ui;
EditorList *mEditorList;
diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui
index 6ee74f29..5ad7ef02 100644
--- a/RedPandaIDE/mainwindow.ui
+++ b/RedPandaIDE/mainwindow.ui
@@ -1603,6 +1603,9 @@
+
+
+
@@ -2821,6 +2824,21 @@
Remotes...
+
+
+ Fetch
+
+
+
+
+ Pull
+
+
+
+
+ Push
+
+
diff --git a/RedPandaIDE/vcs/gitmanager.cpp b/RedPandaIDE/vcs/gitmanager.cpp
index 5417831a..9aac1143 100644
--- a/RedPandaIDE/vcs/gitmanager.cpp
+++ b/RedPandaIDE/vcs/gitmanager.cpp
@@ -284,6 +284,73 @@ QString GitManager::getRemoteURL(const QString &folder, const QString &name)
return runGit(folder,args).trimmed();
}
+QString GitManager::getBranchRemote(const QString &folder, const QString &branch)
+{
+ QStringList args;
+ args.append("config");
+ args.append("--get");
+ args.append(QString("branch.%1.remote").arg(branch));
+ return runGit(folder,args).trimmed();
+}
+
+QString GitManager::getBranchMerge(const QString &folder, const QString &branch)
+{
+ QStringList args;
+ args.append("config");
+ args.append("--get");
+ args.append(QString("branch.%1.merge").arg(branch));
+ return runGit(folder,args).trimmed();
+}
+
+bool GitManager::setBranchUpstream(
+ const QString &folder,
+ const QString &branch,
+ const QString &remoteName,
+ QString& output)
+{
+ QStringList args;
+ args.append("branch");
+ args.append(QString("--set-upstream-to=%1/%2").arg(remoteName,branch));
+ args.append(branch);
+ output = runGit(folder,args).trimmed();
+ return !output.startsWith("error") && !output.startsWith("fatal");
+}
+
+bool GitManager::fetch(const QString &folder, QString &output)
+{
+ QStringList args;
+ args.append("fetch");
+ output = runGit(folder,args).trimmed();
+ return !output.startsWith("error") && !output.startsWith("fatal");
+}
+
+bool GitManager::pull(const QString &folder, QString &output)
+{
+ QStringList args;
+ args.append("pull");
+ output = runGit(folder,args).trimmed();
+ return !output.startsWith("error") && !output.startsWith("fatal");
+}
+
+bool GitManager::push(const QString &folder, QString &output)
+{
+ QStringList args;
+ args.append("push");
+ output = runGit(folder,args).trimmed();
+ return !output.startsWith("error") && !output.startsWith("fatal");
+}
+
+bool GitManager::push(const QString &folder, const QString &remoteName, const QString &branch, QString &output)
+{
+ QStringList args;
+ args.append("push");
+ args.append("--set-upstream");
+ args.append(remoteName);
+ args.append(branch);
+ output = runGit(folder,args).trimmed();
+ return !output.startsWith("error") && !output.startsWith("fatal");
+}
+
QStringList GitManager::listBranches(const QString &folder, int ¤t)
{
QStringList args;
diff --git a/RedPandaIDE/vcs/gitmanager.h b/RedPandaIDE/vcs/gitmanager.h
index d836e5a3..70e6dca2 100644
--- a/RedPandaIDE/vcs/gitmanager.h
+++ b/RedPandaIDE/vcs/gitmanager.h
@@ -50,6 +50,21 @@ public:
bool setRemoteURL(const QString& folder, const QString& name,
const QString& newURL, QString& output);
QString getRemoteURL(const QString& folder, const QString& name);
+ QString getBranchRemote(const QString& folder, const QString& branch);
+ QString getBranchMerge(const QString& folder, const QString& branch);
+ bool setBranchUpstream(const QString& folder,
+ const QString& branch,
+ const QString& remoteName,
+ QString &output);
+
+ bool fetch(const QString& folder, QString& output);
+ bool pull(const QString& folder, QString& output);
+ bool push(const QString& folder, QString& output);
+ bool push(const QString& folder,
+ const QString& remoteName,
+ const QString& branch,
+ QString& output);
+
QStringList listBranches(const QString& folder, int& current);
bool switchToBranch(const QString& folder, const QString& branch, bool create,
diff --git a/RedPandaIDE/vcs/gitremotedialog.cpp b/RedPandaIDE/vcs/gitremotedialog.cpp
index 10464b36..4540d8fe 100644
--- a/RedPandaIDE/vcs/gitremotedialog.cpp
+++ b/RedPandaIDE/vcs/gitremotedialog.cpp
@@ -7,7 +7,8 @@
GitRemoteDialog::GitRemoteDialog(const QString& folder, QWidget *parent) :
QDialog(parent),
ui(new Ui::GitRemoteDialog),
- mFolder(folder)
+ mFolder(folder),
+ mChooseMode(false)
{
ui->setupUi(this);
GitManager manager;
@@ -29,6 +30,18 @@ GitRemoteDialog::~GitRemoteDialog()
delete ui;
}
+QString GitRemoteDialog::chooseRemote()
+{
+ mChooseMode = true;
+ ui->btnClose->setText(tr("Ok"));
+
+ if (exec()==QDialog::Accepted) {
+ if (ui->lstRemotes->selectedItems().count()>0)
+ return ui->lstRemotes->selectedItems()[0]->text();
+ }
+ return "";
+}
+
void GitRemoteDialog::updateIcons()
{
ui->btnAdd->setIcon(pIconsManager->getIcon(IconsManager::ACTION_MISC_ADD));
@@ -81,9 +94,13 @@ void GitRemoteDialog::on_btnAdd_clicked()
ui->pnlProcess->setVisible(true);
ui->btnProcess->setText(tr("Add"));
ui->btnRemove->setEnabled(false);
+ if (ui->lstRemotes->count()==0) {
+ ui->txtName->setText("origin");
+ ui->txtURL->setFocus();
+ } else
+ ui->txtName->setFocus();
}
-
void GitRemoteDialog::on_btnRemove_clicked()
{
if (ui->lstRemotes->selectedItems().count()>0) {
@@ -164,3 +181,9 @@ void GitRemoteDialog::on_txtURL_textChanged(const QString & /*arg1*/)
checkDetails();
}
+
+void GitRemoteDialog::on_btnClose_clicked()
+{
+ accept();
+}
+
diff --git a/RedPandaIDE/vcs/gitremotedialog.h b/RedPandaIDE/vcs/gitremotedialog.h
index 1eafcd0f..b21f18e3 100644
--- a/RedPandaIDE/vcs/gitremotedialog.h
+++ b/RedPandaIDE/vcs/gitremotedialog.h
@@ -14,6 +14,7 @@ class GitRemoteDialog : public QDialog
public:
explicit GitRemoteDialog(const QString& folder, QWidget *parent = nullptr);
~GitRemoteDialog();
+ QString chooseRemote();
private slots:
void updateIcons();
@@ -30,10 +31,13 @@ private slots:
void on_txtURL_textChanged(const QString &arg1);
+ void on_btnClose_clicked();
+
private:
Ui::GitRemoteDialog *ui;
QString mFolder;
QStringList mRemotes;
+ bool mChooseMode;
};
#endif // GITREMOTEDIALOG_H
diff --git a/windows/redpanda-git-askpass/main.c b/windows/redpanda-git-askpass/main.c
new file mode 100644
index 00000000..aa53a301
--- /dev/null
+++ b/windows/redpanda-git-askpass/main.c
@@ -0,0 +1,78 @@
+#include
+#include
+#include "resource.h"
+#include
+
+HINSTANCE hInst;
+
+LRESULT MainDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam);
+
+LRESULT TxtPasswordWndProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam);
+
+WNDPROC lpfnTxtPasswordWndProc=NULL;
+HWND hMainDlg = NULL;
+HWND hwndTxtPassword = NULL;
+
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
+ MSG msg;
+
+
+ hMainDlg = CreateDialog(hInstance, (LPCTSTR)IDD_MAIN_DIALOG, 0,(DLGPROC)MainDlgProc);
+ ShowWindow(hMainDlg, nCmdShow);
+ hwndTxtPassword = GetDlgItem(hMainDlg,ID_TXT_PASSWORD);
+ lpfnTxtPasswordWndProc = (WNDPROC) SetWindowLongPtr(hwndTxtPassword, GWLP_WNDPROC, (LONG_PTR)TxtPasswordWndProc);
+ HWND hwndTxtPrompt = GetDlgItem(hMainDlg,ID_TXT_PROMPT);
+ Static_SetText(hwndTxtPrompt, lpCmdLine);
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ return 0;
+}
+
+//In Subclass Proc
+LRESULT CALLBACK TxtPasswordWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg) {
+ case WM_KEYDOWN:
+ if (wParam==VK_RETURN) {
+ char s[500+1];
+ Edit_GetText(hwndTxtPassword,s,500);
+ printf(s);
+ DestroyWindow(hMainDlg);
+ return TRUE;
+ }
+ break;
+
+ }
+
+ return CallWindowProc(lpfnTxtPasswordWndProc, hwnd, msg, wParam, lParam);
+}
+
+LRESULT MainDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
+ switch (message) {
+ case WM_INITDIALOG :
+ return TRUE ;
+ case WM_COMMAND :
+ switch (LOWORD (wParam)) {
+ case IDOK :
+ case IDCANCEL :
+ DestroyWindow(hDlg);
+ return TRUE ;
+ }
+ break ;
+ case WM_KEYUP:
+ printf("%d\n",wParam);
+ if (wParam == VK_RETURN) {
+ DestroyWindow(hDlg);
+ }
+ break;
+ case WM_CLOSE:
+ DestroyWindow(hDlg);
+ return TRUE;
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ return TRUE;
+ };
+ return FALSE;//返回FALSE给缺省对话框函数DefDlgProc(),表示没有处理本消息
+}
diff --git a/windows/redpanda-git-askpass/redpanda-git-askpass.dev b/windows/redpanda-git-askpass/redpanda-git-askpass.dev
new file mode 100644
index 00000000..0ed9325a
--- /dev/null
+++ b/windows/redpanda-git-askpass/redpanda-git-askpass.dev
@@ -0,0 +1,98 @@
+[Project]
+filename = redpanda-git-askpass.dev
+name = redpanda-git-askpass
+UnitCount = 3
+Type = 0
+Ver = 3
+ObjFiles =
+Includes =
+Libs =
+PrivateResource = redpanda-git-askpass_private.rc
+ResourceIncludes =
+MakeIncludes =
+Compiler =
+CppCompiler =
+Linker =
+IsCpp = 1
+Icon = redpanda-git-askpass.ico
+ExeOutput =
+ObjectOutput =
+LogOutput =
+LogOutputEnabled = 0
+OverrideOutput = 0
+OverrideOutputName =
+HostApplication =
+UseCustomMakefile = 0
+CustomMakefile =
+UsePrecompiledHeader = 0
+PrecompiledHeader =
+CommandLine =
+Folders =
+IncludeVersionInfo = 0
+SupportXPThemes = 0
+CompilerSet = 0
+CompilerSetType = 0
+CompilerSettings = 000000a000000000000010001
+StaticLink = 1
+AddCharset = 1
+Encoding = AUTO
+ModelType = 0
+UseUTF8 = 0
+
+
+[Unit1]
+FileName = main.c
+CompileCpp = 1
+Folder =
+Compile = 1
+Link = 1
+Priority = 1000
+OverrideBuildCmd = 0
+BuildCmd =
+DetectEncoding = 1
+FileEncoding = AUTO
+
+
+[Unit2]
+FileName = resource.rc
+Folder = Resources
+Compile = 1
+Link = 1
+Priority = 1000
+OverrideBuildCmd = 0
+BuildCmd =
+DetectEncoding = 1
+FileEncoding = AUTO
+
+
+[Unit3]
+FileName = resource.h
+CompileCpp = 1
+Folder =
+Compile = 1
+Link = 1
+Priority = 1000
+OverrideBuildCmd = 0
+BuildCmd =
+DetectEncoding = 1
+FileEncoding = AUTO
+
+
+[VersionInfo]
+Major = 1
+Minor = 0
+Release = 0
+Build = 0
+LanguageID = 1033
+CharsetID = 1252
+CompanyName =
+FileVersion =
+FileDescription = Developed using the Red Panda C++ IDE
+InternalName =
+LegalCopyright =
+LegalTrademarks =
+OriginalFilename =
+ProductName =
+ProductVersion =
+AutoIncBuildNr = 0
+SyncProduct = 1
diff --git a/windows/redpanda-git-askpass/redpanda-git-askpass.ico b/windows/redpanda-git-askpass/redpanda-git-askpass.ico
new file mode 100644
index 00000000..94551655
Binary files /dev/null and b/windows/redpanda-git-askpass/redpanda-git-askpass.ico differ
diff --git a/windows/redpanda-git-askpass/redpanda-git-askpass_private.h b/windows/redpanda-git-askpass/redpanda-git-askpass_private.h
new file mode 100644
index 00000000..041b1ce4
--- /dev/null
+++ b/windows/redpanda-git-askpass/redpanda-git-askpass_private.h
@@ -0,0 +1,23 @@
+/* THIS FILE WILL BE OVERWRITTEN BY Red Panda C++ */
+/* DO NOT EDIT ! */
+
+#ifndef redpanda-git-askpass_private_rc
+#define redpanda-git-askpass_private_rc
+
+/* VERSION DEFINITIONS */
+#define VER_STRING "1.0.0.0"
+#define VER_MAJOR 1
+#define VER_MINOR 0
+#define VER_RELEASE 0
+#define VER_BUILD 0
+#define COMPANY_NAME ""
+#define FILE_VERSION ""
+#define FILE_DESCRIPTION "Developed using the Red Panda C++ IDE"
+#define INTERNAL_NAME ""
+#define LEGAL_COPYRIGHT ""
+#define LEGAL_TRADEMARKS ""
+#define ORIGINAL_FILENAME ""
+#define PRODUCT_NAME ""
+#define PRODUCT_VERSION ""
+
+#endif /*redpanda-git-askpass_private_rc*/
diff --git a/windows/redpanda-git-askpass/redpanda-git-askpass_private.rc b/windows/redpanda-git-askpass/redpanda-git-askpass_private.rc
new file mode 100644
index 00000000..7c7dbc06
--- /dev/null
+++ b/windows/redpanda-git-askpass/redpanda-git-askpass_private.rc
@@ -0,0 +1,6 @@
+/* THIS FILE WILL BE OVERWRITTEN BY Red Panda C++ */
+/* DO NOT EDIT! */
+
+#include "resource.rc"
+
+A ICON "redpanda-git-askpass.ico"
diff --git a/windows/redpanda-git-askpass/redpanda-git-askpass_private.res b/windows/redpanda-git-askpass/redpanda-git-askpass_private.res
new file mode 100644
index 00000000..d140298c
Binary files /dev/null and b/windows/redpanda-git-askpass/redpanda-git-askpass_private.res differ
diff --git a/windows/redpanda-git-askpass/resource.h b/windows/redpanda-git-askpass/resource.h
new file mode 100644
index 00000000..78fad4ab
--- /dev/null
+++ b/windows/redpanda-git-askpass/resource.h
@@ -0,0 +1,7 @@
+#ifndef IDC_STATIC
+#define IDC_STATIC (-1)
+#endif
+
+#define IDD_MAIN_DIALOG 101
+#define ID_TXT_PASSWORD 40000
+#define ID_TXT_PROMPT 40001
diff --git a/windows/redpanda-git-askpass/resource.rc b/windows/redpanda-git-askpass/resource.rc
new file mode 100644
index 00000000..a694bfb7
--- /dev/null
+++ b/windows/redpanda-git-askpass/resource.rc
@@ -0,0 +1,24 @@
+// Generated by ResEdit 1.6.5
+// Copyright (C) 2006-2015
+// http://www.resedit.net
+
+#include
+#include
+#include
+#include "resource.h"
+
+
+
+
+//
+// Dialog resources
+//
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+IDD_MAIN_DIALOG DIALOG 0, 0, 180, 56
+STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
+CAPTION "Dialog"
+FONT 12, "Microsoft Sans Serif"
+{
+ LTEXT "Static", ID_TXT_PROMPT, 7, 7, 169, 13, SS_LEFT, WS_EX_LEFT
+ EDITTEXT ID_TXT_PASSWORD, 7, 26, 168, 19, ES_AUTOHSCROLL, WS_EX_LEFT
+}