GenericHighlighter: Download dependent definitions

Change-Id: Idd3ce51316f2e2cc2270c8ed65fb419d9ef91b78
Reviewed-by: David Schulz <david.schulz@digia.com>
This commit is contained in:
Orgad Shaneh
2014-07-01 11:59:46 +03:00
committed by Orgad Shaneh
parent d3c6e59ae9
commit e95ac00f75
4 changed files with 108 additions and 21 deletions

View File

@@ -88,8 +88,18 @@ void DefinitionDownloader::saveData(QNetworkReply *reply)
const QString &fileName =
urlPath.right(urlPath.length() - urlPath.lastIndexOf(QLatin1Char('/')) - 1);
Utils::FileSaver saver(m_localPath + fileName, QIODevice::Text);
saver.write(reply->readAll());
const QByteArray data = reply->readAll();
saver.write(data);
m_status = saver.finalize() ? Ok: WriteError;
QString content = QString::fromUtf8(data);
QRegExp reference(QLatin1String("context\\s*=\\s*\"[^\"]*##([^\"]+)\""));
int index = -1;
forever {
index = reference.indexIn(content, index + 1);
if (index == -1)
break;
emit foundReferencedDefinition(reference.cap(1));
}
}
DefinitionDownloader::Status DefinitionDownloader::status() const

View File

@@ -58,6 +58,9 @@ public:
void run();
Status status() const;
signals:
void foundReferencedDefinition(const QString &name);
private:
QNetworkReply *getData(QNetworkAccessManager *manager) const;
void saveData(QNetworkReply *reply);

View File

