forked from qt-creator/qt-creator
DiffEditor: Refactor the user-facing parts
* Move all data handling into DiffEditorDocument * Move much of the logic of how to update views into the DiffEditor. * Introduce a base class for the different views on the diff to implement. * Remove DiffEditorGuiController * Make DiffEditorController smaller and merge the DiffEditorReloader into the class * Simplify communication between the classes involved * Make much of the implementation private to the plugin Change-Id: I7ccb9df6061923bcb34cf3090d6d8331895e83c7 Reviewed-by: Orgad Shaneh <orgads@gmail.com> Reviewed-by: Jarek Kobus <jaroslaw.kobus@theqtcompany.com>
This commit is contained in:
@@ -31,7 +31,6 @@
|
||||
#include "diffeditor.h"
|
||||
#include "diffeditorconstants.h"
|
||||
#include "diffeditordocument.h"
|
||||
#include "diffeditorguicontroller.h"
|
||||
#include "diffview.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
@@ -62,7 +61,13 @@
|
||||
#include <QTextBlock>
|
||||
|
||||
static const char settingsGroupC[] = "DiffEditor";
|
||||
static const char diffEditorTypeKeyC[] = "DiffEditorType";
|
||||
static const char descriptionVisibleKeyC[] = "DescriptionVisible";
|
||||
static const char horizontalScrollBarSynchronizationKeyC[] =
|
||||
"HorizontalScrollBarSynchronization";
|
||||
static const char contextLineCountKeyC[] = "ContextLineNumbers";
|
||||
static const char ignoreWhitespaceKeyC[] = "IgnoreWhitespace";
|
||||
|
||||
static const char diffViewKeyC[] = "DiffEditorType";
|
||||
|
||||
static const char legacySettingsGroupC[] = "Git";
|
||||
static const char useDiffEditorKeyC[] = "UseDiffEditor";
|
||||
@@ -187,7 +192,6 @@ void DescriptionEditorWidget::highlightCurrentContents()
|
||||
sel.format.setFontUnderline(true);
|
||||
setExtraSelections(TextEditorWidget::OtherSelection,
|
||||
QList<QTextEdit::ExtraSelection>() << sel);
|
||||
|
||||
}
|
||||
|
||||
void DescriptionEditorWidget::handleCurrentContents()
|
||||
@@ -204,15 +208,23 @@ DiffEditor::DiffEditor(const QSharedPointer<DiffEditorDocument> &doc)
|
||||
: m_document(doc)
|
||||
, m_descriptionWidget(0)
|
||||
, m_stackedWidget(0)
|
||||
, m_currentViewIndex(-1)
|
||||
, m_guiController(0)
|
||||
, m_toolBar(0)
|
||||
, m_entriesComboBox(0)
|
||||
, m_toggleSyncAction(0)
|
||||
, m_whitespaceButtonAction(0)
|
||||
, m_contextLabelAction(0)
|
||||
, m_contextSpinBoxAction(0)
|
||||
, m_toggleDescriptionAction(0)
|
||||
, m_reloadAction(0)
|
||||
, m_diffEditorSwitcher(0)
|
||||
, m_currentViewIndex(-1)
|
||||
, m_currentDiffFileIndex(-1)
|
||||
, m_sync(false)
|
||||
, m_showDescription(true)
|
||||
, m_ignoreChanges(true)
|
||||
{
|
||||
QTC_ASSERT(m_document, return);
|
||||
setDuplicateSupported(true);
|
||||
|
||||
QSplitter *splitter = new Core::MiniSplitter(Qt::Vertical);
|
||||
|
||||
@@ -228,29 +240,23 @@ DiffEditor::DiffEditor(const QSharedPointer<DiffEditorDocument> &doc)
|
||||
|
||||
setWidget(splitter);
|
||||
|
||||
DiffEditorController *control = controller();
|
||||
m_guiController = new DiffEditorGuiController(control, this);
|
||||
|
||||
connect(m_descriptionWidget, &DescriptionEditorWidget::requestBranchList,
|
||||
control, &DiffEditorController::expandBranchesRequested);
|
||||
connect(control, &DiffEditorController::cleared, this, &DiffEditor::slotCleared);
|
||||
connect(control, &DiffEditorController::diffFilesChanged,
|
||||
this, &DiffEditor::slotDiffFilesChanged);
|
||||
connect(control, &DiffEditorController::descriptionChanged,
|
||||
this, &DiffEditor::slotDescriptionChanged);
|
||||
connect(control, &DiffEditorController::descriptionEnablementChanged,
|
||||
this, &DiffEditor::slotDescriptionVisibilityChanged);
|
||||
connect(m_guiController, &DiffEditorGuiController::descriptionVisibilityChanged,
|
||||
this, &DiffEditor::slotDescriptionVisibilityChanged);
|
||||
connect(m_guiController, &DiffEditorGuiController::currentDiffFileIndexChanged,
|
||||
this, &DiffEditor::activateEntry);
|
||||
|
||||
slotDescriptionChanged(control->description());
|
||||
slotDescriptionVisibilityChanged();
|
||||
|
||||
showDiffView(readCurrentDiffEditorSetting());
|
||||
m_document.data(), &DiffEditorDocument::requestMoreInformation);
|
||||
connect(m_document.data(), &DiffEditorDocument::documentChanged,
|
||||
this, &DiffEditor::documentHasChanged);
|
||||
connect(m_document.data(), &DiffEditorDocument::descriptionChanged,
|
||||
this, &DiffEditor::updateDescription);
|
||||
connect(m_document.data(), &DiffEditorDocument::aboutToReload,
|
||||
this, &DiffEditor::prepareForReload);
|
||||
connect(m_document.data(), &DiffEditorDocument::reloadFinished,
|
||||
this, &DiffEditor::reloadHasFinished);
|
||||
|
||||
toolBar();
|
||||
|
||||
loadSettings();
|
||||
updateDescription();
|
||||
|
||||
m_ignoreChanges = false;
|
||||
}
|
||||
|
||||
DiffEditor::~DiffEditor()
|
||||
@@ -295,8 +301,6 @@ QWidget *DiffEditor::toolBar()
|
||||
if (m_toolBar)
|
||||
return m_toolBar;
|
||||
|
||||
DiffEditorController *control = controller();
|
||||
|
||||
// Create
|
||||
m_toolBar = createToolBar(m_views.at(0));
|
||||
|
||||
@@ -306,109 +310,77 @@ QWidget *DiffEditor::toolBar()
|
||||
QSizePolicy policy = m_entriesComboBox->sizePolicy();
|
||||
policy.setHorizontalPolicy(QSizePolicy::Expanding);
|
||||
m_entriesComboBox->setSizePolicy(policy);
|
||||
connect(m_entriesComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated),
|
||||
this, &DiffEditor::entryActivated);
|
||||
connect(m_entriesComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||
this, &DiffEditor::setCurrentDiffFileIndex);
|
||||
m_toolBar->addWidget(m_entriesComboBox);
|
||||
|
||||
QToolButton *whitespaceButton = new QToolButton(m_toolBar);
|
||||
whitespaceButton->setText(tr("Ignore Whitespace"));
|
||||
whitespaceButton->setCheckable(true);
|
||||
whitespaceButton->setChecked(control->isIgnoreWhitespace());
|
||||
m_whitespaceButtonAction = m_toolBar->addWidget(whitespaceButton);
|
||||
m_whitespaceButton = new QToolButton(m_toolBar);
|
||||
m_whitespaceButton->setText(tr("Ignore Whitespace"));
|
||||
m_whitespaceButton->setCheckable(true);
|
||||
m_whitespaceButton->setChecked(m_document->ignoreWhitespace());
|
||||
m_whitespaceButtonAction = m_toolBar->addWidget(m_whitespaceButton);
|
||||
|
||||
QLabel *contextLabel = new QLabel(m_toolBar);
|
||||
contextLabel->setText(tr("Context Lines:"));
|
||||
contextLabel->setContentsMargins(6, 0, 6, 0);
|
||||
m_contextLabelAction = m_toolBar->addWidget(contextLabel);
|
||||
|
||||
QSpinBox *contextSpinBox = new QSpinBox(m_toolBar);
|
||||
contextSpinBox->setRange(1, 100);
|
||||
contextSpinBox->setValue(control->contextLinesNumber());
|
||||
contextSpinBox->setFrame(false);
|
||||
contextSpinBox->setSizePolicy(QSizePolicy::Minimum,
|
||||
QSizePolicy::Expanding); // Mac Qt5
|
||||
m_contextSpinBoxAction = m_toolBar->addWidget(contextSpinBox);
|
||||
m_contextSpinBox = new QSpinBox(m_toolBar);
|
||||
m_contextSpinBox->setRange(1, 100);
|
||||
m_contextSpinBox->setValue(m_document->contextLineCount());
|
||||
m_contextSpinBox->setFrame(false);
|
||||
m_contextSpinBox->setSizePolicy(QSizePolicy::Minimum,
|
||||
QSizePolicy::Expanding); // Mac Qt5
|
||||
m_contextSpinBoxAction = m_toolBar->addWidget(m_contextSpinBox);
|
||||
|
||||
QToolButton *toggleDescription = new QToolButton(m_toolBar);
|
||||
toggleDescription->setIcon(QIcon(QLatin1String(Constants::ICON_TOP_BAR)));
|
||||
toggleDescription->setCheckable(true);
|
||||
toggleDescription->setChecked(m_guiController->isDescriptionVisible());
|
||||
toggleDescription->setChecked(m_showDescription);
|
||||
m_toggleDescriptionAction = m_toolBar->addWidget(toggleDescription);
|
||||
slotDescriptionVisibilityChanged();
|
||||
updateDescription();
|
||||
|
||||
QToolButton *reloadButton = new QToolButton(m_toolBar);
|
||||
reloadButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_RELOAD_GRAY)));
|
||||
reloadButton->setToolTip(tr("Reload Editor"));
|
||||
m_reloadAction = m_toolBar->addWidget(reloadButton);
|
||||
slotReloaderChanged();
|
||||
documentStateChanged();
|
||||
|
||||
QToolButton *toggleSync = new QToolButton(m_toolBar);
|
||||
toggleSync->setIcon(QIcon(QLatin1String(Core::Constants::ICON_LINK)));
|
||||
toggleSync->setCheckable(true);
|
||||
toggleSync->setChecked(m_guiController->horizontalScrollBarSynchronization());
|
||||
toggleSync->setToolTip(tr("Synchronize Horizontal Scroll Bars"));
|
||||
m_toolBar->addWidget(toggleSync);
|
||||
m_toggleSyncAction = m_toolBar->addWidget(toggleSync);
|
||||
|
||||
m_diffEditorSwitcher = new QToolButton(m_toolBar);
|
||||
m_toolBar->addWidget(m_diffEditorSwitcher);
|
||||
updateDiffEditorSwitcher();
|
||||
|
||||
connect(whitespaceButton, &QToolButton::clicked,
|
||||
control, &DiffEditorController::setIgnoreWhitespace);
|
||||
connect(control, &DiffEditorController::ignoreWhitespaceChanged,
|
||||
whitespaceButton, &QToolButton::setChecked);
|
||||
connect(contextSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
|
||||
control, &DiffEditorController::setContextLinesNumber);
|
||||
connect(control, &DiffEditorController::contextLinesNumberChanged,
|
||||
contextSpinBox, &QSpinBox::setValue);
|
||||
connect(toggleSync, &QAbstractButton::clicked,
|
||||
m_guiController, &DiffEditorGuiController::setHorizontalScrollBarSynchronization);
|
||||
connect(m_whitespaceButton, &QToolButton::clicked,
|
||||
this, &DiffEditor::ignoreWhitespaceHasChanged);
|
||||
connect(m_contextSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
|
||||
this, &DiffEditor::contextLineCountHasChanged);
|
||||
connect(toggleSync, &QAbstractButton::clicked, this, &DiffEditor::toggleSync);
|
||||
connect(toggleDescription, &QAbstractButton::clicked,
|
||||
m_guiController, &DiffEditorGuiController::setDescriptionVisible);
|
||||
this, &DiffEditor::toggleDescription);
|
||||
connect(m_diffEditorSwitcher, &QAbstractButton::clicked,
|
||||
this, [this]() { showDiffView(nextView()); });
|
||||
connect(reloadButton, &QAbstractButton::clicked,
|
||||
control, &DiffEditorController::requestReload);
|
||||
connect(control, &DiffEditorController::reloaderChanged,
|
||||
this, &DiffEditor::slotReloaderChanged);
|
||||
connect(control, &DiffEditorController::contextLinesNumberEnablementChanged,
|
||||
this, &DiffEditor::slotReloaderChanged);
|
||||
|
||||
connect(reloadButton, &QAbstractButton::clicked, this, [this]() { m_document->reload(); });
|
||||
connect(m_document.data(), &DiffEditorDocument::temporaryStateChanged,
|
||||
this, &DiffEditor::documentStateChanged);
|
||||
|
||||
return m_toolBar;
|
||||
}
|
||||
|
||||
DiffEditorController *DiffEditor::controller() const
|
||||
void DiffEditor::documentHasChanged()
|
||||
{
|
||||
return m_document->controller();
|
||||
}
|
||||
m_ignoreChanges = true;
|
||||
const QList<FileData> diffFileList = m_document->diffFiles();
|
||||
|
||||
void DiffEditor::updateEntryToolTip()
|
||||
{
|
||||
const QString &toolTip = m_entriesComboBox->itemData(
|
||||
m_entriesComboBox->currentIndex(), Qt::ToolTipRole).toString();
|
||||
m_entriesComboBox->setToolTip(toolTip);
|
||||
}
|
||||
|
||||
void DiffEditor::entryActivated(int index)
|
||||
{
|
||||
updateEntryToolTip();
|
||||
m_guiController->setCurrentDiffFileIndex(index);
|
||||
}
|
||||
|
||||
void DiffEditor::slotCleared(const QString &message)
|
||||
{
|
||||
Q_UNUSED(message)
|
||||
|
||||
m_entriesComboBox->clear();
|
||||
updateEntryToolTip();
|
||||
}
|
||||
|
||||
void DiffEditor::slotDiffFilesChanged(const QList<FileData> &diffFileList,
|
||||
const QString &workingDirectory)
|
||||
{
|
||||
Q_UNUSED(workingDirectory)
|
||||
currentView()->setDiff(diffFileList, m_document->baseDirectory());
|
||||
|
||||
m_entriesComboBox->clear();
|
||||
int index = 0;
|
||||
const int count = diffFileList.count();
|
||||
for (int i = 0; i < count; i++) {
|
||||
const DiffFileInfo leftEntry = diffFileList.at(i).leftFileInfo;
|
||||
@@ -449,64 +421,193 @@ void DiffEditor::slotDiffFilesChanged(const QList<FileData> &diffFileList,
|
||||
rightEntry.fileName);
|
||||
}
|
||||
}
|
||||
if (m_currentFileChunk.first == leftEntry.fileName
|
||||
&& m_currentFileChunk.second == rightEntry.fileName)
|
||||
index = i;
|
||||
m_entriesComboBox->addItem(itemText);
|
||||
m_entriesComboBox->setItemData(m_entriesComboBox->count() - 1,
|
||||
leftEntry.fileName, Qt::UserRole);
|
||||
m_entriesComboBox->setItemData(m_entriesComboBox->count() - 1,
|
||||
rightEntry.fileName, Qt::UserRole + 1);
|
||||
m_entriesComboBox->setItemData(m_entriesComboBox->count() - 1,
|
||||
itemToolTip, Qt::ToolTipRole);
|
||||
}
|
||||
updateEntryToolTip();
|
||||
|
||||
m_ignoreChanges = false;
|
||||
|
||||
setCurrentDiffFileIndex(m_entriesComboBox->count() > 0 ? index : -1);
|
||||
}
|
||||
|
||||
void DiffEditor::activateEntry(int index)
|
||||
void DiffEditor::toggleDescription()
|
||||
{
|
||||
m_entriesComboBox->blockSignals(true);
|
||||
m_entriesComboBox->setCurrentIndex(index);
|
||||
m_entriesComboBox->blockSignals(false);
|
||||
updateEntryToolTip();
|
||||
m_showDescription = !m_showDescription;
|
||||
saveSetting(QLatin1String(descriptionVisibleKeyC), m_showDescription);
|
||||
updateDescription();
|
||||
}
|
||||
|
||||
void DiffEditor::slotDescriptionChanged(const QString &description)
|
||||
void DiffEditor::updateDescription()
|
||||
{
|
||||
QString description = m_document->description();
|
||||
m_descriptionWidget->setPlainText(description);
|
||||
}
|
||||
m_descriptionWidget->setVisible(m_showDescription && !description.isEmpty());
|
||||
|
||||
void DiffEditor::slotDescriptionVisibilityChanged()
|
||||
{
|
||||
const bool enabled = controller()->isDescriptionEnabled();
|
||||
const bool visible = m_guiController->isDescriptionVisible();
|
||||
|
||||
m_descriptionWidget->setVisible(visible && enabled);
|
||||
|
||||
if (!m_toggleDescriptionAction)
|
||||
return;
|
||||
QTC_ASSERT(m_toolBar, return);
|
||||
QTC_ASSERT(m_toggleDescriptionAction, return);
|
||||
|
||||
QWidget *toggle = m_toolBar->widgetForAction(m_toggleDescriptionAction);
|
||||
if (visible)
|
||||
toggle->setToolTip(tr("Hide Change Description"));
|
||||
else
|
||||
toggle->setToolTip(tr("Show Change Description"));
|
||||
|
||||
m_toggleDescriptionAction->setVisible(enabled);
|
||||
toggle->setToolTip(m_showDescription ? tr("Hide Change Description")
|
||||
: tr("Show Change Description"));
|
||||
m_toggleDescriptionAction->setVisible(!description.isEmpty());
|
||||
}
|
||||
|
||||
void DiffEditor::slotReloaderChanged()
|
||||
void DiffEditor::contextLineCountHasChanged(int lines)
|
||||
{
|
||||
DiffEditorController *control = controller();
|
||||
const DiffEditorReloader *reloader = control->reloader();
|
||||
const bool contextVisible = control->isContextLinesNumberEnabled();
|
||||
QTC_ASSERT(!m_document->isContextLineCountForced(), return);
|
||||
if (m_ignoreChanges || lines == m_document->contextLineCount())
|
||||
return;
|
||||
|
||||
m_whitespaceButtonAction->setVisible(reloader);
|
||||
m_contextLabelAction->setVisible(reloader && contextVisible);
|
||||
m_contextSpinBoxAction->setVisible(reloader && contextVisible);
|
||||
m_reloadAction->setVisible(reloader);
|
||||
m_document->setContextLineCount(lines);
|
||||
saveSetting(QLatin1String(contextLineCountKeyC), lines);
|
||||
|
||||
m_document->reload();
|
||||
}
|
||||
|
||||
void DiffEditor::ignoreWhitespaceHasChanged(bool ignore)
|
||||
{
|
||||
if (m_ignoreChanges || ignore == m_document->ignoreWhitespace())
|
||||
return;
|
||||
|
||||
m_document->setIgnoreWhitespace(ignore);
|
||||
saveSetting(QLatin1String(ignoreWhitespaceKeyC), ignore);
|
||||
m_document->reload();
|
||||
}
|
||||
|
||||
void DiffEditor::prepareForReload()
|
||||
{
|
||||
documentStateChanged(); // To update actions...
|
||||
|
||||
QTC_ASSERT(currentView(), return);
|
||||
|
||||
if (m_entriesComboBox->count() > 0) {
|
||||
m_currentFileChunk
|
||||
= qMakePair(m_entriesComboBox->itemData(m_currentDiffFileIndex, Qt::UserRole).toString(),
|
||||
m_entriesComboBox->itemData(m_currentDiffFileIndex, Qt::UserRole + 1).toString());
|
||||
} else {
|
||||
m_currentFileChunk = qMakePair(QString(), QString());
|
||||
}
|
||||
|
||||
m_ignoreChanges = true;
|
||||
m_contextSpinBox->setValue(m_document->contextLineCount());
|
||||
m_whitespaceButton->setChecked(m_document->ignoreWhitespace());
|
||||
m_ignoreChanges = false;
|
||||
currentView()->beginOperation();
|
||||
}
|
||||
|
||||
void DiffEditor::reloadHasFinished(bool success)
|
||||
{
|
||||
if (!currentView())
|
||||
return;
|
||||
|
||||
m_currentFileChunk = qMakePair(QString(), QString());
|
||||
|
||||
currentView()->endOperation(success);
|
||||
}
|
||||
|
||||
void DiffEditor::updateEntryToolTip()
|
||||
{
|
||||
const QString &toolTip = m_entriesComboBox->itemData(
|
||||
m_entriesComboBox->currentIndex(), Qt::ToolTipRole).toString();
|
||||
m_entriesComboBox->setToolTip(toolTip);
|
||||
}
|
||||
|
||||
void DiffEditor::setCurrentDiffFileIndex(int index)
|
||||
{
|
||||
if (m_ignoreChanges)
|
||||
return;
|
||||
|
||||
QTC_ASSERT((index < 0) != (m_entriesComboBox->count() > 0), return);
|
||||
|
||||
m_ignoreChanges = true;
|
||||
|
||||
m_currentDiffFileIndex = index;
|
||||
currentView()->setCurrentDiffFileIndex(index);
|
||||
|
||||
m_entriesComboBox->setCurrentIndex(m_entriesComboBox->count() > 0 ? qMax(0, index) : -1);
|
||||
updateEntryToolTip();
|
||||
|
||||
m_ignoreChanges = false;
|
||||
}
|
||||
|
||||
void DiffEditor::documentStateChanged()
|
||||
{
|
||||
const bool canReload = m_document->isTemporary();
|
||||
const bool contextVisible = !m_document->isContextLineCountForced();
|
||||
|
||||
m_whitespaceButtonAction->setVisible(canReload);
|
||||
m_contextLabelAction->setVisible(canReload && contextVisible);
|
||||
m_contextSpinBoxAction->setVisible(canReload && contextVisible);
|
||||
m_reloadAction->setVisible(canReload);
|
||||
}
|
||||
|
||||
void DiffEditor::updateDiffEditorSwitcher()
|
||||
{
|
||||
if (!m_diffEditorSwitcher)
|
||||
return;
|
||||
IDiffView *next = nextView();
|
||||
m_diffEditorSwitcher->setIcon(next->icon());
|
||||
m_diffEditorSwitcher->setToolTip(next->toolTip());
|
||||
}
|
||||
|
||||
m_diffEditorSwitcher->setIcon(currentView()->icon());
|
||||
m_diffEditorSwitcher->setToolTip(currentView()->toolTip());
|
||||
void DiffEditor::toggleSync()
|
||||
{
|
||||
QTC_ASSERT(currentView(), return);
|
||||
m_sync = !m_sync;
|
||||
saveSetting(QLatin1String(horizontalScrollBarSynchronizationKeyC), m_sync);
|
||||
currentView()->setSync(m_sync);
|
||||
}
|
||||
|
||||
void DiffEditor::loadSettings()
|
||||
{
|
||||
QTC_ASSERT(currentView(), return);
|
||||
QSettings *s = Core::ICore::settings();
|
||||
|
||||
// TODO: Remove in 3.6: Read legacy settings first:
|
||||
s->beginGroup(QLatin1String(legacySettingsGroupC));
|
||||
const bool legacyExists = s->contains(QLatin1String(useDiffEditorKeyC));
|
||||
const bool legacyEditor = s->value(
|
||||
QLatin1String(useDiffEditorKeyC), true).toBool();
|
||||
s->remove(QLatin1String(useDiffEditorKeyC));
|
||||
s->endGroup();
|
||||
|
||||
// Save legacy settings to current settings:
|
||||
if (legacyExists) {
|
||||
saveSetting(QLatin1String(diffViewKeyC), legacyEditor ? m_views.at(0)->id().toSetting() :
|
||||
m_views.at(1)->id().toSetting());
|
||||
}
|
||||
|
||||
// Read current settings:
|
||||
s->beginGroup(QLatin1String(settingsGroupC));
|
||||
m_showDescription = s->value(QLatin1String(descriptionVisibleKeyC),
|
||||
true).toBool();
|
||||
m_sync = s->value(QLatin1String(horizontalScrollBarSynchronizationKeyC),
|
||||
true).toBool();
|
||||
m_document->setIgnoreWhitespace(s->value(QLatin1String(ignoreWhitespaceKeyC), false).toBool());
|
||||
m_document->setContextLineCount(s->value(QLatin1String(contextLineCountKeyC), 3).toInt());
|
||||
Core::Id id = Core::Id::fromSetting(s->value(QLatin1String(diffViewKeyC)));
|
||||
s->endGroup();
|
||||
|
||||
IDiffView *view = Utils::findOr(m_views, m_views.at(0), [id](IDiffView *v) { return v->id() == id; });
|
||||
QTC_ASSERT(view, return);
|
||||
|
||||
setupView(view);
|
||||
}
|
||||
|
||||
void DiffEditor::saveSetting(const QString &key, const QVariant &value) const
|
||||
{
|
||||
QSettings *s = Core::ICore::settings();
|
||||
s->beginGroup(QLatin1String(settingsGroupC));
|
||||
s->setValue(key, value);
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
void DiffEditor::addView(IDiffView *view)
|
||||
@@ -514,6 +615,10 @@ void DiffEditor::addView(IDiffView *view)
|
||||
QTC_ASSERT(!m_views.contains(view), return);
|
||||
m_views.append(view);
|
||||
m_stackedWidget->addWidget(view->widget());
|
||||
if (m_views.count() == 1)
|
||||
setCurrentView(view);
|
||||
|
||||
connect(view, &IDiffView::currentDiffFileIndexChanged, this, &DiffEditor::setCurrentDiffFileIndex);
|
||||
}
|
||||
|
||||
IDiffView *DiffEditor::currentView() const
|
||||
@@ -539,71 +644,42 @@ IDiffView *DiffEditor::nextView()
|
||||
return m_views.at(pos);
|
||||
}
|
||||
|
||||
void DiffEditor::showDiffView(IDiffView *newView)
|
||||
void DiffEditor::setupView(IDiffView *view)
|
||||
{
|
||||
QTC_ASSERT(newView, return);
|
||||
QTC_ASSERT(view, return);
|
||||
setCurrentView(view);
|
||||
|
||||
if (currentView() == newView)
|
||||
saveSetting(QLatin1String(diffViewKeyC), currentView()->id().toSetting());
|
||||
|
||||
m_toggleSyncAction->setVisible(currentView()->supportsSync());
|
||||
m_toggleSyncAction->setToolTip(currentView()->syncToolTip());
|
||||
m_toggleSyncAction->setChecked(m_sync);
|
||||
|
||||
view->setDocument(m_document.data());
|
||||
view->setSync(m_sync);
|
||||
|
||||
view->beginOperation();
|
||||
view->setDiff(m_document->diffFiles(), m_document->baseDirectory());
|
||||
view->endOperation(true);
|
||||
view->setCurrentDiffFileIndex(m_currentDiffFileIndex);
|
||||
|
||||
m_stackedWidget->setCurrentWidget(view->widget());
|
||||
|
||||
updateDiffEditorSwitcher();
|
||||
if (widget())
|
||||
widget()->setFocusProxy(view->widget());
|
||||
}
|
||||
|
||||
void DiffEditor::showDiffView(IDiffView *view)
|
||||
{
|
||||
if (currentView() == view)
|
||||
return;
|
||||
|
||||
if (currentView()) // during initialization
|
||||
currentView()->setDiffEditorGuiController(0);
|
||||
setCurrentView(newView);
|
||||
currentView()->setDiffEditorGuiController(m_guiController);
|
||||
currentView()->setDocument(0);
|
||||
|
||||
m_stackedWidget->setCurrentWidget(currentView()->widget());
|
||||
|
||||
writeCurrentDiffEditorSetting(currentView());
|
||||
updateDiffEditorSwitcher();
|
||||
widget()->setFocusProxy(currentView()->widget());
|
||||
}
|
||||
|
||||
// TODO: Remove in 3.6:
|
||||
IDiffView *DiffEditor::readLegacyCurrentDiffEditorSetting()
|
||||
{
|
||||
QTC_ASSERT(!m_views.isEmpty(), return 0);
|
||||
QTC_ASSERT(m_views.count() == 2, return m_views.at(0));
|
||||
|
||||
QSettings *s = Core::ICore::settings();
|
||||
|
||||
s->beginGroup(QLatin1String(legacySettingsGroupC));
|
||||
const bool legacyExists = s->contains(QLatin1String(useDiffEditorKeyC));
|
||||
const bool legacyEditor = s->value(
|
||||
QLatin1String(useDiffEditorKeyC), true).toBool();
|
||||
if (legacyExists)
|
||||
s->remove(QLatin1String(useDiffEditorKeyC));
|
||||
s->endGroup();
|
||||
|
||||
IDiffView *currentEditor = m_views.at(0);
|
||||
if (!legacyEditor)
|
||||
currentEditor = m_views.at(1);
|
||||
|
||||
if (legacyExists)
|
||||
writeCurrentDiffEditorSetting(currentEditor);
|
||||
|
||||
return currentEditor;
|
||||
}
|
||||
|
||||
IDiffView *DiffEditor::readCurrentDiffEditorSetting()
|
||||
{
|
||||
// replace it with m_sideBySideEditor when dropping legacy stuff
|
||||
IDiffView *view = readLegacyCurrentDiffEditorSetting();
|
||||
|
||||
QSettings *s = Core::ICore::settings();
|
||||
s->beginGroup(QLatin1String(settingsGroupC));
|
||||
const Core::Id id = Core::Id::fromSetting(s->value(QLatin1String(diffEditorTypeKeyC)));
|
||||
s->endGroup();
|
||||
|
||||
return Utils::findOr(m_views, view, [id](IDiffView *v) { return v->id() == id; });
|
||||
}
|
||||
|
||||
void DiffEditor::writeCurrentDiffEditorSetting(IDiffView *currentEditor)
|
||||
{
|
||||
QTC_ASSERT(currentEditor, return);
|
||||
QSettings *s = Core::ICore::settings();
|
||||
s->beginGroup(QLatin1String(settingsGroupC));
|
||||
s->setValue(QLatin1String(diffEditorTypeKeyC), currentEditor->id().toSetting());
|
||||
s->endGroup();
|
||||
QTC_ASSERT(view, return);
|
||||
setupView(view);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QComboBox;
|
||||
class QSpinBox;
|
||||
class QToolBar;
|
||||
class QToolButton;
|
||||
class QStackedWidget;
|
||||
@@ -50,7 +51,6 @@ namespace DiffEditor {
|
||||
namespace Internal {
|
||||
class DescriptionEditorWidget;
|
||||
class DiffEditorDocument;
|
||||
class DiffEditorGuiController;
|
||||
class IDiffView;
|
||||
|
||||
class DiffEditor : public Core::IEditor
|
||||
@@ -62,8 +62,6 @@ public:
|
||||
~DiffEditor();
|
||||
|
||||
public:
|
||||
DiffEditorController *controller() const;
|
||||
|
||||
Core::IEditor *duplicate();
|
||||
|
||||
bool open(QString *errorString,
|
||||
@@ -73,44 +71,52 @@ public:
|
||||
|
||||
QWidget *toolBar();
|
||||
|
||||
public slots:
|
||||
void activateEntry(int index);
|
||||
|
||||
private slots:
|
||||
void slotCleared(const QString &message);
|
||||
void slotDiffFilesChanged(const QList<FileData> &diffFileList,
|
||||
const QString &workingDirectory);
|
||||
void entryActivated(int index);
|
||||
void slotDescriptionChanged(const QString &description);
|
||||
void slotDescriptionVisibilityChanged();
|
||||
void slotReloaderChanged();
|
||||
void documentHasChanged();
|
||||
void toggleDescription();
|
||||
void updateDescription();
|
||||
void contextLineCountHasChanged(int lines);
|
||||
void ignoreWhitespaceHasChanged(bool ignore);
|
||||
void prepareForReload();
|
||||
void reloadHasFinished(bool success);
|
||||
void setCurrentDiffFileIndex(int index);
|
||||
void documentStateChanged();
|
||||
|
||||
void toggleSync();
|
||||
|
||||
private:
|
||||
void loadSettings();
|
||||
void saveSetting(const QString &key, const QVariant &value) const;
|
||||
void updateEntryToolTip();
|
||||
void showDiffView(IDiffView *newEditor);
|
||||
void showDiffView(IDiffView *view);
|
||||
void updateDiffEditorSwitcher();
|
||||
void addView(IDiffView *view);
|
||||
IDiffView *currentView() const;
|
||||
void setCurrentView(IDiffView *view);
|
||||
IDiffView *nextView();
|
||||
IDiffView *readLegacyCurrentDiffEditorSetting();
|
||||
IDiffView *readCurrentDiffEditorSetting();
|
||||
void writeCurrentDiffEditorSetting(IDiffView *currentEditor);
|
||||
void setupView(IDiffView *view);
|
||||
|
||||
QSharedPointer<DiffEditorDocument> m_document;
|
||||
DescriptionEditorWidget *m_descriptionWidget;
|
||||
QStackedWidget *m_stackedWidget;
|
||||
QVector<IDiffView *> m_views;
|
||||
int m_currentViewIndex;
|
||||
DiffEditorGuiController *m_guiController;
|
||||
QToolBar *m_toolBar;
|
||||
QComboBox *m_entriesComboBox;
|
||||
QToolButton *m_whitespaceButton;
|
||||
QSpinBox *m_contextSpinBox;
|
||||
QAction *m_toggleSyncAction;
|
||||
QAction *m_whitespaceButtonAction;
|
||||
QAction *m_contextLabelAction;
|
||||
QAction *m_contextSpinBoxAction;
|
||||
QAction *m_toggleDescriptionAction;
|
||||
QAction *m_reloadAction;
|
||||
QToolButton *m_diffEditorSwitcher;
|
||||
QPair<QString, QString> m_currentFileChunk;
|
||||
int m_currentViewIndex;
|
||||
int m_currentDiffFileIndex;
|
||||
bool m_sync;
|
||||
bool m_showDescription;
|
||||
bool m_ignoreChanges;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -7,10 +7,8 @@ HEADERS += diffeditor_global.h \
|
||||
diffeditorcontroller.h \
|
||||
diffeditordocument.h \
|
||||
diffeditorfactory.h \
|
||||
diffeditorguicontroller.h \
|
||||
diffeditormanager.h \
|
||||
diffeditorplugin.h \
|
||||
diffeditorreloader.h \
|
||||
differ.h \
|
||||
diffutils.h \
|
||||
diffview.h \
|
||||
@@ -22,10 +20,8 @@ SOURCES += diffeditor.cpp \
|
||||
diffeditorcontroller.cpp \
|
||||
diffeditordocument.cpp \
|
||||
diffeditorfactory.cpp \
|
||||
diffeditorguicontroller.cpp \
|
||||
diffeditormanager.cpp \
|
||||
diffeditorplugin.cpp \
|
||||
diffeditorreloader.cpp \
|
||||
differ.cpp \
|
||||
diffutils.cpp \
|
||||
diffview.cpp \
|
||||
|
||||
@@ -22,14 +22,10 @@ QtcPlugin {
|
||||
"diffeditordocument.h",
|
||||
"diffeditorfactory.cpp",
|
||||
"diffeditorfactory.h",
|
||||
"diffeditorguicontroller.cpp",
|
||||
"diffeditorguicontroller.h",
|
||||
"diffeditormanager.cpp",
|
||||
"diffeditormanager.h",
|
||||
"diffeditorplugin.cpp",
|
||||
"diffeditorplugin.h",
|
||||
"diffeditorreloader.cpp",
|
||||
"diffeditorreloader.h",
|
||||
"differ.cpp",
|
||||
"differ.h",
|
||||
"diffutils.cpp",
|
||||
|
||||
@@ -30,227 +30,90 @@
|
||||
|
||||
#include "diffeditorconstants.h"
|
||||
#include "diffeditorcontroller.h"
|
||||
#include "diffeditorreloader.h"
|
||||
#include "diffeditordocument.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <QStringList>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
static const char settingsGroupC[] = "DiffEditor";
|
||||
static const char contextLineNumbersKeyC[] = "ContextLineNumbers";
|
||||
static const char ignoreWhitespaceKeyC[] = "IgnoreWhitespace";
|
||||
#include <QStringList>
|
||||
|
||||
namespace DiffEditor {
|
||||
|
||||
DiffEditorController::DiffEditorController(QObject *parent)
|
||||
: QObject(parent),
|
||||
m_reloader(0),
|
||||
m_contextLinesNumber(3),
|
||||
m_diffFileIndex(-1),
|
||||
m_chunkIndex(-1),
|
||||
m_descriptionEnabled(false),
|
||||
m_contextLinesNumberEnabled(true),
|
||||
m_ignoreWhitespace(true)
|
||||
DiffEditorController::DiffEditorController(Core::IDocument *document) :
|
||||
QObject(document),
|
||||
m_document(qobject_cast<Internal::DiffEditorDocument *>(document)),
|
||||
m_isReloading(false),
|
||||
m_diffFileIndex(-1),
|
||||
m_chunkIndex(-1)
|
||||
{
|
||||
QSettings *s = Core::ICore::settings();
|
||||
s->beginGroup(QLatin1String(settingsGroupC));
|
||||
m_contextLinesNumber = s->value(QLatin1String(contextLineNumbersKeyC),
|
||||
m_contextLinesNumber).toInt();
|
||||
m_ignoreWhitespace = s->value(QLatin1String(ignoreWhitespaceKeyC),
|
||||
m_ignoreWhitespace).toBool();
|
||||
s->endGroup();
|
||||
|
||||
clear();
|
||||
QTC_ASSERT(m_document, return);
|
||||
QTC_CHECK(!m_document->controller());
|
||||
m_document->setController(this);
|
||||
}
|
||||
|
||||
DiffEditorController::~DiffEditorController()
|
||||
bool DiffEditorController::isReloading() const
|
||||
{
|
||||
delete m_reloader;
|
||||
return m_isReloading;
|
||||
}
|
||||
|
||||
QString DiffEditorController::clearMessage() const
|
||||
QString DiffEditorController::baseDirectory() const
|
||||
{
|
||||
return m_clearMessage;
|
||||
return m_document->baseDirectory();
|
||||
}
|
||||
|
||||
QList<FileData> DiffEditorController::diffFiles() const
|
||||
int DiffEditorController::contextLineCount() const
|
||||
{
|
||||
return m_diffFiles;
|
||||
return m_document->contextLineCount();
|
||||
}
|
||||
|
||||
QString DiffEditorController::workingDirectory() const
|
||||
bool DiffEditorController::ignoreWhitespace() const
|
||||
{
|
||||
return m_workingDirectory;
|
||||
return m_document->ignoreWhitespace();
|
||||
}
|
||||
|
||||
QString DiffEditorController::description() const
|
||||
QString DiffEditorController::revisionFromDescription() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
bool DiffEditorController::isDescriptionEnabled() const
|
||||
{
|
||||
return m_descriptionEnabled;
|
||||
}
|
||||
|
||||
int DiffEditorController::contextLinesNumber() const
|
||||
{
|
||||
return m_contextLinesNumber;
|
||||
}
|
||||
|
||||
bool DiffEditorController::isContextLinesNumberEnabled() const
|
||||
{
|
||||
return m_contextLinesNumberEnabled;
|
||||
}
|
||||
|
||||
bool DiffEditorController::isIgnoreWhitespace() const
|
||||
{
|
||||
return m_ignoreWhitespace;
|
||||
}
|
||||
|
||||
// ### fixme: git-specific handling should be done in the git plugin:
|
||||
// Remove unexpanded branches and follows-tag, clear indentation
|
||||
// and create E-mail
|
||||
static void formatGitDescription(QString *description)
|
||||
{
|
||||
QString result;
|
||||
result.reserve(description->size());
|
||||
foreach (QString line, description->split(QLatin1Char('\n'))) {
|
||||
if (line.startsWith(QLatin1String("commit "))
|
||||
|| line.startsWith(QLatin1String("Branches: <Expand>"))) {
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith(QLatin1String("Author: ")))
|
||||
line.replace(0, 8, QStringLiteral("From: "));
|
||||
else if (line.startsWith(QLatin1String(" ")))
|
||||
line.remove(0, 4);
|
||||
result.append(line);
|
||||
result.append(QLatin1Char('\n'));
|
||||
}
|
||||
*description = result;
|
||||
}
|
||||
|
||||
QString DiffEditorController::contents() const
|
||||
{
|
||||
QString result = m_description;
|
||||
const int formattingOptions = DiffUtils::GitFormat;
|
||||
if (formattingOptions & DiffUtils::GitFormat)
|
||||
formatGitDescription(&result);
|
||||
|
||||
const QString diff = DiffUtils::makePatch(diffFiles(), formattingOptions);
|
||||
if (!diff.isEmpty()) {
|
||||
if (!result.isEmpty())
|
||||
result += QLatin1Char('\n');
|
||||
result += diff;
|
||||
}
|
||||
return result;
|
||||
// TODO: This is specific for git and does not belong here at all!
|
||||
return m_document->description().mid(7, 12);
|
||||
}
|
||||
|
||||
QString DiffEditorController::makePatch(bool revert, bool addPrefix) const
|
||||
{
|
||||
if (m_diffFileIndex < 0 || m_chunkIndex < 0)
|
||||
return QString();
|
||||
|
||||
if (m_diffFileIndex >= m_diffFiles.count())
|
||||
return QString();
|
||||
|
||||
const FileData fileData = m_diffFiles.at(m_diffFileIndex);
|
||||
if (m_chunkIndex >= fileData.chunks.count())
|
||||
return QString();
|
||||
|
||||
const ChunkData chunkData = fileData.chunks.at(m_chunkIndex);
|
||||
const bool lastChunk = (m_chunkIndex == fileData.chunks.count() - 1);
|
||||
|
||||
const QString fileName = revert
|
||||
? fileData.rightFileInfo.fileName
|
||||
: fileData.leftFileInfo.fileName;
|
||||
|
||||
QString leftPrefix, rightPrefix;
|
||||
if (addPrefix) {
|
||||
leftPrefix = QLatin1String("a/");
|
||||
rightPrefix = QLatin1String("b/");
|
||||
}
|
||||
return DiffUtils::makePatch(chunkData,
|
||||
leftPrefix + fileName,
|
||||
rightPrefix + fileName,
|
||||
lastChunk && fileData.lastChunkAtTheEndOfFile);
|
||||
}
|
||||
|
||||
DiffEditorReloader *DiffEditorController::reloader() const
|
||||
{
|
||||
return m_reloader;
|
||||
}
|
||||
|
||||
// The ownership of reloader is passed to the controller
|
||||
void DiffEditorController::setReloader(DiffEditorReloader *reloader)
|
||||
{
|
||||
if (m_reloader == reloader)
|
||||
return; // nothing changes
|
||||
|
||||
delete m_reloader;
|
||||
|
||||
m_reloader = reloader;
|
||||
|
||||
if (m_reloader)
|
||||
m_reloader->setController(this);
|
||||
|
||||
emit reloaderChanged();
|
||||
}
|
||||
|
||||
void DiffEditorController::clear()
|
||||
{
|
||||
clear(tr("No difference"));
|
||||
}
|
||||
|
||||
void DiffEditorController::clear(const QString &message)
|
||||
{
|
||||
setDescription(QString());
|
||||
setDiffFiles(QList<FileData>());
|
||||
m_clearMessage = message;
|
||||
emit cleared(message);
|
||||
return m_document->makePatch(m_diffFileIndex, m_chunkIndex, revert, addPrefix);
|
||||
}
|
||||
|
||||
void DiffEditorController::setDiffFiles(const QList<FileData> &diffFileList,
|
||||
const QString &workingDirectory)
|
||||
{
|
||||
m_diffFiles = diffFileList;
|
||||
m_workingDirectory = workingDirectory;
|
||||
emit diffFilesChanged(diffFileList, workingDirectory);
|
||||
m_document->setDiffFiles(diffFileList, workingDirectory);
|
||||
}
|
||||
|
||||
void DiffEditorController::setDescription(const QString &description)
|
||||
{
|
||||
if (m_description == description)
|
||||
return;
|
||||
|
||||
m_description = description;
|
||||
emit descriptionChanged(m_description);
|
||||
m_document->setDescription(description);
|
||||
}
|
||||
|
||||
void DiffEditorController::setDescriptionEnabled(bool on)
|
||||
{
|
||||
if (m_descriptionEnabled == on)
|
||||
return;
|
||||
|
||||
m_descriptionEnabled = on;
|
||||
emit descriptionEnablementChanged(on);
|
||||
}
|
||||
|
||||
void DiffEditorController::branchesForCommitReceived(const QString &output)
|
||||
void DiffEditorController::informationForCommitReceived(const QString &output)
|
||||
{
|
||||
// TODO: Git specific code...
|
||||
const QString branches = prepareBranchesForCommit(output);
|
||||
|
||||
m_description.replace(QLatin1String(Constants::EXPAND_BRANCHES), branches);
|
||||
emit descriptionChanged(m_description);
|
||||
QString tmp = m_document->description();
|
||||
tmp.replace(QLatin1String(Constants::EXPAND_BRANCHES), branches);
|
||||
m_document->setDescription(tmp);
|
||||
}
|
||||
|
||||
void DiffEditorController::expandBranchesRequested()
|
||||
void DiffEditorController::requestMoreInformation()
|
||||
{
|
||||
emit requestBranchList(m_description.mid(7, 8));
|
||||
const QString rev = revisionFromDescription();
|
||||
if (!rev.isEmpty())
|
||||
emit requestInformationForCommit(rev);
|
||||
}
|
||||
|
||||
QString DiffEditorController::prepareBranchesForCommit(const QString &output)
|
||||
{
|
||||
// TODO: More git-specific code...
|
||||
QString moreBranches;
|
||||
QString branches;
|
||||
QStringList res;
|
||||
@@ -274,69 +137,40 @@ QString DiffEditorController::prepareBranchesForCommit(const QString &output)
|
||||
return branches;
|
||||
}
|
||||
|
||||
void DiffEditorController::setContextLinesNumber(int lines)
|
||||
/**
|
||||
* @brief Force the lines of context to the given number.
|
||||
*
|
||||
* The user will not be able to change the context lines anymore. This needs to be set before
|
||||
* starting any operation or the flag will be ignored by the UI.
|
||||
*
|
||||
* @param lines Lines of context to display.
|
||||
*/
|
||||
void DiffEditorController::forceContextLineCount(int lines)
|
||||
{
|
||||
const int l = qMax(lines, 1);
|
||||
if (m_contextLinesNumber == l)
|
||||
return;
|
||||
|
||||
m_contextLinesNumber = l;
|
||||
|
||||
QSettings *s = Core::ICore::settings();
|
||||
s->beginGroup(QLatin1String(settingsGroupC));
|
||||
s->setValue(QLatin1String(contextLineNumbersKeyC), m_contextLinesNumber);
|
||||
s->endGroup();
|
||||
|
||||
emit contextLinesNumberChanged(l);
|
||||
}
|
||||
|
||||
void DiffEditorController::setContextLinesNumberEnabled(bool on)
|
||||
{
|
||||
if (m_contextLinesNumberEnabled == on)
|
||||
return;
|
||||
|
||||
m_contextLinesNumberEnabled = on;
|
||||
emit contextLinesNumberEnablementChanged(on);
|
||||
}
|
||||
|
||||
void DiffEditorController::setIgnoreWhitespace(bool ignore)
|
||||
{
|
||||
if (m_ignoreWhitespace == ignore)
|
||||
return;
|
||||
|
||||
m_ignoreWhitespace = ignore;
|
||||
|
||||
QSettings *s = Core::ICore::settings();
|
||||
s->beginGroup(QLatin1String(settingsGroupC));
|
||||
s->setValue(QLatin1String(ignoreWhitespaceKeyC), m_ignoreWhitespace);
|
||||
s->endGroup();
|
||||
|
||||
emit ignoreWhitespaceChanged(ignore);
|
||||
m_document->forceContextLineCount(lines);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Request the diff data to be re-read.
|
||||
*/
|
||||
void DiffEditorController::requestReload()
|
||||
{
|
||||
if (m_reloader)
|
||||
m_reloader->requestReload();
|
||||
m_isReloading = true;
|
||||
m_document->beginReload();
|
||||
reload();
|
||||
}
|
||||
|
||||
void DiffEditorController::requestChunkActions(QMenu *menu,
|
||||
int diffFileIndex,
|
||||
int chunkIndex)
|
||||
void DiffEditorController::reloadFinished(bool success)
|
||||
{
|
||||
m_document->endReload(success);
|
||||
m_isReloading = false;
|
||||
}
|
||||
|
||||
void DiffEditorController::requestChunkActions(QMenu *menu, int diffFileIndex, int chunkIndex)
|
||||
{
|
||||
m_diffFileIndex = diffFileIndex;
|
||||
m_chunkIndex = chunkIndex;
|
||||
emit chunkActionsRequested(menu, diffFileIndex >= 0 && chunkIndex >= 0);
|
||||
}
|
||||
|
||||
void DiffEditorController::requestSaveState()
|
||||
{
|
||||
emit saveStateRequested();
|
||||
}
|
||||
|
||||
void DiffEditorController::requestRestoreState()
|
||||
{
|
||||
emit restoreStateRequested();
|
||||
}
|
||||
|
||||
} // namespace DiffEditor
|
||||
|
||||
@@ -36,81 +36,60 @@
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace DiffEditor {
|
||||
namespace Core { class IDocument; }
|
||||
|
||||
class DiffEditorReloader;
|
||||
namespace DiffEditor {
|
||||
namespace Internal { class DiffEditorDocument; }
|
||||
|
||||
class DIFFEDITOR_EXPORT DiffEditorController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DiffEditorController(QObject *parent = 0);
|
||||
~DiffEditorController();
|
||||
explicit DiffEditorController(Core::IDocument *document);
|
||||
|
||||
QString clearMessage() const;
|
||||
void requestReload();
|
||||
bool isReloading() const;
|
||||
|
||||
QList<FileData> diffFiles() const;
|
||||
QString workingDirectory() const;
|
||||
QString description() const;
|
||||
bool isDescriptionEnabled() const;
|
||||
int contextLinesNumber() const;
|
||||
bool isContextLinesNumberEnabled() const;
|
||||
bool isIgnoreWhitespace() const;
|
||||
QString baseDirectory() const;
|
||||
int contextLineCount() const;
|
||||
bool ignoreWhitespace() const;
|
||||
|
||||
QString revisionFromDescription() const;
|
||||
|
||||
QString makePatch(bool revert, bool addPrefix = false) const;
|
||||
QString contents() const;
|
||||
|
||||
DiffEditorReloader *reloader() const;
|
||||
void setReloader(DiffEditorReloader *reloader);
|
||||
|
||||
public slots:
|
||||
void clear();
|
||||
void clear(const QString &message);
|
||||
void setDiffFiles(const QList<FileData> &diffFileList,
|
||||
const QString &workingDirectory = QString());
|
||||
void setDescription(const QString &description);
|
||||
void setDescriptionEnabled(bool on);
|
||||
void setContextLinesNumber(int lines);
|
||||
void setContextLinesNumberEnabled(bool on);
|
||||
void setIgnoreWhitespace(bool ignore);
|
||||
void requestReload();
|
||||
void requestChunkActions(QMenu *menu,
|
||||
int diffFileIndex,
|
||||
int chunkIndex);
|
||||
void requestSaveState();
|
||||
void requestRestoreState();
|
||||
void branchesForCommitReceived(const QString &output);
|
||||
void expandBranchesRequested();
|
||||
void informationForCommitReceived(const QString &output);
|
||||
|
||||
signals:
|
||||
void cleared(const QString &message);
|
||||
void diffFilesChanged(const QList<FileData> &diffFileList,
|
||||
const QString &workingDirectory);
|
||||
void descriptionChanged(const QString &description);
|
||||
void descriptionEnablementChanged(bool on);
|
||||
void contextLinesNumberChanged(int lines);
|
||||
void contextLinesNumberEnablementChanged(bool on);
|
||||
void ignoreWhitespaceChanged(bool ignore);
|
||||
void chunkActionsRequested(QMenu *menu, bool isValid);
|
||||
void saveStateRequested();
|
||||
void restoreStateRequested();
|
||||
void requestBranchList(const QString &revision);
|
||||
void reloaderChanged();
|
||||
void requestInformationForCommit(const QString &revision);
|
||||
|
||||
protected:
|
||||
// reloadFinished() should be called
|
||||
// inside reload() (for synchronous reload)
|
||||
// or later (for asynchronous reload)
|
||||
virtual void reload() = 0;
|
||||
void reloadFinished(bool success);
|
||||
|
||||
void setDiffFiles(const QList<FileData> &diffFileList,
|
||||
const QString &baseDirectory = QString());
|
||||
void setDescription(const QString &description);
|
||||
void forceContextLineCount(int lines);
|
||||
|
||||
private:
|
||||
QString prepareBranchesForCommit(const QString &output);
|
||||
QString m_clearMessage;
|
||||
void requestMoreInformation();
|
||||
void requestChunkActions(QMenu *menu, int diffFileIndex, int chunkIndex);
|
||||
|
||||
QList<FileData> m_diffFiles;
|
||||
QString m_workingDirectory;
|
||||
QString m_description;
|
||||
DiffEditorReloader *m_reloader;
|
||||
int m_contextLinesNumber;
|
||||
QString prepareBranchesForCommit(const QString &output);
|
||||
|
||||
Internal::DiffEditorDocument *const m_document;
|
||||
|
||||
bool m_isReloading;
|
||||
int m_diffFileIndex;
|
||||
int m_chunkIndex;
|
||||
bool m_descriptionEnabled;
|
||||
bool m_contextLinesNumberEnabled;
|
||||
bool m_ignoreWhitespace;
|
||||
|
||||
friend class Internal::DiffEditorDocument;
|
||||
};
|
||||
|
||||
} // namespace DiffEditor
|
||||
|
||||
@@ -32,33 +32,165 @@
|
||||
#include "diffeditorconstants.h"
|
||||
#include "diffeditorcontroller.h"
|
||||
#include "diffeditormanager.h"
|
||||
#include "diffeditorreloader.h"
|
||||
#include "diffutils.h"
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QMenu>
|
||||
#include <QTextCodec>
|
||||
#include <QUuid>
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
namespace DiffEditor {
|
||||
namespace Internal {
|
||||
|
||||
DiffEditorDocument::DiffEditorDocument() :
|
||||
Core::BaseTextDocument(),
|
||||
m_controller(new DiffEditorController(this))
|
||||
m_controller(0),
|
||||
m_contextLineCount(3),
|
||||
m_isContextLineCountForced(false),
|
||||
m_ignoreWhitespace(false)
|
||||
{
|
||||
setId(Constants::DIFF_EDITOR_ID);
|
||||
setMimeType(QLatin1String(Constants::DIFF_EDITOR_MIMETYPE));
|
||||
setTemporary(true);
|
||||
}
|
||||
|
||||
DiffEditorDocument::~DiffEditorDocument()
|
||||
{
|
||||
DiffEditorManager::removeDocument(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a controller for a document
|
||||
* @param controller The controller to set.
|
||||
*
|
||||
* This method takes ownership of the controller and will delete it after it is done with it.
|
||||
*/
|
||||
void DiffEditorDocument::setController(DiffEditorController *controller)
|
||||
{
|
||||
QTC_ASSERT(isTemporary(), return);
|
||||
if (m_controller == controller)
|
||||
return;
|
||||
|
||||
if (m_controller)
|
||||
m_controller->deleteLater();
|
||||
m_controller = controller;
|
||||
|
||||
if (m_controller) {
|
||||
connect(this, &DiffEditorDocument::chunkActionsRequested,
|
||||
m_controller, &DiffEditorController::requestChunkActions);
|
||||
connect(this, &DiffEditorDocument::requestMoreInformation,
|
||||
m_controller, &DiffEditorController::requestMoreInformation);
|
||||
}
|
||||
}
|
||||
|
||||
DiffEditorController *DiffEditorDocument::controller() const
|
||||
{
|
||||
return m_controller;
|
||||
}
|
||||
|
||||
QString DiffEditorDocument::makePatch(int fileIndex, int chunkIndex, bool revert, bool addPrefix) const
|
||||
{
|
||||
if (fileIndex < 0 || chunkIndex < 0)
|
||||
return QString();
|
||||
|
||||
if (fileIndex >= m_diffFiles.count())
|
||||
return QString();
|
||||
|
||||
const FileData &fileData = m_diffFiles.at(fileIndex);
|
||||
if (chunkIndex >= fileData.chunks.count())
|
||||
return QString();
|
||||
|
||||
const ChunkData &chunkData = fileData.chunks.at(chunkIndex);
|
||||
const bool lastChunk = (chunkIndex == fileData.chunks.count() - 1);
|
||||
|
||||
const QString fileName = revert
|
||||
? fileData.rightFileInfo.fileName
|
||||
: fileData.leftFileInfo.fileName;
|
||||
|
||||
QString leftPrefix, rightPrefix;
|
||||
if (addPrefix) {
|
||||
leftPrefix = QLatin1String("a/");
|
||||
rightPrefix = QLatin1String("b/");
|
||||
}
|
||||
return DiffUtils::makePatch(chunkData,
|
||||
leftPrefix + fileName,
|
||||
rightPrefix + fileName,
|
||||
lastChunk && fileData.lastChunkAtTheEndOfFile);
|
||||
}
|
||||
|
||||
void DiffEditorDocument::setDiffFiles(const QList<FileData> &data, const QString &directory)
|
||||
{
|
||||
m_diffFiles = data;
|
||||
m_baseDirectory = directory;
|
||||
emit documentChanged();
|
||||
}
|
||||
|
||||
QList<FileData> DiffEditorDocument::diffFiles() const
|
||||
{
|
||||
return m_diffFiles;
|
||||
}
|
||||
|
||||
QString DiffEditorDocument::baseDirectory() const
|
||||
{
|
||||
return m_baseDirectory;
|
||||
}
|
||||
|
||||
void DiffEditorDocument::setDescription(const QString &description)
|
||||
{
|
||||
if (m_description == description)
|
||||
return;
|
||||
|
||||
m_description = description;
|
||||
emit descriptionChanged();
|
||||
}
|
||||
|
||||
QString DiffEditorDocument::description() const
|
||||
{
|
||||
return m_description;
|
||||
}
|
||||
|
||||
void DiffEditorDocument::setContextLineCount(int lines)
|
||||
{
|
||||
m_contextLineCount = lines;
|
||||
}
|
||||
|
||||
int DiffEditorDocument::contextLineCount() const
|
||||
{
|
||||
return m_contextLineCount;
|
||||
}
|
||||
|
||||
void DiffEditorDocument::forceContextLineCount(int lines)
|
||||
{
|
||||
m_contextLineCount = lines;
|
||||
m_isContextLineCountForced = true;
|
||||
}
|
||||
|
||||
bool DiffEditorDocument::isContextLineCountForced() const
|
||||
{
|
||||
return m_isContextLineCountForced;
|
||||
}
|
||||
|
||||
void DiffEditorDocument::setIgnoreWhitespace(bool ignore)
|
||||
{
|
||||
if (m_isContextLineCountForced)
|
||||
return;
|
||||
m_ignoreWhitespace = ignore;
|
||||
}
|
||||
|
||||
bool DiffEditorDocument::ignoreWhitespace() const
|
||||
{
|
||||
return m_ignoreWhitespace;
|
||||
}
|
||||
|
||||
bool DiffEditorDocument::setContents(const QByteArray &contents)
|
||||
{
|
||||
Q_UNUSED(contents);
|
||||
@@ -67,7 +199,9 @@ bool DiffEditorDocument::setContents(const QByteArray &contents)
|
||||
|
||||
QString DiffEditorDocument::defaultPath() const
|
||||
{
|
||||
return m_controller->workingDirectory();
|
||||
if (!m_baseDirectory.isEmpty())
|
||||
return m_baseDirectory;
|
||||
return QDir::homePath();
|
||||
}
|
||||
|
||||
bool DiffEditorDocument::save(QString *errorString, const QString &fileName, bool autoSave)
|
||||
@@ -75,23 +209,35 @@ bool DiffEditorDocument::save(QString *errorString, const QString &fileName, boo
|
||||
Q_UNUSED(errorString)
|
||||
Q_UNUSED(autoSave)
|
||||
|
||||
const bool ok = write(fileName, format(), m_controller->contents(), errorString);
|
||||
const bool ok = write(fileName, format(), plainText(), errorString);
|
||||
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
m_controller->setReloader(0);
|
||||
m_controller->setDescription(QString());
|
||||
m_controller->setDescriptionEnabled(false);
|
||||
|
||||
DiffEditorManager::removeDocument(this);
|
||||
|
||||
setController(0);
|
||||
setDescription(QString());
|
||||
|
||||
const QFileInfo fi(fileName);
|
||||
setTemporary(false);
|
||||
setFilePath(Utils::FileName::fromString(fi.absoluteFilePath()));
|
||||
setFilePath(FileName::fromString(fi.absoluteFilePath()));
|
||||
setPreferredDisplayName(QString());
|
||||
emit temporaryStateChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DiffEditorDocument::reload()
|
||||
{
|
||||
if (m_controller) {
|
||||
m_controller->requestReload();
|
||||
} else {
|
||||
QString errorMessage;
|
||||
reload(&errorMessage, Core::IDocument::FlagReload, Core::IDocument::TypeContents);
|
||||
}
|
||||
}
|
||||
|
||||
bool DiffEditorDocument::reload(QString *errorString, ReloadFlag flag, ChangeType type)
|
||||
{
|
||||
Q_UNUSED(type)
|
||||
@@ -102,8 +248,10 @@ bool DiffEditorDocument::reload(QString *errorString, ReloadFlag flag, ChangeTyp
|
||||
|
||||
bool DiffEditorDocument::open(QString *errorString, const QString &fileName)
|
||||
{
|
||||
QTC_ASSERT(errorString, return false);
|
||||
beginReload();
|
||||
QString patch;
|
||||
if (read(fileName, &patch, errorString) != Utils::TextFileFormat::ReadSuccess)
|
||||
if (read(fileName, &patch, errorString) != TextFileFormat::ReadSuccess)
|
||||
return false;
|
||||
|
||||
bool ok = false;
|
||||
@@ -112,49 +260,82 @@ bool DiffEditorDocument::open(QString *errorString, const QString &fileName)
|
||||
*errorString = tr("Could not parse patch file \"%1\". "
|
||||
"The content is not of unified diff format.")
|
||||
.arg(fileName);
|
||||
return false;
|
||||
} else {
|
||||
const QFileInfo fi(fileName);
|
||||
setTemporary(false);
|
||||
emit temporaryStateChanged();
|
||||
setFilePath(FileName::fromString(fi.absoluteFilePath()));
|
||||
setDiffFiles(fileDataList, fi.absolutePath());
|
||||
}
|
||||
|
||||
const QFileInfo fi(fileName);
|
||||
setTemporary(false);
|
||||
setFilePath(Utils::FileName::fromString(fi.absoluteFilePath()));
|
||||
m_controller->setDiffFiles(fileDataList, fi.absolutePath());
|
||||
return true;
|
||||
endReload(ok);
|
||||
return ok;
|
||||
}
|
||||
|
||||
QString DiffEditorDocument::suggestedFileName() const
|
||||
{
|
||||
enum { maxSubjectLength = 50 };
|
||||
QString result = QStringLiteral("0001");
|
||||
const QString description = m_controller->description();
|
||||
if (!description.isEmpty()) {
|
||||
// Derive "git format-patch-type" file name from subject.
|
||||
const int pos = description.indexOf(QLatin1String("\n\n "));
|
||||
const int endPos = pos >= 0 ? description.indexOf(QLatin1Char('\n'), pos + 6) : -1;
|
||||
if (endPos > pos) {
|
||||
const QChar space(QLatin1Char(' '));
|
||||
const QChar dash(QLatin1Char('-'));
|
||||
QString subject = description.mid(pos, endPos - pos);
|
||||
for (int i = 0; i < subject.size(); ++i) {
|
||||
if (!subject.at(i).isLetterOrNumber())
|
||||
subject[i] = space;
|
||||
}
|
||||
subject = subject.simplified();
|
||||
if (subject.size() > maxSubjectLength) {
|
||||
const int lastSpace = subject.lastIndexOf(space, maxSubjectLength);
|
||||
subject.truncate(lastSpace > 0 ? lastSpace : maxSubjectLength);
|
||||
}
|
||||
subject.replace(space, dash);
|
||||
result += dash;
|
||||
result += subject;
|
||||
}
|
||||
const int maxSubjectLength = 50;
|
||||
|
||||
const QString desc = description();
|
||||
if (!desc.isEmpty()) {
|
||||
QString name = QString::fromLatin1("0001-%1").arg(desc.left(desc.indexOf(QLatin1Char('\n'))));
|
||||
name = FileUtils::fileSystemFriendlyName(name);
|
||||
name.truncate(maxSubjectLength);
|
||||
name.append(QLatin1String(".patch"));
|
||||
return name;
|
||||
}
|
||||
return result + QStringLiteral(".patch");
|
||||
return QStringLiteral("0001.patch");
|
||||
}
|
||||
|
||||
// ### fixme: git-specific handling should be done in the git plugin:
|
||||
// Remove unexpanded branches and follows-tag, clear indentation
|
||||
// and create E-mail
|
||||
static void formatGitDescription(QString *description)
|
||||
{
|
||||
QString result;
|
||||
result.reserve(description->size());
|
||||
foreach (QString line, description->split(QLatin1Char('\n'))) {
|
||||
if (line.startsWith(QLatin1String("commit "))
|
||||
|| line.startsWith(QLatin1String("Branches: <Expand>"))) {
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith(QLatin1String("Author: ")))
|
||||
line.replace(0, 8, QStringLiteral("From: "));
|
||||
else if (line.startsWith(QLatin1String(" ")))
|
||||
line.remove(0, 4);
|
||||
result.append(line);
|
||||
result.append(QLatin1Char('\n'));
|
||||
}
|
||||
*description = result;
|
||||
}
|
||||
|
||||
QString DiffEditorDocument::plainText() const
|
||||
{
|
||||
return m_controller->contents();
|
||||
QString result = description();
|
||||
const int formattingOptions = DiffUtils::GitFormat;
|
||||
if (formattingOptions & DiffUtils::GitFormat)
|
||||
formatGitDescription(&result);
|
||||
|
||||
const QString diff = DiffUtils::makePatch(diffFiles(), formattingOptions);
|
||||
if (!diff.isEmpty()) {
|
||||
if (!result.isEmpty())
|
||||
result += QLatin1Char('\n');
|
||||
result += diff;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void DiffEditorDocument::beginReload()
|
||||
{
|
||||
emit aboutToReload();
|
||||
const bool blocked = blockSignals(true);
|
||||
setDiffFiles(QList<FileData>(), QString());
|
||||
setDescription(QString());
|
||||
blockSignals(blocked);
|
||||
}
|
||||
|
||||
void DiffEditorDocument::endReload(bool success)
|
||||
{
|
||||
emit reloadFinished(success);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#ifndef DIFFEDITORDOCUMENT_H
|
||||
#define DIFFEDITORDOCUMENT_H
|
||||
|
||||
#include "diffutils.h"
|
||||
|
||||
#include <coreplugin/textdocument.h>
|
||||
|
||||
namespace DiffEditor {
|
||||
@@ -45,9 +47,26 @@ class DiffEditorDocument : public Core::BaseTextDocument
|
||||
Q_PROPERTY(QString plainText READ plainText STORED false) // For access by code pasters
|
||||
public:
|
||||
DiffEditorDocument();
|
||||
~DiffEditorDocument();
|
||||
|
||||
DiffEditorController *controller() const;
|
||||
|
||||
QString makePatch(int fileIndex, int chunkIndex, bool revert, bool addPrefix = false) const;
|
||||
|
||||
void setDiffFiles(const QList<FileData> &data, const QString &directory);
|
||||
QList<FileData> diffFiles() const;
|
||||
QString baseDirectory() const;
|
||||
|
||||
void setDescription(const QString &description);
|
||||
QString description() const;
|
||||
|
||||
void setContextLineCount(int lines);
|
||||
int contextLineCount() const;
|
||||
void forceContextLineCount(int lines);
|
||||
bool isContextLineCountForced() const;
|
||||
void setIgnoreWhitespace(bool ignore);
|
||||
bool ignoreWhitespace() const;
|
||||
|
||||
bool setContents(const QByteArray &contents);
|
||||
QString defaultPath() const;
|
||||
QString suggestedFileName() const Q_DECL_OVERRIDE;
|
||||
@@ -55,13 +74,35 @@ public:
|
||||
bool isModified() const { return false; }
|
||||
bool isSaveAsAllowed() const { return true; }
|
||||
bool save(QString *errorString, const QString &fileName, bool autoSave);
|
||||
void reload();
|
||||
bool reload(QString *errorString, ReloadFlag flag, ChangeType type);
|
||||
bool open(QString *errorString, const QString &fileName);
|
||||
|
||||
QString plainText() const;
|
||||
|
||||
signals:
|
||||
void temporaryStateChanged();
|
||||
void documentChanged();
|
||||
void descriptionChanged();
|
||||
void chunkActionsRequested(QMenu *menu, int diffFileIndex, int chunkIndex);
|
||||
void requestMoreInformation();
|
||||
|
||||
public slots:
|
||||
void beginReload();
|
||||
void endReload(bool success);
|
||||
|
||||
private:
|
||||
DiffEditorController *const m_controller;
|
||||
void setController(DiffEditorController *controller);
|
||||
|
||||
DiffEditorController *m_controller;
|
||||
QList<FileData> m_diffFiles;
|
||||
QString m_baseDirectory;
|
||||
QString m_description;
|
||||
int m_contextLineCount;
|
||||
bool m_isContextLineCountForced;
|
||||
bool m_ignoreWhitespace;
|
||||
|
||||
friend class ::DiffEditor::DiffEditorController;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "diffeditorguicontroller.h"
|
||||
#include "diffeditorcontroller.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
static const char settingsGroupC[] = "DiffEditor";
|
||||
static const char descriptionVisibleKeyC[] = "DescriptionVisible";
|
||||
static const char horizontalScrollBarSynchronizationKeyC[] =
|
||||
"HorizontalScrollBarSynchronization";
|
||||
|
||||
namespace DiffEditor {
|
||||
namespace Internal {
|
||||
|
||||
DiffEditorGuiController::DiffEditorGuiController(
|
||||
DiffEditorController *controller,
|
||||
QObject *parent)
|
||||
: QObject(parent),
|
||||
m_controller(controller),
|
||||
m_descriptionVisible(true),
|
||||
m_syncScrollBars(true),
|
||||
m_currentDiffFileIndex(-1)
|
||||
{
|
||||
QTC_ASSERT(m_controller, return);
|
||||
QSettings *s = Core::ICore::settings();
|
||||
s->beginGroup(QLatin1String(settingsGroupC));
|
||||
m_descriptionVisible = s->value(QLatin1String(descriptionVisibleKeyC),
|
||||
m_descriptionVisible).toBool();
|
||||
m_syncScrollBars = s->value(QLatin1String(horizontalScrollBarSynchronizationKeyC),
|
||||
m_syncScrollBars).toBool();
|
||||
s->endGroup();
|
||||
|
||||
connect(m_controller, &DiffEditorController::cleared, this,
|
||||
&DiffEditorGuiController::slotUpdateDiffFileIndex);
|
||||
connect(m_controller, &DiffEditorController::diffFilesChanged, this,
|
||||
&DiffEditorGuiController::slotUpdateDiffFileIndex);
|
||||
slotUpdateDiffFileIndex();
|
||||
}
|
||||
|
||||
DiffEditorController *DiffEditorGuiController::controller() const
|
||||
{
|
||||
return m_controller;
|
||||
}
|
||||
|
||||
bool DiffEditorGuiController::isDescriptionVisible() const
|
||||
{
|
||||
return m_descriptionVisible;
|
||||
}
|
||||
|
||||
bool DiffEditorGuiController::horizontalScrollBarSynchronization() const
|
||||
{
|
||||
return m_syncScrollBars;
|
||||
}
|
||||
|
||||
int DiffEditorGuiController::currentDiffFileIndex() const
|
||||
{
|
||||
return m_currentDiffFileIndex;
|
||||
}
|
||||
|
||||
void DiffEditorGuiController::slotUpdateDiffFileIndex()
|
||||
{
|
||||
m_currentDiffFileIndex = (m_controller->diffFiles().isEmpty() ? -1 : 0);
|
||||
}
|
||||
|
||||
void DiffEditorGuiController::setDescriptionVisible(bool on)
|
||||
{
|
||||
if (m_descriptionVisible == on)
|
||||
return;
|
||||
|
||||
m_descriptionVisible = on;
|
||||
|
||||
QSettings *s = Core::ICore::settings();
|
||||
s->beginGroup(QLatin1String(settingsGroupC));
|
||||
s->setValue(QLatin1String(descriptionVisibleKeyC), m_descriptionVisible);
|
||||
s->endGroup();
|
||||
|
||||
emit descriptionVisibilityChanged(on);
|
||||
}
|
||||
|
||||
void DiffEditorGuiController::setHorizontalScrollBarSynchronization(bool on)
|
||||
{
|
||||
if (m_syncScrollBars == on)
|
||||
return;
|
||||
|
||||
m_syncScrollBars = on;
|
||||
|
||||
QSettings *s = Core::ICore::settings();
|
||||
s->beginGroup(QLatin1String(settingsGroupC));
|
||||
s->setValue(QLatin1String(horizontalScrollBarSynchronizationKeyC),
|
||||
m_syncScrollBars);
|
||||
s->endGroup();
|
||||
|
||||
emit horizontalScrollBarSynchronizationChanged(on);
|
||||
}
|
||||
|
||||
void DiffEditorGuiController::setCurrentDiffFileIndex(int diffFileIndex)
|
||||
{
|
||||
if (m_controller->diffFiles().isEmpty())
|
||||
return; // -1 is the only valid value in this case
|
||||
|
||||
const int newIndex = qBound(0, diffFileIndex,
|
||||
m_controller->diffFiles().count() - 1);
|
||||
|
||||
if (m_currentDiffFileIndex == newIndex)
|
||||
return;
|
||||
|
||||
m_currentDiffFileIndex = newIndex;
|
||||
emit currentDiffFileIndexChanged(newIndex);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace DiffEditor
|
||||
@@ -1,78 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DIFFEDITORGUICONTROLLER_H
|
||||
#define DIFFEDITORGUICONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace DiffEditor {
|
||||
|
||||
class DiffEditorController;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class DiffEditorGuiController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DiffEditorGuiController(DiffEditorController *controller,
|
||||
QObject *parent = 0);
|
||||
|
||||
DiffEditorController *controller() const;
|
||||
|
||||
bool isDescriptionVisible() const;
|
||||
bool horizontalScrollBarSynchronization() const;
|
||||
int currentDiffFileIndex() const;
|
||||
|
||||
public slots:
|
||||
void setDescriptionVisible(bool on);
|
||||
void setHorizontalScrollBarSynchronization(bool on);
|
||||
void setCurrentDiffFileIndex(int diffFileIndex);
|
||||
|
||||
signals:
|
||||
void descriptionVisibilityChanged(bool on);
|
||||
void horizontalScrollBarSynchronizationChanged(bool on);
|
||||
void currentDiffFileIndexChanged(int diffFileIndex);
|
||||
|
||||
private slots:
|
||||
void slotUpdateDiffFileIndex();
|
||||
|
||||
private:
|
||||
DiffEditorController *const m_controller;
|
||||
bool m_descriptionVisible;
|
||||
bool m_syncScrollBars;
|
||||
int m_currentDiffFileIndex;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace DiffEditor
|
||||
|
||||
#endif // DIFFEDITORGUICONTROLLER_H
|
||||
@@ -49,10 +49,6 @@ DiffEditorManager::DiffEditorManager(QObject *parent)
|
||||
{
|
||||
QTC_ASSERT(!m_instance, return);
|
||||
m_instance = this;
|
||||
|
||||
Core::EditorManager *editorManager = Core::EditorManager::instance();
|
||||
connect(editorManager, &Core::EditorManager::editorsClosed,
|
||||
this, &DiffEditorManager::slotEditorsClosed);
|
||||
}
|
||||
|
||||
DiffEditorManager::~DiffEditorManager()
|
||||
@@ -60,27 +56,11 @@ DiffEditorManager::~DiffEditorManager()
|
||||
m_instance = 0;
|
||||
}
|
||||
|
||||
void DiffEditorManager::slotEditorsClosed(const QList<Core::IEditor *> &editors)
|
||||
{
|
||||
QMap<Core::IDocument *, int> editorsForDocument;
|
||||
for (int i = 0; i < editors.count(); i++) {
|
||||
DiffEditor *diffEditor = qobject_cast<DiffEditor *>(editors.at(i));
|
||||
if (diffEditor) {
|
||||
Core::IDocument *document = diffEditor->document();
|
||||
editorsForDocument[document]++;
|
||||
}
|
||||
}
|
||||
QMapIterator<Core::IDocument *, int> it(editorsForDocument);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
if (Core::DocumentModel::editorsForDocument(it.key()).count() == 0) // no other editors use that document
|
||||
removeDocument(it.key());
|
||||
}
|
||||
}
|
||||
|
||||
Core::IDocument *DiffEditorManager::find(const QString &vcsId)
|
||||
{
|
||||
return m_instance->m_idToDocument.value(vcsId);
|
||||
Core::IDocument *document = m_instance->m_idToDocument.value(vcsId);
|
||||
QTC_ASSERT(!document || document->isTemporary(), return 0);
|
||||
return document;
|
||||
}
|
||||
|
||||
Core::IDocument *DiffEditorManager::findOrCreate(const QString &vcsId, const QString &displayName)
|
||||
@@ -89,10 +69,8 @@ Core::IDocument *DiffEditorManager::findOrCreate(const QString &vcsId, const QSt
|
||||
if (document)
|
||||
return document;
|
||||
|
||||
const QString msgWait = tr("Waiting for data...");
|
||||
DiffEditor *diffEditor = qobject_cast<DiffEditor *>(
|
||||
Core::EditorManager::openEditorWithContents(Constants::DIFF_EDITOR_ID,
|
||||
0, msgWait.toUtf8()));
|
||||
Core::EditorManager::openEditorWithContents(Constants::DIFF_EDITOR_ID, 0));
|
||||
QTC_ASSERT(diffEditor, return 0);
|
||||
|
||||
document = qobject_cast<Internal::DiffEditorDocument *>(diffEditor->document());
|
||||
|
||||
@@ -53,17 +53,16 @@ public:
|
||||
explicit DiffEditorManager(QObject *parent);
|
||||
virtual ~DiffEditorManager();
|
||||
|
||||
static Core::IDocument *find(const QString &vcsId);
|
||||
static Core::IDocument *findOrCreate(const QString &vcsId, const QString &displayName);
|
||||
static DiffEditorController *controller(Core::IDocument *document);
|
||||
|
||||
private:
|
||||
static Core::IDocument *find(const QString &vcsId);
|
||||
static void removeDocument(Core::IDocument *document);
|
||||
|
||||
private slots:
|
||||
void slotEditorsClosed(const QList<Core::IEditor *> &editors);
|
||||
|
||||
private:
|
||||
QMap<QString, Internal::DiffEditorDocument *> m_idToDocument;
|
||||
|
||||
friend class Internal::DiffEditorDocument;
|
||||
};
|
||||
|
||||
} // namespace DiffEditor
|
||||
|
||||
@@ -31,10 +31,10 @@
|
||||
#include "diffeditorplugin.h"
|
||||
#include "diffeditor.h"
|
||||
#include "diffeditorconstants.h"
|
||||
#include "diffeditorcontroller.h"
|
||||
#include "diffeditordocument.h"
|
||||
#include "diffeditorfactory.h"
|
||||
#include "diffeditormanager.h"
|
||||
#include "diffeditorreloader.h"
|
||||
#include "differ.h"
|
||||
|
||||
#include <QAction>
|
||||
@@ -53,12 +53,12 @@
|
||||
namespace DiffEditor {
|
||||
namespace Internal {
|
||||
|
||||
class SimpleDiffEditorReloader : public DiffEditorReloader
|
||||
class FileDiffController : public DiffEditorController
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SimpleDiffEditorReloader(const QString &leftFileName,
|
||||
const QString &rightFileName);
|
||||
FileDiffController(Core::IDocument *document, const QString &leftFileName,
|
||||
const QString &rightFileName);
|
||||
|
||||
protected:
|
||||
void reload();
|
||||
@@ -68,14 +68,12 @@ private:
|
||||
QString m_rightFileName;
|
||||
};
|
||||
|
||||
SimpleDiffEditorReloader::SimpleDiffEditorReloader(const QString &leftFileName,
|
||||
const QString &rightFileName)
|
||||
: m_leftFileName(leftFileName),
|
||||
m_rightFileName(rightFileName)
|
||||
{
|
||||
}
|
||||
FileDiffController::FileDiffController(Core::IDocument *document, const QString &leftFileName,
|
||||
const QString &rightFileName) :
|
||||
DiffEditorController(document), m_leftFileName(leftFileName), m_rightFileName(rightFileName)
|
||||
{ }
|
||||
|
||||
void SimpleDiffEditorReloader::reload()
|
||||
void FileDiffController::reload()
|
||||
{
|
||||
QString errorString;
|
||||
Utils::TextFileFormat format;
|
||||
@@ -86,7 +84,6 @@ void SimpleDiffEditorReloader::reload()
|
||||
format.codec,
|
||||
&leftText, &format, &errorString)
|
||||
!= Utils::TextFileFormat::ReadSuccess) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -95,13 +92,11 @@ void SimpleDiffEditorReloader::reload()
|
||||
format.codec,
|
||||
&rightText, &format, &errorString)
|
||||
!= Utils::TextFileFormat::ReadSuccess) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Differ differ;
|
||||
QList<Diff> diffList = differ.cleanupSemantics(
|
||||
differ.diff(leftText, rightText));
|
||||
QList<Diff> diffList = differ.cleanupSemantics(differ.diff(leftText, rightText));
|
||||
|
||||
QList<Diff> leftDiffList;
|
||||
QList<Diff> rightDiffList;
|
||||
@@ -109,15 +104,13 @@ void SimpleDiffEditorReloader::reload()
|
||||
QList<Diff> outputLeftDiffList;
|
||||
QList<Diff> outputRightDiffList;
|
||||
|
||||
if (controller()->isIgnoreWhitespace()) {
|
||||
const QList<Diff> leftIntermediate =
|
||||
Differ::moveWhitespaceIntoEqualities(leftDiffList);
|
||||
const QList<Diff> rightIntermediate =
|
||||
Differ::moveWhitespaceIntoEqualities(rightDiffList);
|
||||
Differ::ignoreWhitespaceBetweenEqualities(leftIntermediate,
|
||||
rightIntermediate,
|
||||
&outputLeftDiffList,
|
||||
&outputRightDiffList);
|
||||
if (ignoreWhitespace()) {
|
||||
const QList<Diff> leftIntermediate
|
||||
= Differ::moveWhitespaceIntoEqualities(leftDiffList);
|
||||
const QList<Diff> rightIntermediate
|
||||
= Differ::moveWhitespaceIntoEqualities(rightDiffList);
|
||||
Differ::ignoreWhitespaceBetweenEqualities(leftIntermediate, rightIntermediate,
|
||||
&outputLeftDiffList, &outputRightDiffList);
|
||||
} else {
|
||||
outputLeftDiffList = leftDiffList;
|
||||
outputRightDiffList = rightDiffList;
|
||||
@@ -125,45 +118,31 @@ void SimpleDiffEditorReloader::reload()
|
||||
|
||||
const ChunkData chunkData = DiffUtils::calculateOriginalData(
|
||||
outputLeftDiffList, outputRightDiffList);
|
||||
FileData fileData = DiffUtils::calculateContextData(
|
||||
chunkData, controller()->contextLinesNumber(), 0);
|
||||
FileData fileData = DiffUtils::calculateContextData(chunkData, contextLineCount(), 0);
|
||||
fileData.leftFileInfo.fileName = m_leftFileName;
|
||||
fileData.rightFileInfo.fileName = m_rightFileName;
|
||||
|
||||
QList<FileData> fileDataList;
|
||||
fileDataList << fileData;
|
||||
|
||||
controller()->requestSaveState();
|
||||
controller()->setDiffFiles(fileDataList);
|
||||
controller()->requestRestoreState();
|
||||
|
||||
reloadFinished();
|
||||
setDiffFiles(fileDataList);
|
||||
reloadFinished(true);
|
||||
}
|
||||
|
||||
/////////////////
|
||||
|
||||
DiffEditorPlugin::DiffEditorPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
DiffEditorPlugin::~DiffEditorPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
bool DiffEditorPlugin::initialize(const QStringList &arguments, QString *errorMessage)
|
||||
{
|
||||
Q_UNUSED(arguments)
|
||||
Q_UNUSED(errorMessage)
|
||||
|
||||
//register actions
|
||||
Core::ActionContainer *toolsContainer =
|
||||
Core::ActionManager::actionContainer(Core::Constants::M_TOOLS);
|
||||
toolsContainer->insertGroup(Core::Constants::G_TOOLS_OPTIONS,
|
||||
Constants::G_TOOLS_DIFF);
|
||||
Core::ActionContainer *toolsContainer
|
||||
= Core::ActionManager::actionContainer(Core::Constants::M_TOOLS);
|
||||
toolsContainer->insertGroup(Core::Constants::G_TOOLS_OPTIONS, Constants::G_TOOLS_DIFF);
|
||||
|
||||
QAction *diffAction = new QAction(tr("Diff..."), this);
|
||||
Core::Command *diffCommand = Core::ActionManager::registerAction(diffAction,
|
||||
"DiffEditor.Diff");
|
||||
Core::Command *diffCommand = Core::ActionManager::registerAction(diffAction, "DiffEditor.Diff");
|
||||
connect(diffAction, &QAction::triggered, this, &DiffEditorPlugin::diff);
|
||||
toolsContainer->addAction(diffCommand, Constants::G_TOOLS_DIFF);
|
||||
|
||||
@@ -175,8 +154,7 @@ bool DiffEditorPlugin::initialize(const QStringList &arguments, QString *errorMe
|
||||
}
|
||||
|
||||
void DiffEditorPlugin::extensionsInitialized()
|
||||
{
|
||||
}
|
||||
{ }
|
||||
|
||||
void DiffEditorPlugin::diff()
|
||||
{
|
||||
@@ -193,24 +171,19 @@ void DiffEditorPlugin::diff()
|
||||
return;
|
||||
|
||||
|
||||
const QString documentId = QLatin1String("Diff ") + fileName1
|
||||
+ QLatin1String(", ") + fileName2;
|
||||
const QString documentId = QLatin1String("Diff ") + fileName1 + QLatin1String(", ") + fileName2;
|
||||
QString title = tr("Diff \"%1\", \"%2\"").arg(fileName1).arg(fileName2);
|
||||
Core::IDocument *const document = DiffEditorManager::findOrCreate(documentId, title);
|
||||
auto const document
|
||||
= qobject_cast<DiffEditorDocument *>(DiffEditorManager::findOrCreate(documentId, title));
|
||||
if (!document)
|
||||
return;
|
||||
|
||||
DiffEditorController *controller = DiffEditorManager::controller(document);
|
||||
if (!controller)
|
||||
controller = new FileDiffController(document, fileName1, fileName2);
|
||||
QTC_ASSERT(controller, return);
|
||||
if (!controller->reloader()) {
|
||||
SimpleDiffEditorReloader *reloader =
|
||||
new SimpleDiffEditorReloader(fileName1, fileName2);
|
||||
controller->setReloader(reloader);
|
||||
}
|
||||
|
||||
Core::EditorManager::activateEditorForDocument(document);
|
||||
|
||||
controller->requestReload();
|
||||
document->reload();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -44,9 +44,6 @@ class DiffEditorPlugin : public ExtensionSystem::IPlugin
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "DiffEditor.json")
|
||||
|
||||
public:
|
||||
DiffEditorPlugin();
|
||||
~DiffEditorPlugin();
|
||||
|
||||
bool initialize(const QStringList &arguments, QString *errorMessage = 0);
|
||||
void extensionsInitialized();
|
||||
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "diffeditorreloader.h"
|
||||
#include "diffeditorcontroller.h"
|
||||
|
||||
namespace DiffEditor {
|
||||
|
||||
DiffEditorReloader::DiffEditorReloader()
|
||||
: m_controller(0),
|
||||
m_reloading(false)
|
||||
{
|
||||
}
|
||||
|
||||
DiffEditorReloader::~DiffEditorReloader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
DiffEditorController *DiffEditorReloader::controller() const
|
||||
{
|
||||
return m_controller;
|
||||
}
|
||||
|
||||
void DiffEditorReloader::setController(DiffEditorController *controller)
|
||||
{
|
||||
if (m_controller == controller)
|
||||
return; // nothing changes
|
||||
|
||||
if (m_controller) {
|
||||
disconnect(m_controller, SIGNAL(ignoreWhitespaceChanged(bool)),
|
||||
this, SLOT(requestReload()));
|
||||
disconnect(m_controller, SIGNAL(contextLinesNumberChanged(int)),
|
||||
this, SLOT(requestReload()));
|
||||
}
|
||||
|
||||
m_controller = controller;
|
||||
|
||||
if (m_controller) {
|
||||
connect(m_controller, &DiffEditorController::ignoreWhitespaceChanged,
|
||||
this, &DiffEditorReloader::requestReload);
|
||||
connect(m_controller, &DiffEditorController::contextLinesNumberChanged,
|
||||
this, &DiffEditorReloader::requestReload);
|
||||
}
|
||||
}
|
||||
|
||||
void DiffEditorReloader::requestReload()
|
||||
{
|
||||
if (m_reloading)
|
||||
return;
|
||||
|
||||
if (!m_controller)
|
||||
return;
|
||||
|
||||
m_reloading = true;
|
||||
|
||||
reload();
|
||||
}
|
||||
|
||||
bool DiffEditorReloader::isReloading() const
|
||||
{
|
||||
return m_reloading;
|
||||
}
|
||||
|
||||
void DiffEditorReloader::reloadFinished()
|
||||
{
|
||||
m_reloading = false;
|
||||
}
|
||||
|
||||
} // namespace DiffEditor
|
||||
@@ -1,74 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 The Qt Company Ltd.
|
||||
** Contact: http://www.qt.io/licensing
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms and
|
||||
** conditions see http://www.qt.io/terms-conditions. For further information
|
||||
** use the contact form at http://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 or version 3 as published by the Free
|
||||
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
||||
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
||||
** following information to ensure the GNU Lesser General Public License
|
||||
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, The Qt Company gives you certain additional
|
||||
** rights. These rights are described in The Qt Company LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef DIFFEDITORRELOADER_H
|
||||
#define DIFFEDITORRELOADER_H
|
||||
|
||||
#include "diffeditor_global.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace DiffEditor {
|
||||
|
||||
class DiffEditorController;
|
||||
|
||||
class DIFFEDITOR_EXPORT DiffEditorReloader : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DiffEditorReloader();
|
||||
~DiffEditorReloader();
|
||||
|
||||
bool isReloading() const;
|
||||
DiffEditorController *controller() const;
|
||||
|
||||
public slots:
|
||||
void requestReload();
|
||||
|
||||
protected:
|
||||
// reloadFinished() should be called
|
||||
// inside reload() (for synchronous reload)
|
||||
// or later (for asynchronous reload)
|
||||
virtual void reload() = 0;
|
||||
void setController(DiffEditorController *controller);
|
||||
|
||||
protected slots:
|
||||
void reloadFinished();
|
||||
|
||||
private:
|
||||
DiffEditorController *m_controller;
|
||||
bool m_reloading;
|
||||
|
||||
friend class DiffEditorController;
|
||||
};
|
||||
|
||||
} // namespace DiffEditor
|
||||
|
||||
#endif // DIFFEDITORRELOADER_H
|
||||
@@ -263,11 +263,10 @@ ChunkData DiffUtils::calculateOriginalData(const QList<Diff> &leftDiffList,
|
||||
return chunkData;
|
||||
}
|
||||
|
||||
FileData DiffUtils::calculateContextData(const ChunkData &originalData,
|
||||
int contextLinesNumber,
|
||||
FileData DiffUtils::calculateContextData(const ChunkData &originalData, int contextLineCount,
|
||||
int joinChunkThreshold)
|
||||
{
|
||||
if (contextLinesNumber < 0)
|
||||
if (contextLineCount < 0)
|
||||
return FileData(originalData);
|
||||
|
||||
FileData fileData;
|
||||
@@ -292,9 +291,9 @@ FileData DiffUtils::calculateContextData(const ChunkData &originalData,
|
||||
const bool last = i == originalData.rows.count(); // includes last line?
|
||||
|
||||
const int firstLine = first
|
||||
? 0 : equalRowStart + contextLinesNumber;
|
||||
? 0 : equalRowStart + contextLineCount;
|
||||
const int lastLine = last
|
||||
? originalData.rows.count() : i - contextLinesNumber;
|
||||
? originalData.rows.count() : i - contextLineCount;
|
||||
|
||||
if (firstLine < lastLine - joinChunkThreshold) {
|
||||
for (int j = firstLine; j < lastLine; j++) {
|
||||
|
||||
@@ -138,7 +138,7 @@ public:
|
||||
static ChunkData calculateOriginalData(const QList<Diff> &leftDiffList,
|
||||
const QList<Diff> &rightDiffList);
|
||||
static FileData calculateContextData(const ChunkData &originalData,
|
||||
int contextLinesNumber,
|
||||
int contextLineCount,
|
||||
int joinChunkThreshold = 1);
|
||||
static QString makePatchLine(const QChar &startLineCharacter,
|
||||
const QString &textLine,
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
namespace DiffEditor {
|
||||
namespace Internal {
|
||||
|
||||
IDiffView::IDiffView(QObject *parent) : QObject(parent), m_supportsSync(false)
|
||||
{ }
|
||||
|
||||
QIcon IDiffView::icon() const
|
||||
{
|
||||
return m_icon;
|
||||
@@ -50,6 +53,16 @@ QString IDiffView::toolTip() const
|
||||
return m_toolTip;
|
||||
}
|
||||
|
||||
bool IDiffView::supportsSync() const
|
||||
{
|
||||
return m_supportsSync;
|
||||
}
|
||||
|
||||
QString IDiffView::syncToolTip() const
|
||||
{
|
||||
return m_syncToolTip;
|
||||
}
|
||||
|
||||
Core::Id IDiffView::id() const
|
||||
{
|
||||
return m_id;
|
||||
@@ -70,6 +83,16 @@ void IDiffView::setId(const Core::Id &id)
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
void IDiffView::setSupportsSync(bool sync)
|
||||
{
|
||||
m_supportsSync = sync;
|
||||
}
|
||||
|
||||
void IDiffView::setSyncToolTip(const QString &text)
|
||||
{
|
||||
m_syncToolTip = text;
|
||||
}
|
||||
|
||||
UnifiedView::UnifiedView() : m_widget(0)
|
||||
{
|
||||
setId(UNIFIED_VIEW_ID);
|
||||
@@ -79,15 +102,49 @@ UnifiedView::UnifiedView() : m_widget(0)
|
||||
|
||||
QWidget *UnifiedView::widget()
|
||||
{
|
||||
if (!m_widget)
|
||||
if (!m_widget) {
|
||||
m_widget = new UnifiedDiffEditorWidget;
|
||||
connect(m_widget, &UnifiedDiffEditorWidget::currentDiffFileIndexChanged,
|
||||
this, &UnifiedView::currentDiffFileIndexChanged);
|
||||
}
|
||||
return m_widget;
|
||||
}
|
||||
|
||||
void UnifiedView::setDiffEditorGuiController(DiffEditorGuiController *controller)
|
||||
void UnifiedView::setDocument(DiffEditorDocument *document)
|
||||
{
|
||||
QTC_ASSERT(m_widget, return);
|
||||
m_widget->setDiffEditorGuiController(controller);
|
||||
m_widget->setDocument(document);
|
||||
}
|
||||
|
||||
void UnifiedView::beginOperation()
|
||||
{
|
||||
QTC_ASSERT(m_widget, return);
|
||||
m_widget->saveState();
|
||||
m_widget->clear(tr("Waiting for data..."));
|
||||
}
|
||||
|
||||
void UnifiedView::setDiff(const QList<FileData> &diffFileList, const QString &workingDirectory)
|
||||
{
|
||||
QTC_ASSERT(m_widget, return);
|
||||
m_widget->setDiff(diffFileList, workingDirectory);
|
||||
}
|
||||
|
||||
void UnifiedView::endOperation(bool success)
|
||||
{
|
||||
Q_UNUSED(success);
|
||||
QTC_ASSERT(m_widget, return);
|
||||
m_widget->restoreState();
|
||||
}
|
||||
|
||||
void UnifiedView::setCurrentDiffFileIndex(int index)
|
||||
{
|
||||
QTC_ASSERT(m_widget, return);
|
||||
m_widget->setCurrentDiffFileIndex(index);
|
||||
}
|
||||
|
||||
void UnifiedView::setSync(bool sync)
|
||||
{
|
||||
Q_UNUSED(sync);
|
||||
}
|
||||
|
||||
SideBySideView::SideBySideView() : m_widget(0)
|
||||
@@ -96,19 +153,56 @@ SideBySideView::SideBySideView() : m_widget(0)
|
||||
setIcon(QIcon(QLatin1String(":/diffeditor/images/sidebysidediff.png")));
|
||||
setToolTip(QCoreApplication::translate("DiffEditor::SideBySideView",
|
||||
"Switch to Side By Side Diff Editor"));
|
||||
setSupportsSync(true);
|
||||
setSyncToolTip(tr("Synchronize Horizontal Scroll Bars"));
|
||||
}
|
||||
|
||||
QWidget *SideBySideView::widget()
|
||||
{
|
||||
if (!m_widget)
|
||||
if (!m_widget) {
|
||||
m_widget = new SideBySideDiffEditorWidget;
|
||||
connect(m_widget, &SideBySideDiffEditorWidget::currentDiffFileIndexChanged,
|
||||
this, &SideBySideView::currentDiffFileIndexChanged);
|
||||
}
|
||||
return m_widget;
|
||||
}
|
||||
|
||||
void SideBySideView::setDiffEditorGuiController(DiffEditorGuiController *controller)
|
||||
void SideBySideView::setDocument(DiffEditorDocument *document)
|
||||
{
|
||||
QTC_ASSERT(m_widget, return);
|
||||
m_widget->setDiffEditorGuiController(controller);
|
||||
m_widget->setDocument(document);
|
||||
}
|
||||
|
||||
void SideBySideView::beginOperation()
|
||||
{
|
||||
QTC_ASSERT(m_widget, return);
|
||||
m_widget->saveState();
|
||||
m_widget->clear(tr("Waiting for data..."));
|
||||
}
|
||||
|
||||
void SideBySideView::setCurrentDiffFileIndex(int index)
|
||||
{
|
||||
QTC_ASSERT(m_widget, return);
|
||||
m_widget->setCurrentDiffFileIndex(index);
|
||||
}
|
||||
|
||||
void SideBySideView::setDiff(const QList<FileData> &diffFileList, const QString &workingDirectory)
|
||||
{
|
||||
QTC_ASSERT(m_widget, return);
|
||||
m_widget->setDiff(diffFileList, workingDirectory);
|
||||
}
|
||||
|
||||
void SideBySideView::endOperation(bool success)
|
||||
{
|
||||
Q_UNUSED(success);
|
||||
QTC_ASSERT(m_widget, return);
|
||||
m_widget->restoreState();
|
||||
}
|
||||
|
||||
void SideBySideView::setSync(bool sync)
|
||||
{
|
||||
QTC_ASSERT(m_widget, return);
|
||||
m_widget->setHorizontalSync(sync);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -35,59 +35,101 @@
|
||||
|
||||
#include <QIcon>
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
|
||||
namespace DiffEditor {
|
||||
|
||||
class DiffEditorController;
|
||||
class FileData;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class DiffEditorGuiController;
|
||||
class DiffEditorDocument;
|
||||
class SideBySideDiffEditorWidget;
|
||||
class UnifiedDiffEditorWidget;
|
||||
|
||||
const char SIDE_BY_SIDE_VIEW_ID[] = "SideBySide";
|
||||
const char UNIFIED_VIEW_ID[] = "Unified";
|
||||
|
||||
class IDiffView
|
||||
class IDiffView : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
IDiffView() { }
|
||||
virtual ~IDiffView() { }
|
||||
explicit IDiffView(QObject *parent = 0);
|
||||
|
||||
QIcon icon() const;
|
||||
QString toolTip() const;
|
||||
bool supportsSync() const;
|
||||
QString syncToolTip() const;
|
||||
|
||||
Core::Id id() const;
|
||||
virtual QWidget *widget() = 0;
|
||||
virtual void setDiffEditorGuiController(DiffEditorGuiController *controller) = 0;
|
||||
virtual void setDocument(DiffEditorDocument *document) = 0;
|
||||
|
||||
virtual void beginOperation() = 0;
|
||||
virtual void setCurrentDiffFileIndex(int index) = 0;
|
||||
virtual void setDiff(const QList<FileData> &diffFileList, const QString &workingDirectory) = 0;
|
||||
virtual void endOperation(bool success) = 0;
|
||||
|
||||
virtual void setSync(bool) = 0;
|
||||
|
||||
signals:
|
||||
void currentDiffFileIndexChanged(int index);
|
||||
|
||||
protected:
|
||||
void setIcon(const QIcon &icon);
|
||||
void setToolTip(const QString &toolTip);
|
||||
void setId(const Core::Id &id);
|
||||
void setSupportsSync(bool sync);
|
||||
void setSyncToolTip(const QString &text);
|
||||
|
||||
private:
|
||||
QIcon m_icon;
|
||||
QString m_toolTip;
|
||||
Core::Id m_id;
|
||||
bool m_supportsSync;
|
||||
QString m_syncToolTip;
|
||||
};
|
||||
|
||||
class UnifiedView : public IDiffView {
|
||||
class UnifiedView : public IDiffView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
UnifiedView();
|
||||
|
||||
QWidget *widget();
|
||||
void setDiffEditorGuiController(DiffEditorGuiController *controller);
|
||||
void setDocument(DiffEditorDocument *document);
|
||||
|
||||
void beginOperation();
|
||||
void setCurrentDiffFileIndex(int index);
|
||||
void setDiff(const QList<FileData> &diffFileList, const QString &workingDirectory);
|
||||
void endOperation(bool success);
|
||||
|
||||
void setSync(bool sync);
|
||||
|
||||
private:
|
||||
UnifiedDiffEditorWidget *m_widget;
|
||||
};
|
||||
|
||||
class SideBySideView : public IDiffView {
|
||||
class SideBySideView : public IDiffView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SideBySideView();
|
||||
|
||||
QWidget *widget();
|
||||
void setDiffEditorGuiController(DiffEditorGuiController *controller);
|
||||
void setDocument(DiffEditorDocument *document);
|
||||
|
||||
void beginOperation();
|
||||
void setCurrentDiffFileIndex(int index);
|
||||
void setDiff(const QList<FileData> &diffFileList, const QString &workingDirectory);
|
||||
void endOperation(bool success);
|
||||
|
||||
void setSync(bool sync);
|
||||
|
||||
private:
|
||||
SideBySideDiffEditorWidget *m_widget;
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
|
||||
#include "sidebysidediffeditorwidget.h"
|
||||
#include "selectabletexteditorwidget.h"
|
||||
#include "diffeditorguicontroller.h"
|
||||
#include "diffutils.h"
|
||||
#include "diffeditorcontroller.h"
|
||||
#include "diffeditorconstants.h"
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
@@ -133,11 +133,11 @@ public:
|
||||
return TextEditorWidget::firstVisibleBlock();
|
||||
}
|
||||
// void setDocuments(const QList<QPair<DiffFileInfo, QString> > &documents);
|
||||
void saveState();
|
||||
void restoreState();
|
||||
|
||||
public slots:
|
||||
void setDisplaySettings(const DisplaySettings &ds);
|
||||
void saveStateRequested();
|
||||
void restoreStateRequested();
|
||||
|
||||
signals:
|
||||
void jumpToOriginalFileRequested(int diffFileIndex,
|
||||
@@ -311,20 +311,20 @@ SideDiffEditorWidget::SideDiffEditorWidget(QWidget *parent)
|
||||
// baseTextDocument()->setSyntaxHighlighter(m_highlighter);
|
||||
}
|
||||
|
||||
void SideDiffEditorWidget::saveStateRequested()
|
||||
void SideDiffEditorWidget::saveState()
|
||||
{
|
||||
if (!m_state.isNull())
|
||||
return;
|
||||
|
||||
m_state = saveState();
|
||||
m_state = SelectableTextEditorWidget::saveState();
|
||||
}
|
||||
|
||||
void SideDiffEditorWidget::restoreStateRequested()
|
||||
void SideDiffEditorWidget::restoreState()
|
||||
{
|
||||
if (m_state.isNull())
|
||||
return;
|
||||
|
||||
restoreState(m_state);
|
||||
SelectableTextEditorWidget::restoreState(m_state);
|
||||
m_state.clear();
|
||||
}
|
||||
|
||||
@@ -443,10 +443,8 @@ int SideDiffEditorWidget::blockNumberForFileIndex(int fileIndex) const
|
||||
|
||||
int SideDiffEditorWidget::fileIndexForBlockNumber(int blockNumber) const
|
||||
{
|
||||
QMap<int, DiffFileInfo>::const_iterator it
|
||||
= m_fileInfo.constBegin();
|
||||
QMap<int, DiffFileInfo>::const_iterator itEnd
|
||||
= m_fileInfo.constEnd();
|
||||
QMap<int, DiffFileInfo>::const_iterator it = m_fileInfo.constBegin();
|
||||
QMap<int, DiffFileInfo>::const_iterator itEnd = m_fileInfo.constEnd();
|
||||
|
||||
int i = -1;
|
||||
while (it != itEnd) {
|
||||
@@ -484,7 +482,6 @@ void SideDiffEditorWidget::clearAll(const QString &message)
|
||||
setExtraSelections(TextEditorWidget::OtherSelection,
|
||||
QList<QTextEdit::ExtraSelection>());
|
||||
setPlainText(message);
|
||||
// m_highlighter->setDocuments(QList<QPair<DiffFileInfo, QString> >());
|
||||
}
|
||||
|
||||
void SideDiffEditorWidget::clearAllData()
|
||||
@@ -497,12 +494,7 @@ void SideDiffEditorWidget::clearAllData()
|
||||
m_separators.clear();
|
||||
setSelections(QMap<int, QList<DiffSelection> >());
|
||||
}
|
||||
/*
|
||||
void SideDiffEditorWidget::setDocuments(const QList<QPair<DiffFileInfo, QString> > &documents)
|
||||
{
|
||||
m_highlighter->setDocuments(documents);
|
||||
}
|
||||
*/
|
||||
|
||||
void SideDiffEditorWidget::scrollContentsBy(int dx, int dy)
|
||||
{
|
||||
SelectableTextEditorWidget::scrollContentsBy(dx, dy);
|
||||
@@ -751,10 +743,10 @@ void SideDiffEditorWidget::drawCollapsedBlockPopup(QPainter &painter,
|
||||
|
||||
SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, m_guiController(0)
|
||||
, m_controller(0)
|
||||
, m_document(0)
|
||||
, m_ignoreCurrentIndexChange(false)
|
||||
, m_foldingBlocker(false)
|
||||
, m_horizontalSync(false)
|
||||
, m_contextMenuFileIndex(-1)
|
||||
, m_contextMenuChunkIndex(-1)
|
||||
{
|
||||
@@ -815,8 +807,6 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent)
|
||||
|
||||
connect(m_rightEditor, &QPlainTextEdit::cursorPositionChanged,
|
||||
this, &SideBySideDiffEditorWidget::rightCursorPositionChanged);
|
||||
// connect(m_rightEditor->document()->documentLayout(), SIGNAL(documentSizeChanged(QSizeF)),
|
||||
// this, SLOT(rightDocumentSizeChanged()));
|
||||
|
||||
m_splitter = new MiniSplitter(this);
|
||||
m_splitter->addWidget(m_leftEditor);
|
||||
@@ -825,83 +815,42 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent)
|
||||
l->setMargin(0);
|
||||
l->addWidget(m_splitter);
|
||||
setFocusProxy(m_rightEditor);
|
||||
|
||||
clear(tr("No controller"));
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::setDiffEditorGuiController(
|
||||
DiffEditorGuiController *controller)
|
||||
void SideBySideDiffEditorWidget::setDocument(DiffEditorDocument *document)
|
||||
{
|
||||
if (m_guiController == controller)
|
||||
return;
|
||||
|
||||
if (m_guiController) {
|
||||
disconnect(m_controller, &DiffEditorController::cleared,
|
||||
this, &SideBySideDiffEditorWidget::clearAll);
|
||||
disconnect(m_controller, &DiffEditorController::diffFilesChanged,
|
||||
this, &SideBySideDiffEditorWidget::setDiff);
|
||||
disconnect(m_controller, &DiffEditorController::saveStateRequested,
|
||||
m_leftEditor, &SideDiffEditorWidget::saveStateRequested);
|
||||
disconnect(m_controller, &DiffEditorController::saveStateRequested,
|
||||
m_rightEditor, &SideDiffEditorWidget::saveStateRequested);
|
||||
disconnect(m_controller, &DiffEditorController::restoreStateRequested,
|
||||
m_leftEditor, &SideDiffEditorWidget::restoreStateRequested);
|
||||
disconnect(m_controller, &DiffEditorController::restoreStateRequested,
|
||||
m_rightEditor, &SideDiffEditorWidget::restoreStateRequested);
|
||||
|
||||
disconnect(m_guiController, &DiffEditorGuiController::currentDiffFileIndexChanged,
|
||||
this, &SideBySideDiffEditorWidget::setCurrentDiffFileIndex);
|
||||
|
||||
clearAll(tr("No controller"));
|
||||
}
|
||||
m_guiController = controller;
|
||||
m_controller = 0;
|
||||
if (m_guiController) {
|
||||
m_controller = m_guiController->controller();
|
||||
|
||||
connect(m_controller, &DiffEditorController::cleared,
|
||||
this, &SideBySideDiffEditorWidget::clearAll);
|
||||
connect(m_controller, &DiffEditorController::diffFilesChanged,
|
||||
this, &SideBySideDiffEditorWidget::setDiff);
|
||||
connect(m_controller, &DiffEditorController::saveStateRequested,
|
||||
m_leftEditor, &SideDiffEditorWidget::saveStateRequested);
|
||||
connect(m_controller, &DiffEditorController::saveStateRequested,
|
||||
m_rightEditor, &SideDiffEditorWidget::saveStateRequested);
|
||||
connect(m_controller, &DiffEditorController::restoreStateRequested,
|
||||
m_leftEditor, &SideDiffEditorWidget::restoreStateRequested);
|
||||
connect(m_controller, &DiffEditorController::restoreStateRequested,
|
||||
m_rightEditor, &SideDiffEditorWidget::restoreStateRequested);
|
||||
|
||||
connect(m_guiController, &DiffEditorGuiController::currentDiffFileIndexChanged,
|
||||
this, &SideBySideDiffEditorWidget::setCurrentDiffFileIndex);
|
||||
|
||||
setDiff(m_controller->diffFiles(), m_controller->workingDirectory());
|
||||
setCurrentDiffFileIndex(m_guiController->currentDiffFileIndex());
|
||||
}
|
||||
m_document = document;
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::clear(const QString &message)
|
||||
{
|
||||
const bool oldIgnore = m_ignoreCurrentIndexChange;
|
||||
m_ignoreCurrentIndexChange = true;
|
||||
setDiff(QList<FileData>(), QString());
|
||||
m_leftEditor->clearAll(message);
|
||||
m_rightEditor->clearAll(message);
|
||||
m_ignoreCurrentIndexChange = oldIgnore;
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::clearAll(const QString &message)
|
||||
{
|
||||
setDiff(QList<FileData>(), QString());
|
||||
clear(message);
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::setDiff(const QList<FileData> &diffFileList,
|
||||
const QString &workingDirectory)
|
||||
{
|
||||
Q_UNUSED(workingDirectory)
|
||||
|
||||
const bool oldIgnore = m_ignoreCurrentIndexChange;
|
||||
m_ignoreCurrentIndexChange = true;
|
||||
m_leftEditor->clear();
|
||||
m_rightEditor->clear();
|
||||
|
||||
m_contextFileData = diffFileList;
|
||||
showDiff();
|
||||
if (m_contextFileData.isEmpty()) {
|
||||
const QString msg = tr("No difference");
|
||||
m_leftEditor->setPlainText(msg);
|
||||
m_rightEditor->setPlainText(msg);
|
||||
} else {
|
||||
showDiff();
|
||||
}
|
||||
m_ignoreCurrentIndexChange = oldIgnore;
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::setCurrentDiffFileIndex(int diffFileIndex)
|
||||
@@ -928,14 +877,29 @@ void SideBySideDiffEditorWidget::setCurrentDiffFileIndex(int diffFileIndex)
|
||||
m_ignoreCurrentIndexChange = oldIgnore;
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::setHorizontalSync(bool sync)
|
||||
{
|
||||
m_horizontalSync = sync;
|
||||
rightHSliderChanged();
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::saveState()
|
||||
{
|
||||
m_leftEditor->saveState();
|
||||
m_rightEditor->saveState();
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::restoreState()
|
||||
{
|
||||
m_leftEditor->restoreState();
|
||||
m_rightEditor->restoreState();
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::showDiff()
|
||||
{
|
||||
clear(tr("No difference"));
|
||||
|
||||
QMap<int, QList<DiffSelection> > leftFormats;
|
||||
QMap<int, QList<DiffSelection> > rightFormats;
|
||||
|
||||
// QList<QPair<DiffFileInfo, QString> > leftDocs, rightDocs;
|
||||
QString leftTexts, rightTexts;
|
||||
int blockNumber = 0;
|
||||
QChar separator = QLatin1Char('\n');
|
||||
@@ -1065,16 +1029,11 @@ void SideBySideDiffEditorWidget::showDiff()
|
||||
rightText.replace(QLatin1Char('\r'), QLatin1Char(' '));
|
||||
leftTexts += leftText;
|
||||
rightTexts += rightText;
|
||||
// leftDocs.append(qMakePair(contextFileData.leftFileInfo, leftText));
|
||||
// rightDocs.append(qMakePair(contextFileData.rightFileInfo, rightText));
|
||||
}
|
||||
|
||||
if (leftTexts.isEmpty() && rightTexts.isEmpty())
|
||||
return;
|
||||
|
||||
// m_leftEditor->setDocuments(leftDocs);
|
||||
// m_rightEditor->setDocuments(rightDocs);
|
||||
|
||||
const bool oldIgnore = m_ignoreCurrentIndexChange;
|
||||
m_ignoreCurrentIndexChange = true;
|
||||
m_leftEditor->clear();
|
||||
@@ -1085,63 +1044,6 @@ void SideBySideDiffEditorWidget::showDiff()
|
||||
|
||||
m_leftEditor->setSelections(leftFormats);
|
||||
m_rightEditor->setSelections(rightFormats);
|
||||
|
||||
|
||||
/*
|
||||
QTextBlock leftBlock = m_leftEditor->document()->firstBlock();
|
||||
QTextBlock rightBlock = m_rightEditor->document()->firstBlock();
|
||||
for (int i = 0; i < m_contextFileData.count(); i++) {
|
||||
const FileData &contextFileData = m_contextFileData.at(i);
|
||||
leftBlock = leftBlock.next();
|
||||
rightBlock = rightBlock.next();
|
||||
for (int j = 0; j < contextFileData.chunks.count(); j++) {
|
||||
ChunkData chunkData = contextFileData.chunks.at(j);
|
||||
if (chunkData.contextChunk) {
|
||||
BaseTextDocumentLayout::setFoldingIndent(leftBlock, FILE_LEVEL);
|
||||
BaseTextDocumentLayout::setFoldingIndent(rightBlock, FILE_LEVEL);
|
||||
leftBlock = leftBlock.next();
|
||||
rightBlock = rightBlock.next();
|
||||
}
|
||||
const int indent = chunkData.contextChunk ? CHUNK_LEVEL : FILE_LEVEL;
|
||||
for (int k = 0; k < chunkData.rows.count(); k++) {
|
||||
BaseTextDocumentLayout::setFoldingIndent(leftBlock, indent);
|
||||
BaseTextDocumentLayout::setFoldingIndent(rightBlock, indent);
|
||||
leftBlock = leftBlock.next();
|
||||
rightBlock = rightBlock.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
blockNumber = 0;
|
||||
for (int i = 0; i < m_contextFileData.count(); i++) {
|
||||
const FileData &contextFileData = m_contextFileData.at(i);
|
||||
blockNumber++;
|
||||
for (int j = 0; j < contextFileData.chunks.count(); j++) {
|
||||
ChunkData chunkData = contextFileData.chunks.at(j);
|
||||
if (chunkData.contextChunk) {
|
||||
QTextBlock leftBlock = m_leftEditor->document()->findBlockByNumber(blockNumber);
|
||||
BaseTextDocumentLayout::doFoldOrUnfold(leftBlock, false);
|
||||
QTextBlock rightBlock = m_rightEditor->document()->findBlockByNumber(blockNumber);
|
||||
BaseTextDocumentLayout::doFoldOrUnfold(rightBlock, false);
|
||||
blockNumber++;
|
||||
}
|
||||
blockNumber += chunkData.rows.count();
|
||||
}
|
||||
}
|
||||
m_foldingBlocker = true;
|
||||
BaseTextDocumentLayout *leftLayout = qobject_cast<BaseTextDocumentLayout *>(m_leftEditor->document()->documentLayout());
|
||||
if (leftLayout) {
|
||||
leftLayout->requestUpdate();
|
||||
leftLayout->emitDocumentSizeChanged();
|
||||
}
|
||||
BaseTextDocumentLayout *rightLayout = qobject_cast<BaseTextDocumentLayout *>(m_rightEditor->document()->documentLayout());
|
||||
if (rightLayout) {
|
||||
rightLayout->requestUpdate();
|
||||
rightLayout->emitDocumentSizeChanged();
|
||||
}
|
||||
m_foldingBlocker = false;
|
||||
*/
|
||||
// m_leftEditor->updateFoldingHighlight(QPoint(-1, -1));
|
||||
// m_rightEditor->updateFoldingHighlight(QPoint(-1, -1));
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::setFontSettings(
|
||||
@@ -1212,10 +1114,10 @@ void SideBySideDiffEditorWidget::slotRightJumpToOriginalFileRequested(
|
||||
void SideBySideDiffEditorWidget::jumpToOriginalFile(const QString &fileName,
|
||||
int lineNumber, int columnNumber)
|
||||
{
|
||||
if (!m_controller)
|
||||
if (!m_document)
|
||||
return;
|
||||
|
||||
const QDir dir(m_controller->workingDirectory());
|
||||
const QDir dir(m_document->baseDirectory());
|
||||
const QString absoluteFileName = dir.absoluteFilePath(fileName);
|
||||
QFileInfo fi(absoluteFileName);
|
||||
if (fi.exists() && !fi.isDir())
|
||||
@@ -1249,7 +1151,7 @@ void SideBySideDiffEditorWidget::slotLeftContextMenuRequested(QMenu *menu,
|
||||
if (m_contextMenuChunkIndex >= fileData.chunks.count())
|
||||
return;
|
||||
|
||||
m_controller->requestChunkActions(menu, diffFileIndex, chunkIndex);
|
||||
m_document->chunkActionsRequested(menu, diffFileIndex, chunkIndex);
|
||||
|
||||
if (fileData.leftFileInfo.fileName == fileData.rightFileInfo.fileName)
|
||||
return;
|
||||
@@ -1284,33 +1186,22 @@ void SideBySideDiffEditorWidget::slotRightContextMenuRequested(QMenu *menu,
|
||||
if (m_contextMenuChunkIndex >= fileData.chunks.count())
|
||||
return;
|
||||
|
||||
m_controller->requestChunkActions(menu, diffFileIndex, chunkIndex);
|
||||
m_document->chunkActionsRequested(menu, diffFileIndex, chunkIndex);
|
||||
|
||||
revertAction->setEnabled(true);
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::slotSendChunkToCodePaster()
|
||||
{
|
||||
if (!m_controller)
|
||||
if (!m_document)
|
||||
return;
|
||||
|
||||
if (m_contextMenuFileIndex < 0 || m_contextMenuChunkIndex < 0)
|
||||
return;
|
||||
|
||||
if (m_contextMenuFileIndex >= m_contextFileData.count())
|
||||
return;
|
||||
|
||||
const FileData fileData = m_contextFileData.at(m_contextMenuFileIndex);
|
||||
if (m_contextMenuChunkIndex >= fileData.chunks.count())
|
||||
return;
|
||||
|
||||
const QString patch = m_controller->makePatch(false);
|
||||
const QString patch = m_document->makePatch(m_contextMenuFileIndex, m_contextMenuChunkIndex, false);
|
||||
if (patch.isEmpty())
|
||||
return;
|
||||
|
||||
// Retrieve service by soft dependency.
|
||||
QObject *pasteService =
|
||||
ExtensionSystem::PluginManager::getObjectByClassName(
|
||||
QObject *pasteService= ExtensionSystem::PluginManager::getObjectByClassName(
|
||||
QLatin1String("CodePaster::CodePasterService"));
|
||||
if (pasteService) {
|
||||
QMetaObject::invokeMethod(pasteService, "postText",
|
||||
@@ -1334,18 +1225,10 @@ void SideBySideDiffEditorWidget::slotRevertChunk()
|
||||
|
||||
void SideBySideDiffEditorWidget::patch(bool revert)
|
||||
{
|
||||
if (!m_controller)
|
||||
return;
|
||||
|
||||
if (m_contextMenuFileIndex < 0 || m_contextMenuChunkIndex < 0)
|
||||
return;
|
||||
|
||||
if (m_contextMenuFileIndex >= m_contextFileData.count())
|
||||
if (!m_document)
|
||||
return;
|
||||
|
||||
const FileData fileData = m_contextFileData.at(m_contextMenuFileIndex);
|
||||
if (m_contextMenuChunkIndex >= fileData.chunks.count())
|
||||
return;
|
||||
|
||||
const QString title = revert ? tr("Revert Chunk") : tr("Apply Chunk");
|
||||
const QString question = revert
|
||||
@@ -1358,50 +1241,46 @@ void SideBySideDiffEditorWidget::patch(bool revert)
|
||||
return;
|
||||
}
|
||||
|
||||
const int strip = m_controller->workingDirectory().isEmpty() ? -1 : 0;
|
||||
const int strip = m_document->baseDirectory().isEmpty() ? -1 : 0;
|
||||
|
||||
const QString fileName = revert
|
||||
? fileData.rightFileInfo.fileName
|
||||
: fileData.leftFileInfo.fileName;
|
||||
|
||||
const QString workingDirectory = m_controller->workingDirectory().isEmpty()
|
||||
const QString workingDirectory = m_document->baseDirectory().isEmpty()
|
||||
? QFileInfo(fileName).absolutePath()
|
||||
: m_controller->workingDirectory();
|
||||
: m_document->baseDirectory();
|
||||
|
||||
const QString patch = m_controller->makePatch(revert);
|
||||
const QString patch = m_document->makePatch(m_contextMenuFileIndex, m_contextMenuChunkIndex, revert);
|
||||
|
||||
if (patch.isEmpty())
|
||||
return;
|
||||
|
||||
if (PatchTool::runPatch(EditorManager::defaultTextCodec()->fromUnicode(patch),
|
||||
workingDirectory, strip, revert))
|
||||
m_controller->requestReload();
|
||||
workingDirectory, strip, revert))
|
||||
m_document->reload();
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::leftVSliderChanged()
|
||||
{
|
||||
m_rightEditor->verticalScrollBar()->setValue(
|
||||
m_leftEditor->verticalScrollBar()->value());
|
||||
m_rightEditor->verticalScrollBar()->setValue(m_leftEditor->verticalScrollBar()->value());
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::rightVSliderChanged()
|
||||
{
|
||||
m_leftEditor->verticalScrollBar()->setValue(
|
||||
m_rightEditor->verticalScrollBar()->value());
|
||||
m_leftEditor->verticalScrollBar()->setValue(m_rightEditor->verticalScrollBar()->value());
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::leftHSliderChanged()
|
||||
{
|
||||
if (!m_guiController || m_guiController->horizontalScrollBarSynchronization())
|
||||
m_rightEditor->horizontalScrollBar()->setValue(
|
||||
m_leftEditor->horizontalScrollBar()->value());
|
||||
if (m_horizontalSync)
|
||||
m_rightEditor->horizontalScrollBar()->setValue(m_leftEditor->horizontalScrollBar()->value());
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::rightHSliderChanged()
|
||||
{
|
||||
if (!m_guiController || m_guiController->horizontalScrollBarSynchronization())
|
||||
m_leftEditor->horizontalScrollBar()->setValue(
|
||||
m_rightEditor->horizontalScrollBar()->value());
|
||||
if (m_horizontalSync)
|
||||
m_leftEditor->horizontalScrollBar()->setValue(m_rightEditor->horizontalScrollBar()->value());
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::leftCursorPositionChanged()
|
||||
@@ -1409,17 +1288,13 @@ void SideBySideDiffEditorWidget::leftCursorPositionChanged()
|
||||
leftVSliderChanged();
|
||||
leftHSliderChanged();
|
||||
|
||||
if (!m_guiController)
|
||||
return;
|
||||
|
||||
if (m_ignoreCurrentIndexChange)
|
||||
return;
|
||||
|
||||
const bool oldIgnore = m_ignoreCurrentIndexChange;
|
||||
m_ignoreCurrentIndexChange = true;
|
||||
m_guiController->setCurrentDiffFileIndex(
|
||||
m_leftEditor->fileIndexForBlockNumber(
|
||||
m_leftEditor->textCursor().blockNumber()));
|
||||
emit currentDiffFileIndexChanged(
|
||||
m_leftEditor->fileIndexForBlockNumber(m_leftEditor->textCursor().blockNumber()));
|
||||
m_ignoreCurrentIndexChange = oldIgnore;
|
||||
}
|
||||
|
||||
@@ -1428,161 +1303,16 @@ void SideBySideDiffEditorWidget::rightCursorPositionChanged()
|
||||
rightVSliderChanged();
|
||||
rightHSliderChanged();
|
||||
|
||||
if (!m_guiController)
|
||||
return;
|
||||
|
||||
if (m_ignoreCurrentIndexChange)
|
||||
return;
|
||||
|
||||
const bool oldIgnore = m_ignoreCurrentIndexChange;
|
||||
m_ignoreCurrentIndexChange = true;
|
||||
m_guiController->setCurrentDiffFileIndex(
|
||||
m_rightEditor->fileIndexForBlockNumber(
|
||||
m_rightEditor->textCursor().blockNumber()));
|
||||
emit currentDiffFileIndexChanged(
|
||||
m_rightEditor->fileIndexForBlockNumber(m_rightEditor->textCursor().blockNumber()));
|
||||
m_ignoreCurrentIndexChange = oldIgnore;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void SideBySideDiffEditorWidget::leftDocumentSizeChanged()
|
||||
{
|
||||
synchronizeFoldings(m_leftEditor, m_rightEditor);
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::rightDocumentSizeChanged()
|
||||
{
|
||||
synchronizeFoldings(m_rightEditor, m_leftEditor);
|
||||
}
|
||||
|
||||
/* Special version of that method (original: BaseTextDocumentLayout::doFoldOrUnfold())
|
||||
The hack lies in fact, that when unfolding all direct sub-blocks are made visible,
|
||||
while some of them need to stay invisible (i.e. unfolded chunk lines)
|
||||
*/
|
||||
static void doFoldOrUnfold(SideDiffEditorWidget *editor, const QTextBlock &block, bool unfold)
|
||||
{
|
||||
if (!BaseTextDocumentLayout::canFold(block))
|
||||
return;
|
||||
QTextBlock b = block.next();
|
||||
|
||||
int indent = BaseTextDocumentLayout::foldingIndent(block);
|
||||
while (b.isValid() && BaseTextDocumentLayout::foldingIndent(b) > indent && (unfold || b.next().isValid())) {
|
||||
if (unfold && editor->isChunkLine(b.blockNumber()) && !BaseTextDocumentLayout::isFolded(b)) {
|
||||
b.setVisible(false);
|
||||
b.setLineCount(0);
|
||||
} else {
|
||||
b.setVisible(unfold);
|
||||
b.setLineCount(unfold ? qMax(1, b.layout()->lineCount()) : 0);
|
||||
}
|
||||
if (unfold) { // do not unfold folded sub-blocks
|
||||
if (BaseTextDocumentLayout::isFolded(b) && b.next().isValid()) {
|
||||
int jndent = BaseTextDocumentLayout::foldingIndent(b);
|
||||
b = b.next();
|
||||
while (b.isValid() && BaseTextDocumentLayout::foldingIndent(b) > jndent)
|
||||
b = b.next();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
b = b.next();
|
||||
}
|
||||
BaseTextDocumentLayout::setFolded(block, !unfold);
|
||||
}
|
||||
|
||||
void SideBySideDiffEditorWidget::synchronizeFoldings(SideDiffEditorWidget *source, SideDiffEditorWidget *destination)
|
||||
{
|
||||
if (m_foldingBlocker)
|
||||
return;
|
||||
|
||||
m_foldingBlocker = true;
|
||||
QTextBlock sourceBlock = source->document()->firstBlock();
|
||||
QTextBlock destinationBlock = destination->document()->firstBlock();
|
||||
while (sourceBlock.isValid() && destinationBlock.isValid()) {
|
||||
if (BaseTextDocumentLayout::canFold(sourceBlock)) {
|
||||
const bool isSourceFolded = BaseTextDocumentLayout::isFolded(sourceBlock);
|
||||
const bool isDestinationFolded = BaseTextDocumentLayout::isFolded(destinationBlock);
|
||||
if (isSourceFolded != isDestinationFolded) {
|
||||
if (source->isFileLine(sourceBlock.blockNumber())) {
|
||||
doFoldOrUnfold(source, sourceBlock, !isSourceFolded);
|
||||
doFoldOrUnfold(destination, destinationBlock, !isSourceFolded);
|
||||
} else {
|
||||
if (isSourceFolded) { // we fold the destination (shrinking)
|
||||
QTextBlock previousSource = sourceBlock.previous(); // skippedLines
|
||||
QTextBlock previousDestination = destinationBlock.previous(); // skippedLines
|
||||
if (source->isChunkLine(previousSource.blockNumber())) {
|
||||
QTextBlock firstVisibleDestinationBlock = destination->firstVisibleBlock();
|
||||
QTextBlock firstDestinationBlock = destination->document()->firstBlock();
|
||||
BaseTextDocumentLayout::doFoldOrUnfold(destinationBlock, !isSourceFolded);
|
||||
BaseTextDocumentLayout::setFoldingIndent(sourceBlock, CHUNK_LEVEL);
|
||||
BaseTextDocumentLayout::setFoldingIndent(destinationBlock, CHUNK_LEVEL);
|
||||
previousSource.setVisible(true);
|
||||
previousSource.setLineCount(1);
|
||||
previousDestination.setVisible(true);
|
||||
previousDestination.setLineCount(1);
|
||||
sourceBlock.setVisible(false);
|
||||
sourceBlock.setLineCount(0);
|
||||
destinationBlock.setVisible(false);
|
||||
destinationBlock.setLineCount(0);
|
||||
BaseTextDocumentLayout::setFolded(previousSource, true);
|
||||
BaseTextDocumentLayout::setFolded(previousDestination, true);
|
||||
|
||||
if (firstVisibleDestinationBlock == destinationBlock) {
|
||||
/*
|
||||
The following hack is completely crazy. That's the only way to scroll 1 line up
|
||||
in case destinationBlock was the top visible block.
|
||||
There is no need to scroll the source since this is in sync anyway
|
||||
(leftSliderChanged(), rightSliderChanged())
|
||||
*/
|
||||
destination->verticalScrollBar()->setValue(destination->verticalScrollBar()->value() - 1);
|
||||
destination->verticalScrollBar()->setValue(destination->verticalScrollBar()->value() + 1);
|
||||
if (firstVisibleDestinationBlock.previous() == firstDestinationBlock) {
|
||||
/*
|
||||
Even more crazy case: the destinationBlock was the first top visible block.
|
||||
*/
|
||||
destination->verticalScrollBar()->setValue(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // we unfold the destination (expanding)
|
||||
if (source->isChunkLine(sourceBlock.blockNumber())) {
|
||||
QTextBlock nextSource = sourceBlock.next();
|
||||
QTextBlock nextDestination = destinationBlock.next();
|
||||
BaseTextDocumentLayout::doFoldOrUnfold(destinationBlock, !isSourceFolded);
|
||||
BaseTextDocumentLayout::setFoldingIndent(nextSource, FILE_LEVEL);
|
||||
BaseTextDocumentLayout::setFoldingIndent(nextDestination, FILE_LEVEL);
|
||||
sourceBlock.setVisible(false);
|
||||
sourceBlock.setLineCount(0);
|
||||
destinationBlock.setVisible(false);
|
||||
destinationBlock.setLineCount(0);
|
||||
BaseTextDocumentLayout::setFolded(nextSource, false);
|
||||
BaseTextDocumentLayout::setFolded(nextDestination, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
break; // only one should be synchronized
|
||||
}
|
||||
}
|
||||
|
||||
sourceBlock = sourceBlock.next();
|
||||
destinationBlock = destinationBlock.next();
|
||||
}
|
||||
|
||||
BaseTextDocumentLayout *sourceLayout = qobject_cast<BaseTextDocumentLayout *>(source->document()->documentLayout());
|
||||
if (sourceLayout) {
|
||||
sourceLayout->requestUpdate();
|
||||
sourceLayout->emitDocumentSizeChanged();
|
||||
}
|
||||
|
||||
QWidget *ea = source->extraArea();
|
||||
if (ea->contentsRect().contains(ea->mapFromGlobal(QCursor::pos())))
|
||||
source->updateFoldingHighlight(source->mapFromGlobal(QCursor::pos()));
|
||||
|
||||
BaseTextDocumentLayout *destinationLayout = qobject_cast<BaseTextDocumentLayout *>(destination->document()->documentLayout());
|
||||
if (destinationLayout) {
|
||||
destinationLayout->requestUpdate();
|
||||
destinationLayout->emitDocumentSizeChanged();
|
||||
}
|
||||
m_foldingBlocker = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace DiffEditor
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#define SIDEBYSIDEDIFFEDITORWIDGET_H
|
||||
|
||||
#include "differ.h"
|
||||
#include "diffeditorcontroller.h"
|
||||
#include "diffeditordocument.h"
|
||||
#include <QWidget>
|
||||
#include <QTextCharFormat>
|
||||
|
||||
@@ -60,16 +60,23 @@ class SideBySideDiffEditorWidget : public QWidget
|
||||
public:
|
||||
explicit SideBySideDiffEditorWidget(QWidget *parent = 0);
|
||||
|
||||
void setDiffEditorGuiController(Internal::DiffEditorGuiController *controller);
|
||||
void setDocument(DiffEditorDocument *document);
|
||||
|
||||
private slots:
|
||||
void clear(const QString &message = QString());
|
||||
void clearAll(const QString &message = QString());
|
||||
void setDiff(const QList<FileData> &diffFileList,
|
||||
const QString &workingDirectory);
|
||||
|
||||
void setCurrentDiffFileIndex(int diffFileIndex);
|
||||
|
||||
void setHorizontalSync(bool sync);
|
||||
|
||||
void saveState();
|
||||
void restoreState();
|
||||
|
||||
void clear(const QString &message = QString());
|
||||
|
||||
signals:
|
||||
void currentDiffFileIndexChanged(int index);
|
||||
|
||||
private slots:
|
||||
void setFontSettings(const TextEditor::FontSettings &fontSettings);
|
||||
void slotLeftJumpToOriginalFileRequested(int diffFileIndex,
|
||||
int lineNumber, int columnNumber);
|
||||
@@ -98,16 +105,16 @@ private:
|
||||
int lineNumber, int columnNumber);
|
||||
void patch(bool revert);
|
||||
|
||||
DiffEditorGuiController *m_guiController;
|
||||
DiffEditorController *m_controller;
|
||||
DiffEditorDocument *m_document;
|
||||
SideDiffEditorWidget *m_leftEditor;
|
||||
SideDiffEditorWidget *m_rightEditor;
|
||||
QSplitter *m_splitter;
|
||||
|
||||
QList<FileData> m_contextFileData; // ultimate data to be shown, contextLinesNumber taken into account
|
||||
QList<FileData> m_contextFileData; // ultimate data to be shown, contextLineCount taken into account
|
||||
|
||||
bool m_ignoreCurrentIndexChange;
|
||||
bool m_foldingBlocker;
|
||||
bool m_horizontalSync;
|
||||
int m_contextMenuFileIndex;
|
||||
int m_contextMenuChunkIndex;
|
||||
|
||||
|
||||
@@ -29,9 +29,10 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "unifieddiffeditorwidget.h"
|
||||
#include "diffeditorguicontroller.h"
|
||||
#include "diffutils.h"
|
||||
|
||||
#include "diffeditorconstants.h"
|
||||
#include "diffeditordocument.h"
|
||||
#include "diffutils.h"
|
||||
|
||||
#include <QPlainTextEdit>
|
||||
#include <QVBoxLayout>
|
||||
@@ -75,8 +76,7 @@ namespace Internal {
|
||||
|
||||
UnifiedDiffEditorWidget::UnifiedDiffEditorWidget(QWidget *parent)
|
||||
: SelectableTextEditorWidget("DiffEditor.UnifiedDiffEditor", parent)
|
||||
, m_guiController(0)
|
||||
, m_controller(0)
|
||||
, m_document(0)
|
||||
, m_ignoreCurrentIndexChange(false)
|
||||
, m_contextMenuFileIndex(-1)
|
||||
, m_contextMenuChunkIndex(-1)
|
||||
@@ -102,70 +102,35 @@ UnifiedDiffEditorWidget::UnifiedDiffEditorWidget(QWidget *parent)
|
||||
this, &UnifiedDiffEditorWidget::setFontSettings);
|
||||
setFontSettings(TextEditorSettings::fontSettings());
|
||||
|
||||
clear(tr("No controller"));
|
||||
clear(tr("No document"));
|
||||
|
||||
connect(this, &QPlainTextEdit::cursorPositionChanged,
|
||||
this, &UnifiedDiffEditorWidget::slotCursorPositionChangedInEditor);
|
||||
}
|
||||
|
||||
void UnifiedDiffEditorWidget::setDiffEditorGuiController(
|
||||
DiffEditorGuiController *controller)
|
||||
void UnifiedDiffEditorWidget::setDocument(DiffEditorDocument *document)
|
||||
{
|
||||
if (m_guiController == controller)
|
||||
return;
|
||||
|
||||
if (m_guiController) {
|
||||
disconnect(m_controller, &DiffEditorController::cleared,
|
||||
this, &UnifiedDiffEditorWidget::clearAll);
|
||||
disconnect(m_controller, &DiffEditorController::diffFilesChanged,
|
||||
this, &UnifiedDiffEditorWidget::setDiff);
|
||||
disconnect(m_controller, &DiffEditorController::saveStateRequested,
|
||||
this, &UnifiedDiffEditorWidget::saveStateRequested);
|
||||
disconnect(m_controller, &DiffEditorController::restoreStateRequested,
|
||||
this, &UnifiedDiffEditorWidget::restoreStateRequested);
|
||||
|
||||
disconnect(m_guiController, &DiffEditorGuiController::currentDiffFileIndexChanged,
|
||||
this, &UnifiedDiffEditorWidget::setCurrentDiffFileIndex);
|
||||
|
||||
clear(tr("No controller"));
|
||||
}
|
||||
m_guiController = controller;
|
||||
m_controller = 0;
|
||||
if (m_guiController) {
|
||||
m_controller = m_guiController->controller();
|
||||
|
||||
connect(m_controller, &DiffEditorController::cleared,
|
||||
this, &UnifiedDiffEditorWidget::clearAll);
|
||||
connect(m_controller, &DiffEditorController::diffFilesChanged,
|
||||
this, &UnifiedDiffEditorWidget::setDiff);
|
||||
connect(m_controller, &DiffEditorController::saveStateRequested,
|
||||
this, &UnifiedDiffEditorWidget::saveStateRequested);
|
||||
connect(m_controller, &DiffEditorController::restoreStateRequested,
|
||||
this, &UnifiedDiffEditorWidget::restoreStateRequested);
|
||||
|
||||
connect(m_guiController, &DiffEditorGuiController::currentDiffFileIndexChanged,
|
||||
this, &UnifiedDiffEditorWidget::setCurrentDiffFileIndex);
|
||||
|
||||
setDiff(m_controller->diffFiles(), m_controller->workingDirectory());
|
||||
setCurrentDiffFileIndex(m_guiController->currentDiffFileIndex());
|
||||
}
|
||||
m_document = document;
|
||||
}
|
||||
|
||||
void UnifiedDiffEditorWidget::saveStateRequested()
|
||||
void UnifiedDiffEditorWidget::saveState()
|
||||
{
|
||||
if (!m_state.isNull())
|
||||
return;
|
||||
|
||||
m_state = saveState();
|
||||
m_state = SelectableTextEditorWidget::saveState();
|
||||
}
|
||||
|
||||
void UnifiedDiffEditorWidget::restoreStateRequested()
|
||||
void UnifiedDiffEditorWidget::restoreState()
|
||||
{
|
||||
if (m_state.isNull())
|
||||
return;
|
||||
|
||||
restoreState(m_state);
|
||||
const bool oldIgnore = m_ignoreCurrentIndexChange;
|
||||
m_ignoreCurrentIndexChange = true;
|
||||
SelectableTextEditorWidget::restoreState(m_state);
|
||||
m_state.clear();
|
||||
m_ignoreCurrentIndexChange = oldIgnore;
|
||||
}
|
||||
|
||||
void UnifiedDiffEditorWidget::setDisplaySettings(const DisplaySettings &ds)
|
||||
@@ -187,16 +152,12 @@ void UnifiedDiffEditorWidget::setFontSettings(const FontSettings &fontSettings)
|
||||
|
||||
void UnifiedDiffEditorWidget::slotCursorPositionChangedInEditor()
|
||||
{
|
||||
if (!m_guiController)
|
||||
return;
|
||||
|
||||
if (m_ignoreCurrentIndexChange)
|
||||
return;
|
||||
|
||||
const bool oldIgnore = m_ignoreCurrentIndexChange;
|
||||
m_ignoreCurrentIndexChange = true;
|
||||
m_guiController->setCurrentDiffFileIndex(fileIndexForBlockNumber(
|
||||
textCursor().blockNumber()));
|
||||
emit currentDiffFileIndexChanged(fileIndexForBlockNumber(textCursor().blockNumber()));
|
||||
m_ignoreCurrentIndexChange = oldIgnore;
|
||||
}
|
||||
|
||||
@@ -230,7 +191,7 @@ void UnifiedDiffEditorWidget::addContextMenuActions(QMenu *menu,
|
||||
int diffFileIndex,
|
||||
int chunkIndex)
|
||||
{
|
||||
if (!m_controller)
|
||||
if (!m_document || !m_document->controller())
|
||||
return;
|
||||
|
||||
menu->addSeparator();
|
||||
@@ -260,7 +221,7 @@ void UnifiedDiffEditorWidget::addContextMenuActions(QMenu *menu,
|
||||
if (m_contextMenuChunkIndex >= fileData.chunks.count())
|
||||
return;
|
||||
|
||||
m_controller->requestChunkActions(menu, diffFileIndex, chunkIndex);
|
||||
m_document->chunkActionsRequested(menu, diffFileIndex, chunkIndex);
|
||||
|
||||
revertAction->setEnabled(true);
|
||||
|
||||
@@ -272,20 +233,10 @@ void UnifiedDiffEditorWidget::addContextMenuActions(QMenu *menu,
|
||||
|
||||
void UnifiedDiffEditorWidget::slotSendChunkToCodePaster()
|
||||
{
|
||||
if (!m_controller)
|
||||
if (!m_document)
|
||||
return;
|
||||
|
||||
if (m_contextMenuFileIndex < 0 || m_contextMenuChunkIndex < 0)
|
||||
return;
|
||||
|
||||
if (m_contextMenuFileIndex >= m_contextFileData.count())
|
||||
return;
|
||||
|
||||
const FileData fileData = m_contextFileData.at(m_contextMenuFileIndex);
|
||||
if (m_contextMenuChunkIndex >= fileData.chunks.count())
|
||||
return;
|
||||
|
||||
const QString patch = m_controller->makePatch(false);
|
||||
const QString patch = m_document->makePatch(m_contextMenuFileIndex, m_contextMenuChunkIndex, false);
|
||||
|
||||
if (patch.isEmpty())
|
||||
return;
|
||||
@@ -316,17 +267,7 @@ void UnifiedDiffEditorWidget::slotRevertChunk()
|
||||
|
||||
void UnifiedDiffEditorWidget::patch(bool revert)
|
||||
{
|
||||
if (!m_controller)
|
||||
return;
|
||||
|
||||
if (m_contextMenuFileIndex < 0 || m_contextMenuChunkIndex < 0)
|
||||
return;
|
||||
|
||||
if (m_contextMenuFileIndex >= m_contextFileData.count())
|
||||
return;
|
||||
|
||||
const FileData fileData = m_contextFileData.at(m_contextMenuFileIndex);
|
||||
if (m_contextMenuChunkIndex >= fileData.chunks.count())
|
||||
if (!m_document)
|
||||
return;
|
||||
|
||||
const QString title = revert ? tr("Revert Chunk") : tr("Apply Chunk");
|
||||
@@ -339,24 +280,24 @@ void UnifiedDiffEditorWidget::patch(bool revert)
|
||||
return;
|
||||
}
|
||||
|
||||
const int strip = m_controller->workingDirectory().isEmpty() ? -1 : 0;
|
||||
const int strip = m_document->baseDirectory().isEmpty() ? -1 : 0;
|
||||
|
||||
const FileData fileData = m_contextFileData.at(m_contextMenuFileIndex);
|
||||
const QString fileName = revert
|
||||
? fileData.rightFileInfo.fileName
|
||||
: fileData.leftFileInfo.fileName;
|
||||
|
||||
const QString workingDirectory = m_controller->workingDirectory().isEmpty()
|
||||
const QString workingDirectory = m_document->baseDirectory().isEmpty()
|
||||
? QFileInfo(fileName).absolutePath()
|
||||
: m_controller->workingDirectory();
|
||||
: m_document->baseDirectory();
|
||||
|
||||
const QString patch = m_controller->makePatch(revert);
|
||||
const QString patch = m_document->makePatch(m_contextMenuFileIndex, m_contextMenuChunkIndex, revert);
|
||||
if (patch.isEmpty())
|
||||
return;
|
||||
|
||||
if (PatchTool::runPatch(
|
||||
EditorManager::defaultTextCodec()->fromUnicode(patch),
|
||||
workingDirectory, strip, revert))
|
||||
m_controller->requestReload();
|
||||
if (PatchTool::runPatch(EditorManager::defaultTextCodec()->fromUnicode(patch),
|
||||
workingDirectory, strip, revert))
|
||||
m_document->reload();
|
||||
}
|
||||
|
||||
void UnifiedDiffEditorWidget::clear(const QString &message)
|
||||
@@ -372,16 +313,11 @@ void UnifiedDiffEditorWidget::clear(const QString &message)
|
||||
const bool oldIgnore = m_ignoreCurrentIndexChange;
|
||||
m_ignoreCurrentIndexChange = true;
|
||||
SelectableTextEditorWidget::clear();
|
||||
setDiff(QList<FileData>(), QString());
|
||||
setPlainText(message);
|
||||
m_ignoreCurrentIndexChange = oldIgnore;
|
||||
}
|
||||
|
||||
void UnifiedDiffEditorWidget::clearAll(const QString &message)
|
||||
{
|
||||
setDiff(QList<FileData>(), QString());
|
||||
clear(message);
|
||||
}
|
||||
|
||||
QString UnifiedDiffEditorWidget::lineNumber(int blockNumber) const
|
||||
{
|
||||
QString lineNumberString;
|
||||
@@ -618,8 +554,6 @@ QString UnifiedDiffEditorWidget::showChunk(const ChunkData &chunkData,
|
||||
|
||||
void UnifiedDiffEditorWidget::showDiff()
|
||||
{
|
||||
clear(tr("No difference"));
|
||||
|
||||
QString diffText;
|
||||
|
||||
int blockNumber = 0;
|
||||
@@ -669,8 +603,10 @@ void UnifiedDiffEditorWidget::showDiff()
|
||||
|
||||
}
|
||||
|
||||
if (diffText.isEmpty())
|
||||
if (diffText.isEmpty()) {
|
||||
setPlainText(tr("No difference."));
|
||||
return;
|
||||
}
|
||||
|
||||
diffText.replace(QLatin1Char('\r'), QLatin1Char(' '));
|
||||
const bool oldIgnore = m_ignoreCurrentIndexChange;
|
||||
@@ -783,10 +719,10 @@ void UnifiedDiffEditorWidget::jumpToOriginalFile(const QString &fileName,
|
||||
int lineNumber,
|
||||
int columnNumber)
|
||||
{
|
||||
if (!m_controller)
|
||||
if (!m_document)
|
||||
return;
|
||||
|
||||
const QDir dir(m_controller->workingDirectory());
|
||||
const QDir dir(m_document->baseDirectory());
|
||||
const QString absoluteFileName = dir.absoluteFilePath(fileName);
|
||||
QFileInfo fi(absoluteFileName);
|
||||
if (fi.exists() && !fi.isDir())
|
||||
|
||||
@@ -47,9 +47,8 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace DiffEditor {
|
||||
|
||||
namespace Internal { class DiffEditorGuiController; }
|
||||
|
||||
class ChunkData;
|
||||
class DiffEditorController;
|
||||
class FileData;
|
||||
|
||||
namespace Internal {
|
||||
@@ -60,7 +59,19 @@ class UnifiedDiffEditorWidget : public SelectableTextEditorWidget
|
||||
public:
|
||||
UnifiedDiffEditorWidget(QWidget *parent = 0);
|
||||
|
||||
void setDiffEditorGuiController(Internal::DiffEditorGuiController *controller);
|
||||
void setDocument(DiffEditorDocument *document);
|
||||
|
||||
void setDiff(const QList<FileData> &diffFileList,
|
||||
const QString &workingDirectory);
|
||||
void setCurrentDiffFileIndex(int diffFileIndex);
|
||||
|
||||
void saveState();
|
||||
void restoreState();
|
||||
|
||||
void clear(const QString &message = QString());
|
||||
|
||||
signals:
|
||||
void currentDiffFileIndexChanged(int index);
|
||||
|
||||
public slots:
|
||||
void setDisplaySettings(const TextEditor::DisplaySettings &ds);
|
||||
@@ -72,13 +83,6 @@ protected:
|
||||
int lineNumberDigits() const;
|
||||
|
||||
private slots:
|
||||
void clear(const QString &message = QString());
|
||||
void clearAll(const QString &message = QString());
|
||||
void setDiff(const QList<FileData> &diffFileList,
|
||||
const QString &workingDirectory);
|
||||
|
||||
void setCurrentDiffFileIndex(int diffFileIndex);
|
||||
|
||||
void setFontSettings(const TextEditor::FontSettings &fontSettings);
|
||||
|
||||
void slotCursorPositionChangedInEditor();
|
||||
@@ -86,8 +90,6 @@ private slots:
|
||||
void slotSendChunkToCodePaster();
|
||||
void slotApplyChunk();
|
||||
void slotRevertChunk();
|
||||
void saveStateRequested();
|
||||
void restoreStateRequested();
|
||||
|
||||
private:
|
||||
void setLeftLineNumber(int blockNumber, int lineNumber);
|
||||
@@ -114,8 +116,7 @@ private:
|
||||
int chunkIndex);
|
||||
void patch(bool revert);
|
||||
|
||||
Internal::DiffEditorGuiController *m_guiController;
|
||||
DiffEditorController *m_controller;
|
||||
DiffEditorDocument *m_document;
|
||||
|
||||
// block number, visual line number.
|
||||
QMap<int, int> m_leftLineNumbers;
|
||||
@@ -132,7 +133,7 @@ private:
|
||||
QMap<int, QPair<int, int> > m_chunkInfo;
|
||||
|
||||
QList<FileData> m_contextFileData; // ultimate data to be shown
|
||||
// contextLinesNumber taken into account
|
||||
// contextLineCount taken into account
|
||||
|
||||
QTextCharFormat m_fileLineFormat;
|
||||
QTextCharFormat m_chunkLineFormat;
|
||||
|
||||
Reference in New Issue
Block a user