forked from qt-creator/qt-creator
VcsBaseDiffEditorController: Get rid of VcsCommandResultProxy
The workaround with VcsCommandResultProxy, introduced in
0b1eaacabb
isn't needed anymore
since finished() and stdOutText() signals are now emitted
synchronously from the caller's thread.
Give a context object to watcher's finished handler.
Change-Id: I6608b7c2806fc0c18649ff40f91684e9eaa7b15d
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
This commit is contained in:
@@ -33,35 +33,6 @@ static void readPatch(QFutureInterface<QList<FileData>> &futureInterface,
|
|||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
|
|
||||||
// We need a way to disconnect from signals posted from different thread
|
|
||||||
// so that signals that are already posted from the other thread and not delivered
|
|
||||||
// yet will be ignored. Unfortunately, simple QObject::disconnect() doesn't
|
|
||||||
// work like that, since signals that are already posted and are awaiting
|
|
||||||
// to be delivered WILL BE delivered later, even after a call to QObject::disconnect().
|
|
||||||
// The delivery will happen when the control returns to the main event loop.
|
|
||||||
|
|
||||||
// This proxy class solves the above problem. Instead of a call to
|
|
||||||
// QObject::disconnect(), which would still deliver posted signals,
|
|
||||||
// we delete the proxy object immediately. In this way signals which are
|
|
||||||
// already posted and are awaiting to be delivered won't be delivered to the
|
|
||||||
// destroyed object.
|
|
||||||
|
|
||||||
// So the only reason for this proxy object is to be able to disconnect
|
|
||||||
// effectively from the signals posted from different threads.
|
|
||||||
|
|
||||||
class VcsCommandResultProxy : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
VcsCommandResultProxy(VcsCommand *command, VcsBaseDiffEditorControllerPrivate *target);
|
|
||||||
private:
|
|
||||||
void storeOutput(const QString &output);
|
|
||||||
void commandFinished(bool success);
|
|
||||||
|
|
||||||
VcsBaseDiffEditorControllerPrivate *m_target;
|
|
||||||
};
|
|
||||||
|
|
||||||
/////////////////////
|
|
||||||
|
|
||||||
class VcsBaseDiffEditorControllerPrivate
|
class VcsBaseDiffEditorControllerPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -71,7 +42,6 @@ public:
|
|||||||
void processingFinished();
|
void processingFinished();
|
||||||
void processDiff(const QString &patch);
|
void processDiff(const QString &patch);
|
||||||
void cancelReload();
|
void cancelReload();
|
||||||
void storeOutput(const QString &output);
|
|
||||||
void commandFinished(bool success);
|
void commandFinished(bool success);
|
||||||
|
|
||||||
VcsBaseDiffEditorController *q;
|
VcsBaseDiffEditorController *q;
|
||||||
@@ -83,37 +53,12 @@ public:
|
|||||||
QString m_output;
|
QString m_output;
|
||||||
QString m_displayName;
|
QString m_displayName;
|
||||||
QPointer<VcsCommand> m_command;
|
QPointer<VcsCommand> m_command;
|
||||||
QPointer<VcsCommandResultProxy> m_commandResultProxy;
|
|
||||||
QFutureWatcher<QList<FileData>> *m_processWatcher = nullptr;
|
QFutureWatcher<QList<FileData>> *m_processWatcher = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////
|
|
||||||
|
|
||||||
VcsCommandResultProxy::VcsCommandResultProxy(VcsCommand *command,
|
|
||||||
VcsBaseDiffEditorControllerPrivate *target)
|
|
||||||
: QObject(target->q)
|
|
||||||
, m_target(target)
|
|
||||||
{
|
|
||||||
connect(command, &VcsCommand::stdOutText,
|
|
||||||
this, &VcsCommandResultProxy::storeOutput);
|
|
||||||
connect(command, &VcsCommand::finished,
|
|
||||||
this, &VcsCommandResultProxy::commandFinished);
|
|
||||||
connect(command, &VcsCommand::destroyed,
|
|
||||||
this, &QObject::deleteLater);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VcsCommandResultProxy::storeOutput(const QString &output)
|
|
||||||
{
|
|
||||||
m_target->storeOutput(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VcsCommandResultProxy::commandFinished(bool success)
|
|
||||||
{
|
|
||||||
m_target->commandFinished(success);
|
|
||||||
}
|
|
||||||
|
|
||||||
VcsBaseDiffEditorControllerPrivate::~VcsBaseDiffEditorControllerPrivate()
|
VcsBaseDiffEditorControllerPrivate::~VcsBaseDiffEditorControllerPrivate()
|
||||||
{
|
{
|
||||||
|
delete m_command;
|
||||||
cancelReload();
|
cancelReload();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,8 +87,8 @@ void VcsBaseDiffEditorControllerPrivate::processDiff(const QString &patch)
|
|||||||
|
|
||||||
m_processWatcher = new QFutureWatcher<QList<FileData>>();
|
m_processWatcher = new QFutureWatcher<QList<FileData>>();
|
||||||
|
|
||||||
QObject::connect(m_processWatcher, &QFutureWatcher<QList<FileData>>::finished,
|
QObject::connect(m_processWatcher, &QFutureWatcherBase::finished,
|
||||||
[this] () { processingFinished(); } );
|
q, [this] { processingFinished(); });
|
||||||
|
|
||||||
m_processWatcher->setFuture(Utils::runAsync(&readPatch, patch));
|
m_processWatcher->setFuture(Utils::runAsync(&readPatch, patch));
|
||||||
|
|
||||||
@@ -153,14 +98,7 @@ void VcsBaseDiffEditorControllerPrivate::processDiff(const QString &patch)
|
|||||||
|
|
||||||
void VcsBaseDiffEditorControllerPrivate::cancelReload()
|
void VcsBaseDiffEditorControllerPrivate::cancelReload()
|
||||||
{
|
{
|
||||||
if (m_command) {
|
m_command.clear();
|
||||||
m_command->cancel();
|
|
||||||
m_command.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disconnect effectively, don't deliver already posted signals
|
|
||||||
if (m_commandResultProxy)
|
|
||||||
delete m_commandResultProxy.data();
|
|
||||||
|
|
||||||
if (m_processWatcher) {
|
if (m_processWatcher) {
|
||||||
// Cancel the running process without the further processingFinished()
|
// Cancel the running process without the further processingFinished()
|
||||||
@@ -173,24 +111,11 @@ void VcsBaseDiffEditorControllerPrivate::cancelReload()
|
|||||||
m_output = QString();
|
m_output = QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VcsBaseDiffEditorControllerPrivate::storeOutput(const QString &output)
|
|
||||||
{
|
|
||||||
m_output = output;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VcsBaseDiffEditorControllerPrivate::commandFinished(bool success)
|
void VcsBaseDiffEditorControllerPrivate::commandFinished(bool success)
|
||||||
{
|
{
|
||||||
if (m_command)
|
// Don't delete here, as it is called from command finished signal.
|
||||||
m_command.clear();
|
// Clear it only, as we may call runCommand() again from inside processCommandOutput overload.
|
||||||
|
m_command.clear();
|
||||||
// Prevent direct deletion of m_commandResultProxy inside the possible
|
|
||||||
// subsequent synchronous calls to cancelReload() [called e.g. by
|
|
||||||
// processCommandOutput() overload], since
|
|
||||||
// commandFinished() is called directly by the m_commandResultProxy.
|
|
||||||
// m_commandResultProxy is removed via deleteLater right after
|
|
||||||
// a call to this commandFinished() is finished
|
|
||||||
if (m_commandResultProxy)
|
|
||||||
m_commandResultProxy.clear();
|
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
cancelReload();
|
cancelReload();
|
||||||
@@ -198,7 +123,7 @@ void VcsBaseDiffEditorControllerPrivate::commandFinished(bool success)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
q->processCommandOutput(QString(m_output)); // pass a copy of m_output
|
q->processCommandOutput(m_output);
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
@@ -219,12 +144,16 @@ void VcsBaseDiffEditorController::runCommand(const QList<QStringList> &args, uns
|
|||||||
// processingFinished() notifications, as right after that
|
// processingFinished() notifications, as right after that
|
||||||
// we re-reload it from scratch. So no intermediate "Retrieving data failed."
|
// we re-reload it from scratch. So no intermediate "Retrieving data failed."
|
||||||
// and "Waiting for data..." will be shown.
|
// and "Waiting for data..." will be shown.
|
||||||
|
delete d->m_command;
|
||||||
d->cancelReload();
|
d->cancelReload();
|
||||||
|
|
||||||
d->m_command = VcsBaseClient::createVcsCommand(workingDirectory(), d->m_processEnvironment);
|
d->m_command = VcsBaseClient::createVcsCommand(workingDirectory(), d->m_processEnvironment);
|
||||||
d->m_command->setDisplayName(d->m_displayName);
|
d->m_command->setDisplayName(d->m_displayName);
|
||||||
d->m_command->setCodec(codec ? codec : EditorManager::defaultTextCodec());
|
d->m_command->setCodec(codec ? codec : EditorManager::defaultTextCodec());
|
||||||
d->m_commandResultProxy = new VcsCommandResultProxy(d->m_command.data(), d);
|
connect(d->m_command.data(), &VcsCommand::stdOutText,
|
||||||
|
this, [this](const QString &output) { d->m_output = output; });
|
||||||
|
connect(d->m_command.data(), &VcsCommand::finished,
|
||||||
|
this, [this](bool success) { d->commandFinished(success); });
|
||||||
d->m_command->addFlags(flags);
|
d->m_command->addFlags(flags);
|
||||||
|
|
||||||
for (const QStringList &arg : args) {
|
for (const QStringList &arg : args) {
|
||||||
@@ -283,5 +212,3 @@ void VcsBaseDiffEditorController::setProcessEnvironment(const Environment &value
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace VcsBase
|
} // namespace VcsBase
|
||||||
|
|
||||||
#include "vcsbasediffeditorcontroller.moc"
|
|
||||||
|
Reference in New Issue
Block a user