summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Nienhüser <nienhueser@kde.org>2016-08-06 20:25:59 (GMT)
committerDennis Nienhüser <nienhueser@kde.org>2016-08-06 20:28:56 (GMT)
commit99c25c19efbb3080a3d8b2dff4010eafc8ae310e (patch)
treed5c513d669a80ebf006dd0d8bce5001bb025b7f1
parentfc42208f6d7cded4a314c6cdd809f86979f4ed0e (diff)
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.
-rw-r--r--src/lib/marble/geodata/CMakeLists.txt2
-rw-r--r--src/lib/marble/geodata/writer/GeoDataDocumentWriter.cpp81
-rw-r--r--src/lib/marble/geodata/writer/GeoDataDocumentWriter.h65
-rw-r--r--src/lib/marble/geodata/writer/GeoTagWriter.h1
-rw-r--r--src/lib/marble/geodata/writer/GeoWriter.h1
-rw-r--r--src/lib/marble/geodata/writer/GeoWriterBackend.cpp27
-rw-r--r--src/lib/marble/geodata/writer/GeoWriterBackend.h51
7 files changed, 228 insertions, 0 deletions
diff --git a/src/lib/marble/geodata/CMakeLists.txt b/src/lib/marble/geodata/CMakeLists.txt
index 44b88b7..e21f3b1 100644
--- a/src/lib/marble/geodata/CMakeLists.txt
+++ b/src/lib/marble/geodata/CMakeLists.txt
@@ -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
diff --git a/src/lib/marble/geodata/writer/GeoDataDocumentWriter.cpp b/src/lib/marble/geodata/writer/GeoDataDocumentWriter.cpp
new file mode 100644
index 0000000..30bfd75
--- /dev/null
+++ b/src/lib/marble/geodata/writer/GeoDataDocumentWriter.cpp
@@ -0,0 +1,81 @@
+//
+// 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;
+}
+
+}
diff --git a/src/lib/marble/geodata/writer/GeoDataDocumentWriter.h b/src/lib/marble/geodata/writer/GeoDataDocumentWriter.h
new file mode 100644
index 0000000..e7bedf8
--- /dev/null
+++ b/src/lib/marble/geodata/writer/GeoDataDocumentWriter.h
@@ -0,0 +1,65 @@
+//
+// 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
diff --git a/src/lib/marble/geodata/writer/GeoTagWriter.h b/src/lib/marble/geodata/writer/GeoTagWriter.h
index 1e8b617..fe0174f 100644
--- a/src/lib/marble/geodata/writer/GeoTagWriter.h
+++ b/src/lib/marble/geodata/writer/GeoTagWriter.h
@@ -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&);
};
diff --git a/src/lib/marble/geodata/writer/GeoWriter.h b/src/lib/marble/geodata/writer/GeoWriter.h
index b0f5e9b..5f449e4 100644
--- a/src/lib/marble/geodata/writer/GeoWriter.h
+++ b/src/lib/marble/geodata/writer/GeoWriter.h
@@ -84,6 +84,7 @@ public:
private:
friend class GeoTagWriter;
+ friend class GeoDataDocumentWriter;
bool writeElement( const GeoNode* object );
private:
diff --git a/src/lib/marble/geodata/writer/GeoWriterBackend.cpp b/src/lib/marble/geodata/writer/GeoWriterBackend.cpp
new file mode 100644
index 0000000..92fdd10
--- /dev/null
+++ b/src/lib/marble/geodata/writer/GeoWriterBackend.cpp
@@ -0,0 +1,27 @@
+//
+// 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);
+}
+
+}
diff --git a/src/lib/marble/geodata/writer/GeoWriterBackend.h b/src/lib/marble/geodata/writer/GeoWriterBackend.h
new file mode 100644
index 0000000..0de1898
--- /dev/null
+++ b/src/lib/marble/geodata/writer/GeoWriterBackend.h
@@ -0,0 +1,51 @@
+//
+// 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