diff --git a/src/plugins/texteditor/generichighlighter/definitiondownloader.cpp b/src/plugins/texteditor/generichighlighter/definitiondownloader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..373c16b92793c8212a53d03a74151a6cd7823cbc --- /dev/null +++ b/src/plugins/texteditor/generichighlighter/definitiondownloader.cpp @@ -0,0 +1,94 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "definitiondownloader.h" + +#include <QtCore/QLatin1Char> +#include <QtCore/QEventLoop> +#include <QtCore/QFile> +#include <QtNetwork/QNetworkAccessManager> +#include <QtNetwork/QNetworkRequest> +#include <QtNetwork/QNetworkReply> + +using namespace TextEditor; +using namespace Internal; + +DefinitionDownloader::DefinitionDownloader(const QUrl &url, const QString &localPath) : + m_url(url), m_localPath(localPath) +{} + +void DefinitionDownloader::start() +{ + QNetworkReply *reply; + QNetworkAccessManager manager; + + int currentAttempt = 0; + const int maxAttempts = 5; + while (currentAttempt < maxAttempts) { + reply = getData(&manager); + if (reply->error() != QNetworkReply::NoError) + break; + + ++currentAttempt; + QVariant variant = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (variant.isValid() && currentAttempt < maxAttempts) { + m_url = variant.toUrl(); + delete reply; + } else if (!variant.isValid()) { + saveData(reply); + break; + } + } + + delete reply; +} + +QNetworkReply *DefinitionDownloader::getData(QNetworkAccessManager *manager) const +{ + QNetworkRequest request(m_url); + QNetworkReply *reply = manager->get(request); + + QEventLoop eventLoop; + connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit())); + eventLoop.exec(); + + return reply; +} + +void DefinitionDownloader::saveData(QNetworkReply *reply) const +{ + const QString &urlPath = m_url.path(); + const QString &fileName = + urlPath.right(urlPath.length() - urlPath.lastIndexOf(QLatin1Char('/')) - 1); + QFile file(m_localPath + fileName); + if (!file.open(QIODevice::Text | QIODevice::WriteOnly)) + return; + file.write(reply->readAll()); + file.close(); +} diff --git a/src/plugins/texteditor/generichighlighter/definitiondownloader.h b/src/plugins/texteditor/generichighlighter/definitiondownloader.h new file mode 100644 index 0000000000000000000000000000000000000000..c2866183c75a65dfb862155a792ab58f8e9edfe7 --- /dev/null +++ b/src/plugins/texteditor/generichighlighter/definitiondownloader.h @@ -0,0 +1,75 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef DEFINITIONDOWNLOADER_H +#define DEFINITIONDOWNLOADER_H + +#include <QtCore/QObject> +#include <QtCore/QString> +#include <QtCore/QUrl> + +QT_BEGIN_NAMESPACE +class QNetworkReply; +class QNetworkAccessManager; +QT_END_NAMESPACE + +namespace TextEditor { +namespace Internal { + +class DefinitionDownloader : public QObject +{ + Q_OBJECT +public: + DefinitionDownloader(const QUrl &url, const QString &localPath); + + void start(); + +private: + QNetworkReply *getData(QNetworkAccessManager *manager) const; + void saveData(QNetworkReply *reply) const; + + QUrl m_url; + QString m_localPath; +}; + +// Currently QtConcurrent::map does not support passing member functions for sequence of pointers +// (only works for operator.*) which is the case for the downloaders held by the manager. Then the +// reason for the following functor. If something is implemented (for example a type traits) to +// handle operator->* in QtConcurrent::map this functor will not be necessary since it would be +// possible to directly pass DefinitionDownloader::start. +struct DownloaderStarter +{ + void operator()(DefinitionDownloader *downloader) + { downloader->start(); } +}; + +} // namespace Internal +} // namespace TextEditor + +#endif // DEFINITIONDOWNLOADER_H diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp b/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp index c6a023aaf8afc9d5e9774ae0f4ef0d49436275a7..a157d944611df108f6ccd82af2e1c7845ebf5cd2 100644 --- a/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp +++ b/src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp @@ -437,6 +437,9 @@ void HighlightDefinitionHandler::processIncludeRules(const QSharedPointer<Contex const QSharedPointer<HighlightDefinition> &externalDefinition = Manager::instance()->definition(id); + if (externalDefinition.isNull()) + continue; + sourceContext = externalDefinition->initialContext(); } else if (!sourceName.startsWith(kHash)) { sourceContext = m_definition->context(sourceName); @@ -444,6 +447,8 @@ void HighlightDefinitionHandler::processIncludeRules(const QSharedPointer<Contex // Recursion is done only for context direct rules. Child rules are not processed // because they cannot be include rules. processIncludeRules(sourceContext); + } else { + continue; } if (instruction.replaceItemData()) { diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.cpp b/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.cpp new file mode 100644 index 0000000000000000000000000000000000000000..49e7e684978bb3599aab7fcc929655a2ac7286ab --- /dev/null +++ b/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.cpp @@ -0,0 +1,72 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "highlightdefinitionmetadata.h" + +using namespace TextEditor; +using namespace Internal; + +const QLatin1String HighlightDefinitionMetaData::kName("name"); +const QLatin1String HighlightDefinitionMetaData::kExtensions("extensions"); +const QLatin1String HighlightDefinitionMetaData::kMimeType("mimetype"); +const QLatin1String HighlightDefinitionMetaData::kVersion("version"); +const QLatin1String HighlightDefinitionMetaData::kUrl("url"); + +HighlightDefinitionMetaData::HighlightDefinitionMetaData() +{} + +void HighlightDefinitionMetaData::setName(const QString &name) +{ m_name = name; } + +const QString &HighlightDefinitionMetaData::name() const +{ return m_name; } + +void HighlightDefinitionMetaData::setVersion(const QString &version) +{ m_version = version; } + +const QString &HighlightDefinitionMetaData::version() const +{ return m_version; } + +void HighlightDefinitionMetaData::setPatterns(const QStringList &patterns) +{ m_patterns = patterns; } + +const QStringList &HighlightDefinitionMetaData::patterns() const +{ return m_patterns; } + +void HighlightDefinitionMetaData::setMimeTypes(const QStringList &mimeTypes) +{ m_mimeTypes = mimeTypes; } + +const QStringList &HighlightDefinitionMetaData::mimeTypes() const +{ return m_mimeTypes; } + +void HighlightDefinitionMetaData::setUrl(const QUrl &url) +{ m_url = url; } + +const QUrl &HighlightDefinitionMetaData::url() const +{ return m_url; } diff --git a/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.h b/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.h new file mode 100644 index 0000000000000000000000000000000000000000..2536104c26615157d8f65fba9de2f8dfb9befafa --- /dev/null +++ b/src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.h @@ -0,0 +1,78 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef HIGHLIGHTDEFINITIONMETADATA_H +#define HIGHLIGHTDEFINITIONMETADATA_H + +#include <QtCore/QString> +#include <QtCore/QLatin1String> +#include <QtCore/QStringList> +#include <QtCore/QUrl> + +namespace TextEditor { +namespace Internal { + +class HighlightDefinitionMetaData +{ +public: + HighlightDefinitionMetaData(); + + void setName(const QString &name); + const QString &name() const; + + void setVersion(const QString &version); + const QString &version() const; + + void setPatterns(const QStringList &patterns); + const QStringList &patterns() const; + + void setMimeTypes(const QStringList &mimeTypes); + const QStringList &mimeTypes() const; + + void setUrl(const QUrl &url); + const QUrl &url() const; + + static const QLatin1String kName; + static const QLatin1String kExtensions; + static const QLatin1String kMimeType; + static const QLatin1String kVersion; + static const QLatin1String kUrl; + +private: + QString m_name; + QString m_version; + QStringList m_patterns; + QStringList m_mimeTypes; + QUrl m_url; +}; + +} // namespace Internal +} // namespace TextEditor + +#endif // HIGHLIGHTDEFINITIONMETADATA_H diff --git a/src/plugins/texteditor/generichighlighter/highlightersettingspage.cpp b/src/plugins/texteditor/generichighlighter/highlightersettingspage.cpp index 2209fd0958373be8a0da7093df75cb1204ba8158..adb6af254c7dceea06e2853225f60172160e2a6a 100644 --- a/src/plugins/texteditor/generichighlighter/highlightersettingspage.cpp +++ b/src/plugins/texteditor/generichighlighter/highlightersettingspage.cpp @@ -30,11 +30,14 @@ #include "highlightersettingspage.h" #include "highlightersettings.h" #include "manager.h" +#include "managedefinitionsdialog.h" #include "ui_highlightersettingspage.h" #include <coreplugin/icore.h> #include <coreplugin/coreconstants.h> +#include <QtGui/QMessageBox> + using namespace TextEditor; using namespace Internal; @@ -102,8 +105,9 @@ QWidget *HighlighterSettingsPage::createPage(QWidget *parent) } connect(m_d->m_page.resetButton, SIGNAL(clicked()), this, SLOT(resetDefinitionsLocation())); - connect(m_d->m_page.downloadNoteLabel, SIGNAL(linkActivated(QString)), - Manager::instance(), SLOT(openDefinitionsUrl(QString))); + connect(m_d->m_page.manageDefinitionsButton, SIGNAL(clicked()), + this, SLOT(requestAvailableDefinitionsMetaData())); + connect(w, SIGNAL(destroyed()), this, SLOT(ignoreDownloadReply())); return w; } @@ -152,6 +156,45 @@ void HighlighterSettingsPage::resetDefinitionsLocation() m_d->m_page.definitionFilesPath->setPath(findDefinitionsLocation()); } +void HighlighterSettingsPage::requestAvailableDefinitionsMetaData() +{ + m_d->m_page.manageDefinitionsButton->setEnabled(false); + + Manager::instance()->downloadAvailableDefinitionsMetaData(); + connect(Manager::instance(), + SIGNAL(definitionsMetaDataReady(QList<Internal::HighlightDefinitionMetaData>)), + this, + SLOT(manageDefinitions(QList<Internal::HighlightDefinitionMetaData>)), + Qt::UniqueConnection); + connect(Manager::instance(), SIGNAL(errorDownloadingDefinitionsMetaData()), + this, SLOT(showError()), Qt::UniqueConnection); +} + +void HighlighterSettingsPage::ignoreDownloadReply() +{ + disconnect(Manager::instance(), + SIGNAL(definitionsMetaDataReady(QList<Internal::HighlightDefinitionMetaData>)), + this, + SLOT(manageDefinitions(QList<Internal::HighlightDefinitionMetaData>))); + disconnect(Manager::instance(), SIGNAL(errorDownloadingDefinitionsMetaData()), + this, SLOT(showError())); +} + +void HighlighterSettingsPage::manageDefinitions(const QList<HighlightDefinitionMetaData> &metaData) +{ + ManageDefinitionsDialog dialog(metaData, m_d->m_page.manageDefinitionsButton->window()); + dialog.exec(); + m_d->m_page.manageDefinitionsButton->setEnabled(true); +} + +void HighlighterSettingsPage::showError() +{ + QMessageBox::critical(m_d->m_page.manageDefinitionsButton->window(), + tr("Error connecting to server."), + tr("Not possible to retrieve data.")); + m_d->m_page.manageDefinitionsButton->setEnabled(true); +} + bool HighlighterSettingsPage::settingsChanged() const { if (m_d->m_settings.definitionFilesPath() != m_d->m_page.definitionFilesPath->path()) diff --git a/src/plugins/texteditor/generichighlighter/highlightersettingspage.h b/src/plugins/texteditor/generichighlighter/highlightersettingspage.h index 0edef5fa076f8bd2f232a93a9c10619de8337ad6..262f3d78cc0140bc9fc20fb6523336fb2ef668f3 100644 --- a/src/plugins/texteditor/generichighlighter/highlightersettingspage.h +++ b/src/plugins/texteditor/generichighlighter/highlightersettingspage.h @@ -32,8 +32,16 @@ #include "texteditoroptionspage.h" +QT_BEGIN_NAMESPACE +template <class> class QList; +QT_END_NAMESPACE + namespace TextEditor { +namespace Internal { +class HighlightDefinitionMetaData; +} + class HighlighterSettings; class HighlighterSettingsPage : public TextEditorOptionsPage @@ -58,6 +66,10 @@ signals: private slots: void resetDefinitionsLocation(); + void requestAvailableDefinitionsMetaData(); + void manageDefinitions(const QList<Internal::HighlightDefinitionMetaData> &metaData); + void showError(); + void ignoreDownloadReply(); private: void settingsFromUI(); diff --git a/src/plugins/texteditor/generichighlighter/highlightersettingspage.ui b/src/plugins/texteditor/generichighlighter/highlightersettingspage.ui index ee365fb1183e41ca5ec8e30c297c34f9f0ebcb5b..812cdaf509878a5f0237d805055acb993276fe2a 100644 --- a/src/plugins/texteditor/generichighlighter/highlightersettingspage.ui +++ b/src/plugins/texteditor/generichighlighter/highlightersettingspage.ui @@ -21,47 +21,87 @@ </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> - <widget class="QLabel" name="downloadNoteLabel"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="locationLabel"> + <property name="text"> + <string>Location:</string> + </property> + </widget> + </item> + <item> + <widget class="Utils::PathChooser" name="definitionFilesPath" native="true"/> + </item> + </layout> + </item> + <item> + <widget class="QToolButton" name="resetButton"> + <property name="toolTip"> + <string>Reset to default</string> + </property> + <property name="text"> + <string>R</string> + </property> + <property name="icon"> + <iconset resource="../../coreplugin/core.qrc"> + <normaloff>:/core/images/reset.png</normaloff>:/core/images/reset.png</iconset> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="definitionsInfolabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="text"> <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Definitions can be downloaded from the </span><a href="http://kate-editor.org/downloads/syntax_highlighting"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Kate Text Editor</span></a><span style=" font-size:8pt;"> website and stored at the location below.</span></p></body></html></string> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Highlight definitions are available from the </span><a href="http://kate-editor.org/downloads/syntax_highlighting?kateversion=3.2"><span style=" font-size:8pt; text-decoration: underline; color:#0000ff;">Kate Text Editor</span></a><span style=" font-size:8pt;"> website. Qt Creator can download a list of available definitions and then install the selected ones.</span></p></body></html></string> </property> <property name="textFormat"> <enum>Qt::RichText</enum> </property> - <property name="textInteractionFlags"> - <set>Qt::TextBrowserInteraction</set> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + <property name="openExternalLinks"> + <bool>true</bool> </property> </widget> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout"> + <layout class="QHBoxLayout" name="horizontalLayout_4"> <item> - <widget class="QLabel" name="locationLabel"> + <widget class="QPushButton" name="manageDefinitionsButton"> <property name="text"> - <string>Location:</string> + <string>Manage Definitions</string> </property> </widget> </item> <item> - <widget class="Utils::PathChooser" name="definitionFilesPath" native="true"/> - </item> - <item> - <widget class="QToolButton" name="resetButton"> - <property name="toolTip"> - <string>Reset to default</string> - </property> - <property name="text"> - <string>R</string> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> </property> - <property name="icon"> - <iconset resource="../../coreplugin/core.qrc"> - <normaloff>:/core/images/reset.png</normaloff>:/core/images/reset.png</iconset> + <property name="sizeHint" stdset="0"> + <size> + <width>328</width> + <height>20</height> + </size> </property> - </widget> + </spacer> </item> </layout> </item> @@ -77,7 +117,7 @@ p, li { white-space: pre-wrap; } <item> <widget class="QCheckBox" name="alertWhenNoDefinition"> <property name="text"> - <string>Alert when a highlight definition is not found.</string> + <string>Alert when a highlight definition is not found</string> </property> </widget> </item> @@ -125,6 +165,12 @@ p, li { white-space: pre-wrap; } </slots> </customwidget> </customwidgets> + <tabstops> + <tabstop>resetButton</tabstop> + <tabstop>manageDefinitionsButton</tabstop> + <tabstop>alertWhenNoDefinition</tabstop> + <tabstop>ignoreEdit</tabstop> + </tabstops> <resources> <include location="../../coreplugin/core.qrc"/> </resources> diff --git a/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.cpp b/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bc69ca272abbe922e9c1e56eb20683c14b7d9701 --- /dev/null +++ b/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.cpp @@ -0,0 +1,121 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "managedefinitionsdialog.h" +#include "manager.h" + +#include <QtCore> +#include <QtCore/QUrl> +#include <QtCore/QIODevice> +#include <QtCore/QXmlStreamReader> +#include <QtCore/QXmlStreamAttributes> +#include <QtCore/QFuture> +#include <QtCore/QFutureWatcher> +#include <QtCore/QtConcurrentMap> +#include <QtGui/QMessageBox> + +#include <QDebug> + +using namespace TextEditor; +using namespace Internal; + +ManageDefinitionsDialog::ManageDefinitionsDialog( + const QList<HighlightDefinitionMetaData> &metaDataList, QWidget *parent) : + m_definitionsMetaData(metaDataList), QDialog(parent) +{ + ui.setupUi(this); + ui.definitionsTable->setHorizontalHeaderLabels( + QStringList() << tr("Definition Name") << tr("Installed") << tr("Available")); + ui.definitionsTable->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch); + + setWindowTitle(tr("Manage Definitions")); + + populateDefinitionsWidget(); + + connect(ui.downloadButton, SIGNAL(clicked()), this, SLOT(downloadDefinitions())); +} + +void ManageDefinitionsDialog::populateDefinitionsWidget() +{ + const int size = m_definitionsMetaData.size(); + ui.definitionsTable->setRowCount(size); + for (int i = 0; i < size; ++i) { + const HighlightDefinitionMetaData &downloadData = m_definitionsMetaData.at(i); + + QString installedVersion; + const QString &id = Manager::instance()->definitionIdByName(downloadData.name()); + const QSharedPointer<HighlightDefinitionMetaData> &metaData = + Manager::instance()->definitionMetaData(id); + if (!metaData.isNull()) + installedVersion = metaData->version(); + + for (int j = 0; j < 3; ++j) { + QTableWidgetItem *item = new QTableWidgetItem; + if (j == 0) + item->setText(downloadData.name()); + else if (j == 1) { + item->setText(installedVersion); + item->setTextAlignment(Qt::AlignCenter); + } else if (j == 2) { + item->setText(downloadData.version()); + item->setTextAlignment(Qt::AlignCenter); + } + ui.definitionsTable->setItem(i, j, item); + } + } +} + +void ManageDefinitionsDialog::downloadDefinitions() +{ + if (Manager::instance()->isDownloadingDefinitions()) { + QMessageBox::information( + this, + tr("Download Information"), + tr("There is already one download in progress. Please wait until it is finished.")); + return; + } + + QList<QUrl> urls; + foreach (const QModelIndex &index, ui.definitionsTable->selectionModel()->selectedRows()) + urls.append(m_definitionsMetaData.at(index.row()).url()); + Manager::instance()->downloadDefinitions(urls); + close(); +} + +void ManageDefinitionsDialog::changeEvent(QEvent *e) +{ + QDialog::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui.retranslateUi(this); + break; + default: + break; + } +} diff --git a/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.h b/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.h new file mode 100644 index 0000000000000000000000000000000000000000..80961ba3abede975301b78a140c4b3a988b0a365 --- /dev/null +++ b/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.h @@ -0,0 +1,64 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MANAGEDEFINITIONSDIALOG_H +#define MANAGEDEFINITIONSDIALOG_H + +#include "ui_managedefinitionsdialog.h" +#include "highlightdefinitionmetadata.h" + +#include <QtCore/QList> + +namespace TextEditor { +namespace Internal { + +class ManageDefinitionsDialog : public QDialog +{ + Q_OBJECT +public: + explicit ManageDefinitionsDialog(const QList<HighlightDefinitionMetaData> &metaDataList, + QWidget *parent = 0); + +protected: + void changeEvent(QEvent *e); + +private slots: + void downloadDefinitions(); + +private: + void populateDefinitionsWidget(); + + QList<HighlightDefinitionMetaData> m_definitionsMetaData; + Ui::ManageDefinitionsDialog ui; +}; + +} // namespace Internal +} // namespace TextEditor + +#endif // MANAGEDEFINITIONSDIALOG_H diff --git a/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui b/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..2f1a4501f6b9c3c49cfef5db868eb339ff6bdb5f --- /dev/null +++ b/src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ManageDefinitionsDialog</class> + <widget class="QDialog" name="ManageDefinitionsDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>447</width> + <height>315</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QGroupBox" name="definitionsGroupBox"> + <property name="title"> + <string>Available Definitions</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTableWidget" name="definitionsTable"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + <property name="columnCount"> + <number>3</number> + </property> + <attribute name="verticalHeaderVisible"> + <bool>false</bool> + </attribute> + <attribute name="verticalHeaderDefaultSectionSize"> + <number>20</number> + </attribute> + <column/> + <column/> + <column/> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="downloadButton"> + <property name="text"> + <string>Download Selected Definitions</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>188</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>298</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="closeButton"> + <property name="text"> + <string>Close</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>closeButton</sender> + <signal>clicked()</signal> + <receiver>ManageDefinitionsDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>381</x> + <y>294</y> + </hint> + <hint type="destinationlabel"> + <x>306</x> + <y>298</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/plugins/texteditor/generichighlighter/manager.cpp b/src/plugins/texteditor/generichighlighter/manager.cpp index 2a7d1b6be3b1f3c54b7a19d2f80135a3e757f251..b5a9858872ec7098082cfb662bbf145e79a17f7c 100644 --- a/src/plugins/texteditor/generichighlighter/manager.cpp +++ b/src/plugins/texteditor/generichighlighter/manager.cpp @@ -31,14 +31,16 @@ #include "highlightdefinition.h" #include "highlightdefinitionhandler.h" #include "highlighterexception.h" -#include "texteditorplugin.h" -#include "texteditorsettings.h" -#include "plaintexteditorfactory.h" +#include "definitiondownloader.h" #include "highlightersettings.h" +#include "plaintexteditorfactory.h" #include "texteditorconstants.h" +#include "texteditorplugin.h" +#include "texteditorsettings.h" #include <coreplugin/icore.h> #include <utils/qtcassert.h> +#include <coreplugin/progressmanager/progressmanager.h> #include <qtconcurrent/QtConcurrentTools> #include <QtCore/QtAlgorithms> @@ -50,22 +52,27 @@ #include <QtCore/QFile> #include <QtCore/QFileInfo> #include <QtCore/QDir> -#include <QtCore/QList> #include <QtCore/QRegExp> #include <QtCore/QFuture> #include <QtCore/QtConcurrentRun> +#include <QtCore/QtConcurrentMap> #include <QtCore/QUrl> #include <QtGui/QDesktopServices> #include <QtXml/QXmlSimpleReader> #include <QtXml/QXmlInputSource> #include <QtXml/QXmlStreamReader> #include <QtXml/QXmlStreamAttributes> +#include <QtNetwork/QNetworkRequest> +#include <QtNetwork/QNetworkReply> using namespace TextEditor; using namespace Internal; -Manager::Manager() -{} +Manager::Manager() : m_downloadingDefinitions(false) +{ + connect(&m_mimeTypeWatcher, SIGNAL(resultReadyAt(int)), this, SLOT(registerMimeType(int))); + connect(&m_downloadWatcher, SIGNAL(finished()), this, SLOT(downloadDefinitionsFinished())); +} Manager::~Manager() {} @@ -80,19 +87,7 @@ QString Manager::definitionIdByName(const QString &name) const { return m_idByName.value(name); } QString Manager::definitionIdByMimeType(const QString &mimeType) const -{ - if (m_idByMimeType.count(mimeType) > 1) { - QStringList candidateIds; - QMultiHash<QString, QString>::const_iterator it = m_idByMimeType.find(mimeType); - QMultiHash<QString, QString>::const_iterator endIt = m_idByMimeType.end(); - for (; it != endIt && it.key() == mimeType; ++it) - candidateIds.append(it.value()); - - qSort(candidateIds.begin(), candidateIds.end(), m_priorityComp); - return candidateIds.last(); - } - return m_idByMimeType.value(mimeType); -} +{ return m_idByMimeType.value(mimeType); } QString Manager::definitionIdByAnyMimeType(const QStringList &mimeTypes) const { @@ -105,31 +100,37 @@ QString Manager::definitionIdByAnyMimeType(const QStringList &mimeTypes) const return definitionId; } -const QSharedPointer<HighlightDefinition> &Manager::definition(const QString &id) +QSharedPointer<HighlightDefinition> Manager::definition(const QString &id) { - if (!m_definitions.contains(id)) { - m_isBuilding.insert(id); - + if (!id.isEmpty() && !m_definitions.contains(id)) { QFile definitionFile(id); if (!definitionFile.open(QIODevice::ReadOnly | QIODevice::Text)) - throw HighlighterException(); - QXmlInputSource source(&definitionFile); + return QSharedPointer<HighlightDefinition>(); QSharedPointer<HighlightDefinition> definition(new HighlightDefinition); HighlightDefinitionHandler handler(definition); + QXmlInputSource source(&definitionFile); QXmlSimpleReader reader; reader.setContentHandler(&handler); - reader.parse(source); + m_isBuilding.insert(id); + try { + reader.parse(source); + } catch (HighlighterException &) { + definition.clear(); + } + m_isBuilding.remove(id); + definitionFile.close(); m_definitions.insert(id, definition); - definitionFile.close(); - m_isBuilding.remove(id); } - return *m_definitions.constFind(id); + return m_definitions.value(id); } +QSharedPointer<HighlightDefinitionMetaData> Manager::definitionMetaData(const QString &id) const +{ return m_definitionsMetaData.value(id); } + bool Manager::isBuildingDefinition(const QString &id) const { return m_isBuilding.contains(id); } @@ -138,9 +139,7 @@ void Manager::registerMimeTypes() clear(); QFuture<Core::MimeType> future = QtConcurrent::run(&Manager::gatherDefinitionsMimeTypes, this); - m_watcher.setFuture(future); - - connect(&m_watcher, SIGNAL(resultReadyAt(int)), this, SLOT(registerMimeType(int))); + m_mimeTypeWatcher.setFuture(future); } void Manager::gatherDefinitionsMimeTypes(QFutureInterface<Core::MimeType> &future) @@ -153,10 +152,13 @@ void Manager::gatherDefinitionsMimeTypes(QFutureInterface<Core::MimeType> &futur const QFileInfoList &filesInfo = definitionsDir.entryInfoList(); foreach (const QFileInfo &fileInfo, filesInfo) { - QString comment; - QStringList mimeTypes; - QStringList patterns; - parseDefinitionMetadata(fileInfo, &comment, &mimeTypes, &patterns); + const QSharedPointer<HighlightDefinitionMetaData> &metaData = parseMetadata(fileInfo); + if (metaData.isNull()) + continue; + + const QString &id = fileInfo.absoluteFilePath(); + m_idByName.insert(metaData->name(), id); + m_definitionsMetaData.insert(id, metaData); // A definition can specify multiple MIME types and file extensions/patterns. However, each // thing is done with a single string. Then, there is no direct way to tell which patterns @@ -165,19 +167,20 @@ void Manager::gatherDefinitionsMimeTypes(QFutureInterface<Core::MimeType> &futur static const QStringList textPlain(QLatin1String("text/plain")); - QList<QRegExp> expressions; - foreach (const QString &type, mimeTypes) { + QList<QRegExp> patterns; + foreach (const QString &type, metaData->mimeTypes()) { + m_idByMimeType.insert(type, id); Core::MimeType mimeType = Core::ICore::instance()->mimeDatabase()->findByType(type); if (mimeType.isNull()) { - if (expressions.isEmpty()) { - foreach (const QString &pattern, patterns) - expressions.append(QRegExp(pattern, Qt::CaseSensitive, QRegExp::Wildcard)); + if (patterns.isEmpty()) { + foreach (const QString &pattern, metaData->patterns()) + patterns.append(QRegExp(pattern, Qt::CaseSensitive, QRegExp::Wildcard)); } mimeType.setType(type); mimeType.setSubClassesOf(textPlain); - mimeType.setComment(comment); - mimeType.setGlobPatterns(expressions); + mimeType.setComment(metaData->name()); + mimeType.setGlobPatterns(patterns); future.reportResult(mimeType); } @@ -187,76 +190,129 @@ void Manager::gatherDefinitionsMimeTypes(QFutureInterface<Core::MimeType> &futur void Manager::registerMimeType(int index) const { - const Core::MimeType &mimeType = m_watcher.resultAt(index); - Core::ICore::instance()->mimeDatabase()->addMimeType(mimeType); + const Core::MimeType &mimeType = m_mimeTypeWatcher.resultAt(index); TextEditorPlugin::instance()->editorFactory()->addMimeType(mimeType.type()); + Core::ICore::instance()->mimeDatabase()->addMimeType(mimeType); } -void Manager::parseDefinitionMetadata(const QFileInfo &fileInfo, - QString *comment, - QStringList *mimeTypes, - QStringList *patterns) +QSharedPointer<HighlightDefinitionMetaData> Manager::parseMetadata(const QFileInfo &fileInfo) { static const QLatin1Char kSemiColon(';'); static const QLatin1Char kSlash('/'); static const QLatin1String kLanguage("language"); - static const QLatin1String kName("name"); - static const QLatin1String kExtensions("extensions"); - static const QLatin1String kMimeType("mimetype"); - static const QLatin1String kPriority("priority"); static const QLatin1String kArtificial("artificial"); - const QString &id = fileInfo.absoluteFilePath(); - - QFile definitionFile(id); + QFile definitionFile(fileInfo.absoluteFilePath()); if (!definitionFile.open(QIODevice::ReadOnly | QIODevice::Text)) - return; + return QSharedPointer<HighlightDefinitionMetaData>(); + + QSharedPointer<HighlightDefinitionMetaData> metaData(new HighlightDefinitionMetaData); QXmlStreamReader reader(&definitionFile); while (!reader.atEnd() && !reader.hasError()) { if (reader.readNext() == QXmlStreamReader::StartElement && reader.name() == kLanguage) { - const QXmlStreamAttributes &attr = reader.attributes(); + const QXmlStreamAttributes &atts = reader.attributes(); - *comment = attr.value(kName).toString(); - m_idByName.insert(*comment, id); + metaData->setName(atts.value(HighlightDefinitionMetaData::kName).toString()); + metaData->setVersion(atts.value(HighlightDefinitionMetaData::kVersion).toString()); + metaData->setPatterns(atts.value(HighlightDefinitionMetaData::kExtensions). + toString().split(kSemiColon, QString::SkipEmptyParts)); - *patterns = attr.value(kExtensions).toString().split(kSemiColon, - QString::SkipEmptyParts); - - *mimeTypes = attr.value(kMimeType).toString().split(kSemiColon, - QString::SkipEmptyParts); - if (mimeTypes->isEmpty()) { + QStringList mimeTypes = atts.value(HighlightDefinitionMetaData::kMimeType). + toString().split(kSemiColon, QString::SkipEmptyParts); + if (mimeTypes.isEmpty()) { // There are definitions which do not specify a MIME type, but specify file // patterns. Creating an artificial MIME type is a workaround. QString artificialType(kArtificial); - artificialType.append(kSlash).append(*comment); - m_idByMimeType.insert(artificialType, id); - mimeTypes->append(artificialType); - } else { - foreach (const QString &type, *mimeTypes) - m_idByMimeType.insert(type, id); + artificialType.append(kSlash).append(metaData->name()); + mimeTypes.append(artificialType); } - - // The priority below should not be confused with the priority used when matching files - // to MIME types. Kate uses this when there are definitions which share equal - // extensions/patterns. Here it is for choosing a highlight definition if there are - // multiple ones associated with the same MIME type (should not happen in general). - m_priorityComp.m_priorityById.insert(id, attr.value(kPriority).toString().toInt()); + metaData->setMimeTypes(mimeTypes); break; } } reader.clear(); definitionFile.close(); + + return metaData; } -void Manager::clear() +QList<HighlightDefinitionMetaData> Manager::parseAvailableDefinitionsList(QIODevice *device) const { - m_priorityComp.m_priorityById.clear(); - m_idByName.clear(); - m_idByMimeType.clear(); - m_definitions.clear(); + static const QLatin1String kDefinition("Definition"); + + QList<HighlightDefinitionMetaData> metaDataList; + QXmlStreamReader reader(device); + while (!reader.atEnd() && !reader.hasError()) { + if (reader.readNext() == QXmlStreamReader::StartElement && + reader.name() == kDefinition) { + const QXmlStreamAttributes &atts = reader.attributes(); + + HighlightDefinitionMetaData metaData; + metaData.setName(atts.value(HighlightDefinitionMetaData::kName).toString()); + metaData.setUrl(QUrl(atts.value(HighlightDefinitionMetaData::kUrl).toString())); + metaData.setVersion(atts.value(HighlightDefinitionMetaData::kVersion).toString()); + + metaDataList.append(metaData); + } + } + reader.clear(); + + return metaDataList; +} + +void Manager::downloadAvailableDefinitionsMetaData() +{ + QUrl url(QLatin1String("http://www.kate-editor.org/syntax/update-3.2.xml")); + QNetworkRequest request(url); + // Currently this takes a couple of seconds on Windows 7: QTBUG-10106. + QNetworkReply *reply = m_networkManager.get(request); + connect(reply, SIGNAL(finished()), this, SLOT(downloadAvailableDefinitionsListFinished())); +} + +void Manager::downloadAvailableDefinitionsListFinished() +{ + if (QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender())) { + if (reply->error() == QNetworkReply::NoError) + emit definitionsMetaDataReady(parseAvailableDefinitionsList(reply)); + else + emit errorDownloadingDefinitionsMetaData(); + reply->deleteLater(); + } +} + +void Manager::downloadDefinitions(const QList<QUrl> &urls) +{ + const QString &savePath = + TextEditorSettings::instance()->highlighterSettings().definitionFilesPath() + + QLatin1Char('/'); + + m_downloaders.clear(); + foreach (const QUrl &url, urls) + m_downloaders.append(new DefinitionDownloader(url, savePath)); + + m_downloadingDefinitions = true; + QFuture<void> future = QtConcurrent::map(m_downloaders, DownloaderStarter()); + m_downloadWatcher.setFuture(future); + Core::ICore::instance()->progressManager()->addTask(future, + tr("Downloading definitions"), + Constants::TASK_DOWNLOAD); +} + +void Manager::downloadDefinitionsFinished() +{ + foreach (DefinitionDownloader *downloader, m_downloaders) + delete downloader; + + registerMimeTypes(); + m_downloadingDefinitions = false; +} + +bool Manager::isDownloadingDefinitions() const +{ + return m_downloadingDefinitions; } void Manager::showGenericHighlighterOptions() const @@ -265,7 +321,10 @@ void Manager::showGenericHighlighterOptions() const Constants::TEXT_EDITOR_HIGHLIGHTER_SETTINGS); } -void Manager::openDefinitionsUrl(const QString &location) const +void Manager::clear() { - QDesktopServices::openUrl(QUrl(location)); + m_idByName.clear(); + m_idByMimeType.clear(); + m_definitions.clear(); + m_definitionsMetaData.clear(); } diff --git a/src/plugins/texteditor/generichighlighter/manager.h b/src/plugins/texteditor/generichighlighter/manager.h index 4963c33c5a2856540593ce91904864e5f0897c01..6c31a4451c2a2092f29d80973329a7326efe0dab 100644 --- a/src/plugins/texteditor/generichighlighter/manager.h +++ b/src/plugins/texteditor/generichighlighter/manager.h @@ -30,19 +30,23 @@ #ifndef MANAGER_H #define MANAGER_H +#include "highlightdefinitionmetadata.h" + #include <coreplugin/mimedatabase.h> #include <QtCore/QString> #include <QtCore/QHash> -#include <QtCore/QMultiHash> #include <QtCore/QSet> +#include <QtCore/QUrl> +#include <QtCore/QList> #include <QtCore/QSharedPointer> #include <QtCore/QFutureWatcher> +#include <QtNetwork/QNetworkAccessManager> QT_BEGIN_NAMESPACE class QFileInfo; class QStringList; -class QDir; +class QIODevice; template <class> class QFutureInterface; QT_END_NAMESPACE @@ -50,6 +54,7 @@ namespace TextEditor { namespace Internal { class HighlightDefinition; +class DefinitionDownloader; class Manager : public QObject { @@ -61,43 +66,50 @@ public: QString definitionIdByName(const QString &name) const; QString definitionIdByMimeType(const QString &mimeType) const; QString definitionIdByAnyMimeType(const QStringList &mimeTypes) const; + bool isBuildingDefinition(const QString &id) const; - const QSharedPointer<HighlightDefinition> &definition(const QString &id); + + QSharedPointer<HighlightDefinition> definition(const QString &id); + QSharedPointer<HighlightDefinitionMetaData> definitionMetaData(const QString &id) const; + + void downloadAvailableDefinitionsMetaData(); + void downloadDefinitions(const QList<QUrl> &urls); + bool isDownloadingDefinitions() const; public slots: void registerMimeTypes(); void showGenericHighlighterOptions() const; - void openDefinitionsUrl(const QString &location) const; private slots: void registerMimeType(int index) const; + void downloadAvailableDefinitionsListFinished(); + void downloadDefinitionsFinished(); private: Manager(); Q_DISABLE_COPY(Manager) - void clear(); void gatherDefinitionsMimeTypes(QFutureInterface<Core::MimeType> &future); - void parseDefinitionMetadata(const QFileInfo &fileInfo, - QString *comment, - QStringList *mimeTypes, - QStringList *patterns); - - struct PriorityCompare - { - bool operator()(const QString &a, const QString &b) const - { return m_priorityById.value(a) < m_priorityById.value(b); } - - QHash<QString, int> m_priorityById; - }; - PriorityCompare m_priorityComp; - - QFutureWatcher<Core::MimeType> m_watcher; + QSharedPointer<HighlightDefinitionMetaData> parseMetadata(const QFileInfo &fileInfo); + QList<HighlightDefinitionMetaData> parseAvailableDefinitionsList(QIODevice *device) const; + void clear(); QHash<QString, QString> m_idByName; - QMultiHash<QString, QString> m_idByMimeType; + QHash<QString, QString> m_idByMimeType; QHash<QString, QSharedPointer<HighlightDefinition> > m_definitions; + QHash<QString, QSharedPointer<HighlightDefinitionMetaData> > m_definitionsMetaData; QSet<QString> m_isBuilding; + + QList<DefinitionDownloader *> m_downloaders; + bool m_downloadingDefinitions; + QNetworkAccessManager m_networkManager; + + QFutureWatcher<void> m_downloadWatcher; + QFutureWatcher<Core::MimeType> m_mimeTypeWatcher; + +signals: + void definitionsMetaDataReady(const QList<Internal::HighlightDefinitionMetaData>&); + void errorDownloadingDefinitionsMetaData(); }; } // namespace Internal diff --git a/src/plugins/texteditor/plaintexteditor.cpp b/src/plugins/texteditor/plaintexteditor.cpp index 222517bec18986f4fdff9c8ce254a199d8c1b200..17a77fb80aed24b22a64d71f4f542f8b207260e1 100644 --- a/src/plugins/texteditor/plaintexteditor.cpp +++ b/src/plugins/texteditor/plaintexteditor.cpp @@ -173,10 +173,9 @@ void PlainTextEditor::configure(const Core::MimeType &mimeType) definitionId = findDefinitionId(mimeType, true); if (!definitionId.isEmpty()) { - try { - const QSharedPointer<HighlightDefinition> &definition = - Manager::instance()->definition(definitionId); - + const QSharedPointer<HighlightDefinition> &definition = + Manager::instance()->definition(definitionId); + if (!definition.isNull()) { Highlighter *highlighter = new Highlighter(definition->initialContext()); baseTextDocument()->setSyntaxHighlighter(highlighter); @@ -188,7 +187,6 @@ void PlainTextEditor::configure(const Core::MimeType &mimeType) setFontSettings(TextEditorSettings::instance()->fontSettings()); m_isMissingSyntaxDefinition = false; - } catch (const HighlighterException &) { } } else if (file()) { const QString &fileName = file()->fileName(); diff --git a/src/plugins/texteditor/texteditor.pro b/src/plugins/texteditor/texteditor.pro index 747c5dadc77119b3e1dd44152614d79c0413bef4..0c404e9ea7cb682c83c14d0ffc30b752d725bc65 100644 --- a/src/plugins/texteditor/texteditor.pro +++ b/src/plugins/texteditor/texteditor.pro @@ -1,7 +1,7 @@ TEMPLATE = lib TARGET = TextEditor DEFINES += TEXTEDITOR_LIBRARY -QT += xml +QT += xml network include(../../qtcreatorplugin.pri) include(texteditor_dependencies.pri) INCLUDEPATH += generichighlighter @@ -55,7 +55,10 @@ SOURCES += texteditorplugin.cpp \ generichighlighter/manager.cpp \ generichighlighter/highlightdefinitionhandler.cpp \ generichighlighter/highlightersettingspage.cpp \ - generichighlighter/highlightersettings.cpp + generichighlighter/highlightersettings.cpp \ + generichighlighter/managedefinitionsdialog.cpp \ + generichighlighter/highlightdefinitionmetadata.cpp \ + generichighlighter/definitiondownloader.cpp HEADERS += texteditorplugin.h \ textfilewizard.h \ @@ -113,13 +116,17 @@ HEADERS += texteditorplugin.h \ generichighlighter/manager.h \ generichighlighter/highlightdefinitionhandler.h \ generichighlighter/highlightersettingspage.h \ - generichighlighter/highlightersettings.h + generichighlighter/highlightersettings.h \ + generichighlighter/managedefinitionsdialog.h \ + generichighlighter/highlightdefinitionmetadata.h \ + generichighlighter/definitiondownloader.h FORMS += behaviorsettingspage.ui \ displaysettingspage.ui \ fontsettingspage.ui \ colorschemeedit.ui \ - generichighlighter/highlightersettingspage.ui + generichighlighter/highlightersettingspage.ui \ + generichighlighter/managedefinitionsdialog.ui RESOURCES += texteditor.qrc OTHER_FILES += TextEditor.pluginspec TextEditor.mimetypes.xml diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h index 12338d16f1be46d164286ff4e0b318aa3bff72b8..1dc5d365d413fdbd4521990cb644d2d0fa002bbe 100644 --- a/src/plugins/texteditor/texteditorconstants.h +++ b/src/plugins/texteditor/texteditorconstants.h @@ -88,7 +88,7 @@ const char * const GOTO_PREVIOUS_WORD_WITH_SELECTION = "TextEditor.GotoPreviousW const char * const GOTO_NEXT_WORD_WITH_SELECTION = "TextEditor.GotoNextWordWithSelection"; const char * const C_TEXTEDITOR_MIMETYPE_TEXT = "text/plain"; const char * const INFO_SYNTAX_DEFINITION = "TextEditor.InfoSyntaxDefinition"; - +const char * const TASK_DOWNLOAD = "TextEditor.Task.Download"; // Text color and style categories const char * const C_TEXT = "Text";