Commit ce80ee4f authored by Leandro Melo's avatar Leandro Melo
Browse files

Generic highlighter: Interface for automatic download of available...

Generic highlighter: Interface for automatic download of available definitions. Refactorings and changes in related parts of the code.
parent 90cb7df5
/**************************************************************************
**
** 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();
}
/**************************************************************************
**
** 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
......@@ -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()) {
......
/**************************************************************************
**
** 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; }
/**************************************************************************
**
** 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
......@@ -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())
......
......@@ -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();
......
......@@ -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>
......
/**************************************************************************
**
** 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