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 +}