diff options
author | Lorenz Haas <lykurg@gmail.com> | 2014-06-26 00:00:08 +0200 |
---|---|---|
committer | Lorenz Haas <lykurg@gmail.com> | 2014-07-09 09:39:36 +0200 |
commit | ae39a009083066fd7dd2435f0932bb4a81f38376 (patch) | |
tree | c83425b73b0f20b731a90e607c00d38e336f30ba /src | |
parent | 0e6609155f7e5231549ea7c003cbf8f31ca61be3 (diff) | |
download | qt-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>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/beautifier/artisticstyle/artisticstyle.cpp | 5 | ||||
-rw-r--r-- | src/plugins/beautifier/artisticstyle/artisticstyle.h | 6 | ||||
-rw-r--r-- | src/plugins/beautifier/beautifierplugin.cpp | 101 | ||||
-rw-r--r-- | src/plugins/beautifier/beautifierplugin.h | 40 | ||||
-rw-r--r-- | src/plugins/beautifier/clangformat/clangformat.cpp | 7 | ||||
-rw-r--r-- | src/plugins/beautifier/clangformat/clangformat.h | 6 | ||||
-rw-r--r-- | src/plugins/beautifier/uncrustify/uncrustify.cpp | 5 | ||||
-rw-r--r-- | src/plugins/beautifier/uncrustify/uncrustify.h | 6 |
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; }; |