UnifiedDiffEditor: Move showing diff into separate thread

Before, when all the data was finished, we called showDiff()
in main thread. This consisted of 2 parts:

1. Calculating some extra data and generating actual text
   for UnifiedDiffEditor out of input data.
2. Calling setPlainText() with generated text.

For a really big diffs this could freeze the main thread for a
couple of seconds. Like e.g. 05c35356ab
(initial Creator import) - it contained 7 million characters,
part 1. took about 500 ms and part 2. took about 2.5 seconds.

This two tasks are now done in separate thread.
However, since we can't call TextEditorWidget::setPlainText()
directly from non-GUI thread, we create a separate
TextDocument object in the worker thread, fill it with
generated diff input and move the TextDocument object
into the main thread as a result of async computation.
In main thread we replace TextDocument object of the
TextEditorWidget with the one generated in other thread.
This replacement is very fast.

Change-Id: I49a717ced1dc2d5b8946e0fd6bee244b25071f35
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
Jarek Kobus
2022-09-22 13:48:54 +02:00
parent 5c0cafa68e
commit 054d7d65d2
6 changed files with 206 additions and 39 deletions

View File

@@ -2,7 +2,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
#include "diffeditorplugin.h"
#include "diffeditor.h"
#include "diffeditorconstants.h"
#include "diffeditorcontroller.h"
#include "diffeditordocument.h"
@@ -24,10 +23,10 @@
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
#include "texteditor/texteditoractionhandler.h"
#include <utils/algorithm.h>
#include <utils/differ.h>
#include <utils/futuresynchronizer.h>
#include <utils/mapreduce.h>
#include <utils/qtcassert.h>
@@ -440,12 +439,14 @@ public:
QAction *m_diffCurrentFileAction = nullptr;
QAction *m_diffOpenFilesAction = nullptr;
DiffEditorFactory editorFactory;
DiffEditorServiceImpl service;
DiffEditorFactory m_editorFactory;
DiffEditorServiceImpl m_service;
FutureSynchronizer m_futureSynchronizer;
};
DiffEditorPluginPrivate::DiffEditorPluginPrivate()
{
m_futureSynchronizer.setCancelOnWait(true);
//register actions
ActionContainer *toolsContainer
= ActionManager::actionContainer(Core::Constants::M_TOOLS);
@@ -571,9 +572,17 @@ void DiffEditorPluginPrivate::diffExternalFiles()
document->reload();
}
static DiffEditorPlugin *s_instance = nullptr;
DiffEditorPlugin::DiffEditorPlugin()
{
s_instance = this;
}
DiffEditorPlugin::~DiffEditorPlugin()
{
delete d;
s_instance = nullptr;
}
bool DiffEditorPlugin::initialize(const QStringList &arguments, QString *errorMessage)
@@ -586,6 +595,13 @@ bool DiffEditorPlugin::initialize(const QStringList &arguments, QString *errorMe
return true;
}
void DiffEditorPlugin::addFuture(const QFuture<void> &future)
{
QTC_ASSERT(s_instance, return);
s_instance->d->m_futureSynchronizer.addFuture(future);
}
} // namespace Internal
} // namespace DiffEditor