@@ -76,22 +76,55 @@ const char kMimeType[] = "mimetype";
const char kVersion[] = "version";
const char kUrl[] = "url";
class MultiDefinitionDownloader : public QObject
{
Q_OBJECT
public:
MultiDefinitionDownloader(const QString &savePath, const QList<QString> &installedDefinitions) :
m_downloadPath(savePath),
m_installedDefinitions(installedDefinitions)
{
connect(&m_downloadWatcher, SIGNAL(finished()), this, SLOT(downloadDefinitionsFinished()));
}
~MultiDefinitionDownloader()
{
if (m_downloadWatcher.isRunning())
m_downloadWatcher.cancel();
}
void downloadDefinitions(const QList<QUrl> &urls);
signals:
void finished();
private slots:
void downloadReferencedDefinition(const QString &name);
void downloadDefinitionsFinished();
private:
QFutureWatcher<void> m_downloadWatcher;
QList<DefinitionDownloader *> m_downloaders;
QList<QString> m_installedDefinitions;
QSet<QString> m_referencedDefinitions;
QString m_downloadPath;
};
Manager::Manager() :
m_isDownloadingDefinitionsSpec(false),
m_multiDownloader(0),
m_hasQueuedRegistration(false)
{
connect(&m_registeringWatcher, SIGNAL(finished()), this, SLOT(registerMimeTypesFinished()));
connect(&m_downloadWatcher, SIGNAL(finished()), this, SLOT(downloadDefinitionsFinished()));
}
Manager::~Manager()
{
disconnect(&m_registeringWatcher);
disconnect(&m_downloadWatcher);
disconnect(m_multiDownloader);
if (m_registeringWatcher.isRunning())
m_registeringWatcher.cancel();
if (m_downloadWatcher.isRunning())
m_downloadWatcher.cancel();
delete m_multiDownloader;
}
Manager *Manager::instance()
@@ -121,6 +154,11 @@ QString Manager::definitionIdByAnyMimeType(const QStringList &mimeTypes) const
return definitionId;
}
DefinitionMetaDataPtr Manager::availableDefinitionByName(const QString &name) const
{
return m_availableDefinitions.value(name);
}
QSharedPointer<HighlightDefinition> Manager::definition(const QString &id)
{
if (!id.isEmpty() && !m_definitions.contains(id)) {
@@ -380,12 +418,12 @@ DefinitionMetaDataPtr Manager::parseMetadata(const QFileInfo &fileInfo)
return metaData;
}
QList<DefinitionMetaDataPtr> Manager::parseAvailableDefinitionsList(QIODevice *device) const
QList<DefinitionMetaDataPtr> Manager::parseAvailableDefinitionsList(QIODevice *device)
{
static const QLatin1Char kSlash('/');
static const QLatin1String kDefinition("Definition");
QList<DefinitionMetaDataPtr> metaDataList;
m_availableDefinitions.clear();
QXmlStreamReader reader(device);
while (!reader.atEnd() && !reader.hasError()) {
if (reader.readNext() == QXmlStreamReader::StartElement &&
@@ -401,12 +439,12 @@ QList<DefinitionMetaDataPtr> Manager::parseAvailableDefinitionsList(QIODevice *d
if (slash != -1)
metaData->fileName = url.right(url.length() - slash - 1);
metaDataList.append(metaData);
m_availableDefinitions.insert(metaData->name, metaData);
}
}
reader.clear();
return metaDataList;
return m_availableDefinitions.values();
}
void Manager::downloadAvailableDefinitionsMetaData()
@@ -431,18 +469,28 @@ void Manager::downloadAvailableDefinitionsListFinished()
void Manager::downloadDefinitions(const QList<QUrl> &urls, const QString &savePath)
{
m_downloaders.clear();
foreach (const QUrl &url, urls)
m_downloaders.append(new DefinitionDownloader(url, savePath));
m_multiDownloader = new MultiDefinitionDownloader(savePath, m_register.m_idByName.keys());
connect(m_multiDownloader, SIGNAL(finished()), this, SLOT(downloadDefinitionsFinished()));
m_multiDownloader->downloadDefinitions(urls);
}
void MultiDefinitionDownloader::downloadDefinitions(const QList<QUrl> &urls)
{
m_downloaders.clear();
foreach (const QUrl &url, urls) {
DefinitionDownloader *downloader = new DefinitionDownloader(url, m_downloadPath);
connect(downloader, SIGNAL(foundReferencedDefinition(QString)),
this, SLOT(downloadReferencedDefinition(QString)));
m_downloaders.append(downloader);
}
m_isDownloadingDefinitionsSpec = true;
QFuture<void> future = QtConcurrent::map(m_downloaders, DownloaderStarter());
m_downloadWatcher.setFuture(future);
ProgressManager::addTask(future, tr("Downloading Highlighting Definitions"),
"TextEditor.Task.Download");
}
void Manager::downloadDefinitionsFinished()
void MultiDefinitionDownloader::downloadDefinitionsFinished()
{
int errors = 0;
bool writeError = false;
@@ -467,12 +515,37 @@ void Manager::downloadDefinitionsFinished()
QMessageBox::critical(0, tr("Download Error"), text);
}
m_isDownloadingDefinitionsSpec = false;
QList<QUrl> urls;
foreach (const QString &definition, m_referencedDefinitions) {
if (DefinitionMetaDataPtr metaData =
Manager::instance()->availableDefinitionByName(definition)) {
urls << metaData->url;
}
}
m_referencedDefinitions.clear();
if (urls.isEmpty())
emit finished();
else
downloadDefinitions(urls);
}
void Manager::downloadDefinitionsFinished()
{
delete m_multiDownloader;
m_multiDownloader = 0;
}
void MultiDefinitionDownloader::downloadReferencedDefinition(const QString &name)
{
if (m_installedDefinitions.contains(name))
return;
m_referencedDefinitions.insert(name);
m_installedDefinitions.append(name);
}
bool Manager::isDownloadingDefinitions() const
{
return m_isDownloadingDefinitionsSpec;
return m_multiDownloader != 0;
}
void Manager::clear()

View File

@@ -56,6 +56,7 @@ namespace Internal {
class HighlightDefinition;
class DefinitionDownloader;
class ManagerProcessor;
class MultiDefinitionDownloader;
// This is the generic highlighter manager. It is not thread-safe.
@@ -69,6 +70,7 @@ public:
QString definitionIdByName(const QString &name) const;
QString definitionIdByMimeType(const QString &mimeType) const;
QString definitionIdByAnyMimeType(const QStringList &mimeTypes) const;
DefinitionMetaDataPtr availableDefinitionByName(const QString &name) const;
bool isBuildingDefinition(const QString &id) const;
QSharedPointer<HighlightDefinition> definition(const QString &id);
@@ -96,13 +98,12 @@ private:
void clear();
bool m_isDownloadingDefinitionsSpec;
QList<DefinitionDownloader *> m_downloaders;
QFutureWatcher<void> m_downloadWatcher;
QList<DefinitionMetaDataPtr> parseAvailableDefinitionsList(QIODevice *device) const;
MultiDefinitionDownloader *m_multiDownloader;
QList<DefinitionMetaDataPtr> parseAvailableDefinitionsList(QIODevice *device);
QSet<QString> m_isBuildingDefinition;
QHash<QString, QSharedPointer<HighlightDefinition> > m_definitions;
QHash<QString, DefinitionMetaDataPtr> m_availableDefinitions;
struct RegisterData
{