aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLeandro Melo <leandro.melo@nokia.com>2010-06-11 12:13:52 +0200
committerLeandro Melo <leandro.melo@nokia.com>2010-06-11 13:02:53 +0200
commitce80ee4f5e14eae425fd99c570885ac3e39814c6 (patch)
tree2a24fdf6ce09d3597a9fb08f84f66c09b32b7b91 /src
parent90cb7df5be0fe0105a70273b84c2fa400294c9ad (diff)
Generic highlighter: Interface for automatic download of available definitions. Refactorings and changes in related parts of the code.
Diffstat (limited to 'src')
-rw-r--r--src/plugins/texteditor/generichighlighter/definitiondownloader.cpp94
-rw-r--r--src/plugins/texteditor/generichighlighter/definitiondownloader.h75
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightdefinitionhandler.cpp5
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.cpp72
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightdefinitionmetadata.h78
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightersettingspage.cpp47
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightersettingspage.h12
-rw-r--r--src/plugins/texteditor/generichighlighter/highlightersettingspage.ui88
-rw-r--r--src/plugins/texteditor/generichighlighter/managedefinitionsdialog.cpp121
-rw-r--r--src/plugins/texteditor/generichighlighter/managedefinitionsdialog.h64
-rw-r--r--src/plugins/texteditor/generichighlighter/managedefinitionsdialog.ui117
-rw-r--r--src/plugins/texteditor/generichighlighter/manager.cpp229
-rw-r--r--src/plugins/texteditor/generichighlighter/manager.h54
-rw-r--r--src/plugins/texteditor/plaintexteditor.cpp8
-rw-r--r--src/plugins/texteditor/texteditor.pro15
-rw-r--r--src/plugins/texteditor/texteditorconstants.h2
16 files changed, 942 insertions, 139 deletions
diff --git a/src/plugins/texteditor/generichighlighter/definitiondownloader.cpp b/src/plugins/texteditor/generichighlighter/definitiondownloader.cpp
new file mode 100644
index 0000000000..373c16b927
--- /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 0000000000..c2866183c7
--- /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 c6a023aaf8..a157d94461 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 0000000000..49e7e68497
--- /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 0000000000..2536104c26
--- /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 2209fd0958..adb6af254c 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 0edef5fa07..262f3d78cc 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 ee365fb118..812cdaf509 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>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;&quot;&gt;
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Definitions can be downloaded from the &lt;/span&gt;&lt;a href=&quot;http://kate-editor.org/downloads/syntax_highlighting&quot;&gt;&lt;span style=&quot; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;Kate Text Editor&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; website and stored at the location below.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;Highlight definitions are available from the &lt;/span&gt;&lt;a href=&quot;http://kate-editor.org/downloads/syntax_highlighting?kateversion=3.2&quot;&gt;&lt;span style=&quot; font-size:8pt; text-decoration: underline; color:#0000ff;&quot;&gt;Kate Text Editor&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt; website. Qt Creator can download a list of available definitions and then install the selected ones.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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 0000000000..bc69ca272a
--- /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 0000000000..80961ba3ab
--- /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 0000000000..2f1a4501f6
--- /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 2a7d1b6be3..b5a9858872 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 4963c33c5a..6c31a4451c 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 222517bec1..17a77fb80a 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 747c5dadc7..0c404e9ea7 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 12338d16f1..1dc5d365d4 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";