aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <[email protected]>2012-04-30 17:26:07 +0200
committerFriedemann Kleint <[email protected]>2012-05-02 11:12:49 +0200
commit9a5fa0dd48ca4cb0a258606b3b8d7d39da2ae937 (patch)
treeb93922252bf653023fbca4a90186e8c3b97ad4a5
parentaefb7d061ca0d8a770f0e6eda8dbc4f20d638dcd (diff)
Git: Offer recent list of changes for reset --hard.
This makes it easier to remove changed applied for review by Gerrit. Change-Id: I2e3407ae4e74b650d08d53fed37e9aeb11071a4e Reviewed-by: Tobias Hunger <[email protected]>
-rw-r--r--src/plugins/git/git.pro6
-rw-r--r--src/plugins/git/gitclient.cpp24
-rw-r--r--src/plugins/git/gitclient.h3
-rw-r--r--src/plugins/git/gitplugin.cpp14
-rw-r--r--src/plugins/git/resetdialog.cpp145
-rw-r--r--src/plugins/git/resetdialog.h73
6 files changed, 254 insertions, 11 deletions
diff --git a/src/plugins/git/git.pro b/src/plugins/git/git.pro
index 756865db59a..fb887a2e55e 100644
--- a/src/plugins/git/git.pro
+++ b/src/plugins/git/git.pro
@@ -27,7 +27,8 @@ HEADERS += gitplugin.h \
gitutils.h \
remotemodel.h \
remotedialog.h \
- branchadddialog.h
+ branchadddialog.h \
+ resetdialog.h
SOURCES += gitplugin.cpp \
gitclient.cpp \
@@ -48,7 +49,8 @@ SOURCES += gitplugin.cpp \
gitutils.cpp \
remotemodel.cpp \
remotedialog.cpp \
- branchadddialog.cpp
+ branchadddialog.cpp \
+ resetdialog.cpp
FORMS += changeselectiondialog.ui \
settingspage.ui \
diff --git a/src/plugins/git/gitclient.cpp b/src/plugins/git/gitclient.cpp
index a810c9c33e6..1186ca8abcd 100644
--- a/src/plugins/git/gitclient.cpp
+++ b/src/plugins/git/gitclient.cpp
@@ -825,6 +825,30 @@ void GitClient::addFile(const QString &workingDirectory, const QString &fileName
executeGit(workingDirectory, arguments, 0, true);
}
+bool GitClient::synchronousLog(const QString &workingDirectory, const QStringList &arguments,
+ QString *output, QString *errorMessageIn)
+{
+ QByteArray outputText;
+ QByteArray errorText;
+ QStringList allArguments;
+ allArguments << QLatin1String("log") << QLatin1String(GitClient::noColorOption);
+ allArguments.append(arguments);
+ const bool rc = fullySynchronousGit(workingDirectory, allArguments, &outputText, &errorText);
+ if (rc) {
+ *output = commandOutputFromLocal8Bit(outputText);
+ } else {
+ const QString errorMessage = tr("Cannot obtain log of \"%1\": %2").
+ arg(QDir::toNativeSeparators(workingDirectory),
+ commandOutputFromLocal8Bit(errorText));
+ if (errorMessageIn) {
+ *errorMessageIn = errorMessage;
+ } else {
+ outputWindow()->appendError(errorMessage);
+ }
+ }
+ return rc;
+}
+
// Warning: 'intendToAdd' works only from 1.6.1 onwards
bool GitClient::synchronousAdd(const QString &workingDirectory,
bool intendToAdd,
diff --git a/src/plugins/git/gitclient.h b/src/plugins/git/gitclient.h
index 01108522380..4b9856b2421 100644
--- a/src/plugins/git/gitclient.h
+++ b/src/plugins/git/gitclient.h
@@ -107,6 +107,9 @@ public:
void checkoutBranch(const QString &workingDirectory, const QString &branch);
void hardReset(const QString &workingDirectory, const QString &commit = QString());
void addFile(const QString &workingDirectory, const QString &fileName);
+ bool synchronousLog(const QString &workingDirectory,
+ const QStringList &arguments,
+ QString *output, QString *errorMessage = 0);
bool synchronousAdd(const QString &workingDirectory,
// Warning: Works only from 1.6.1 onwards
bool intendToAdd,
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 427ff643506..5f0b1568aaa 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -45,6 +45,7 @@
#include "gitoriousclonewizard.h"
#include "stashdialog.h"
#include "settingspage.h"
+#include "resetdialog.h"
#include <gerritplugin.h>
@@ -643,15 +644,10 @@ void GitPlugin::undoRepositoryChanges()
{
const VcsBase::VcsBasePluginState state = currentState();
QTC_ASSERT(state.hasTopLevel(), return);
- const QString msg = tr("Undo all pending changes to the repository\n%1?").arg(QDir::toNativeSeparators(state.topLevel()));
- const QMessageBox::StandardButton answer
- = QMessageBox::question(Core::ICore::mainWindow(),
- tr("Undo Changes"), msg,
- QMessageBox::Yes|QMessageBox::No,
- QMessageBox::No);
- if (answer == QMessageBox::No)
- return;
- m_gitClient->hardReset(state.topLevel(), QString());
+
+ ResetDialog dialog;
+ if (dialog.runDialog(state.topLevel()))
+ m_gitClient->hardReset(state.topLevel(), dialog.commit());
}
void GitPlugin::stageFile()
diff --git a/src/plugins/git/resetdialog.cpp b/src/plugins/git/resetdialog.cpp
new file mode 100644
index 00000000000..225ce2a0d66
--- /dev/null
+++ b/src/plugins/git/resetdialog.cpp
@@ -0,0 +1,145 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation ([email protected])
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at [email protected].
+**
+**************************************************************************/
+
+#include "resetdialog.h"
+#include "gitplugin.h"
+#include "gitclient.h"
+
+#include <QTreeView>
+#include <QLabel>
+#include <QDialogButtonBox>
+#include <QPushButton>
+#include <QStandardItemModel>
+#include <QItemSelectionModel>
+#include <QVBoxLayout>
+#include <QDir>
+
+namespace Git {
+namespace Internal {
+
+enum Columns
+{
+ Sha1Column,
+ SubjectColumn,
+ ColumnCount
+};
+
+ResetDialog::ResetDialog(QWidget *parent)
+ : QDialog(parent)
+ , m_treeView(new QTreeView(this))
+ , m_model(new QStandardItemModel(0, ColumnCount, this))
+ , m_dialogButtonBox(new QDialogButtonBox(this))
+{
+ QStringList headers;
+ headers << tr("Sha1")<< tr("Subject");
+ m_model->setHorizontalHeaderLabels(headers);
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ layout->addWidget(new QLabel(tr("Reset to:")));
+ m_treeView->setModel(m_model);
+ m_treeView->setMinimumWidth(300);
+ m_treeView->setUniformRowHeights(true);
+ m_treeView->setRootIsDecorated(false);
+ m_treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
+ layout->addWidget(m_treeView);
+ layout->addWidget(m_dialogButtonBox);
+ m_dialogButtonBox->addButton(QDialogButtonBox::Cancel);
+ QPushButton *okButton = m_dialogButtonBox->addButton(QDialogButtonBox::Ok);
+ connect(m_treeView, SIGNAL(doubleClicked(QModelIndex)),
+ okButton, SLOT(animateClick()));
+
+ connect(m_dialogButtonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(m_dialogButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
+
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+ resize(600, 400);
+}
+
+bool ResetDialog::runDialog(const QString &repository)
+{
+ setWindowTitle(tr("Undo Changes to %1").arg(QDir::toNativeSeparators(repository)));
+
+ if (!populateLog(repository) || !m_model->rowCount())
+ return QDialog::Rejected;
+
+ m_treeView->selectionModel()->select(m_model->index(0, 0),
+ QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
+
+ return exec() == QDialog::Accepted;
+}
+
+QString ResetDialog::commit() const
+{
+ // Return Sha1, or empty for top commit.
+ if (const QStandardItem *sha1Item = currentItem(Sha1Column))
+ return sha1Item->row() ? sha1Item->text() : QString();
+ return QString();
+}
+
+bool ResetDialog::populateLog(const QString &repository)
+{
+ if (const int rowCount = m_model->rowCount())
+ m_model->removeRows(0, rowCount);
+
+ // Retrieve log using a custom format "Sha1:Subject"
+ GitClient *client = GitPlugin::instance()->gitClient();
+ QStringList arguments;
+ arguments << QLatin1String("--max-count=30") << QLatin1String("--format=%h:%s");
+ QString output;
+ if (!client->synchronousLog(repository, arguments, &output))
+ return false;
+ foreach (const QString &line, output.split(QLatin1Char('\n'))) {
+ const int colonPos = line.indexOf(QLatin1Char(':'));
+ if (colonPos != -1) {
+ QList<QStandardItem *> row;
+ for (int c = 0; c < ColumnCount; ++c) {
+ QStandardItem *item = new QStandardItem;
+ item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
+ row.push_back(item);
+ }
+ row[Sha1Column]->setText(line.left(colonPos));
+ row[SubjectColumn]->setText(line.right(line.size() - colonPos - 1));
+ m_model->appendRow(row);
+ }
+ }
+ return true;
+}
+
+const QStandardItem *ResetDialog::currentItem(int column) const
+{
+ const QModelIndex currentIndex = m_treeView->selectionModel()->currentIndex();
+ if (currentIndex.isValid())
+ return m_model->item(currentIndex.row(), column);
+ return 0;
+}
+
+} // namespace Internal
+} // namespace Git
diff --git a/src/plugins/git/resetdialog.h b/src/plugins/git/resetdialog.h
new file mode 100644
index 00000000000..a9945aaee82
--- /dev/null
+++ b/src/plugins/git/resetdialog.h
@@ -0,0 +1,73 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation ([email protected])
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at [email protected].
+**
+**************************************************************************/
+
+#ifndef GIT_INTERNAL_RESETDIALOG_H
+#define GIT_INTERNAL_RESETDIALOG_H
+
+#include <QDialog>
+
+QT_BEGIN_NAMESPACE
+class QTreeView;
+class QDialogButtonBox;
+class QStandardItemModel;
+class QStandardItem;
+QT_END_NAMESPACE
+
+namespace Git {
+namespace Internal {
+
+// A dialog that lists SHA1 and subject of the changes
+// for reset --hard.
+
+class ResetDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit ResetDialog(QWidget *parent = 0);
+
+ bool runDialog(const QString &repository);
+
+ QString commit() const;
+
+private:
+ bool populateLog(const QString &repository);
+ const QStandardItem *currentItem(int column = 0) const;
+
+ QTreeView *m_treeView;
+ QStandardItemModel *m_model;
+ QDialogButtonBox *m_dialogButtonBox;
+};
+
+} // namespace Internal
+} // namespace Git
+
+#endif // GIT_INTERNAL_RESETDIALOG_H