From 81bf2ec154f8a98269040b1e185d9b59d2c6f3e9 Mon Sep 17 00:00:00 2001 From: Petar Perisin Date: Sun, 16 Dec 2012 20:35:58 +0100 Subject: Git: Auto stash for branches Allow user to handle local changes when switching branches. Task-number: QTCREATORBUG-8417 Change-Id: I62d615aadfbd81c8ae03f3cd292b98773a36e1e7 Reviewed-by: Orgad Shaneh Reviewed-by: Tobias Hunger --- src/plugins/git/branchcheckoutdialog.cpp | 88 ++++++++++++++++++++ src/plugins/git/branchcheckoutdialog.h | 45 +++++++++++ src/plugins/git/branchcheckoutdialog.ui | 133 +++++++++++++++++++++++++++++++ src/plugins/git/branchdialog.cpp | 57 ++++++++++++- src/plugins/git/git.pro | 9 ++- src/plugins/git/git.qbs | 3 + 6 files changed, 331 insertions(+), 4 deletions(-) create mode 100644 src/plugins/git/branchcheckoutdialog.cpp create mode 100644 src/plugins/git/branchcheckoutdialog.h create mode 100644 src/plugins/git/branchcheckoutdialog.ui (limited to 'src') diff --git a/src/plugins/git/branchcheckoutdialog.cpp b/src/plugins/git/branchcheckoutdialog.cpp new file mode 100644 index 0000000000..fc0c34aefa --- /dev/null +++ b/src/plugins/git/branchcheckoutdialog.cpp @@ -0,0 +1,88 @@ +#include "branchcheckoutdialog.h" +#include "ui_branchcheckoutdialog.h" + +namespace Git { +namespace Internal { + +BranchCheckoutDialog::BranchCheckoutDialog(QWidget *parent, + const QString& currentBranch, + const QString& nextBranch) : + QDialog(parent), + m_ui(new Ui::BranchCheckoutDialog), + m_foundStashForNextBranch(false), + m_hasLocalChanges(true) +{ + m_ui->setupUi(this); + + setWindowTitle(tr("Checkout branch \"%1\"").arg(nextBranch)); + m_ui->moveChangesRadioButton->setText(tr("Move Local Changes to \"%1\"").arg(nextBranch)); + m_ui->popStashCheckBox->setText(tr("Pop Stash of \"%1\"").arg(nextBranch)); + + if (!currentBranch.isEmpty()) { + m_ui->makeStashRadioButton->setText(tr("Create Branch Stash for \"%1\"").arg(currentBranch)); + } else { + m_ui->makeStashRadioButton->setText(tr("Create Branch Stash for Current Branch")); + foundNoLocalChanges(); + } + + connect(m_ui->moveChangesRadioButton, SIGNAL(toggled(bool)), this, SLOT(updatePopStashCheckBox(bool))); +} + +BranchCheckoutDialog::~BranchCheckoutDialog() +{ + delete m_ui; +} + +void BranchCheckoutDialog::foundNoLocalChanges() +{ + m_ui->discardChangesRadioButton->setChecked(true); + m_ui->localChangesGroupBox->setEnabled(false); + m_hasLocalChanges = false; +} + +void BranchCheckoutDialog::foundStashForNextBranch() +{ + m_ui->popStashCheckBox->setChecked(true); + m_ui->popStashCheckBox->setEnabled(true); + m_foundStashForNextBranch = true; +} + +bool BranchCheckoutDialog::makeStashOfCurrentBranch() +{ + return m_ui->makeStashRadioButton->isChecked(); +} + +bool BranchCheckoutDialog::moveLocalChangesToNextBranch() +{ + return m_ui->moveChangesRadioButton->isChecked(); +} + +bool BranchCheckoutDialog::discardLocalChanges() +{ + return m_ui->discardChangesRadioButton->isChecked() && m_ui->localChangesGroupBox->isEnabled(); +} + +bool BranchCheckoutDialog::popStashOfNextBranch() +{ + return m_ui->popStashCheckBox->isChecked(); +} + +bool BranchCheckoutDialog::hasStashForNextBranch() +{ + return m_foundStashForNextBranch; +} + +bool BranchCheckoutDialog::hasLocalChanges() +{ + return m_hasLocalChanges; +} + +void BranchCheckoutDialog::updatePopStashCheckBox(bool moveChangesChecked) +{ + m_ui->popStashCheckBox->setChecked(!moveChangesChecked && m_foundStashForNextBranch); + m_ui->popStashCheckBox->setEnabled(!moveChangesChecked && m_foundStashForNextBranch); +} + +} // namespace Internal +} // namespace Git + diff --git a/src/plugins/git/branchcheckoutdialog.h b/src/plugins/git/branchcheckoutdialog.h new file mode 100644 index 0000000000..a794b8ef36 --- /dev/null +++ b/src/plugins/git/branchcheckoutdialog.h @@ -0,0 +1,45 @@ +#ifndef BRANCHCHECKOUTDIALOG_H +#define BRANCHCHECKOUTDIALOG_H + +#include + +namespace Git { +namespace Internal { + +namespace Ui { + class BranchCheckoutDialog; +} + +class BranchCheckoutDialog : public QDialog +{ + Q_OBJECT + +public: + explicit BranchCheckoutDialog(QWidget *parent, const QString& currentBranch, + const QString& nextBranch); + ~BranchCheckoutDialog(); + + void foundNoLocalChanges(); + void foundStashForNextBranch(); + + bool makeStashOfCurrentBranch(); + bool moveLocalChangesToNextBranch(); + bool discardLocalChanges(); + bool popStashOfNextBranch(); + + bool hasStashForNextBranch(); + bool hasLocalChanges(); + +private slots: + void updatePopStashCheckBox(bool moveChangesChecked); + +private: + Ui::BranchCheckoutDialog *m_ui; + bool m_foundStashForNextBranch; + bool m_hasLocalChanges; +}; + +} // namespace Internal +} // namespace Git + +#endif // BRANCHCHECKOUTDIALOG_H diff --git a/src/plugins/git/branchcheckoutdialog.ui b/src/plugins/git/branchcheckoutdialog.ui new file mode 100644 index 0000000000..b8cbc406a9 --- /dev/null +++ b/src/plugins/git/branchcheckoutdialog.ui @@ -0,0 +1,133 @@ + + + Git::Internal::BranchCheckoutDialog + + + Qt::WindowModal + + + + 0 + 0 + 394 + 199 + + + + Dialog + + + true + + + + + + Local Changes Found. Choose Action: + + + + + + RadioButton + + + true + + + + + + + RadioButton + + + + + + + true + + + Discard Local Changes + + + + + + + + + + false + + + CheckBox + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + discardChangesRadioButton + buttonBox + + + + + buttonBox + accepted() + Git::Internal::BranchCheckoutDialog + accept() + + + 227 + 219 + + + 157 + 179 + + + + + buttonBox + rejected() + Git::Internal::BranchCheckoutDialog + reject() + + + 295 + 219 + + + 286 + 179 + + + + + diff --git a/src/plugins/git/branchdialog.cpp b/src/plugins/git/branchdialog.cpp index b39adce43c..bf36548700 100644 --- a/src/plugins/git/branchdialog.cpp +++ b/src/plugins/git/branchdialog.cpp @@ -29,9 +29,11 @@ #include "branchdialog.h" #include "branchadddialog.h" +#include "branchcheckoutdialog.h" #include "branchmodel.h" #include "gitclient.h" #include "gitplugin.h" +#include "gitutils.h" #include "ui_branchdialog.h" #include "stashdialog.h" // Label helpers @@ -42,6 +44,7 @@ #include #include #include +#include #include @@ -159,7 +162,59 @@ void BranchDialog::checkout() QModelIndex idx = selectedIndex(); QTC_CHECK(m_model->isLocal(idx)); - m_model->checkoutBranch(idx); + const QString currentBranch = m_model->branchName(m_model->currentBranch()); + const QString nextBranch = m_model->branchName(idx); + const QString popMessageStart = QCoreApplication::applicationName() + + QLatin1String(" ") + nextBranch + QLatin1String("-AutoStash "); + + BranchCheckoutDialog branchCheckoutDialog(this, currentBranch, nextBranch); + GitClient *gitClient = GitPlugin::instance()->gitClient(); + + if (gitClient->gitStatus(m_repository, StatusMode(NoUntracked | NoSubmodules)) != GitClient::StatusChanged) + branchCheckoutDialog.foundNoLocalChanges(); + + QList stashes; + gitClient->synchronousStashList(m_repository, &stashes); + foreach (const Stash &stash, stashes) { + if (stash.message.startsWith(popMessageStart)) { + branchCheckoutDialog.foundStashForNextBranch(); + break; + } + } + + if (!branchCheckoutDialog.hasLocalChanges() && + !branchCheckoutDialog.hasStashForNextBranch()) { + // No local changes and no Auto Stash - no need to open dialog + m_model->checkoutBranch(idx); + } else if (branchCheckoutDialog.exec() == QDialog::Accepted && m_model) { + + QString stashMessage; + if (branchCheckoutDialog.makeStashOfCurrentBranch() + || branchCheckoutDialog.moveLocalChangesToNextBranch()) { + stashMessage = gitClient->synchronousStash(m_repository, currentBranch + QLatin1String("-AutoStash")); + } else if (branchCheckoutDialog.discardLocalChanges()) { + gitClient->synchronousReset(m_repository); + } + + m_model->checkoutBranch(idx); + + QString stashName; + gitClient->synchronousStashList(m_repository, &stashes); + foreach (const Stash &stash, stashes) { + if (stash.message.startsWith(popMessageStart)) { + stashName = stash.name; + break; + } + } + + if (!stashMessage.isEmpty() && branchCheckoutDialog.moveLocalChangesToNextBranch()) + gitClient->stashPop(m_repository); + else if (branchCheckoutDialog.popStashOfNextBranch()) + gitClient->synchronousStashRestore(m_repository, stashName); + + if (branchCheckoutDialog.hasStashForNextBranch()) + gitClient->synchronousStashRemove(m_repository, stashName); + } enableButtons(); } diff --git a/src/plugins/git/git.pro b/src/plugins/git/git.pro index 873ad6bacd..7ddef37097 100644 --- a/src/plugins/git/git.pro +++ b/src/plugins/git/git.pro @@ -29,7 +29,8 @@ HEADERS += gitplugin.h \ remotedialog.h \ branchadddialog.h \ resetdialog.h \ - mergetool.h + mergetool.h \ + branchcheckoutdialog.h SOURCES += gitplugin.cpp \ gitclient.cpp \ @@ -52,7 +53,8 @@ SOURCES += gitplugin.cpp \ remotedialog.cpp \ branchadddialog.cpp \ resetdialog.cpp \ - mergetool.cpp + mergetool.cpp \ + branchcheckoutdialog.cpp FORMS += changeselectiondialog.ui \ settingspage.ui \ @@ -61,7 +63,8 @@ FORMS += changeselectiondialog.ui \ stashdialog.ui \ remotedialog.ui \ remoteadditiondialog.ui \ - branchadddialog.ui + branchadddialog.ui \ + branchcheckoutdialog.ui include(gitorious/gitorious.pri) diff --git a/src/plugins/git/git.qbs b/src/plugins/git/git.qbs index ec5a0af292..92c2597219 100644 --- a/src/plugins/git/git.qbs +++ b/src/plugins/git/git.qbs @@ -21,6 +21,9 @@ QtcPlugin { "branchadddialog.cpp", "branchadddialog.h", "branchadddialog.ui", + "branchcheckoutdialog.cpp", + "branchcheckoutdialog.h", + "branchcheckoutdialog.ui", "branchdialog.cpp", "branchdialog.h", "branchdialog.ui", -- cgit v1.2.1