diff options
author | jkobus <jaroslaw.kobus@digia.com> | 2014-02-13 16:43:28 +0100 |
---|---|---|
committer | Jarek Kobus <jaroslaw.kobus@digia.com> | 2014-06-06 12:33:59 +0200 |
commit | 8cad94534f97849081bd595da458670d168d6b63 (patch) | |
tree | 5575aab843ad47d38a30d5bbc38f1449254eaf4e /src/plugins/diffeditor/sidebysidediffeditorwidget.cpp | |
parent | 8cb25f9e3e1afcc1ccfa17966cdcc31a95c02289 (diff) | |
download | qt-creator-8cad94534f97849081bd595da458670d168d6b63.tar.gz |
Implement unified diff editor
Change-Id: I93e0bfd71a8a650afbe2ca9e0f1f3dbfc9d57db0
Reviewed-by: Jarek Kobus <jaroslaw.kobus@digia.com>
Diffstat (limited to 'src/plugins/diffeditor/sidebysidediffeditorwidget.cpp')
-rw-r--r-- | src/plugins/diffeditor/sidebysidediffeditorwidget.cpp | 837 |
1 files changed, 519 insertions, 318 deletions
diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp index 9f0c7e8604..32d8ce73eb 100644 --- a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp +++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp @@ -28,8 +28,10 @@ ****************************************************************************/ #include "sidebysidediffeditorwidget.h" +#include "selectabletexteditorwidget.h" #include "diffeditorguicontroller.h" #include "diffutils.h" +#include "diffeditorconstants.h" #include <QPlainTextEdit> #include <QVBoxLayout> @@ -39,6 +41,8 @@ #include <QPainter> #include <QDir> #include <QToolButton> +#include <QTextCodec> +#include <QMessageBox> #include <texteditor/basetexteditor.h> #include <texteditor/basetextdocumentlayout.h> @@ -53,6 +57,7 @@ #include <coreplugin/icore.h> #include <coreplugin/minisplitter.h> #include <coreplugin/mimedatabase.h> +#include <coreplugin/patchtool.h> #include <extensionsystem/pluginmanager.h> @@ -67,8 +72,6 @@ using namespace TextEditor; namespace DiffEditor { -using namespace Internal; - ////////////////////// class SideDiffEditor : public BaseTextEditor @@ -84,12 +87,14 @@ public: } private slots: - void slotTooltipRequested(TextEditor::ITextEditor *editor, const QPoint &globalPoint, int position); + void slotTooltipRequested(TextEditor::ITextEditor *editor, + const QPoint &globalPoint, + int position); }; //////////////////////// - +/* class MultiHighlighter : public SyntaxHighlighter { Q_OBJECT @@ -98,7 +103,7 @@ public: ~MultiHighlighter(); virtual void setFontSettings(const TextEditor::FontSettings &fontSettings); - void setDocuments(const QList<QPair<DiffEditorController::DiffFileInfo, QString> > &documents); + void setDocuments(const QList<QPair<DiffFileInfo, QString> > &documents); protected: virtual void highlightBlock(const QString &text); @@ -109,36 +114,43 @@ private: QList<SyntaxHighlighter *> m_highlighters; QList<QTextDocument *> m_documents; }; - +*/ //////////////////////// -class SideDiffEditorWidget : public BaseTextEditorWidget +class SideDiffEditorWidget : public SelectableTextEditorWidget { Q_OBJECT public: - class ExtendedFileInfo { - public: - DiffEditorController::DiffFileInfo fileInfo; - TextEditor::SyntaxHighlighter *highlighter; - }; - SideDiffEditorWidget(QWidget *parent = 0); // block number, file info - QMap<int, DiffEditorController::DiffFileInfo> fileInfo() const { return m_fileInfo; } + QMap<int, DiffFileInfo> fileInfo() const { return m_fileInfo; } void setLineNumber(int blockNumber, int lineNumber); - void setFileInfo(int blockNumber, const DiffEditorController::DiffFileInfo &fileInfo); - void setSkippedLines(int blockNumber, int skippedLines) { m_skippedLines[blockNumber] = skippedLines; setSeparator(blockNumber, true); } - void setSeparator(int blockNumber, bool separator) { m_separators[blockNumber] = separator; } - bool isFileLine(int blockNumber) const { return m_fileInfo.contains(blockNumber); } + void setFileInfo(int blockNumber, const DiffFileInfo &fileInfo); + void setSkippedLines(int blockNumber, int skippedLines) { + m_skippedLines[blockNumber] = skippedLines; + setSeparator(blockNumber, true); + } + void setChunkIndex(int startBlockNumber, int blockCount, int chunkIndex); + void setSeparator(int blockNumber, bool separator) { + m_separators[blockNumber] = separator; + } + bool isFileLine(int blockNumber) const { + return m_fileInfo.contains(blockNumber); + } int blockNumberForFileIndex(int fileIndex) const; int fileIndexForBlockNumber(int blockNumber) const; - bool isChunkLine(int blockNumber) const { return m_skippedLines.contains(blockNumber); } + int chunkIndexForBlockNumber(int blockNumber) const; + bool isChunkLine(int blockNumber) const { + return m_skippedLines.contains(blockNumber); + } void clearAll(const QString &message); void clearAllData(); - QTextBlock firstVisibleBlock() const { return BaseTextEditorWidget::firstVisibleBlock(); } - void setDocuments(const QList<QPair<DiffEditorController::DiffFileInfo, QString> > &documents); + QTextBlock firstVisibleBlock() const { + return BaseTextEditorWidget::firstVisibleBlock(); + } +// void setDocuments(const QList<QPair<DiffFileInfo, QString> > &documents); public slots: void setDisplaySettings(const DisplaySettings &ds); @@ -147,9 +159,14 @@ signals: void jumpToOriginalFileRequested(int diffFileIndex, int lineNumber, int columnNumber); + void contextMenuRequested(QMenu *menu, + int diffFileIndex, + int chunkIndex); protected: - virtual int extraAreaWidth(int *markWidthPtr = 0) const { return BaseTextEditorWidget::extraAreaWidth(markWidthPtr); } + virtual int extraAreaWidth(int *markWidthPtr = 0) const { + return SelectableTextEditorWidget::extraAreaWidth(markWidthPtr); + } void applyFontSettings(); BaseTextEditor *createEditor() { return new SideDiffEditor(this); } virtual QString lineNumber(int blockNumber) const; @@ -158,16 +175,17 @@ protected: virtual bool replacementVisible(int blockNumber) const; QColor replacementPenColor(int blockNumber) const; virtual QString plainTextFromSelection(const QTextCursor &cursor) const; - virtual void drawCollapsedBlockPopup(QPainter &painter, - const QTextBlock &block, - QPointF offset, - const QRect &clip); +// virtual void drawCollapsedBlockPopup(QPainter &painter, +// const QTextBlock &block, +// QPointF offset, +// const QRect &clip); void mouseDoubleClickEvent(QMouseEvent *e); + void contextMenuEvent(QContextMenuEvent *e); virtual void paintEvent(QPaintEvent *e); virtual void scrollContentsBy(int dx, int dy); private: - void paintCollapsedBlockPopup(QPainter &painter, const QRect &clipRect); +// void paintCollapsedBlockPopup(QPainter &painter, const QRect &clipRect); void paintSeparator(QPainter &painter, QColor &color, const QString &text, const QTextBlock &block, int top); void jumpToOriginalFile(const QTextCursor &cursor); @@ -176,28 +194,32 @@ private: QMap<int, int> m_lineNumbers; int m_lineNumberDigits; // block number, fileInfo. Set for file lines only. - QMap<int, DiffEditorController::DiffFileInfo> m_fileInfo; + QMap<int, DiffFileInfo> m_fileInfo; // block number, skipped lines. Set for chunk lines only. QMap<int, int> m_skippedLines; + // start block number, block count of a chunk, chunk index inside a file. + QMap<int, QPair<int, int> > m_chunkInfo; // block number, separator. Set for file, chunk or span line. QMap<int, bool> m_separators; bool m_inPaintEvent; QColor m_fileLineForeground; QColor m_chunkLineForeground; QColor m_textForeground; - MultiHighlighter *m_highlighter; +// MultiHighlighter *m_highlighter; }; //////////////////////// -void SideDiffEditor::slotTooltipRequested(TextEditor::ITextEditor *editor, const QPoint &globalPoint, int position) +void SideDiffEditor::slotTooltipRequested(TextEditor::ITextEditor *editor, + const QPoint &globalPoint, + int position) { SideDiffEditorWidget *ew = qobject_cast<SideDiffEditorWidget *>(editorWidget()); if (!ew) return; - QMap<int, DiffEditorController::DiffFileInfo> fi = ew->fileInfo(); - QMap<int, DiffEditorController::DiffFileInfo>::const_iterator it + QMap<int, DiffFileInfo> fi = ew->fileInfo(); + QMap<int, DiffFileInfo>::const_iterator it = fi.constFind(ew->document()->findBlock(position).blockNumber()); if (it != fi.constEnd()) { Utils::ToolTip::show(globalPoint, Utils::TextContent(it.value().fileName), @@ -208,7 +230,7 @@ void SideDiffEditor::slotTooltipRequested(TextEditor::ITextEditor *editor, const } //////////////////////// - +/* MultiHighlighter::MultiHighlighter(SideDiffEditorWidget *editor, QTextDocument *document) : SyntaxHighlighter(document), m_editor(editor) @@ -224,7 +246,7 @@ MultiHighlighter::MultiHighlighter(SideDiffEditorWidget *editor, QTextDocument * MultiHighlighter::~MultiHighlighter() { - setDocuments(QList<QPair<DiffEditorController::DiffFileInfo, QString> >()); + setDocuments(QList<QPair<DiffFileInfo, QString> >()); } void MultiHighlighter::setFontSettings(const TextEditor::FontSettings &fontSettings) @@ -237,7 +259,7 @@ void MultiHighlighter::setFontSettings(const TextEditor::FontSettings &fontSetti } } -void MultiHighlighter::setDocuments(const QList<QPair<DiffEditorController::DiffFileInfo, QString> > &documents) +void MultiHighlighter::setDocuments(const QList<QPair<DiffFileInfo, QString> > &documents) { // clear old documents qDeleteAll(m_documents); @@ -247,7 +269,7 @@ void MultiHighlighter::setDocuments(const QList<QPair<DiffEditorController::Diff // create new documents for (int i = 0; i < documents.count(); i++) { - DiffEditorController::DiffFileInfo fileInfo = documents.at(i).first; + DiffFileInfo fileInfo = documents.at(i).first; const QString contents = documents.at(i).second; QTextDocument *document = new QTextDocument(contents); const MimeType mimeType = MimeDatabase::findByFile(QFileInfo(fileInfo.fileName)); @@ -293,11 +315,13 @@ void MultiHighlighter::highlightBlock(const QString &text) QList<QTextLayout::FormatRange> formats = documentBlock.layout()->additionalFormats(); setExtraAdditionalFormats(block, formats); } - +*/ //////////////////////// SideDiffEditorWidget::SideDiffEditorWidget(QWidget *parent) - : BaseTextEditorWidget(parent), m_lineNumberDigits(1), m_inPaintEvent(false) + : SelectableTextEditorWidget(parent), + m_lineNumberDigits(1), + m_inPaintEvent(false) { DisplaySettings settings = displaySettings(); settings.m_textWrapping = false; @@ -306,25 +330,24 @@ SideDiffEditorWidget::SideDiffEditorWidget(QWidget *parent) settings.m_displayFoldingMarkers = true; settings.m_markTextChanges = false; settings.m_highlightBlocks = false; - BaseTextEditorWidget::setDisplaySettings(settings); + SelectableTextEditorWidget::setDisplaySettings(settings); - setCodeFoldingSupported(true); - setFrameStyle(QFrame::NoFrame); +// setCodeFoldingSupported(true); - m_highlighter = new MultiHighlighter(this, baseTextDocument()->document()); - baseTextDocument()->setSyntaxHighlighter(m_highlighter); +// m_highlighter = new MultiHighlighter(this, baseTextDocument()->document()); +// baseTextDocument()->setSyntaxHighlighter(m_highlighter); } void SideDiffEditorWidget::setDisplaySettings(const DisplaySettings &ds) { DisplaySettings settings = displaySettings(); settings.m_visualizeWhitespace = ds.m_visualizeWhitespace; - BaseTextEditorWidget::setDisplaySettings(settings); + SelectableTextEditorWidget::setDisplaySettings(settings); } void SideDiffEditorWidget::applyFontSettings() { - BaseTextEditorWidget::applyFontSettings(); + SelectableTextEditorWidget::applyFontSettings(); const TextEditor::FontSettings &fs = baseTextDocument()->fontSettings(); m_fileLineForeground = fs.formatFor(C_DIFF_FILE_LINE).foreground(); m_chunkLineForeground = fs.formatFor(C_DIFF_CONTEXT_LINE).foreground(); @@ -352,7 +375,8 @@ bool SideDiffEditorWidget::selectionVisible(int blockNumber) const bool SideDiffEditorWidget::replacementVisible(int blockNumber) const { return isChunkLine(blockNumber) || (isFileLine(blockNumber) - && TextEditor::BaseTextDocumentLayout::isFolded(document()->findBlockByNumber(blockNumber))); + && TextEditor::BaseTextDocumentLayout::isFolded( + document()->findBlockByNumber(blockNumber))); } QColor SideDiffEditorWidget::replacementPenColor(int blockNumber) const @@ -403,18 +427,23 @@ void SideDiffEditorWidget::setLineNumber(int blockNumber, int lineNumber) m_lineNumberDigits = qMax(m_lineNumberDigits, lineNumberString.count()); } -void SideDiffEditorWidget::setFileInfo(int blockNumber, const DiffEditorController::DiffFileInfo &fileInfo) +void SideDiffEditorWidget::setFileInfo(int blockNumber, const DiffFileInfo &fileInfo) { m_fileInfo[blockNumber] = fileInfo; setSeparator(blockNumber, true); } +void SideDiffEditorWidget::setChunkIndex(int startBlockNumber, int blockCount, int chunkIndex) +{ + m_chunkInfo.insert(startBlockNumber, qMakePair(blockCount, chunkIndex)); +} + int SideDiffEditorWidget::blockNumberForFileIndex(int fileIndex) const { if (fileIndex < 0 || fileIndex >= m_fileInfo.count()) return -1; - QMap<int, DiffEditorController::DiffFileInfo>::const_iterator it + QMap<int, DiffFileInfo>::const_iterator it = m_fileInfo.constBegin(); for (int i = 0; i < fileIndex; i++) ++it; @@ -424,9 +453,9 @@ int SideDiffEditorWidget::blockNumberForFileIndex(int fileIndex) const int SideDiffEditorWidget::fileIndexForBlockNumber(int blockNumber) const { - QMap<int, DiffEditorController::DiffFileInfo>::const_iterator it + QMap<int, DiffFileInfo>::const_iterator it = m_fileInfo.constBegin(); - QMap<int, DiffEditorController::DiffFileInfo>::const_iterator itEnd + QMap<int, DiffFileInfo>::const_iterator itEnd = m_fileInfo.constEnd(); int i = -1; @@ -439,13 +468,33 @@ int SideDiffEditorWidget::fileIndexForBlockNumber(int blockNumber) const return i; } +int SideDiffEditorWidget::chunkIndexForBlockNumber(int blockNumber) const +{ + if (m_chunkInfo.isEmpty()) + return -1; + + QMap<int, QPair<int, int> >::const_iterator it + = m_chunkInfo.upperBound(blockNumber); + if (it == m_chunkInfo.constBegin()) + return -1; + + --it; + + if (blockNumber < it.key() + it.value().first) + return it.value().second; + + return -1; +} + void SideDiffEditorWidget::clearAll(const QString &message) { setBlockSelection(false); clear(); clearAllData(); + setExtraSelections(BaseTextEditorWidget::OtherSelection, + QList<QTextEdit::ExtraSelection>()); setPlainText(message); - m_highlighter->setDocuments(QList<QPair<DiffEditorController::DiffFileInfo, QString> >()); +// m_highlighter->setDocuments(QList<QPair<DiffFileInfo, QString> >()); } void SideDiffEditorWidget::clearAllData() @@ -454,17 +503,19 @@ void SideDiffEditorWidget::clearAllData() m_lineNumbers.clear(); m_fileInfo.clear(); m_skippedLines.clear(); + m_chunkInfo.clear(); m_separators.clear(); + setSelections(QMap<int, QList<DiffSelection> >()); } - -void SideDiffEditorWidget::setDocuments(const QList<QPair<DiffEditorController::DiffFileInfo, QString> > &documents) +/* +void SideDiffEditorWidget::setDocuments(const QList<QPair<DiffFileInfo, QString> > &documents) { m_highlighter->setDocuments(documents); } - +*/ void SideDiffEditorWidget::scrollContentsBy(int dx, int dy) { - BaseTextEditorWidget::scrollContentsBy(dx, dy); + SelectableTextEditorWidget::scrollContentsBy(dx, dy); // TODO: update only chunk lines viewport()->update(); } @@ -491,8 +542,10 @@ void SideDiffEditorWidget::paintSeparator(QPainter &painter, + QLatin1String("}; "); const int replacementTextWidth = fontMetrics().width(replacementText) + 24; int x = replacementTextWidth + offset.x(); - if (x < document()->documentMargin() || !TextEditor::BaseTextDocumentLayout::isFolded(block)) + if (x < document()->documentMargin() + || !TextEditor::BaseTextDocumentLayout::isFolded(block)) { x = document()->documentMargin(); + } const QString elidedText = fontMetrics().elidedText(text, Qt::ElideRight, viewport()->width() - x); @@ -515,7 +568,22 @@ void SideDiffEditorWidget::mouseDoubleClickEvent(QMouseEvent *e) e->accept(); return; } - BaseTextEditorWidget::mouseDoubleClickEvent(e); + SelectableTextEditorWidget::mouseDoubleClickEvent(e); +} + +void SideDiffEditorWidget::contextMenuEvent(QContextMenuEvent *e) +{ + QPointer<QMenu> menu = createStandardContextMenu(); + + QTextCursor cursor = cursorForPosition(e->pos()); + const int blockNumber = cursor.blockNumber(); + + emit contextMenuRequested(menu, fileIndexForBlockNumber(blockNumber), + chunkIndexForBlockNumber(blockNumber)); + + connect(this, SIGNAL(destroyed()), menu, SLOT(deleteLater())); + menu->exec(e->globalPos()); + delete menu; } void SideDiffEditorWidget::jumpToOriginalFile(const QTextCursor &cursor) @@ -530,16 +598,26 @@ void SideDiffEditorWidget::jumpToOriginalFile(const QTextCursor &cursor) const int lineNumber = m_lineNumbers.value(blockNumber); - emit jumpToOriginalFileRequested(fileIndexForBlockNumber(blockNumber), lineNumber, columnNumber); + emit jumpToOriginalFileRequested(fileIndexForBlockNumber(blockNumber), + lineNumber, columnNumber); +} + +static QString skippedText(int skippedNumber) +{ + if (skippedNumber > 0) + return SideBySideDiffEditorWidget::tr("Skipped %n lines...", 0, skippedNumber); + if (skippedNumber == -2) + return SideBySideDiffEditorWidget::tr("Binary files differ"); + return SideBySideDiffEditorWidget::tr("Skipped unknown number of lines..."); } void SideDiffEditorWidget::paintEvent(QPaintEvent *e) { m_inPaintEvent = true; - BaseTextEditorWidget::paintEvent(e); + SelectableTextEditorWidget::paintEvent(e); m_inPaintEvent = false; - QPainter painter(viewport()); + QPainter painter(viewport()); QPointF offset = contentOffset(); QTextBlock firstBlock = firstVisibleBlock(); QTextBlock currentBlock = firstBlock; @@ -557,16 +635,17 @@ void SideDiffEditorWidget::paintEvent(QPaintEvent *e) const int skippedBefore = m_skippedLines.value(blockNumber); if (skippedBefore) { - const QString skippedRowsText = tr("Skipped %n lines...", 0, skippedBefore); + const QString skippedRowsText = skippedText(skippedBefore); paintSeparator(painter, m_chunkLineForeground, skippedRowsText, currentBlock, top); } - const DiffEditorController::DiffFileInfo fileInfo = m_fileInfo.value(blockNumber); + const DiffFileInfo fileInfo = m_fileInfo.value(blockNumber); if (!fileInfo.fileName.isEmpty()) { const QString fileNameText = fileInfo.typeInfo.isEmpty() ? fileInfo.fileName - : tr("[%1] %2").arg(fileInfo.typeInfo).arg(fileInfo.fileName); + : tr("[%1] %2").arg(fileInfo.typeInfo) + .arg(fileInfo.fileName); paintSeparator(painter, m_fileLineForeground, fileNameText, currentBlock, top); } @@ -574,9 +653,9 @@ void SideDiffEditorWidget::paintEvent(QPaintEvent *e) } currentBlock = currentBlock.next(); } - paintCollapsedBlockPopup(painter, e->rect()); +// paintCollapsedBlockPopup(painter, e->rect()); } - +/* void SideDiffEditorWidget::paintCollapsedBlockPopup(QPainter &painter, const QRect &clipRect) { QPointF offset(contentOffset()); @@ -620,7 +699,7 @@ void SideDiffEditorWidget::drawCollapsedBlockPopup(QPainter &painter, QPointF offset, const QRect &clip) { - // We ignore the call coming from the BaseTextEditorWidget::paintEvent() + // We ignore the call coming from the SelectableTextEditorWidget::paintEvent() // since we will draw it later, after custom drawings of this paintEvent. // We need to draw it after our custom drawings, otherwise custom // drawings will appear in front of block popup. @@ -676,7 +755,7 @@ void SideDiffEditorWidget::drawCollapsedBlockPopup(QPainter &painter, b = b.next(); } } - +*/ ////////////////// @@ -684,7 +763,10 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent) : QWidget(parent) , m_guiController(0) , m_controller(0) + , m_ignoreCurrentIndexChange(false) , m_foldingBlocker(false) + , m_contextMenuFileIndex(-1) + , m_contextMenuChunkIndex(-1) { m_leftEditor = new SideDiffEditorWidget(this); m_leftEditor->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); @@ -696,6 +778,8 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent) m_leftEditor->setCodeStyle(TextEditorSettings::codeStyle()); connect(m_leftEditor, SIGNAL(jumpToOriginalFileRequested(int,int,int)), this, SLOT(slotLeftJumpToOriginalFileRequested(int,int,int))); + connect(m_leftEditor, SIGNAL(contextMenuRequested(QMenu*,int,int)), + this, SLOT(slotLeftContextMenuRequested(QMenu*,int,int))); m_rightEditor = new SideDiffEditorWidget(this); m_rightEditor->setReadOnly(true); @@ -706,6 +790,8 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent) m_rightEditor->setCodeStyle(TextEditorSettings::codeStyle()); connect(m_rightEditor, SIGNAL(jumpToOriginalFileRequested(int,int,int)), this, SLOT(slotRightJumpToOriginalFileRequested(int,int,int))); + connect(m_rightEditor, SIGNAL(contextMenuRequested(QMenu*,int,int)), + this, SLOT(slotRightContextMenuRequested(QMenu*,int,int))); connect(TextEditorSettings::instance(), SIGNAL(fontSettingsChanged(TextEditor::FontSettings)), @@ -724,8 +810,8 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent) connect(m_leftEditor, SIGNAL(cursorPositionChanged()), this, SLOT(leftCursorPositionChanged())); - connect(m_leftEditor->document()->documentLayout(), SIGNAL(documentSizeChanged(QSizeF)), - this, SLOT(leftDocumentSizeChanged())); +// connect(m_leftEditor->document()->documentLayout(), SIGNAL(documentSizeChanged(QSizeF)), +// this, SLOT(leftDocumentSizeChanged())); connect(m_rightEditor->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(rightVSliderChanged())); @@ -739,8 +825,8 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent) connect(m_rightEditor, SIGNAL(cursorPositionChanged()), this, SLOT(rightCursorPositionChanged())); - connect(m_rightEditor->document()->documentLayout(), SIGNAL(documentSizeChanged(QSizeF)), - this, SLOT(rightDocumentSizeChanged())); +// connect(m_rightEditor->document()->documentLayout(), SIGNAL(documentSizeChanged(QSizeF)), +// this, SLOT(rightDocumentSizeChanged())); m_splitter = new Core::MiniSplitter(this); m_splitter->addWidget(m_leftEditor); @@ -757,42 +843,38 @@ SideBySideDiffEditorWidget::~SideBySideDiffEditorWidget() } -void SideBySideDiffEditorWidget::setDiffEditorGuiController(DiffEditorGuiController *controller) +void SideBySideDiffEditorWidget::setDiffEditorGuiController( + DiffEditorGuiController *controller) { if (m_guiController == controller) return; if (m_guiController) { - disconnect(m_controller, SIGNAL(cleared(QString)), this, SLOT(clear(QString))); - disconnect(m_controller, SIGNAL(diffContentsChanged(QList<DiffEditorController::DiffFilesContents>,QString)), - this, SLOT(setDiff(QList<DiffEditorController::DiffFilesContents>,QString))); - - disconnect(m_guiController, SIGNAL(contextLinesNumberChanged(int)), - this, SLOT(setContextLinesNumber(int))); - disconnect(m_guiController, SIGNAL(ignoreWhitespacesChanged(bool)), - this, SLOT(setIgnoreWhitespaces(bool))); + disconnect(m_controller, SIGNAL(cleared(QString)), + this, SLOT(clearAll(QString))); + disconnect(m_controller, SIGNAL(diffFilesChanged(QList<FileData>,QString)), + this, SLOT(setDiff(QList<FileData>,QString))); + disconnect(m_guiController, SIGNAL(currentDiffFileIndexChanged(int)), - this, SLOT(setCurrentDiffFileIndex(int))); + this, SLOT(setCurrentDiffFileIndex(int))); - clear(tr("No controller")); + clearAll(tr("No controller")); } m_guiController = controller; m_controller = 0; if (m_guiController) { m_controller = m_guiController->controller(); - connect(m_controller, SIGNAL(cleared(QString)), this, SLOT(clear(QString))); - connect(m_controller, SIGNAL(diffContentsChanged(QList<DiffEditorController::DiffFilesContents>,QString)), - this, SLOT(setDiff(QList<DiffEditorController::DiffFilesContents>,QString))); + connect(m_controller, SIGNAL(cleared(QString)), + this, SLOT(clearAll(QString))); + connect(m_controller, SIGNAL(diffFilesChanged(QList<FileData>,QString)), + this, SLOT(setDiff(QList<FileData>,QString))); - connect(m_guiController, SIGNAL(contextLinesNumberChanged(int)), - this, SLOT(setContextLinesNumber(int))); - connect(m_guiController, SIGNAL(ignoreWhitespacesChanged(bool)), - this, SLOT(setIgnoreWhitespaces(bool))); connect(m_guiController, SIGNAL(currentDiffFileIndexChanged(int)), this, SLOT(setCurrentDiffFileIndex(int))); - setDiff(m_controller->diffContents(), m_controller->workingDirectory()); + setDiff(m_controller->diffFiles(), m_controller->workingDirectory()); + setCurrentDiffFileIndex(m_guiController->currentDiffFileIndex()); } } @@ -804,91 +886,37 @@ DiffEditorGuiController *SideBySideDiffEditorWidget::diffEditorGuiController() c void SideBySideDiffEditorWidget::clear(const QString &message) { + const bool oldIgnore = m_ignoreCurrentIndexChange; + m_ignoreCurrentIndexChange = true; m_leftEditor->clearAll(message); m_rightEditor->clearAll(message); + m_ignoreCurrentIndexChange = oldIgnore; } -void SideBySideDiffEditorWidget::setDiff(const QList<DiffEditorController::DiffFilesContents> &diffFileList, const QString &workingDirectory) +void SideBySideDiffEditorWidget::clearAll(const QString &message) { - Q_UNUSED(workingDirectory) - - Differ differ; - QList<DiffList> diffList; - for (int i = 0; i < diffFileList.count(); i++) { - DiffEditorController::DiffFilesContents dfc = diffFileList.at(i); - DiffList dl; - dl.leftFileInfo = dfc.leftFileInfo; - dl.rightFileInfo = dfc.rightFileInfo; - dl.diffList = differ.cleanupSemantics(differ.diff(dfc.leftText, dfc.rightText)); - diffList.append(dl); - } - setDiff(diffList); -} - -void SideBySideDiffEditorWidget::setDiff(const QList<DiffList> &diffList) -{ - m_diffList = diffList; - m_originalChunkData.clear(); - m_contextFileData.clear(); - const int contextLinesNumber = m_guiController ? m_guiController->contextLinesNumber() : 3; - - for (int i = 0; i < m_diffList.count(); i++) { - const DiffList &dl = m_diffList.at(i); - QList<Diff> leftDiffs; - QList<Diff> rightDiffs; - handleWhitespaces(dl.diffList, &leftDiffs, &rightDiffs); - ChunkData chunkData = calculateOriginalData(leftDiffs, rightDiffs); - m_originalChunkData.append(chunkData); - FileData fileData = calculateContextData(chunkData, contextLinesNumber); - fileData.leftFileInfo = dl.leftFileInfo; - fileData.rightFileInfo = dl.rightFileInfo; - m_contextFileData.append(fileData); - } - showDiff(); -} - -void SideBySideDiffEditorWidget::handleWhitespaces(const QList<Diff> &input, - QList<Diff> *leftOutput, - QList<Diff> *rightOutput) const -{ - if (!leftOutput || !rightOutput) - return; - - Differ::splitDiffList(input, leftOutput, rightOutput); - if (m_guiController && m_guiController->isIgnoreWhitespaces()) { - const QList<Diff> leftDiffList = Differ::moveWhitespaceIntoEqualities(*leftOutput); - const QList<Diff> rightDiffList = Differ::moveWhitespaceIntoEqualities(*rightOutput); - Differ::diffBetweenEqualities(leftDiffList, rightDiffList, leftOutput, rightOutput); - } + setDiff(QList<FileData>(), QString()); + clear(message); } -void SideBySideDiffEditorWidget::setContextLinesNumber(int lines) +void SideBySideDiffEditorWidget::setDiff(const QList<FileData> &diffFileList, + const QString &workingDirectory) { - Q_UNUSED(lines) - const int contextLinesNumber = m_guiController ? m_guiController->contextLinesNumber() : 3; - - for (int i = 0; i < m_contextFileData.count(); i++) { - const FileData oldFileData = m_contextFileData.at(i); - FileData newFileData = calculateContextData(m_originalChunkData.at(i), contextLinesNumber); - newFileData.leftFileInfo = oldFileData.leftFileInfo; - newFileData.rightFileInfo = oldFileData.rightFileInfo; - m_contextFileData[i] = newFileData; - } + Q_UNUSED(workingDirectory) + m_contextFileData = diffFileList; showDiff(); } -void SideBySideDiffEditorWidget::setIgnoreWhitespaces(bool ignore) -{ - Q_UNUSED(ignore) - - setDiff(m_diffList); -} - void SideBySideDiffEditorWidget::setCurrentDiffFileIndex(int diffFileIndex) { + if (m_ignoreCurrentIndexChange) + return; + const int blockNumber = m_leftEditor->blockNumberForFileIndex(diffFileIndex); + const bool oldIgnore = m_ignoreCurrentIndexChange; + m_ignoreCurrentIndexChange = true; QTextBlock leftBlock = m_leftEditor->document()->findBlockByNumber(blockNumber); QTextCursor leftCursor = m_leftEditor->textCursor(); leftCursor.setPosition(leftBlock.position()); @@ -901,6 +929,7 @@ void SideBySideDiffEditorWidget::setCurrentDiffFileIndex(int diffFileIndex) m_leftEditor->centerCursor(); m_rightEditor->centerCursor(); + m_ignoreCurrentIndexChange = oldIgnore; } void SideBySideDiffEditorWidget::showDiff() @@ -912,7 +941,10 @@ void SideBySideDiffEditorWidget::showDiff() clear(tr("No difference")); - QList<QPair<DiffEditorController::DiffFileInfo, QString> > leftDocs, rightDocs; + 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'); @@ -920,68 +952,151 @@ void SideBySideDiffEditorWidget::showDiff() QString leftText, rightText; const FileData &contextFileData = m_contextFileData.at(i); - int leftLineNumber = 0; - int rightLineNumber = 0; + leftFormats[blockNumber].append(DiffSelection(&m_fileLineFormat)); + rightFormats[blockNumber].append(DiffSelection(&m_fileLineFormat)); m_leftEditor->setFileInfo(blockNumber, contextFileData.leftFileInfo); m_rightEditor->setFileInfo(blockNumber, contextFileData.rightFileInfo); leftText = separator; rightText = separator; blockNumber++; - for (int j = 0; j < contextFileData.chunks.count(); j++) { - ChunkData chunkData = contextFileData.chunks.at(j); - if (chunkData.contextChunk) { - const int skippedLines = chunkData.rows.count(); - m_leftEditor->setSkippedLines(blockNumber, skippedLines); - m_rightEditor->setSkippedLines(blockNumber, skippedLines); - leftText += separator; - rightText += separator; - blockNumber++; - } + int lastLeftLineNumber = -1; - for (int k = 0; k < chunkData.rows.count(); k++) { - RowData rowData = chunkData.rows.at(k); - TextLineData leftLineData = rowData.leftLine; - TextLineData rightLineData = rowData.rightLine; - if (leftLineData.textLineType == TextLineData::TextLine) { - leftText += leftLineData.text; - leftLineNumber++; - m_leftEditor->setLineNumber(blockNumber, leftLineNumber); - } else if (leftLineData.textLineType == TextLineData::Separator) { - m_leftEditor->setSeparator(blockNumber, true); + if (contextFileData.binaryFiles) { + leftFormats[blockNumber].append(DiffSelection(&m_chunkLineFormat)); + rightFormats[blockNumber].append(DiffSelection(&m_chunkLineFormat)); + m_leftEditor->setSkippedLines(blockNumber, -2); + m_rightEditor->setSkippedLines(blockNumber, -2); + leftText += separator; + rightText += separator; + blockNumber++; + } else { + for (int j = 0; j < contextFileData.chunks.count(); j++) { + ChunkData chunkData = contextFileData.chunks.at(j); + + int leftLineNumber = chunkData.leftStartingLineNumber; + int rightLineNumber = chunkData.rightStartingLineNumber; + + if (!chunkData.contextChunk) { + const int skippedLines = leftLineNumber - lastLeftLineNumber - 1; + if (skippedLines > 0) { + leftFormats[blockNumber].append(DiffSelection(&m_chunkLineFormat)); + rightFormats[blockNumber].append(DiffSelection(&m_chunkLineFormat)); + m_leftEditor->setSkippedLines(blockNumber, skippedLines); + m_rightEditor->setSkippedLines(blockNumber, skippedLines); + leftText += separator; + rightText += separator; + blockNumber++; + } + + m_leftEditor->setChunkIndex(blockNumber, chunkData.rows.count(), j); + m_rightEditor->setChunkIndex(blockNumber, chunkData.rows.count(), j); + + for (int k = 0; k < chunkData.rows.count(); k++) { + RowData rowData = chunkData.rows.at(k); + TextLineData leftLineData = rowData.leftLine; + TextLineData rightLineData = rowData.rightLine; + if (leftLineData.textLineType == TextLineData::TextLine) { + leftText += leftLineData.text; + lastLeftLineNumber = leftLineNumber; + leftLineNumber++; + m_leftEditor->setLineNumber(blockNumber, leftLineNumber); + } else if (leftLineData.textLineType == TextLineData::Separator) { + m_leftEditor->setSeparator(blockNumber, true); + } + + if (rightLineData.textLineType == TextLineData::TextLine) { + rightText += rightLineData.text; + rightLineNumber++; + m_rightEditor->setLineNumber(blockNumber, rightLineNumber); + } else if (rightLineData.textLineType == TextLineData::Separator) { + m_rightEditor->setSeparator(blockNumber, true); + } + + if (!rowData.equal) { + if (rowData.leftLine.textLineType == TextLineData::TextLine) + leftFormats[blockNumber].append(DiffSelection(&m_leftLineFormat)); + else + leftFormats[blockNumber].append(DiffSelection(&m_spanLineFormat)); + if (rowData.rightLine.textLineType == TextLineData::TextLine) + rightFormats[blockNumber].append(DiffSelection(&m_rightLineFormat)); + else + rightFormats[blockNumber].append(DiffSelection(&m_spanLineFormat)); + } + + QMapIterator<int, int> itLeft(leftLineData.changedPositions); + while (itLeft.hasNext()) { + itLeft.next(); + leftFormats[blockNumber].append( + DiffSelection(itLeft.key(), itLeft.value(), + &m_leftCharFormat)); + } + + QMapIterator<int, int> itRight(rightLineData.changedPositions); + while (itRight.hasNext()) { + itRight.next(); + rightFormats[blockNumber].append( + DiffSelection(itRight.key(), itRight.value(), + &m_rightCharFormat)); + } + + leftText += separator; + rightText += separator; + blockNumber++; + } } - if (rightLineData.textLineType == TextLineData::TextLine) { - rightText += rightLineData.text; - rightLineNumber++; - m_rightEditor->setLineNumber(blockNumber, rightLineNumber); - } else if (rightLineData.textLineType == TextLineData::Separator) { - m_rightEditor->setSeparator(blockNumber, true); + if (j == contextFileData.chunks.count() - 1) { // the last chunk + int skippedLines = -2; + if (chunkData.contextChunk) { + // if it's context chunk + skippedLines = chunkData.rows.count(); + } else if (!contextFileData.lastChunkAtTheEndOfFile + && !contextFileData.contextChunksIncluded) { + // if not a context chunk and not a chunk at the end of file + // and context lines not included + skippedLines = -1; // unknown count skipped by the end of file + } + + if (skippedLines >= -1) { + leftFormats[blockNumber].append(DiffSelection(&m_chunkLineFormat)); + rightFormats[blockNumber].append(DiffSelection(&m_chunkLineFormat)); + m_leftEditor->setSkippedLines(blockNumber, skippedLines); + m_rightEditor->setSkippedLines(blockNumber, skippedLines); + leftText += separator; + rightText += separator; + blockNumber++; + } // otherwise nothing skipped } - leftText += separator; - rightText += separator; - blockNumber++; } } leftText.replace(QLatin1Char('\r'), QLatin1Char(' ')); rightText.replace(QLatin1Char('\r'), QLatin1Char(' ')); leftTexts += leftText; rightTexts += rightText; - leftDocs.append(qMakePair(contextFileData.leftFileInfo, leftText)); - rightDocs.append(qMakePair(contextFileData.rightFileInfo, 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); +// m_leftEditor->setDocuments(leftDocs); +// m_rightEditor->setDocuments(rightDocs); + const bool oldIgnore = m_ignoreCurrentIndexChange; + m_ignoreCurrentIndexChange = true; + m_leftEditor->clear(); m_leftEditor->setPlainText(leftTexts); + m_rightEditor->clear(); m_rightEditor->setPlainText(rightTexts); + m_ignoreCurrentIndexChange = oldIgnore; - colorDiff(m_contextFileData); + 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++) { @@ -1033,134 +1148,38 @@ void SideBySideDiffEditorWidget::showDiff() rightLayout->emitDocumentSizeChanged(); } m_foldingBlocker = false; - +*/ m_leftEditor->verticalScrollBar()->setValue(verticalValue); m_rightEditor->verticalScrollBar()->setValue(verticalValue); m_leftEditor->horizontalScrollBar()->setValue(leftHorizontalValue); m_rightEditor->horizontalScrollBar()->setValue(rightHorizontalValue); - m_leftEditor->updateFoldingHighlight(QPoint(-1, -1)); - m_rightEditor->updateFoldingHighlight(QPoint(-1, -1)); -} - -void SideBySideDiffEditorWidget::colorDiff(const QList<FileData> &fileDataList) -{ - QPalette pal = m_leftEditor->extraArea()->palette(); - pal.setCurrentColorGroup(QPalette::Active); - QTextCharFormat spanLineFormat; - spanLineFormat.setBackground(pal.color(QPalette::Background)); - spanLineFormat.setProperty(QTextFormat::FullWidthSelection, true); - - int leftPos = 0; - int rightPos = 0; - // <start position, end position> - QMap<int, int> leftLinePos; - QMap<int, int> rightLinePos; - QMap<int, int> leftCharPos; - QMap<int, int> rightCharPos; - QMap<int, int> leftSkippedPos; - QMap<int, int> rightSkippedPos; - QMap<int, int> leftChunkPos; - QMap<int, int> rightChunkPos; - QMap<int, int> leftFilePos; - QMap<int, int> rightFilePos; - int leftLastDiffBlockStartPos = 0; - int rightLastDiffBlockStartPos = 0; - int leftLastSkippedBlockStartPos = 0; - int rightLastSkippedBlockStartPos = 0; - - for (int i = 0; i < fileDataList.count(); i++) { - const FileData &fileData = fileDataList.at(i); - leftFilePos[leftPos] = leftPos + 1; - rightFilePos[rightPos] = rightPos + 1; - leftPos++; // for file line - rightPos++; // for file line - - for (int j = 0; j < fileData.chunks.count(); j++) { - const ChunkData &chunkData = fileData.chunks.at(j); - if (chunkData.contextChunk) { - leftChunkPos[leftPos] = leftPos + 1; - rightChunkPos[rightPos] = rightPos + 1; - leftPos++; // for chunk line - rightPos++; // for chunk line - } - leftLastDiffBlockStartPos = leftPos; - rightLastDiffBlockStartPos = rightPos; - leftLastSkippedBlockStartPos = leftPos; - rightLastSkippedBlockStartPos = rightPos; - - for (int k = 0; k < chunkData.rows.count(); k++) { - const RowData &rowData = chunkData.rows.at(k); - - addChangedPositions(leftPos, rowData.leftLine.changedPositions, &leftCharPos); - addChangedPositions(rightPos, rowData.rightLine.changedPositions, &rightCharPos); - - leftPos += rowData.leftLine.text.count() + 1; // +1 for '\n' - rightPos += rowData.rightLine.text.count() + 1; // +1 for '\n' - - if (!rowData.equal) { - if (rowData.leftLine.textLineType == TextLineData::TextLine) { - leftLinePos[leftLastDiffBlockStartPos] = leftPos; - leftLastSkippedBlockStartPos = leftPos; - } else { - leftSkippedPos[leftLastSkippedBlockStartPos] = leftPos; - leftLastDiffBlockStartPos = leftPos; - } - if (rowData.rightLine.textLineType == TextLineData::TextLine) { - rightLinePos[rightLastDiffBlockStartPos] = rightPos; - rightLastSkippedBlockStartPos = rightPos; - } else { - rightSkippedPos[rightLastSkippedBlockStartPos] = rightPos; - rightLastDiffBlockStartPos = rightPos; - } - } else { - leftLastDiffBlockStartPos = leftPos; - leftLastSkippedBlockStartPos = leftPos; - rightLastDiffBlockStartPos = rightPos; - rightLastSkippedBlockStartPos = rightPos; - } - } - } - } - - QTextCursor leftCursor = m_leftEditor->textCursor(); - QTextCursor rightCursor = m_rightEditor->textCursor(); - QList<QTextEdit::ExtraSelection> leftSelections; - leftSelections += colorPositions(m_leftLineFormat, leftCursor, leftLinePos); - leftSelections += colorPositions(m_leftCharFormat, leftCursor, leftCharPos); - leftSelections += colorPositions(spanLineFormat, leftCursor, leftSkippedPos); - leftSelections += colorPositions(m_chunkLineFormat, leftCursor, leftChunkPos); - leftSelections += colorPositions(m_fileLineFormat, leftCursor, leftFilePos); - - QList<QTextEdit::ExtraSelection> rightSelections; - rightSelections += colorPositions(m_rightLineFormat, rightCursor, rightLinePos); - rightSelections += colorPositions(m_rightCharFormat, rightCursor, rightCharPos); - rightSelections += colorPositions(spanLineFormat, rightCursor, rightSkippedPos); - rightSelections += colorPositions(m_chunkLineFormat, rightCursor, rightChunkPos); - rightSelections += colorPositions(m_fileLineFormat, rightCursor, rightFilePos); - - m_leftEditor->setExtraSelections(BaseTextEditorWidget::OtherSelection, leftSelections); - m_rightEditor->setExtraSelections(BaseTextEditorWidget::OtherSelection, rightSelections); +// m_leftEditor->updateFoldingHighlight(QPoint(-1, -1)); +// m_rightEditor->updateFoldingHighlight(QPoint(-1, -1)); } -void SideBySideDiffEditorWidget::setFontSettings(const TextEditor::FontSettings &fontSettings) +void SideBySideDiffEditorWidget::setFontSettings( + const TextEditor::FontSettings &fontSettings) { m_leftEditor->baseTextDocument()->setFontSettings(fontSettings); m_rightEditor->baseTextDocument()->setFontSettings(fontSettings); - m_fileLineFormat = fullWidthFormatForTextStyle(fontSettings, C_DIFF_FILE_LINE); - m_chunkLineFormat = fullWidthFormatForTextStyle(fontSettings, C_DIFF_CONTEXT_LINE); - m_leftLineFormat = fullWidthFormatForTextStyle(fontSettings, C_DIFF_SOURCE_LINE); - m_leftCharFormat = fullWidthFormatForTextStyle(fontSettings, C_DIFF_SOURCE_CHAR); - m_rightLineFormat = fullWidthFormatForTextStyle(fontSettings, C_DIFF_DEST_LINE); - m_rightCharFormat = fullWidthFormatForTextStyle(fontSettings, C_DIFF_DEST_CHAR); + m_spanLineFormat = fontSettings.toTextCharFormat(C_LINE_NUMBER); + m_fileLineFormat = fontSettings.toTextCharFormat(C_DIFF_FILE_LINE); + m_chunkLineFormat = fontSettings.toTextCharFormat(C_DIFF_CONTEXT_LINE); + m_leftLineFormat = fontSettings.toTextCharFormat(C_DIFF_SOURCE_LINE); + m_leftCharFormat = fontSettings.toTextCharFormat(C_DIFF_SOURCE_CHAR); + m_rightLineFormat = fontSettings.toTextCharFormat(C_DIFF_DEST_LINE); + m_rightCharFormat = fontSettings.toTextCharFormat(C_DIFF_DEST_CHAR); - colorDiff(m_contextFileData); + m_leftEditor->update(); + m_rightEditor->update(); } -void SideBySideDiffEditorWidget::slotLeftJumpToOriginalFileRequested(int diffFileIndex, - int lineNumber, - int columnNumber) +void SideBySideDiffEditorWidget::slotLeftJumpToOriginalFileRequested( + int diffFileIndex, + int lineNumber, + int columnNumber) { if (diffFileIndex < 0 || diffFileIndex >= m_contextFileData.count()) return; @@ -1196,8 +1215,10 @@ void SideBySideDiffEditorWidget::slotLeftJumpToOriginalFileRequested(int diffFil } } -void SideBySideDiffEditorWidget::slotRightJumpToOriginalFileRequested(int diffFileIndex, - int lineNumber, int columnNumber) +void SideBySideDiffEditorWidget::slotRightJumpToOriginalFileRequested( + int diffFileIndex, + int lineNumber, + int columnNumber) { if (diffFileIndex < 0 || diffFileIndex >= m_contextFileData.count()) return; @@ -1218,26 +1239,188 @@ void SideBySideDiffEditorWidget::jumpToOriginalFile(const QString &fileName, Core::EditorManager::openEditorAt(absoluteFileName, lineNumber, columnNumber); } +void SideBySideDiffEditorWidget::slotLeftContextMenuRequested(QMenu *menu, + int diffFileIndex, + int chunkIndex) +{ + menu->addSeparator(); + QAction *sendChunkToCodePasterAction = + menu->addAction(tr("Send Chunk to CodePaster...")); + connect(sendChunkToCodePasterAction, SIGNAL(triggered()), + this, SLOT(slotSendChunkToCodePaster())); + menu->addSeparator(); + QAction *applyAction = menu->addAction(tr("Apply Chunk...")); + connect(applyAction, SIGNAL(triggered()), this, SLOT(slotApplyChunk())); + applyAction->setEnabled(false); + + m_contextMenuFileIndex = diffFileIndex; + m_contextMenuChunkIndex = chunkIndex; + + 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; + + emit m_controller->chunkActionsRequested(menu, diffFileIndex, chunkIndex); + + if (fileData.leftFileInfo.fileName == fileData.rightFileInfo.fileName) + return; + + applyAction->setEnabled(true); +} + +void SideBySideDiffEditorWidget::slotRightContextMenuRequested(QMenu *menu, + int diffFileIndex, + int chunkIndex) +{ + menu->addSeparator(); + QAction *sendChunkToCodePasterAction = + menu->addAction(tr("Send Chunk to CodePaster...")); + connect(sendChunkToCodePasterAction, SIGNAL(triggered()), + this, SLOT(slotSendChunkToCodePaster())); + menu->addSeparator(); + QAction *revertAction = menu->addAction(tr("Revert Chunk...")); + connect(revertAction, SIGNAL(triggered()), this, SLOT(slotRevertChunk())); + revertAction->setEnabled(false); + + m_contextMenuFileIndex = diffFileIndex; + m_contextMenuChunkIndex = chunkIndex; + + 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; + + emit m_controller->chunkActionsRequested(menu, diffFileIndex, chunkIndex); + + revertAction->setEnabled(true); +} + +void SideBySideDiffEditorWidget::slotSendChunkToCodePaster() +{ + 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()) + return; + + const QString patch = m_controller->makePatch(m_contextMenuFileIndex, + m_contextMenuChunkIndex, + false); + if (patch.isEmpty()) + return; + + // Retrieve service by soft dependency. + QObject *pasteService = + ExtensionSystem::PluginManager::getObjectByClassName( + QLatin1String("CodePaster::CodePasterService")); + if (pasteService) { + QMetaObject::invokeMethod(pasteService, "postText", + Q_ARG(QString, patch), + Q_ARG(QString, QLatin1String(DiffEditor::Constants::DIFF_EDITOR_MIMETYPE))); + } else { + QMessageBox::information(this, tr("Unable to Paste"), + tr("Code pasting services are not available.")); + } +} + +void SideBySideDiffEditorWidget::slotApplyChunk() +{ + patch(m_contextMenuFileIndex, m_contextMenuChunkIndex, false); +} + +void SideBySideDiffEditorWidget::slotRevertChunk() +{ + patch(m_contextMenuFileIndex, m_contextMenuChunkIndex, true); +} + +void SideBySideDiffEditorWidget::patch(int diffFileIndex, int chunkIndex, bool revert) +{ + if (!m_controller) + return; + + if (diffFileIndex < 0 || chunkIndex < 0) + return; + + if (diffFileIndex >= m_contextFileData.count()) + return; + + const FileData fileData = m_contextFileData.at(diffFileIndex); + if (chunkIndex >= fileData.chunks.count()) + return; + + const QString title = revert ? tr("Revert Chunk") : tr("Apply Chunk"); + const QString question = revert + ? tr("Would you like to revert the chunk?") + : tr("Would you like to apply the chunk?"); + if (QMessageBox::No == QMessageBox::question(this, title, + question, + QMessageBox::Yes + | QMessageBox::No)) { + return; + } + + const int strip = m_controller->workingDirectory().isEmpty() ? -1 : 0; + + const QString fileName = revert + ? fileData.rightFileInfo.fileName + : fileData.leftFileInfo.fileName; + + const QString workingDirectory = m_controller->workingDirectory().isEmpty() + ? QFileInfo(fileName).absolutePath() + : m_controller->workingDirectory(); + + const QString patch = m_controller->makePatch(diffFileIndex, chunkIndex, revert); + + if (patch.isEmpty()) + return; + + if (PatchTool::runPatch(Core::EditorManager::defaultTextCodec()->fromUnicode(patch), + workingDirectory, strip, revert)) + m_controller->requestReload(); +} + 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()); + 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()); + m_leftEditor->horizontalScrollBar()->setValue( + m_rightEditor->horizontalScrollBar()->value()); } void SideBySideDiffEditorWidget::leftCursorPositionChanged() @@ -1248,7 +1431,15 @@ void SideBySideDiffEditorWidget::leftCursorPositionChanged() if (!m_guiController) return; - m_guiController->setCurrentDiffFileIndex(m_leftEditor->fileIndexForBlockNumber(m_leftEditor->textCursor().blockNumber())); + if (m_ignoreCurrentIndexChange) + return; + + const bool oldIgnore = m_ignoreCurrentIndexChange; + m_ignoreCurrentIndexChange = true; + m_guiController->setCurrentDiffFileIndex( + m_leftEditor->fileIndexForBlockNumber( + m_leftEditor->textCursor().blockNumber())); + m_ignoreCurrentIndexChange = oldIgnore; } void SideBySideDiffEditorWidget::rightCursorPositionChanged() @@ -1259,9 +1450,18 @@ void SideBySideDiffEditorWidget::rightCursorPositionChanged() if (!m_guiController) return; - m_guiController->setCurrentDiffFileIndex(m_rightEditor->fileIndexForBlockNumber(m_rightEditor->textCursor().blockNumber())); + if (m_ignoreCurrentIndexChange) + return; + + const bool oldIgnore = m_ignoreCurrentIndexChange; + m_ignoreCurrentIndexChange = true; + m_guiController->setCurrentDiffFileIndex( + m_rightEditor->fileIndexForBlockNumber( + m_rightEditor->textCursor().blockNumber())); + m_ignoreCurrentIndexChange = oldIgnore; } +#if 0 void SideBySideDiffEditorWidget::leftDocumentSizeChanged() { synchronizeFoldings(m_leftEditor, m_rightEditor); @@ -1400,6 +1600,7 @@ void SideBySideDiffEditorWidget::synchronizeFoldings(SideDiffEditorWidget *sourc } m_foldingBlocker = false; } +#endif } // namespace DiffEditor |