Commit 99c25c19 authored by Dennis Nienhüser's avatar Dennis Nienhüser

Generalize GeoWriter to support non-XML formats

Use GeoDataDocumentWriter instead of GeoWriter to register new writers
as well as to write geo data documents. For XML files it uses
GeoWriter.
parent fc42208f
......@@ -472,6 +472,8 @@ SET ( geodata_parser_SRCS
SET( geodata_writer_SRCS
geodata/writer/GeoTagWriter.cpp
geodata/writer/GeoWriter.cpp
geodata/writer/GeoWriterBackend.cpp
geodata/writer/GeoDataDocumentWriter.cpp
)
SET( geodata_SRCS
......
//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2016 Dennis Nienhüser <nienhueser@kde.org>
//
#include "GeoDataDocumentWriter.h"
#include "GeoWriterBackend.h"
#include "GeoWriter.h"
#include "GeoTagWriter.h"
#include "KmlElementDictionary.h"
#include <QFileInfo>
#include <MarbleDebug.h>
namespace Marble {
QSet<QPair<QString, GeoWriterBackend*> > GeoDataDocumentWriter::s_backends;
bool GeoDataDocumentWriter::write(QIODevice *device, const GeoDataDocument &document, const QString &documentIdentifier)
{
const GeoTagWriter* tagWriter = GeoTagWriter::recognizes(GeoTagWriter::QualifiedName(QString(), documentIdentifier));
if (tagWriter) {
GeoWriter writer;
writer.setDocumentType(documentIdentifier);
return writer.write(device, &document);
} else {
foreach(const auto &backend, s_backends) {
if (backend.first == documentIdentifier) {
backend.second->write(device, document);
return true;
}
}
mDebug() << "No writer registered to handle " << documentIdentifier;
return false;
}
}
bool GeoDataDocumentWriter::write(QString &filename, const GeoDataDocument &document, const QString &documentIdentifier)
{
QFile file(filename);
if (!file.open(QIODevice::WriteOnly)) {
mDebug() << "Cannot open" << filename << "for writing:" << file.errorString();
return false;
}
QString const docType = documentIdentifier.isEmpty() ? determineDocumentIdentifier(filename) : documentIdentifier;
return write(&file, document, docType);
}
void GeoDataDocumentWriter::registerWriter(GeoWriterBackend *writer, const QString &fileExtension)
{
s_backends << QPair<QString, GeoWriterBackend*>(fileExtension, writer);
}
QString GeoDataDocumentWriter::determineDocumentIdentifier(const QString &filename)
{
QString const fileExtension = QFileInfo(filename).suffix().toLower();
if (fileExtension == "kml") {
return kml::kmlTag_nameSpaceOgc22;
} else if (fileExtension == "osm") {
return "0.6";
}
foreach(const auto &backend, s_backends) {
if (backend.first == fileExtension) {
return backend.first;
}
}
qDebug() << "Unable to determine document from file extension " << fileExtension << ", falling back to KML document type";
return kml::kmlTag_nameSpaceOgc22;
}
}
//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2016 Dennis Nienhüser <nienhueser@kde.org>
//
#ifndef MARBLE_GEODATADOCUMENTWRITER_H
#define MARBLE_GEODATADOCUMENTWRITER_H
#include "GeoDataDocument.h"
#include "marble_export.h"
#include <QIODevice>
#include <QSet>
namespace Marble
{
class GeoWriterBackend;
/**
* Write GeoDataDocument content to I/O devices (e.g. a file)
*/
class MARBLE_EXPORT GeoDataDocumentWriter
{
public:
/**
* Write the content of the given GeoDataDocument to the given I/O device
* @param device An I/O device open for writing
* @param document A GeoDataDocument with content to write
* @param documentIdentifier XML document identifier or file extension that determines
* @return True if writing is successful, false otherwise
*/
static bool write(QIODevice* device, const GeoDataDocument &document, const QString &documentIdentifier);
/**
* Convenience method that uses a QFile as QIODevice and determines the document type from the filename extension
* @param filename Target file's name
* @param document Document to write
* @param documentIdentifier XML document identifier or filename extension that determines the content type.
* Use an empty string (default) to determine it automatically
* @return True if writing is successful, false otherwise
*/
static bool write(QString &filename, const GeoDataDocument &document, const QString &documentIdentifier = QString());
/**
* Registers a plugin as a backend for writing a certain file extension. Usually called by the MARBLE_ADD_WRITER macro.
* @param writer Backend to register
* @param fileExtension File extension to associate the backend with
*/
static void registerWriter(GeoWriterBackend* writer, const QString &fileExtension);
private:
static QString determineDocumentIdentifier(const QString &filename);
static QSet<QPair<QString, GeoWriterBackend*> > s_backends;
};
}
#endif
......@@ -68,6 +68,7 @@ private:
private:
// Only our writer is allowed to access tag handlers.
friend class GeoWriter;
friend class GeoDataDocumentWriter;
static const GeoTagWriter* recognizes(const QualifiedName&);
};
......
......@@ -84,6 +84,7 @@ public:
private:
friend class GeoTagWriter;
friend class GeoDataDocumentWriter;
bool writeElement( const GeoNode* object );
private:
......
//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2016 Dennis Nienhüser <nienhueser@kde.org>
//
#include "GeoWriterBackend.h"
#include "GeoDataDocumentWriter.h"
namespace Marble {
GeoWriterBackend::~GeoWriterBackend()
{
// does nothing
}
GeoWriterBackendRegistrar::GeoWriterBackendRegistrar(GeoWriterBackend *writer, const QString &fileExtension)
{
GeoDataDocumentWriter::registerWriter(writer, fileExtension);
}
}
//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2016 Dennis Nienhüser <nienhueser@kde.org>
//
#ifndef MARBLE_GEOWRITERBACKEND_H
#define MARBLE_GEOWRITERBACKEND_H
#include "GeoDataDocument.h"
#include "marble_export.h"
class QIODevice;
namespace Marble
{
class MARBLE_EXPORT GeoWriterBackend
{
public:
virtual ~GeoWriterBackend();
/**
* Write the contents of the given document to the device. This method is to be implemented by plugins.
* @param device An I/O device open for writing
* @param document A GeoDataDocument with content to write
* @return True if the content is successfully written to the device, false otherwise
*/
virtual bool write(QIODevice* device, const GeoDataDocument &document) = 0;
};
/**
* Helper class for writer backend registration. This class is commonly used through the MARBLE_ADD_WRITER macro
*/
class MARBLE_EXPORT GeoWriterBackendRegistrar
{
public:
GeoWriterBackendRegistrar(GeoWriterBackend* writer, const QString &fileExtension);
};
#define MARBLE_ADD_WRITER(Class, fileExtension) \
static GeoWriterBackendRegistrar s_##Class##Registrar(new Class, fileExtension);
}
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment