forked from qt-creator/qt-creator
DiffEditor: Use QtConcurrent invocation for async tasks
Change-Id: I06640837ffee830e60e8dd2a566f9388f8444010 Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
@@ -14,11 +14,10 @@ publication by Neil Fraser: http://neil.fraser.name/writing/diff/
|
|||||||
#include "utilstr.h"
|
#include "utilstr.h"
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QStringList>
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QPair>
|
#include <QPair>
|
||||||
#include <QFutureInterfaceBase>
|
#include <QRegularExpression>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
|
|
||||||
@@ -937,10 +936,9 @@ QString Diff::toString() const
|
|||||||
|
|
||||||
///////////////
|
///////////////
|
||||||
|
|
||||||
Differ::Differ(QFutureInterfaceBase *jobController)
|
Differ::Differ(const QFuture<void> &future)
|
||||||
: m_jobController(jobController)
|
: m_future(future)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<Diff> Differ::diff(const QString &text1, const QString &text2)
|
QList<Diff> Differ::diff(const QString &text1, const QString &text2)
|
||||||
@@ -1075,7 +1073,7 @@ QList<Diff> Differ::diffMyers(const QString &text1, const QString &text2)
|
|||||||
int kMinReverse = -D;
|
int kMinReverse = -D;
|
||||||
int kMaxReverse = D;
|
int kMaxReverse = D;
|
||||||
for (int d = 0; d <= D; d++) {
|
for (int d = 0; d <= D; d++) {
|
||||||
if (m_jobController && m_jobController->isCanceled()) {
|
if (m_future.isCanceled()) {
|
||||||
delete [] forwardV;
|
delete [] forwardV;
|
||||||
delete [] reverseV;
|
delete [] reverseV;
|
||||||
return QList<Diff>();
|
return QList<Diff>();
|
||||||
@@ -1193,17 +1191,10 @@ QList<Diff> Differ::diffNonCharMode(const QString &text1, const QString &text2)
|
|||||||
QString lastDelete;
|
QString lastDelete;
|
||||||
QString lastInsert;
|
QString lastInsert;
|
||||||
QList<Diff> newDiffList;
|
QList<Diff> newDiffList;
|
||||||
if (m_jobController) {
|
|
||||||
m_jobController->setProgressRange(0, diffList.count());
|
|
||||||
m_jobController->setProgressValue(0);
|
|
||||||
}
|
|
||||||
for (int i = 0; i <= diffList.count(); i++) {
|
for (int i = 0; i <= diffList.count(); i++) {
|
||||||
if (m_jobController) {
|
if (m_future.isCanceled()) {
|
||||||
if (m_jobController->isCanceled()) {
|
m_currentDiffMode = diffMode;
|
||||||
m_currentDiffMode = diffMode;
|
return {};
|
||||||
return QList<Diff>();
|
|
||||||
}
|
|
||||||
m_jobController->setProgressValue(i + 1);
|
|
||||||
}
|
}
|
||||||
const Diff diffItem = i < diffList.count()
|
const Diff diffItem = i < diffList.count()
|
||||||
? diffList.at(i)
|
? diffList.at(i)
|
||||||
|
|||||||
@@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
#include "utils_global.h"
|
#include "utils_global.h"
|
||||||
|
|
||||||
|
#include <QFuture>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
template <class K, class T>
|
template <class K, class T>
|
||||||
class QMap;
|
class QMap;
|
||||||
class QFutureInterfaceBase;
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
@@ -42,7 +42,7 @@ public:
|
|||||||
WordMode,
|
WordMode,
|
||||||
LineMode
|
LineMode
|
||||||
};
|
};
|
||||||
Differ(QFutureInterfaceBase *jobController = nullptr);
|
Differ(const QFuture<void> &future = {});
|
||||||
QList<Diff> diff(const QString &text1, const QString &text2);
|
QList<Diff> diff(const QString &text1, const QString &text2);
|
||||||
QList<Diff> unifiedDiff(const QString &text1, const QString &text2);
|
QList<Diff> unifiedDiff(const QString &text1, const QString &text2);
|
||||||
void setDiffMode(DiffMode mode);
|
void setDiffMode(DiffMode mode);
|
||||||
@@ -90,7 +90,7 @@ private:
|
|||||||
int subTextStart);
|
int subTextStart);
|
||||||
DiffMode m_diffMode = Differ::LineMode;
|
DiffMode m_diffMode = Differ::LineMode;
|
||||||
DiffMode m_currentDiffMode = Differ::LineMode;
|
DiffMode m_currentDiffMode = Differ::LineMode;
|
||||||
QFutureInterfaceBase *m_jobController = nullptr;
|
QFuture<void> m_future;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Utils
|
} // namespace Utils
|
||||||
|
|||||||
@@ -291,8 +291,8 @@ Core::IDocument::OpenResult DiffEditorDocument::open(QString *errorString, const
|
|||||||
return OpenResult::ReadError;
|
return OpenResult::ReadError;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ok = false;
|
const std::optional<QList<FileData>> fileDataList = DiffUtils::readPatch(patch);
|
||||||
QList<FileData> fileDataList = DiffUtils::readPatch(patch, &ok);
|
bool ok = fileDataList.has_value();
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
*errorString = Tr::tr("Could not parse patch file \"%1\". "
|
*errorString = Tr::tr("Could not parse patch file \"%1\". "
|
||||||
"The content is not of unified diff format.")
|
"The content is not of unified diff format.")
|
||||||
@@ -302,7 +302,7 @@ Core::IDocument::OpenResult DiffEditorDocument::open(QString *errorString, const
|
|||||||
emit temporaryStateChanged();
|
emit temporaryStateChanged();
|
||||||
setFilePath(filePath.absoluteFilePath());
|
setFilePath(filePath.absoluteFilePath());
|
||||||
setWorkingDirectory(filePath.absoluteFilePath());
|
setWorkingDirectory(filePath.absoluteFilePath());
|
||||||
setDiffFiles(fileDataList);
|
setDiffFiles(*fileDataList);
|
||||||
}
|
}
|
||||||
endReload(ok);
|
endReload(ok);
|
||||||
if (!ok && readResult == TextFileFormat::ReadEncodingError)
|
if (!ok && readResult == TextFileFormat::ReadEncodingError)
|
||||||
|
|||||||
@@ -47,13 +47,12 @@ public:
|
|||||||
m_ignoreWhitespace(ignoreWhitespace)
|
m_ignoreWhitespace(ignoreWhitespace)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void operator()(QFutureInterface<FileData> &futureInterface,
|
void operator()(QPromise<FileData> &promise, const ReloadInput &reloadInput) const
|
||||||
const ReloadInput &reloadInput) const
|
|
||||||
{
|
{
|
||||||
if (reloadInput.text[LeftSide] == reloadInput.text[RightSide])
|
if (reloadInput.text[LeftSide] == reloadInput.text[RightSide])
|
||||||
return; // We show "No difference" in this case, regardless if it's binary or not
|
return; // We show "No difference" in this case, regardless if it's binary or not
|
||||||
|
|
||||||
Differ differ(&futureInterface);
|
Differ differ(QFuture<void>(promise.future()));
|
||||||
|
|
||||||
FileData fileData;
|
FileData fileData;
|
||||||
if (!reloadInput.binaryFiles) {
|
if (!reloadInput.binaryFiles) {
|
||||||
@@ -85,7 +84,7 @@ public:
|
|||||||
fileData.fileInfo = reloadInput.fileInfo;
|
fileData.fileInfo = reloadInput.fileInfo;
|
||||||
fileData.fileOperation = reloadInput.fileOperation;
|
fileData.fileOperation = reloadInput.fileOperation;
|
||||||
fileData.binaryFiles = reloadInput.binaryFiles;
|
fileData.binaryFiles = reloadInput.binaryFiles;
|
||||||
futureInterface.reportResult(fileData);
|
promise.addResult(fileData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -115,7 +114,7 @@ DiffFilesController::DiffFilesController(IDocument *document)
|
|||||||
QList<std::optional<FileData>> *outputList = storage.activeStorage();
|
QList<std::optional<FileData>> *outputList = storage.activeStorage();
|
||||||
|
|
||||||
const auto setupDiff = [this](AsyncTask<FileData> &async, const ReloadInput &reloadInput) {
|
const auto setupDiff = [this](AsyncTask<FileData> &async, const ReloadInput &reloadInput) {
|
||||||
async.setAsyncCallData(DiffFile(ignoreWhitespace(), contextLineCount()), reloadInput);
|
async.setConcurrentCallData(DiffFile(ignoreWhitespace(), contextLineCount()), reloadInput);
|
||||||
async.setFutureSynchronizer(Internal::DiffEditorPlugin::futureSynchronizer());
|
async.setFutureSynchronizer(Internal::DiffEditorPlugin::futureSynchronizer());
|
||||||
};
|
};
|
||||||
const auto onDiffDone = [outputList](const AsyncTask<FileData> &async, int i) {
|
const auto onDiffDone = [outputList](const AsyncTask<FileData> &async, int i) {
|
||||||
@@ -771,13 +770,13 @@ void DiffEditor::Internal::DiffEditorPlugin::testMakePatch()
|
|||||||
|
|
||||||
QCOMPARE(result, patchText);
|
QCOMPARE(result, patchText);
|
||||||
|
|
||||||
bool ok;
|
const std::optional<QList<FileData>> resultList = DiffUtils::readPatch(result);
|
||||||
QList<FileData> resultList = DiffUtils::readPatch(result, &ok);
|
const bool ok = resultList.has_value();
|
||||||
|
|
||||||
QVERIFY(ok);
|
QVERIFY(ok);
|
||||||
QCOMPARE(resultList.count(), 1);
|
QCOMPARE(resultList->count(), 1);
|
||||||
for (int i = 0; i < resultList.count(); i++) {
|
for (int i = 0; i < resultList->count(); i++) {
|
||||||
const FileData &resultFileData = resultList.at(i);
|
const FileData &resultFileData = resultList->at(i);
|
||||||
QCOMPARE(resultFileData.fileInfo[LeftSide].fileName, fileName);
|
QCOMPARE(resultFileData.fileInfo[LeftSide].fileName, fileName);
|
||||||
QCOMPARE(resultFileData.fileInfo[RightSide].fileName, fileName);
|
QCOMPARE(resultFileData.fileInfo[RightSide].fileName, fileName);
|
||||||
QCOMPARE(resultFileData.chunks.count(), 1);
|
QCOMPARE(resultFileData.chunks.count(), 1);
|
||||||
@@ -1335,14 +1334,14 @@ void DiffEditor::Internal::DiffEditorPlugin::testReadPatch()
|
|||||||
QFETCH(QString, sourcePatch);
|
QFETCH(QString, sourcePatch);
|
||||||
QFETCH(QList<FileData>, fileDataList);
|
QFETCH(QList<FileData>, fileDataList);
|
||||||
|
|
||||||
bool ok;
|
const std::optional<QList<FileData>> result = DiffUtils::readPatch(sourcePatch);
|
||||||
const QList<FileData> &result = DiffUtils::readPatch(sourcePatch, &ok);
|
const bool ok = result.has_value();
|
||||||
|
|
||||||
QVERIFY(ok);
|
QVERIFY(ok);
|
||||||
QCOMPARE(result.count(), fileDataList.count());
|
QCOMPARE(result->count(), fileDataList.count());
|
||||||
for (int i = 0; i < fileDataList.count(); i++) {
|
for (int i = 0; i < fileDataList.count(); i++) {
|
||||||
const FileData &origFileData = fileDataList.at(i);
|
const FileData &origFileData = fileDataList.at(i);
|
||||||
const FileData &resultFileData = result.at(i);
|
const FileData &resultFileData = result->at(i);
|
||||||
QCOMPARE(resultFileData.fileInfo[LeftSide].fileName, origFileData.fileInfo[LeftSide].fileName);
|
QCOMPARE(resultFileData.fileInfo[LeftSide].fileName, origFileData.fileInfo[LeftSide].fileName);
|
||||||
QCOMPARE(resultFileData.fileInfo[LeftSide].typeInfo, origFileData.fileInfo[LeftSide].typeInfo);
|
QCOMPARE(resultFileData.fileInfo[LeftSide].typeInfo, origFileData.fileInfo[LeftSide].typeInfo);
|
||||||
QCOMPARE(resultFileData.fileInfo[RightSide].fileName, origFileData.fileInfo[RightSide].fileName);
|
QCOMPARE(resultFileData.fileInfo[RightSide].fileName, origFileData.fileInfo[RightSide].fileName);
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/differ.h>
|
#include <utils/differ.h>
|
||||||
|
|
||||||
#include <QFutureInterfaceBase>
|
#include <QFuture>
|
||||||
|
#include <QPromise>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
@@ -892,7 +893,7 @@ static FileData readDiffHeaderAndChunks(QStringView headerAndChunks, bool *ok)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static QList<FileData> readDiffPatch(QStringView patch, bool *ok, QFutureInterfaceBase *jobController)
|
static void readDiffPatch(QPromise<QList<FileData>> &promise, QStringView patch)
|
||||||
{
|
{
|
||||||
const QRegularExpression diffRegExp("(?:\\n|^)" // new line of the beginning of a patch
|
const QRegularExpression diffRegExp("(?:\\n|^)" // new line of the beginning of a patch
|
||||||
"(" // either
|
"(" // either
|
||||||
@@ -911,23 +912,20 @@ static QList<FileData> readDiffPatch(QStringView patch, bool *ok, QFutureInterfa
|
|||||||
")"); // end of or
|
")"); // end of or
|
||||||
|
|
||||||
bool readOk = false;
|
bool readOk = false;
|
||||||
|
|
||||||
QList<FileData> fileDataList;
|
QList<FileData> fileDataList;
|
||||||
|
|
||||||
QRegularExpressionMatch diffMatch = diffRegExp.match(patch);
|
QRegularExpressionMatch diffMatch = diffRegExp.match(patch);
|
||||||
if (diffMatch.hasMatch()) {
|
if (diffMatch.hasMatch()) {
|
||||||
readOk = true;
|
readOk = true;
|
||||||
int lastPos = -1;
|
int lastPos = -1;
|
||||||
do {
|
do {
|
||||||
if (jobController && jobController->isCanceled())
|
if (promise.isCanceled())
|
||||||
return {};
|
return;
|
||||||
|
|
||||||
int pos = diffMatch.capturedStart();
|
int pos = diffMatch.capturedStart();
|
||||||
if (lastPos >= 0) {
|
if (lastPos >= 0) {
|
||||||
QStringView headerAndChunks = patch.mid(lastPos, pos - lastPos);
|
QStringView headerAndChunks = patch.mid(lastPos, pos - lastPos);
|
||||||
|
|
||||||
const FileData fileData = readDiffHeaderAndChunks(headerAndChunks,
|
const FileData fileData = readDiffHeaderAndChunks(headerAndChunks, &readOk);
|
||||||
&readOk);
|
|
||||||
|
|
||||||
if (!readOk)
|
if (!readOk)
|
||||||
break;
|
break;
|
||||||
@@ -942,21 +940,15 @@ static QList<FileData> readDiffPatch(QStringView patch, bool *ok, QFutureInterfa
|
|||||||
if (readOk) {
|
if (readOk) {
|
||||||
QStringView headerAndChunks = patch.mid(lastPos, patch.size() - lastPos - 1);
|
QStringView headerAndChunks = patch.mid(lastPos, patch.size() - lastPos - 1);
|
||||||
|
|
||||||
const FileData fileData = readDiffHeaderAndChunks(headerAndChunks,
|
const FileData fileData = readDiffHeaderAndChunks(headerAndChunks, &readOk);
|
||||||
&readOk);
|
|
||||||
|
|
||||||
if (readOk)
|
if (readOk)
|
||||||
fileDataList.append(fileData);
|
fileDataList.append(fileData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok)
|
|
||||||
*ok = readOk;
|
|
||||||
|
|
||||||
if (!readOk)
|
if (!readOk)
|
||||||
return {};
|
return;
|
||||||
|
promise.addResult(fileDataList);
|
||||||
return fileDataList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The git diff patch format (ChangeFile, NewFile, DeleteFile)
|
// The git diff patch format (ChangeFile, NewFile, DeleteFile)
|
||||||
@@ -1203,7 +1195,7 @@ static bool detectFileData(QStringView patch, FileData *fileData, QStringView *r
|
|||||||
return detectIndexAndBinary(*remainingPatch, fileData, remainingPatch);
|
return detectIndexAndBinary(*remainingPatch, fileData, remainingPatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QList<FileData> readGitPatch(QStringView patch, bool *ok, QFutureInterfaceBase *jobController)
|
static void readGitPatch(QPromise<QList<FileData>> &promise, QStringView patch)
|
||||||
{
|
{
|
||||||
int position = -1;
|
int position = -1;
|
||||||
|
|
||||||
@@ -1221,13 +1213,12 @@ static QList<FileData> readGitPatch(QStringView patch, bool *ok, QFutureInterfac
|
|||||||
};
|
};
|
||||||
|
|
||||||
const QChar newLine('\n');
|
const QChar newLine('\n');
|
||||||
bool readOk = true;
|
|
||||||
|
|
||||||
QVector<PatchInfo> patches;
|
QVector<PatchInfo> patches;
|
||||||
const int count = startingPositions.size();
|
const int count = startingPositions.size();
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
if (jobController && jobController->isCanceled())
|
if (promise.isCanceled())
|
||||||
return {};
|
return;
|
||||||
|
|
||||||
const int diffStart = startingPositions.at(i);
|
const int diffStart = startingPositions.at(i);
|
||||||
const int diffEnd = (i < count - 1)
|
const int diffEnd = (i < count - 1)
|
||||||
@@ -1242,32 +1233,21 @@ static QList<FileData> readGitPatch(QStringView patch, bool *ok, QFutureInterfac
|
|||||||
|
|
||||||
FileData fileData;
|
FileData fileData;
|
||||||
QStringView remainingFileDiff;
|
QStringView remainingFileDiff;
|
||||||
readOk = detectFileData(fileDiff, &fileData, &remainingFileDiff);
|
if (!detectFileData(fileDiff, &fileData, &remainingFileDiff))
|
||||||
|
return;
|
||||||
if (!readOk)
|
|
||||||
break;
|
|
||||||
|
|
||||||
patches.append(PatchInfo { remainingFileDiff, fileData });
|
patches.append(PatchInfo { remainingFileDiff, fileData });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!readOk) {
|
promise.setProgressRange(0, patches.size());
|
||||||
if (ok)
|
|
||||||
*ok = readOk;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jobController)
|
|
||||||
jobController->setProgressRange(0, patches.size());
|
|
||||||
|
|
||||||
QList<FileData> fileDataList;
|
QList<FileData> fileDataList;
|
||||||
readOk = false;
|
bool readOk = false;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const auto &patchInfo : std::as_const(patches)) {
|
for (const auto &patchInfo : std::as_const(patches)) {
|
||||||
if (jobController) {
|
if (promise.isCanceled())
|
||||||
if (jobController->isCanceled())
|
return;
|
||||||
return {};
|
promise.setProgressValue(i++);
|
||||||
jobController->setProgressValue(i++);
|
|
||||||
}
|
|
||||||
|
|
||||||
FileData fileData = patchInfo.fileData;
|
FileData fileData = patchInfo.fileData;
|
||||||
if (!patchInfo.patch.isEmpty() || fileData.fileOperation == FileData::ChangeFile)
|
if (!patchInfo.patch.isEmpty() || fileData.fileOperation == FileData::ChangeFile)
|
||||||
@@ -1276,31 +1256,27 @@ static QList<FileData> readGitPatch(QStringView patch, bool *ok, QFutureInterfac
|
|||||||
readOk = true;
|
readOk = true;
|
||||||
|
|
||||||
if (!readOk)
|
if (!readOk)
|
||||||
break;
|
return;
|
||||||
|
|
||||||
fileDataList.append(fileData);
|
fileDataList.append(fileData);
|
||||||
}
|
}
|
||||||
|
promise.addResult(fileDataList);
|
||||||
if (ok)
|
|
||||||
*ok = readOk;
|
|
||||||
|
|
||||||
if (!readOk)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
return fileDataList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<FileData> DiffUtils::readPatch(const QString &patch, bool *ok,
|
std::optional<QList<FileData>> DiffUtils::readPatch(const QString &patch)
|
||||||
QFutureInterfaceBase *jobController)
|
|
||||||
{
|
{
|
||||||
bool readOk = false;
|
QPromise<QList<FileData>> promise;
|
||||||
|
promise.start();
|
||||||
|
readPatchWithPromise(promise, patch);
|
||||||
|
if (promise.future().resultCount() == 0)
|
||||||
|
return {};
|
||||||
|
return promise.future().result();
|
||||||
|
}
|
||||||
|
|
||||||
QList<FileData> fileDataList;
|
void DiffUtils::readPatchWithPromise(QPromise<QList<FileData>> &promise, const QString &patch)
|
||||||
|
{
|
||||||
if (jobController) {
|
promise.setProgressRange(0, 1);
|
||||||
jobController->setProgressRange(0, 1);
|
promise.setProgressValue(0);
|
||||||
jobController->setProgressValue(0);
|
|
||||||
}
|
|
||||||
QStringView croppedPatch = QStringView(patch);
|
QStringView croppedPatch = QStringView(patch);
|
||||||
// Crop e.g. "-- \n2.10.2.windows.1\n\n" at end of file
|
// Crop e.g. "-- \n2.10.2.windows.1\n\n" at end of file
|
||||||
const QRegularExpression formatPatchEndingRegExp("(\\n-- \\n\\S*\\n\\n$)");
|
const QRegularExpression formatPatchEndingRegExp("(\\n-- \\n\\S*\\n\\n$)");
|
||||||
@@ -1308,14 +1284,9 @@ QList<FileData> DiffUtils::readPatch(const QString &patch, bool *ok,
|
|||||||
if (match.hasMatch())
|
if (match.hasMatch())
|
||||||
croppedPatch = croppedPatch.left(match.capturedStart() + 1);
|
croppedPatch = croppedPatch.left(match.capturedStart() + 1);
|
||||||
|
|
||||||
fileDataList = readGitPatch(croppedPatch, &readOk, jobController);
|
readGitPatch(promise, croppedPatch);
|
||||||
if (!readOk)
|
if (promise.future().resultCount() == 0)
|
||||||
fileDataList = readDiffPatch(croppedPatch, &readOk, jobController);
|
readDiffPatch(promise, croppedPatch);
|
||||||
|
|
||||||
if (ok)
|
|
||||||
*ok = readOk;
|
|
||||||
|
|
||||||
return fileDataList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace DiffEditor
|
} // namespace DiffEditor
|
||||||
|
|||||||
@@ -14,7 +14,8 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QFutureInterfaceBase;
|
template <class T>
|
||||||
|
class QPromise;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Utils { class Diff; }
|
namespace Utils { class Diff; }
|
||||||
@@ -142,9 +143,8 @@ public:
|
|||||||
const QString &rightFileName,
|
const QString &rightFileName,
|
||||||
bool lastChunk = false);
|
bool lastChunk = false);
|
||||||
static QString makePatch(const QList<FileData> &fileDataList);
|
static QString makePatch(const QList<FileData> &fileDataList);
|
||||||
static QList<FileData> readPatch(const QString &patch,
|
static std::optional<QList<FileData>> readPatch(const QString &patch);
|
||||||
bool *ok = nullptr,
|
static void readPatchWithPromise(QPromise<QList<FileData>> &promise, const QString &patch);
|
||||||
QFutureInterfaceBase *jobController = nullptr);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace DiffEditor
|
} // namespace DiffEditor
|
||||||
|
|||||||
@@ -8,14 +8,8 @@
|
|||||||
#include "diffeditorplugin.h"
|
#include "diffeditorplugin.h"
|
||||||
#include "diffeditortr.h"
|
#include "diffeditortr.h"
|
||||||
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QScrollBar>
|
|
||||||
#include <QTextBlock>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
|
||||||
#include <coreplugin/find/highlightscrollbarcontroller.h>
|
#include <coreplugin/find/highlightscrollbarcontroller.h>
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/minisplitter.h>
|
#include <coreplugin/minisplitter.h>
|
||||||
#include <coreplugin/progressmanager/progressmanager.h>
|
#include <coreplugin/progressmanager/progressmanager.h>
|
||||||
|
|
||||||
@@ -29,6 +23,11 @@
|
|||||||
#include <utils/mathutils.h>
|
#include <utils/mathutils.h>
|
||||||
#include <utils/tooltip/tooltip.h>
|
#include <utils/tooltip/tooltip.h>
|
||||||
|
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
@@ -245,7 +244,7 @@ QString SideDiffEditorWidget::plainTextFromSelection(const QTextCursor &cursor)
|
|||||||
return TextDocument::convertToPlainText(text);
|
return TextDocument::convertToPlainText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
SideBySideDiffOutput SideDiffData::diffOutput(QFutureInterface<void> &fi, int progressMin,
|
SideBySideDiffOutput SideDiffData::diffOutput(QFutureInterfaceBase &fi, int progressMin,
|
||||||
int progressMax, const DiffEditorInput &input)
|
int progressMax, const DiffEditorInput &input)
|
||||||
{
|
{
|
||||||
SideBySideDiffOutput output;
|
SideBySideDiffOutput output;
|
||||||
@@ -914,19 +913,15 @@ void SideBySideDiffEditorWidget::showDiff()
|
|||||||
|
|
||||||
const DiffEditorInput input(&m_controller);
|
const DiffEditorInput input(&m_controller);
|
||||||
|
|
||||||
auto getDocument = [input](QFutureInterface<ShowResults> &futureInterface) {
|
auto getDocument = [input](QPromise<ShowResults> &promise) {
|
||||||
auto cleanup = qScopeGuard([&futureInterface] {
|
|
||||||
if (futureInterface.isCanceled())
|
|
||||||
futureInterface.reportCanceled();
|
|
||||||
});
|
|
||||||
const int firstPartMax = 20; // diffOutput is about 4 times quicker than filling document
|
const int firstPartMax = 20; // diffOutput is about 4 times quicker than filling document
|
||||||
const int leftPartMax = 60;
|
const int leftPartMax = 60;
|
||||||
const int rightPartMax = 100;
|
const int rightPartMax = 100;
|
||||||
futureInterface.setProgressRange(0, rightPartMax);
|
promise.setProgressRange(0, rightPartMax);
|
||||||
futureInterface.setProgressValue(0);
|
promise.setProgressValue(0);
|
||||||
QFutureInterface<void> fi = futureInterface;
|
QFutureInterfaceBase fi = QFutureInterfaceBase::get(promise.future());
|
||||||
const SideBySideDiffOutput output = SideDiffData::diffOutput(fi, 0, firstPartMax, input);
|
const SideBySideDiffOutput output = SideDiffData::diffOutput(fi, 0, firstPartMax, input);
|
||||||
if (futureInterface.isCanceled())
|
if (promise.isCanceled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ShowResult leftResult{TextDocumentPtr(new TextDocument("DiffEditor.SideDiffEditor")),
|
const ShowResult leftResult{TextDocumentPtr(new TextDocument("DiffEditor.SideDiffEditor")),
|
||||||
@@ -935,7 +930,7 @@ void SideBySideDiffEditorWidget::showDiff()
|
|||||||
output.side[RightSide].diffData, output.side[RightSide].selections};
|
output.side[RightSide].diffData, output.side[RightSide].selections};
|
||||||
const ShowResults result{leftResult, rightResult};
|
const ShowResults result{leftResult, rightResult};
|
||||||
|
|
||||||
auto propagateDocument = [&output, &fi](DiffSide side, const ShowResult &result,
|
auto propagateDocument = [&output, &promise](DiffSide side, const ShowResult &result,
|
||||||
int progressMin, int progressMax) {
|
int progressMin, int progressMax) {
|
||||||
// No need to store the change history
|
// No need to store the change history
|
||||||
result.textDocument->document()->setUndoRedoEnabled(false);
|
result.textDocument->document()->setUndoRedoEnabled(false);
|
||||||
@@ -952,8 +947,9 @@ void SideBySideDiffEditorWidget::showDiff()
|
|||||||
const QString package = output.side[side].diffText.mid(currentPos, packageSize);
|
const QString package = output.side[side].diffText.mid(currentPos, packageSize);
|
||||||
cursor.insertText(package);
|
cursor.insertText(package);
|
||||||
currentPos += package.size();
|
currentPos += package.size();
|
||||||
fi.setProgressValue(MathUtils::interpolateLinear(currentPos, 0, diffSize, progressMin, progressMax));
|
promise.setProgressValue(MathUtils::interpolateLinear(currentPos, 0, diffSize,
|
||||||
if (fi.isCanceled())
|
progressMin, progressMax));
|
||||||
|
if (promise.isCanceled())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -968,16 +964,16 @@ void SideBySideDiffEditorWidget::showDiff()
|
|||||||
};
|
};
|
||||||
|
|
||||||
propagateDocument(LeftSide, leftResult, firstPartMax, leftPartMax);
|
propagateDocument(LeftSide, leftResult, firstPartMax, leftPartMax);
|
||||||
if (fi.isCanceled())
|
if (promise.isCanceled())
|
||||||
return;
|
return;
|
||||||
propagateDocument(RightSide, rightResult, leftPartMax, rightPartMax);
|
propagateDocument(RightSide, rightResult, leftPartMax, rightPartMax);
|
||||||
if (fi.isCanceled())
|
if (promise.isCanceled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
futureInterface.reportResult(result);
|
promise.addResult(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
m_asyncTask->setAsyncCallData(getDocument);
|
m_asyncTask->setConcurrentCallData(getDocument);
|
||||||
m_asyncTask->start();
|
m_asyncTask->start();
|
||||||
ProgressManager::addTask(m_asyncTask->future(), Tr::tr("Rendering diff"), "DiffEditor");
|
ProgressManager::addTask(m_asyncTask->future(), Tr::tr("Rendering diff"), "DiffEditor");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#include "diffeditorwidgetcontroller.h"
|
#include "diffeditorwidgetcontroller.h"
|
||||||
#include "selectabletexteditorwidget.h" // TODO: we need DiffSelections here only
|
#include "selectabletexteditorwidget.h" // TODO: we need DiffSelections here only
|
||||||
|
|
||||||
#include <QFutureInterface>
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
namespace Core { class IContext; }
|
namespace Core { class IContext; }
|
||||||
@@ -23,6 +22,7 @@ class AsyncTask;
|
|||||||
}
|
}
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QFutureInterfaceBase;
|
||||||
class QMenu;
|
class QMenu;
|
||||||
class QSplitter;
|
class QSplitter;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
@@ -40,7 +40,7 @@ class SideBySideDiffOutput;
|
|||||||
class SideDiffData
|
class SideDiffData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static SideBySideDiffOutput diffOutput(QFutureInterface<void> &fi, int progressMin,
|
static SideBySideDiffOutput diffOutput(QFutureInterfaceBase &fi, int progressMin,
|
||||||
int progressMax, const DiffEditorInput &input);
|
int progressMax, const DiffEditorInput &input);
|
||||||
|
|
||||||
DiffChunkInfo m_chunkInfo;
|
DiffChunkInfo m_chunkInfo;
|
||||||
|
|||||||
@@ -8,23 +8,20 @@
|
|||||||
#include "diffeditorplugin.h"
|
#include "diffeditorplugin.h"
|
||||||
#include "diffeditortr.h"
|
#include "diffeditortr.h"
|
||||||
|
|
||||||
#include <QMenu>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QScrollBar>
|
|
||||||
#include <QTextBlock>
|
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/progressmanager/progressmanager.h>
|
#include <coreplugin/progressmanager/progressmanager.h>
|
||||||
|
|
||||||
#include <texteditor/fontsettings.h>
|
#include <texteditor/fontsettings.h>
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
#include <texteditor/textdocumentlayout.h>
|
|
||||||
#include <texteditor/texteditorsettings.h>
|
#include <texteditor/texteditorsettings.h>
|
||||||
|
|
||||||
#include <utils/asynctask.h>
|
#include <utils/asynctask.h>
|
||||||
#include <utils/mathutils.h>
|
#include <utils/mathutils.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/tooltip/tooltip.h>
|
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QTextBlock>
|
||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
@@ -48,10 +45,10 @@ UnifiedDiffEditorWidget::UnifiedDiffEditorWidget(QWidget *parent)
|
|||||||
connect(this, &QPlainTextEdit::cursorPositionChanged,
|
connect(this, &QPlainTextEdit::cursorPositionChanged,
|
||||||
this, &UnifiedDiffEditorWidget::slotCursorPositionChangedInEditor);
|
this, &UnifiedDiffEditorWidget::slotCursorPositionChangedInEditor);
|
||||||
|
|
||||||
auto context = new Core::IContext(this);
|
auto context = new IContext(this);
|
||||||
context->setWidget(this);
|
context->setWidget(this);
|
||||||
context->setContext(Core::Context(Constants::UNIFIED_VIEW_ID));
|
context->setContext(Context(Constants::UNIFIED_VIEW_ID));
|
||||||
Core::ICore::addContextObject(context);
|
ICore::addContextObject(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnifiedDiffEditorWidget::~UnifiedDiffEditorWidget() = default;
|
UnifiedDiffEditorWidget::~UnifiedDiffEditorWidget() = default;
|
||||||
@@ -391,7 +388,7 @@ QString UnifiedDiffData::setChunk(const DiffEditorInput &input, const ChunkData
|
|||||||
return diffText;
|
return diffText;
|
||||||
}
|
}
|
||||||
|
|
||||||
UnifiedDiffOutput UnifiedDiffData::diffOutput(QFutureInterface<void> &fi, int progressMin,
|
UnifiedDiffOutput UnifiedDiffData::diffOutput(QFutureInterfaceBase &fi, int progressMin,
|
||||||
int progressMax, const DiffEditorInput &input)
|
int progressMax, const DiffEditorInput &input)
|
||||||
{
|
{
|
||||||
UnifiedDiffOutput output;
|
UnifiedDiffOutput output;
|
||||||
@@ -481,18 +478,14 @@ void UnifiedDiffEditorWidget::showDiff()
|
|||||||
|
|
||||||
const DiffEditorInput input(&m_controller);
|
const DiffEditorInput input(&m_controller);
|
||||||
|
|
||||||
auto getDocument = [input](QFutureInterface<ShowResult> &futureInterface) {
|
auto getDocument = [input](QPromise<ShowResult> &promise) {
|
||||||
auto cleanup = qScopeGuard([&futureInterface] {
|
|
||||||
if (futureInterface.isCanceled())
|
|
||||||
futureInterface.reportCanceled();
|
|
||||||
});
|
|
||||||
const int progressMax = 100;
|
const int progressMax = 100;
|
||||||
const int firstPartMax = 20; // diffOutput is about 4 times quicker than filling document
|
const int firstPartMax = 20; // diffOutput is about 4 times quicker than filling document
|
||||||
futureInterface.setProgressRange(0, progressMax);
|
promise.setProgressRange(0, progressMax);
|
||||||
futureInterface.setProgressValue(0);
|
promise.setProgressValue(0);
|
||||||
QFutureInterface<void> fi = futureInterface;
|
QFutureInterfaceBase fi = QFutureInterfaceBase::get(promise.future());
|
||||||
const UnifiedDiffOutput output = UnifiedDiffData::diffOutput(fi, 0, firstPartMax, input);
|
const UnifiedDiffOutput output = UnifiedDiffData::diffOutput(fi, 0, firstPartMax, input);
|
||||||
if (futureInterface.isCanceled())
|
if (promise.isCanceled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const ShowResult result = {TextDocumentPtr(new TextDocument("DiffEditor.UnifiedDiffEditor")),
|
const ShowResult result = {TextDocumentPtr(new TextDocument("DiffEditor.UnifiedDiffEditor")),
|
||||||
@@ -512,8 +505,9 @@ void UnifiedDiffEditorWidget::showDiff()
|
|||||||
const QString package = output.diffText.mid(currentPos, packageSize);
|
const QString package = output.diffText.mid(currentPos, packageSize);
|
||||||
cursor.insertText(package);
|
cursor.insertText(package);
|
||||||
currentPos += package.size();
|
currentPos += package.size();
|
||||||
fi.setProgressValue(MathUtils::interpolateLinear(currentPos, 0, diffSize, firstPartMax, progressMax));
|
promise.setProgressValue(MathUtils::interpolateLinear(currentPos, 0, diffSize,
|
||||||
if (futureInterface.isCanceled())
|
firstPartMax, progressMax));
|
||||||
|
if (promise.isCanceled())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,10 +519,10 @@ void UnifiedDiffEditorWidget::showDiff()
|
|||||||
// to caller's thread. We push it to no thread (make object to have no thread affinity),
|
// to caller's thread. We push it to no thread (make object to have no thread affinity),
|
||||||
// and later, in the caller's thread, we pull it back to the caller's thread.
|
// and later, in the caller's thread, we pull it back to the caller's thread.
|
||||||
result.textDocument->moveToThread(nullptr);
|
result.textDocument->moveToThread(nullptr);
|
||||||
futureInterface.reportResult(result);
|
promise.addResult(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
m_asyncTask->setAsyncCallData(getDocument);
|
m_asyncTask->setConcurrentCallData(getDocument);
|
||||||
m_asyncTask->start();
|
m_asyncTask->start();
|
||||||
ProgressManager::addTask(m_asyncTask->future(), Tr::tr("Rendering diff"), "DiffEditor");
|
ProgressManager::addTask(m_asyncTask->future(), Tr::tr("Rendering diff"), "DiffEditor");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,6 @@
|
|||||||
#include "diffeditorwidgetcontroller.h"
|
#include "diffeditorwidgetcontroller.h"
|
||||||
#include "selectabletexteditorwidget.h"
|
#include "selectabletexteditorwidget.h"
|
||||||
|
|
||||||
#include <QFutureInterface>
|
|
||||||
|
|
||||||
namespace Core { class IContext; }
|
namespace Core { class IContext; }
|
||||||
|
|
||||||
namespace TextEditor { class FontSettings; }
|
namespace TextEditor { class FontSettings; }
|
||||||
@@ -17,6 +15,10 @@ template <typename R>
|
|||||||
class AsyncTask;
|
class AsyncTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QFutureInterfaceBase;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace DiffEditor {
|
namespace DiffEditor {
|
||||||
|
|
||||||
class ChunkData;
|
class ChunkData;
|
||||||
@@ -31,7 +33,7 @@ class UnifiedDiffOutput;
|
|||||||
class UnifiedDiffData
|
class UnifiedDiffData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static UnifiedDiffOutput diffOutput(QFutureInterface<void> &fi, int progressMin, int progressMax,
|
static UnifiedDiffOutput diffOutput(QFutureInterfaceBase &fi, int progressMin, int progressMax,
|
||||||
const DiffEditorInput &input);
|
const DiffEditorInput &input);
|
||||||
|
|
||||||
DiffChunkInfo m_chunkInfo;
|
DiffChunkInfo m_chunkInfo;
|
||||||
|
|||||||
@@ -15,15 +15,6 @@ using namespace Utils;
|
|||||||
|
|
||||||
namespace VcsBase {
|
namespace VcsBase {
|
||||||
|
|
||||||
static void readPatch(QFutureInterface<QList<FileData>> &futureInterface, const QString &patch)
|
|
||||||
{
|
|
||||||
bool ok;
|
|
||||||
const QList<FileData> &fileDataList = DiffUtils::readPatch(patch, &ok, &futureInterface);
|
|
||||||
futureInterface.reportResult(fileDataList);
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////
|
|
||||||
|
|
||||||
class VcsBaseDiffEditorControllerPrivate
|
class VcsBaseDiffEditorControllerPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -61,11 +52,11 @@ Tasking::TaskItem VcsBaseDiffEditorController::postProcessTask()
|
|||||||
QTC_ASSERT(storage, qWarning("Using postProcessTask() requires putting inputStorage() "
|
QTC_ASSERT(storage, qWarning("Using postProcessTask() requires putting inputStorage() "
|
||||||
"into task tree's root group."));
|
"into task tree's root group."));
|
||||||
const QString inputData = storage ? *storage : QString();
|
const QString inputData = storage ? *storage : QString();
|
||||||
async.setAsyncCallData(readPatch, inputData);
|
async.setConcurrentCallData(&DiffUtils::readPatchWithPromise, inputData);
|
||||||
async.setFutureSynchronizer(Internal::VcsPlugin::futureSynchronizer());
|
async.setFutureSynchronizer(Internal::VcsPlugin::futureSynchronizer());
|
||||||
};
|
};
|
||||||
const auto onDiffProcessorDone = [this](const AsyncTask<QList<FileData>> &async) {
|
const auto onDiffProcessorDone = [this](const AsyncTask<QList<FileData>> &async) {
|
||||||
setDiffFiles(async.result());
|
setDiffFiles(async.isResultAvailable() ? async.result() : QList<FileData>());
|
||||||
};
|
};
|
||||||
const auto onDiffProcessorError = [this](const AsyncTask<QList<FileData>> &) {
|
const auto onDiffProcessorError = [this](const AsyncTask<QList<FileData>> &) {
|
||||||
setDiffFiles({});
|
setDiffFiles({});
|
||||||
|
|||||||
Reference in New Issue
Block a user