From 01542eb2ec98bc8ac6db5d2af4b55c2dc8be7ba0 Mon Sep 17 00:00:00 2001 From: Alex Gutikov Date: Fri, 18 Feb 2022 16:57:14 +0300 Subject: [PATCH] PatchContent shows changes only for selected file if size of patch text exceeds configured limit. Added configuration option "Max patch size MiB". If size of patch text exceeds that limit - PatchContent splits it into per-file change and shows changes for each selected file separately. Otherwise - no changes, will be shown entire patch content. --- src/common.h | 1 + src/namespace_def.cpp | 1 + src/patchcontent.cpp | 39 ++++++++++++++++++++++++++++++++++++++- src/patchcontent.h | 10 ++++++++++ src/settings.ui | 39 ++++++++++++++++++++++++++++++++++++++- src/settingsimpl.cpp | 7 +++++++ src/settingsimpl.h | 1 + 7 files changed, 96 insertions(+), 2 deletions(-) diff --git a/src/common.h b/src/common.h index c01c5381..cb851543 100644 --- a/src/common.h +++ b/src/common.h @@ -213,6 +213,7 @@ namespace QGit { extern const QString ACT_GROUP_KEY; extern const QString ACT_TEXT_KEY; extern const QString ACT_FLAGS_KEY; + extern const QString MAX_PATCH_KEY; // settings default values extern const QString CMT_TEMPL_DEF; diff --git a/src/namespace_def.cpp b/src/namespace_def.cpp index 486d7e17..c6ba6bfd 100644 --- a/src/namespace_def.cpp +++ b/src/namespace_def.cpp @@ -174,6 +174,7 @@ const QString QGit::FLAGS_KEY = "flags"; const QString QGit::PATCH_DIR_KEY = "Patch/last_dir"; const QString QGit::FMT_P_OPT_KEY = "Patch/args"; const QString QGit::AM_P_OPT_KEY = "Patch/args_2"; +const QString QGit::MAX_PATCH_KEY = "max_patch_size_show_complete"; const QString QGit::EX_KEY = "Working_dir/exclude_file_path"; const QString QGit::EX_PER_DIR_KEY = "Working_dir/exclude_per_directory_file_name"; const QString QGit::CON_GEOM_KEY = "Console/geometry"; diff --git a/src/patchcontent.cpp b/src/patchcontent.cpp index 831d9506..5d338876 100644 --- a/src/patchcontent.cpp +++ b/src/patchcontent.cpp @@ -6,6 +6,8 @@ */ #include #include +#include +#include #include "common.h" #include "domain.h" #include "git.h" @@ -117,6 +119,8 @@ void PatchContent::clear() { matches.clear(); diffLoaded = false; seekTarget = !target.isEmpty(); + patchByFile.clear(); + patchStats.clear(); } void PatchContent::refresh() { @@ -188,6 +192,14 @@ void PatchContent::centerOnFileHeader(StateInfo& st) { target = st.fileName(); bool combined = (st.isMerge() && !st.allMergeFiles()); git->formatPatchFileHeader(&target, st.sha(), st.diffToSha(), combined, st.allMergeFiles()); + + auto it = patchByFile.constFind(target); + if (it != patchByFile.constEnd()) { + // If target is in the mapping + // then show per-file changesets. + setPlainText(it.value()); + } + seekTarget = !target.isEmpty(); if (seekTarget) seekTarget = !centerTarget(target); @@ -215,6 +227,20 @@ void PatchContent::typeWriterFontChanged() { setPlainText(toPlainText()); } +void PatchContent::parseDiff(const QString &data) { + + static const QString delim = "diff --"; + QStringList lst = data.split("\n" + delim, QString::SkipEmptyParts); + + patchStats = lst.takeFirst(); + + for (auto& item : lst) { + QString file_diff = delim + item; + QString first_line = QTextStream(&file_diff).readLine(); + patchByFile[first_line] = file_diff; + } +} + void PatchContent::processData(const QByteArray& fileChunk, int* prevLineNum) { QString newLines; @@ -286,7 +312,18 @@ void PatchContent::processData(const QByteArray& fileChunk, int* prevLineNum) { if (prevLineNum || document()->isEmpty()) { // use the faster setPlainText() - setPlainText(newLines); + QSettings settings; + if (double(newLines.size()) / (1024*1024) > settings.value(QGit::MAX_PATCH_KEY).toDouble()) { + // If patch size exceeds the limit + // editor will show changes for individual files. + parseDiff(newLines); + setPlainText(patchStats); + } else { + // If patch size fits the limit + // editor will show complete patch. + setPlainText(newLines); + } + moveCursor(QTextCursor::Start); } else { int topLine = cursorForPosition(QPoint(1, 1)).blockNumber(); diff --git a/src/patchcontent.h b/src/patchcontent.h index f9f1912f..3e445aa2 100644 --- a/src/patchcontent.h +++ b/src/patchcontent.h @@ -11,6 +11,7 @@ #include #include #include "common.h" +#include class Domain; class Git; @@ -63,6 +64,7 @@ public slots: void centerMatch(int id = 0); bool centerTarget(SCRef target); void processData(const QByteArray& data, int* prevLineNum = NULL); + void parseDiff(const QString& data); Git* git; DiffHighlighter* diffHighlighter; @@ -75,6 +77,14 @@ public slots: QString target; bool seekTarget; + // Mapping of first string of file changeset ("diff --git a/... b/...") + // to complete file changeset; + // empty if size of patch less than maxPatchSizeShowComplete. + QHash patchByFile; + // First section of patch text with changes stats; + // empty if size of patch less than maxPatchSizeShowComplete. + QString patchStats; + struct MatchSelection { int paraFrom; int indexFrom; diff --git a/src/settings.ui b/src/settings.ui index d5a35f85..97b670ea 100644 --- a/src/settings.ui +++ b/src/settings.ui @@ -7,7 +7,7 @@ 0 0 513 - 377 + 416 @@ -576,6 +576,27 @@ + + + + + + Max patch size MiB + + + Qt::PlainText + + + + + + + Bigger patches will be shown by-file + + + + + @@ -1683,6 +1704,22 @@ + + doubleSpinBoxMaxPatchSize + valueChanged(double) + settingsBase + doubleSpinBoxMaxPatchSize_valueChanged(double) + + + 20 + 20 + + + 20 + 20 + + + comboBoxGitConfigSource activated(int) diff --git a/src/settingsimpl.cpp b/src/settingsimpl.cpp index 3fd9621e..53c1fa25 100644 --- a/src/settingsimpl.cpp +++ b/src/settingsimpl.cpp @@ -66,6 +66,7 @@ SettingsImpl::SettingsImpl(QWidget* p, Git* g, int defTab) : QDialog(p), git(g) SCRef exPDir(set.value(EX_PER_DIR_KEY, EX_PER_DIR_DEF).toString()); SCRef tmplt(set.value(CMT_TEMPL_KEY, CMT_TEMPL_DEF).toString()); SCRef CMArgs(set.value(CMT_ARGS_KEY).toString()); + double MPOpt(set.value(MAX_PATCH_KEY).toDouble()); lineEditApplyPatchExtraOptions->setText(APOpt); lineEditFormatPatchExtraOptions->setText(FPOpt); @@ -77,6 +78,7 @@ SettingsImpl::SettingsImpl(QWidget* p, Git* g, int defTab) : QDialog(p), git(g) lineEditCommitExtraOptions->setText(CMArgs); lineEditTypeWriterFont->setText(TYPE_WRITER_FONT.toString()); lineEditTypeWriterFont->setCursorPosition(0); // font description could be long + doubleSpinBoxMaxPatchSize->setValue(MPOpt); comboBoxDoubleClickAction->setCurrentIndex(set.value(DCLICK_ACT_KEY).toUInt()); setupCodecsCombo(); @@ -346,6 +348,11 @@ void SettingsImpl::lineEditExternalDiffViewer_textChanged(const QString& s) { writeSetting(EXT_DIFF_KEY, s); } +void SettingsImpl::doubleSpinBoxMaxPatchSize_valueChanged(double d) { + + writeSetting(MAX_PATCH_KEY, d); +} + void SettingsImpl::lineEditExternalEditor_textChanged(const QString& s) { writeSetting(EXT_EDITOR_KEY, s); diff --git a/src/settingsimpl.h b/src/settingsimpl.h index c114320b..a8205ab8 100644 --- a/src/settingsimpl.h +++ b/src/settingsimpl.h @@ -44,6 +44,7 @@ protected slots: void lineEditExcludePerDir_textChanged(const QString& s); void lineEditTemplate_textChanged(const QString& s); void lineEditCommitExtraOptions_textChanged(const QString& s); + void doubleSpinBoxMaxPatchSize_valueChanged(double d); void comboBoxDoubleClickAction_activated(int i); void comboBoxCodecs_activated(int i); void comboBoxUserSrc_activated(int i);