forked from qt-creator/qt-creator
Git: Add on-demand branches expanding
Make "branches expanding" on demand and asynchronous. After "git show" there is clickable text: "Branches: <Expand>" in description. If user clicks this text then branches for commit is triggered and done asynchronously. Task-number: QTCREATORBUG-11293 Done-with: Przemyslaw Gorszkowski <pgorszkowski@gmail.com> Change-Id: I772cfef823d3f95e2b3060dfb5973157d81fc11a Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
This commit is contained in:
committed by
Orgad Shaneh
parent
281aa9e0d6
commit
d6583f0f47
@@ -52,6 +52,7 @@
|
|||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
|
#include <QTextBlock>
|
||||||
|
|
||||||
static const char settingsGroupC[] = "DiffEditor";
|
static const char settingsGroupC[] = "DiffEditor";
|
||||||
static const char diffEditorTypeKeyC[] = "DiffEditorType";
|
static const char diffEditorTypeKeyC[] = "DiffEditorType";
|
||||||
@@ -74,6 +75,9 @@ public:
|
|||||||
DescriptionEditorWidget(QWidget *parent = 0);
|
DescriptionEditorWidget(QWidget *parent = 0);
|
||||||
virtual QSize sizeHint() const;
|
virtual QSize sizeHint() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void expandBranchesRequested();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setDisplaySettings(const DisplaySettings &ds);
|
void setDisplaySettings(const DisplaySettings &ds);
|
||||||
|
|
||||||
@@ -84,6 +88,15 @@ protected:
|
|||||||
editor->document()->setId("DiffEditor.DescriptionEditor");
|
editor->document()->setId("DiffEditor.DescriptionEditor");
|
||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
|
void mouseMoveEvent(QMouseEvent *e);
|
||||||
|
void mouseReleaseEvent(QMouseEvent *e);
|
||||||
|
|
||||||
|
bool findContentsUnderCursor(const QTextCursor &cursor);
|
||||||
|
void highlightCurrentContents();
|
||||||
|
void handleCurrentContents();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTextCursor m_currentCursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
DescriptionEditorWidget::DescriptionEditorWidget(QWidget *parent)
|
DescriptionEditorWidget::DescriptionEditorWidget(QWidget *parent)
|
||||||
@@ -118,6 +131,67 @@ void DescriptionEditorWidget::setDisplaySettings(const DisplaySettings &ds)
|
|||||||
BaseTextEditorWidget::setDisplaySettings(settings);
|
BaseTextEditorWidget::setDisplaySettings(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DescriptionEditorWidget::mouseMoveEvent(QMouseEvent *e)
|
||||||
|
{
|
||||||
|
if (e->buttons()) {
|
||||||
|
TextEditor::BaseTextEditorWidget::mouseMoveEvent(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::CursorShape cursorShape;
|
||||||
|
|
||||||
|
const QTextCursor cursor = cursorForPosition(e->pos());
|
||||||
|
if (findContentsUnderCursor(cursor)) {
|
||||||
|
highlightCurrentContents();
|
||||||
|
cursorShape = Qt::PointingHandCursor;
|
||||||
|
} else {
|
||||||
|
setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>());
|
||||||
|
cursorShape = Qt::IBeamCursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextEditor::BaseTextEditorWidget::mouseMoveEvent(e);
|
||||||
|
viewport()->setCursor(cursorShape);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionEditorWidget::mouseReleaseEvent(QMouseEvent *e)
|
||||||
|
{
|
||||||
|
if (e->button() == Qt::LeftButton && !(e->modifiers() & Qt::ShiftModifier)) {
|
||||||
|
const QTextCursor cursor = cursorForPosition(e->pos());
|
||||||
|
if (findContentsUnderCursor(cursor)) {
|
||||||
|
handleCurrentContents();
|
||||||
|
e->accept();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextEditor::BaseTextEditorWidget::mouseReleaseEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DescriptionEditorWidget::findContentsUnderCursor(const QTextCursor &cursor)
|
||||||
|
{
|
||||||
|
m_currentCursor = cursor;
|
||||||
|
return cursor.block().text() == QLatin1String(Constants::EXPAND_BRANCHES);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionEditorWidget::highlightCurrentContents()
|
||||||
|
{
|
||||||
|
QTextEdit::ExtraSelection sel;
|
||||||
|
sel.cursor = m_currentCursor;
|
||||||
|
sel.cursor.select(QTextCursor::LineUnderCursor);
|
||||||
|
sel.format.setFontUnderline(true);
|
||||||
|
setExtraSelections(BaseTextEditorWidget::OtherSelection,
|
||||||
|
QList<QTextEdit::ExtraSelection>() << sel);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DescriptionEditorWidget::handleCurrentContents()
|
||||||
|
{
|
||||||
|
m_currentCursor.select(QTextCursor::LineUnderCursor);
|
||||||
|
m_currentCursor.removeSelectedText();
|
||||||
|
m_currentCursor.insertText(QLatin1String("Branches: Expanding..."));
|
||||||
|
emit expandBranchesRequested();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|
||||||
///////////////////////////////// DiffEditor //////////////////////////////////
|
///////////////////////////////// DiffEditor //////////////////////////////////
|
||||||
@@ -179,6 +253,8 @@ void DiffEditor::ctor()
|
|||||||
|
|
||||||
setWidget(splitter);
|
setWidget(splitter);
|
||||||
|
|
||||||
|
connect(m_descriptionWidget, SIGNAL(expandBranchesRequested()),
|
||||||
|
m_document->controller(), SLOT(expandBranchesRequested()));
|
||||||
connect(TextEditorSettings::instance(),
|
connect(TextEditorSettings::instance(),
|
||||||
SIGNAL(displaySettingsChanged(TextEditor::DisplaySettings)),
|
SIGNAL(displaySettingsChanged(TextEditor::DisplaySettings)),
|
||||||
m_descriptionWidget,
|
m_descriptionWidget,
|
||||||
|
@@ -44,6 +44,8 @@ const char ICON_SIDE_BY_SIDE_DIFF[] = ":/diffeditor/images/sidebysidediff.png";
|
|||||||
const char ICON_UNIFIED_DIFF[] = ":/diffeditor/images/unifieddiff.png";
|
const char ICON_UNIFIED_DIFF[] = ":/diffeditor/images/unifieddiff.png";
|
||||||
const char ICON_TOP_BAR[] = ":/diffeditor/images/topbar.png";
|
const char ICON_TOP_BAR[] = ":/diffeditor/images/topbar.png";
|
||||||
|
|
||||||
|
const char EXPAND_BRANCHES[] = "Branches: <Expand>";
|
||||||
|
|
||||||
} // namespace Constants
|
} // namespace Constants
|
||||||
} // namespace DiffEditor
|
} // namespace DiffEditor
|
||||||
|
|
||||||
|
@@ -27,10 +27,13 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "diffeditorconstants.h"
|
||||||
#include "diffeditorcontroller.h"
|
#include "diffeditorcontroller.h"
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
static const char settingsGroupC[] = "DiffEditor";
|
static const char settingsGroupC[] = "DiffEditor";
|
||||||
static const char contextLineNumbersKeyC[] = "ContextLineNumbers";
|
static const char contextLineNumbersKeyC[] = "ContextLineNumbers";
|
||||||
static const char ignoreWhitespaceKeyC[] = "IgnoreWhitespace";
|
static const char ignoreWhitespaceKeyC[] = "IgnoreWhitespace";
|
||||||
@@ -148,7 +151,11 @@ void DiffEditorController::setDescription(const QString &description)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
m_description = description;
|
m_description = description;
|
||||||
emit descriptionChanged(description);
|
// Empty line before headers and commit message
|
||||||
|
const int emptyLine = m_description.indexOf(QLatin1String("\n\n"));
|
||||||
|
if (emptyLine != -1)
|
||||||
|
m_description.insert(emptyLine, QLatin1Char('\n') + QLatin1String(Constants::EXPAND_BRANCHES));
|
||||||
|
emit descriptionChanged(m_description);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiffEditorController::setDescriptionEnabled(bool on)
|
void DiffEditorController::setDescriptionEnabled(bool on)
|
||||||
@@ -160,6 +167,44 @@ void DiffEditorController::setDescriptionEnabled(bool on)
|
|||||||
emit descriptionEnablementChanged(on);
|
emit descriptionEnablementChanged(on);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiffEditorController::branchesForCommitReceived(const QString &output)
|
||||||
|
{
|
||||||
|
const QString branches = prepareBranchesForCommit(output);
|
||||||
|
|
||||||
|
m_description.replace(QLatin1String(Constants::EXPAND_BRANCHES), branches);
|
||||||
|
emit descriptionChanged(m_description);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DiffEditorController::expandBranchesRequested()
|
||||||
|
{
|
||||||
|
emit expandBranchesRequested(m_description.mid(7, 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString DiffEditorController::prepareBranchesForCommit(const QString &output)
|
||||||
|
{
|
||||||
|
QString moreBranches;
|
||||||
|
QString branches;
|
||||||
|
QStringList res;
|
||||||
|
foreach (const QString &branch, output.split(QLatin1Char('\n'))) {
|
||||||
|
const QString b = branch.mid(2).trimmed();
|
||||||
|
if (!b.isEmpty())
|
||||||
|
res << b;
|
||||||
|
}
|
||||||
|
const int branchCount = res.count();
|
||||||
|
// If there are more than 20 branches, list first 10 followed by a hint
|
||||||
|
if (branchCount > 20) {
|
||||||
|
const int leave = 10;
|
||||||
|
//: Displayed after the untranslated message "Branches: branch1, branch2 'and %n more'"
|
||||||
|
// in git show.
|
||||||
|
moreBranches = QLatin1Char(' ') + tr("and %n more", 0, branchCount - leave);
|
||||||
|
res.erase(res.begin() + leave, res.end());
|
||||||
|
}
|
||||||
|
if (!res.isEmpty())
|
||||||
|
branches = (QLatin1String("Branches: ") + res.join(QLatin1String(", ")) + moreBranches);
|
||||||
|
|
||||||
|
return branches;
|
||||||
|
}
|
||||||
|
|
||||||
void DiffEditorController::setContextLinesNumber(int lines)
|
void DiffEditorController::setContextLinesNumber(int lines)
|
||||||
{
|
{
|
||||||
const int l = qMax(lines, 1);
|
const int l = qMax(lines, 1);
|
||||||
|
@@ -68,6 +68,8 @@ public slots:
|
|||||||
void requestChunkActions(QMenu *menu,
|
void requestChunkActions(QMenu *menu,
|
||||||
int diffFileIndex,
|
int diffFileIndex,
|
||||||
int chunkIndex);
|
int chunkIndex);
|
||||||
|
void branchesForCommitReceived(const QString &output);
|
||||||
|
void expandBranchesRequested();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void cleared(const QString &message);
|
void cleared(const QString &message);
|
||||||
@@ -81,9 +83,10 @@ signals:
|
|||||||
void chunkActionsRequested(QMenu *menu,
|
void chunkActionsRequested(QMenu *menu,
|
||||||
int diffFileIndex,
|
int diffFileIndex,
|
||||||
int chunkIndex);
|
int chunkIndex);
|
||||||
|
void expandBranchesRequested(const QString &revision);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QString prepareBranchesForCommit(const QString &output);
|
||||||
QString m_clearMessage;
|
QString m_clearMessage;
|
||||||
|
|
||||||
QList<FileData> m_diffFiles;
|
QList<FileData> m_diffFiles;
|
||||||
|
@@ -1139,6 +1139,10 @@ void GitClient::show(const QString &source, const QString &id, const QString &na
|
|||||||
DiffEditor::DiffEditorManager::find(documentId);
|
DiffEditor::DiffEditorManager::find(documentId);
|
||||||
if (!diffEditorDocument) {
|
if (!diffEditorDocument) {
|
||||||
diffEditorDocument = createDiffEditor(documentId, source, title);
|
diffEditorDocument = createDiffEditor(documentId, source, title);
|
||||||
|
|
||||||
|
connect(diffEditorDocument->controller(), SIGNAL(expandBranchesRequested(QString)),
|
||||||
|
this, SLOT(branchesForCommit(QString)));
|
||||||
|
|
||||||
diffEditorDocument->controller()->setDescriptionEnabled(true);
|
diffEditorDocument->controller()->setDescriptionEnabled(true);
|
||||||
|
|
||||||
GitDiffEditorReloader *reloader =
|
GitDiffEditorReloader *reloader =
|
||||||
@@ -1738,23 +1742,25 @@ void GitClient::synchronousTagsForCommit(const QString &workingDirectory, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList GitClient::synchronousBranchesForCommit(const QString &workingDirectory, const QString &revision)
|
void GitClient::branchesForCommit(const QString &revision)
|
||||||
{
|
{
|
||||||
QByteArray outputData;
|
|
||||||
QString output;
|
|
||||||
QStringList arguments;
|
QStringList arguments;
|
||||||
arguments << QLatin1String("branch") << QLatin1String(noColorOption)
|
arguments << QLatin1String("branch") << QLatin1String(noColorOption)
|
||||||
<< QLatin1String("-a") << QLatin1String("--contains") << revision;
|
<< QLatin1String("-a") << QLatin1String("--contains") << revision;
|
||||||
fullySynchronousGit(workingDirectory, arguments, &outputData, 0,
|
|
||||||
VcsBasePlugin::SuppressCommandLogging);
|
DiffEditor::DiffEditorController *editorController
|
||||||
output = commandOutputFromLocal8Bit(outputData);
|
= qobject_cast<DiffEditor::DiffEditorController *>(sender());
|
||||||
QStringList res;
|
QString workingDirectory = editorController->workingDirectory();
|
||||||
foreach (const QString &branch, output.split(QLatin1Char('\n'))) {
|
VcsBase::Command *command = new VcsBase::Command(gitBinaryPath(), workingDirectory,
|
||||||
const QString b = branch.mid(2).trimmed();
|
processEnvironment());
|
||||||
if (!b.isEmpty())
|
command->setCodec(getSourceCodec(currentDocumentPath()));
|
||||||
res << b;
|
|
||||||
}
|
connect(command, SIGNAL(output(QString)), editorController,
|
||||||
return res;
|
SLOT(branchesForCommitReceived(QString)));
|
||||||
|
|
||||||
|
command->addJob(arguments, -1);
|
||||||
|
command->execute();
|
||||||
|
command->setCookie(workingDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GitClient::isRemoteCommit(const QString &workingDirectory, const QString &commit)
|
bool GitClient::isRemoteCommit(const QString &workingDirectory, const QString &commit)
|
||||||
|
@@ -241,8 +241,6 @@ public:
|
|||||||
QString synchronousTopRevision(const QString &workingDirectory, QString *errorMessage = 0);
|
QString synchronousTopRevision(const QString &workingDirectory, QString *errorMessage = 0);
|
||||||
void synchronousTagsForCommit(const QString &workingDirectory, const QString &revision,
|
void synchronousTagsForCommit(const QString &workingDirectory, const QString &revision,
|
||||||
QString &precedes, QString &follows);
|
QString &precedes, QString &follows);
|
||||||
QStringList synchronousBranchesForCommit(const QString &workingDirectory,
|
|
||||||
const QString &revision);
|
|
||||||
bool isRemoteCommit(const QString &workingDirectory, const QString &commit);
|
bool isRemoteCommit(const QString &workingDirectory, const QString &commit);
|
||||||
bool isFastForwardMerge(const QString &workingDirectory, const QString &branch);
|
bool isFastForwardMerge(const QString &workingDirectory, const QString &branch);
|
||||||
|
|
||||||
@@ -349,6 +347,7 @@ private slots:
|
|||||||
void slotChunkActionsRequested(QMenu *menu, int diffFileIndex, int chunkIndex);
|
void slotChunkActionsRequested(QMenu *menu, int diffFileIndex, int chunkIndex);
|
||||||
void slotStageChunk();
|
void slotStageChunk();
|
||||||
void slotUnstageChunk();
|
void slotUnstageChunk();
|
||||||
|
void branchesForCommit(const QString &revision);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString makePatch(int diffFileIndex, int chunkIndex, bool revert) const;
|
QString makePatch(int diffFileIndex, int chunkIndex, bool revert) const;
|
||||||
|
Reference in New Issue
Block a user