summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLorenz Haas <lykurg@gmail.com>2014-06-26 00:00:08 +0200
committerLorenz Haas <lykurg@gmail.com>2014-07-09 09:39:36 +0200
commitae39a009083066fd7dd2435f0932bb4a81f38376 (patch)
treec83425b73b0f20b731a90e607c00d38e336f30ba
parent0e6609155f7e5231549ea7c003cbf8f31ca61be3 (diff)
downloadqt-creator-ae39a009083066fd7dd2435f0932bb4a81f38376.tar.gz
Beautifier: Format current file asynchronous
The formatting tool is now called asynchronous. Change-Id: I0415611655a584ba0275f4bccd065ea1182f83dc Reviewed-by: David Schulz <david.schulz@digia.com>
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstyle.cpp5
-rw-r--r--src/plugins/beautifier/artisticstyle/artisticstyle.h6
-rw-r--r--src/plugins/beautifier/beautifierplugin.cpp101
-rw-r--r--src/plugins/beautifier/beautifierplugin.h40
-rw-r--r--src/plugins/beautifier/clangformat/clangformat.cpp7
-rw-r--r--src/plugins/beautifier/clangformat/clangformat.h6
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustify.cpp5
-rw-r--r--src/plugins/beautifier/uncrustify/uncrustify.h6
8 files changed, 142 insertions, 34 deletions
diff --git a/src/plugins/beautifier/artisticstyle/artisticstyle.cpp b/src/plugins/beautifier/artisticstyle/artisticstyle.cpp
index 9ba0abd8d1..7aed71f288 100644
--- a/src/plugins/beautifier/artisticstyle/artisticstyle.cpp
+++ b/src/plugins/beautifier/artisticstyle/artisticstyle.cpp
@@ -59,8 +59,9 @@ namespace Beautifier {
namespace Internal {
namespace ArtisticStyle {
-ArtisticStyle::ArtisticStyle(QObject *parent) :
+ArtisticStyle::ArtisticStyle(BeautifierPlugin *parent) :
BeautifierAbstractTool(parent),
+ m_beautifierPlugin(parent),
m_settings(new ArtisticStyleSettings)
{
}
@@ -151,7 +152,7 @@ void ArtisticStyle::formatFile()
command.addOption(QLatin1String("%file"));
}
- BeautifierPlugin::formatCurrentFile(command);
+ m_beautifierPlugin->formatCurrentFile(command);
}
}
diff --git a/src/plugins/beautifier/artisticstyle/artisticstyle.h b/src/plugins/beautifier/artisticstyle/artisticstyle.h
index 630d4f376a..4217172fd4 100644
--- a/src/plugins/beautifier/artisticstyle/artisticstyle.h
+++ b/src/plugins/beautifier/artisticstyle/artisticstyle.h
@@ -38,6 +38,9 @@ QT_FORWARD_DECLARE_CLASS(QAction)
namespace Beautifier {
namespace Internal {
+
+class BeautifierPlugin;
+
namespace ArtisticStyle {
class ArtisticStyleSettings;
@@ -47,7 +50,7 @@ class ArtisticStyle : public BeautifierAbstractTool
Q_OBJECT
public:
- explicit ArtisticStyle(QObject *parent = 0);
+ explicit ArtisticStyle(BeautifierPlugin *parent = 0);
virtual ~ArtisticStyle();
bool initialize() QTC_OVERRIDE;
void updateActions(Core::IEditor *editor) QTC_OVERRIDE;
@@ -57,6 +60,7 @@ private slots:
void formatFile();
private:
+ BeautifierPlugin *m_beautifierPlugin;
QAction *m_formatFile;
ArtisticStyleSettings *m_settings;
};
diff --git a/src/plugins/beautifier/beautifierplugin.cpp b/src/plugins/beautifier/beautifierplugin.cpp
index 0aacfd8c79..5aae557785 100644
--- a/src/plugins/beautifier/beautifierplugin.cpp
+++ b/src/plugins/beautifier/beautifierplugin.cpp
@@ -30,7 +30,6 @@
#include "beautifierplugin.h"
#include "beautifierconstants.h"
-#include "command.h"
#include "artisticstyle/artisticstyle.h"
#include "clangformat/clangformat.h"
@@ -51,10 +50,12 @@
#include <texteditor/basetexteditor.h>
#include <texteditor/texteditorconstants.h>
#include <utils/fileutils.h>
+#include <utils/QtConcurrentTools>
#include <QAction>
#include <QDir>
#include <QFileInfo>
+#include <QFutureWatcher>
#include <QPlainTextEdit>
#include <QProcess>
#include <QScrollBar>
@@ -65,12 +66,17 @@
namespace Beautifier {
namespace Internal {
-BeautifierPlugin::BeautifierPlugin()
+BeautifierPlugin::BeautifierPlugin() :
+ m_asyncFormatMapper(new QSignalMapper)
{
+ connect(m_asyncFormatMapper, SIGNAL(mapped(QObject *)),
+ this, SLOT(formatCurrentFileContinue(QObject*)));
+ connect(this, SIGNAL(pipeError(QString)), this, SLOT(showError(QString)));
}
BeautifierPlugin::~BeautifierPlugin()
{
+ m_asyncFormatMapper->deleteLater();
}
bool BeautifierPlugin::initialize(const QStringList &arguments, QString *errorString)
@@ -119,7 +125,9 @@ void BeautifierPlugin::updateActions(Core::IEditor *editor)
m_tools.at(i)->updateActions(editor);
}
-QString BeautifierPlugin::format(const QString &text, const Command &command, const QString &fileName)
+// Use pipeError() instead of calling showError() because this function may run in another thread.
+QString BeautifierPlugin::format(const QString &text, const Command &command,
+ const QString &fileName, bool *timeout)
{
const QString executable = command.executable();
if (executable.isEmpty())
@@ -134,8 +142,8 @@ QString BeautifierPlugin::format(const QString &text, const Command &command, co
sourceFile.setAutoRemove(true);
sourceFile.write(text.toUtf8());
if (!sourceFile.finalize()) {
- showError(tr("Cannot create temporary file \"%1\": %2.")
- .arg(sourceFile.fileName()).arg(sourceFile.errorString()));
+ emit pipeError(tr("Cannot create temporary file \"%1\": %2.")
+ .arg(sourceFile.fileName()).arg(sourceFile.errorString()));
return QString();
}
@@ -144,19 +152,22 @@ QString BeautifierPlugin::format(const QString &text, const Command &command, co
QStringList options = command.options();
options.replaceInStrings(QLatin1String("%file"), sourceFile.fileName());
process.start(executable, options);
- if (!process.waitForFinished()) {
- showError(tr("Cannot call %1 or some other error occurred.").arg(executable));
+ if (!process.waitForFinished(5000)) {
+ if (timeout)
+ *timeout = true;
+ process.kill();
+ emit pipeError(tr("Cannot call %1 or some other error occurred.").arg(executable));
return QString();
}
const QByteArray output = process.readAllStandardError();
if (!output.isEmpty())
- showError(executable + QLatin1String(": ") + QString::fromUtf8(output));
+ emit pipeError(executable + QLatin1String(": ") + QString::fromUtf8(output));
// Read text back
Utils::FileReader reader;
if (!reader.fetch(sourceFile.fileName(), QIODevice::Text)) {
- showError(tr("Cannot read file \"%1\": %2.")
- .arg(sourceFile.fileName()).arg(reader.errorString()));
+ emit pipeError(tr("Cannot read file \"%1\": %2.")
+ .arg(sourceFile.fileName()).arg(reader.errorString()));
return QString();
}
return QString::fromUtf8(reader.data());
@@ -167,19 +178,23 @@ QString BeautifierPlugin::format(const QString &text, const Command &command, co
QStringList options = command.options();
options.replaceInStrings(QLatin1String("%file"), fileName);
process.start(executable, options);
- if (!process.waitForStarted()) {
- showError(tr("Cannot call %1 or some other error occurred.").arg(executable));
+ if (!process.waitForStarted(3000)) {
+ emit pipeError(tr("Cannot call %1 or some other error occurred.").arg(executable));
return QString();
}
process.write(text.toUtf8());
process.closeWriteChannel();
- if (!process.waitForFinished()) {
- showError(tr("Cannot call %1 or some other error occurred.").arg(executable));
+ if (!process.waitForFinished(5000)) {
+ if (timeout)
+ *timeout = true;
+ process.kill();
+ emit pipeError(tr("Cannot call %1 or some other error occurred.").arg(executable));
return QString();
}
- const QByteArray error = process.readAllStandardError();
- if (!error.isEmpty()) {
- showError(executable + QLatin1String(": ") + QString::fromUtf8(error));
+ const QByteArray errorText = process.readAllStandardError();
+ if (!errorText.isEmpty()) {
+ emit pipeError(QString::fromLatin1("%1: %2").arg(executable)
+ .arg(QString::fromUtf8(errorText)));
return QString();
}
@@ -198,9 +213,12 @@ QString BeautifierPlugin::format(const QString &text, const Command &command, co
void BeautifierPlugin::formatCurrentFile(const Command &command)
{
QPlainTextEdit *textEditor = 0;
+ QString filePath;
if (TextEditor::BaseTextEditor *editor
- = qobject_cast<TextEditor::BaseTextEditor *>(Core::EditorManager::currentEditor()))
+ = qobject_cast<TextEditor::BaseTextEditor *>(Core::EditorManager::currentEditor())) {
textEditor = qobject_cast<QPlainTextEdit *>(editor->editorWidget());
+ filePath = editor->document()->filePath();
+ }
if (!textEditor)
return;
@@ -208,8 +226,51 @@ void BeautifierPlugin::formatCurrentFile(const Command &command)
if (sourceData.isEmpty())
return;
- const QString formattedData = format(sourceData, command,
- Core::EditorManager::currentDocument()->filePath());
+ QFutureWatcher<FormatTask> *watcher = new QFutureWatcher<FormatTask>;
+ connect(textEditor->document(), SIGNAL(contentsChanged()), watcher, SLOT(cancel()));
+ connect(watcher, SIGNAL(finished()), m_asyncFormatMapper, SLOT(map()));
+ m_asyncFormatMapper->setMapping(watcher, watcher);
+ watcher->setFuture(QtConcurrent::run(&BeautifierPlugin::formatAsync, this,
+ FormatTask(textEditor, filePath, sourceData, command)));
+}
+
+void BeautifierPlugin::formatAsync(QFutureInterface<FormatTask> &future, FormatTask task)
+{
+ task.formattedData = format(task.sourceData, task.command, task.filePath, &task.timeout);
+ future.reportResult(task);
+}
+
+void BeautifierPlugin::formatCurrentFileContinue(QObject *watcher)
+{
+ QFutureWatcher<FormatTask> *futureWatcher = static_cast<QFutureWatcher<FormatTask>*>(watcher);
+ if (!futureWatcher) {
+ if (watcher)
+ watcher->deleteLater();
+ return;
+ }
+
+ if (futureWatcher->isCanceled()) {
+ showError(tr("File was modified."));
+ futureWatcher->deleteLater();
+ return;
+ }
+
+ const FormatTask task = futureWatcher->result();
+ futureWatcher->deleteLater();
+
+ if (task.timeout) {
+ showError(tr("Time out reached while formatting file %1.").arg(task.filePath));
+ return;
+ }
+
+ QPlainTextEdit *textEditor = task.editor;
+ if (!textEditor) {
+ showError(tr("File %1 was closed.").arg(task.filePath));
+ return;
+ }
+
+ const QString sourceData = textEditor->toPlainText();
+ const QString formattedData = task.formattedData;
if ((sourceData == formattedData) || formattedData.isEmpty())
return;
diff --git a/src/plugins/beautifier/beautifierplugin.h b/src/plugins/beautifier/beautifierplugin.h
index 42f5733988..c495dcb009 100644
--- a/src/plugins/beautifier/beautifierplugin.h
+++ b/src/plugins/beautifier/beautifierplugin.h
@@ -30,16 +30,39 @@
#ifndef BEAUTIFIER_BEAUTIFIER_H
#define BEAUTIFIER_BEAUTIFIER_H
+#include "command.h"
+
#include <extensionsystem/iplugin.h>
#include <utils/qtcoverride.h>
+#include <QFutureInterface>
+#include <QPlainTextEdit>
+#include <QSignalMapper>
+
namespace Core { class IEditor; }
namespace Beautifier {
namespace Internal {
class BeautifierAbstractTool;
-class Command;
+
+struct FormatTask
+{
+ FormatTask(QPlainTextEdit *_editor, const QString &_filePath, const QString &_sourceData,
+ const Command &_command) :
+ editor(_editor),
+ filePath(_filePath),
+ sourceData(_sourceData),
+ command(_command),
+ timeout(false) {}
+
+ QPointer<QPlainTextEdit> editor;
+ QString filePath;
+ QString sourceData;
+ Command command;
+ QString formattedData;
+ bool timeout;
+};
class BeautifierPlugin : public ExtensionSystem::IPlugin
{
@@ -53,20 +76,29 @@ public:
void extensionsInitialized() QTC_OVERRIDE;
ShutdownFlag aboutToShutdown() QTC_OVERRIDE;
- static QString format(const QString &text, const Command &command, const QString &fileName);
- static void formatCurrentFile(const Command &command);
- static void showError(const QString &error);
+ QString format(const QString &text, const Command &command, const QString &fileName,
+ bool *timeout = 0);
+ void formatCurrentFile(const Command &command);
+ void formatAsync(QFutureInterface<FormatTask> &future, FormatTask task);
static QString msgCannotGetConfigurationFile(const QString &command);
static QString msgFormatCurrentFile();
static QString msgFormatSelectedText();
static QString msgCommandPromptDialogTitle(const QString &command);
+public slots:
+ static void showError(const QString &error);
+
private slots:
void updateActions(Core::IEditor *editor = 0);
+ void formatCurrentFileContinue(QObject *watcher = 0);
+
+signals:
+ void pipeError(QString);
private:
QList<BeautifierAbstractTool *> m_tools;
+ QSignalMapper *m_asyncFormatMapper;
};
} // namespace Internal
diff --git a/src/plugins/beautifier/clangformat/clangformat.cpp b/src/plugins/beautifier/clangformat/clangformat.cpp
index dc980559f5..c1a90d2fe1 100644
--- a/src/plugins/beautifier/clangformat/clangformat.cpp
+++ b/src/plugins/beautifier/clangformat/clangformat.cpp
@@ -56,8 +56,9 @@ namespace Beautifier {
namespace Internal {
namespace ClangFormat {
-ClangFormat::ClangFormat(QObject *parent) :
+ClangFormat::ClangFormat(BeautifierPlugin *parent) :
BeautifierAbstractTool(parent),
+ m_beautifierPlugin(parent),
m_settings(new ClangFormatSettings)
{
}
@@ -107,7 +108,7 @@ QList<QObject *> ClangFormat::autoReleaseObjects()
void ClangFormat::formatFile()
{
- BeautifierPlugin::formatCurrentFile(command());
+ m_beautifierPlugin->formatCurrentFile(command());
}
void ClangFormat::formatSelectedText()
@@ -121,7 +122,7 @@ void ClangFormat::formatSelectedText()
if (tc.hasSelection()) {
const int offset = tc.selectionStart();
const int length = tc.selectionEnd() - offset;
- BeautifierPlugin::formatCurrentFile(command(offset, length));
+ m_beautifierPlugin->formatCurrentFile(command(offset, length));
} else if (m_settings->formatEntireFileFallback()) {
formatFile();
}
diff --git a/src/plugins/beautifier/clangformat/clangformat.h b/src/plugins/beautifier/clangformat/clangformat.h
index 6806cd7d08..e92d52cfdd 100644
--- a/src/plugins/beautifier/clangformat/clangformat.h
+++ b/src/plugins/beautifier/clangformat/clangformat.h
@@ -39,6 +39,9 @@ QT_FORWARD_DECLARE_CLASS(QAction)
namespace Beautifier {
namespace Internal {
+
+class BeautifierPlugin;
+
namespace ClangFormat {
class ClangFormatSettings;
@@ -48,7 +51,7 @@ class ClangFormat : public BeautifierAbstractTool
Q_OBJECT
public:
- explicit ClangFormat(QObject *parent = 0);
+ explicit ClangFormat(BeautifierPlugin *parent = 0);
virtual ~ClangFormat();
bool initialize() QTC_OVERRIDE;
void updateActions(Core::IEditor *editor) QTC_OVERRIDE;
@@ -59,6 +62,7 @@ private slots:
void formatSelectedText();
private:
+ BeautifierPlugin *m_beautifierPlugin;
QAction *m_formatFile;
QAction *m_formatRange;
ClangFormatSettings *m_settings;
diff --git a/src/plugins/beautifier/uncrustify/uncrustify.cpp b/src/plugins/beautifier/uncrustify/uncrustify.cpp
index 1db39853b2..595e981b15 100644
--- a/src/plugins/beautifier/uncrustify/uncrustify.cpp
+++ b/src/plugins/beautifier/uncrustify/uncrustify.cpp
@@ -59,8 +59,9 @@ namespace Beautifier {
namespace Internal {
namespace Uncrustify {
-Uncrustify::Uncrustify(QObject *parent) :
+Uncrustify::Uncrustify(BeautifierPlugin *parent) :
BeautifierAbstractTool(parent),
+ m_beautifierPlugin(parent),
m_settings(new UncrustifySettings)
{
}
@@ -142,7 +143,7 @@ void Uncrustify::formatFile()
command.addOption(QLatin1String("1-2"));
command.addOption(QLatin1String("-c"));
command.addOption(cfgFileName);
- BeautifierPlugin::formatCurrentFile(command);
+ m_beautifierPlugin->formatCurrentFile(command);
}
}
diff --git a/src/plugins/beautifier/uncrustify/uncrustify.h b/src/plugins/beautifier/uncrustify/uncrustify.h
index 7397380d0b..93dba09d27 100644
--- a/src/plugins/beautifier/uncrustify/uncrustify.h
+++ b/src/plugins/beautifier/uncrustify/uncrustify.h
@@ -38,6 +38,9 @@ QT_FORWARD_DECLARE_CLASS(QAction)
namespace Beautifier {
namespace Internal {
+
+class BeautifierPlugin;
+
namespace Uncrustify {
class UncrustifySettings;
@@ -47,7 +50,7 @@ class Uncrustify : public BeautifierAbstractTool
Q_OBJECT
public:
- explicit Uncrustify(QObject *parent = 0);
+ explicit Uncrustify(BeautifierPlugin *parent = 0);
virtual ~Uncrustify();
bool initialize() QTC_OVERRIDE;
void updateActions(Core::IEditor *editor) QTC_OVERRIDE;
@@ -57,6 +60,7 @@ private slots:
void formatFile();
private:
+ BeautifierPlugin *m_beautifierPlugin;
QAction *m_formatFile;
UncrustifySettings *m_settings;
};