[Marble-devel] [PATCH 1/8] FileManager: the new store for files
Thibaut GRIDEL
tgridel at free.fr
Tue Sep 1 23:24:29 CEST 2009
split from PlacemarkManager
6 files changed, 649 insertions(+), 1 deletions(-)
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index ab909b0..f8de6b7 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -130,6 +130,8 @@ set(marblewidget_SRCS
#jsonparser.cpp
VectorComposer.cpp
VectorMap.cpp
+ FileLoader.cpp
+ FileManager.cpp
FileViewModel.cpp
GpxFileViewItem.cpp
KmlFileViewItem.cpp
diff --git a/src/lib/FileLoader.cpp b/src/lib/FileLoader.cpp
new file mode 100644
index 0000000..e0173e6
--- /dev/null
+++ b/src/lib/FileLoader.cpp
@@ -0,0 +1,256 @@
+//
+// This file is part of the Marble Desktop 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 2008 Patrick Spendrin <ps_ml at gmx.de>
+//
+
+#include "FileLoader.h"
+
+#include <QtCore/QBuffer>
+#include <QtCore/QDataStream>
+#include <QtCore/QDateTime>
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QThread>
+
+#include "GeoDataParser.h"
+#include "GeoDataDocument.h"
+#include "GeoDataPlacemark.h"
+#include "MarbleDirs.h"
+
+namespace Marble
+{
+
+FileLoader::FileLoader( QObject* parent, const QString& file )
+ : QThread( parent ),
+ m_filepath( file ),
+ m_contents( QString() ),
+ m_document( 0 )
+{
+}
+
+FileLoader::FileLoader( QObject* parent, const QString& contents, const QString& file )
+ : QThread( parent ),
+ m_filepath( file ),
+ m_contents( contents ),
+ m_document( 0 )
+{
+}
+
+FileLoader::~FileLoader()
+{
+ delete m_document;
+}
+
+QString FileLoader::path() const
+{
+ return m_filepath;
+}
+
+void FileLoader::run()
+{
+ if( m_contents.isEmpty() ) {
+ QString defaultcachename;
+ QString defaultsrcname;
+ QString defaulthomecache;
+
+ if( m_filepath.endsWith(".kml") ) {
+ m_filepath.remove(QRegExp("\\.kml$"));
+ }
+ qDebug() << "starting parser for" << m_filepath;
+
+ QFileInfo fileinfo(m_filepath);
+ if ( fileinfo.isAbsolute() ) {
+ // We got an _absolute_ path now: e.g. "/patrick.kml"
+ defaultcachename = m_filepath + ".cache";
+ defaultsrcname = m_filepath + ".kml";
+ }
+ else {
+ if ( m_filepath.contains( '/' ) ) {
+ // _relative_ path: "maps/mars/viking/patrick.kml"
+ defaultcachename = MarbleDirs::path( m_filepath + ".cache" );
+ defaultsrcname = MarbleDirs::path( m_filepath + ".kml");
+ defaulthomecache = MarbleDirs::localPath() + m_filepath + ".cache";
+ }
+ else {
+ // _standard_ shared placemarks: "placemarks/patrick.kml"
+ defaultcachename = MarbleDirs::path( "placemarks/" + m_filepath + ".cache" );
+ defaultsrcname = MarbleDirs::path( "placemarks/" + m_filepath + ".kml");
+ defaulthomecache = MarbleDirs::localPath() + "/placemarks/" + m_filepath + ".cache";
+ }
+ }
+
+ if ( QFile::exists( defaultcachename ) ) {
+ qDebug() << "Loading Cache File:" + defaultcachename;
+
+ bool cacheoutdated = false;
+ QDateTime sourceLastModified;
+ QDateTime cacheLastModified;
+
+ if ( QFile::exists( defaultsrcname ) ) {
+ sourceLastModified = QFileInfo( defaultsrcname ).lastModified();
+ cacheLastModified = QFileInfo( defaultcachename ).lastModified();
+
+ if ( cacheLastModified < sourceLastModified )
+ cacheoutdated = true;
+ }
+
+ bool loadok = false;
+
+ if ( !cacheoutdated ) {
+ loadok = loadFile( defaultcachename );
+ if ( loadok )
+ emit newGeoDataDocumentAdded( m_document );
+ }
+ qDebug() << "Loading ended" << loadok;
+ if ( loadok ) {
+ qDebug() << "placemarksLoaded";
+ return;
+ }
+ }
+
+
+ if ( QFile::exists( defaultsrcname ) ) {
+ // Read the KML file.
+ importKml( defaultsrcname );
+ }
+ else {
+ qDebug() << "No Default Placemark Source File for " << m_filepath;
+ emit fileLoaderFailed( this );
+ }
+ } else {
+ // Read the KML Data
+ importKmlFromData();
+ }
+}
+
+const quint32 MarbleMagicNumber = 0x31415926;
+
+void FileLoader::importKml( const QString& filename )
+{
+ GeoDataParser parser( GeoData_KML );
+
+ QFile file( filename );
+ if ( !file.exists() ) {
+ qWarning( "File does not exist!" );
+ return;
+ }
+
+ // Open file in right mode
+ file.open( QIODevice::ReadOnly );
+
+ if ( !parser.read( &file ) ) {
+ qWarning( "Could not parse file!" );
+ return;
+ }
+ GeoDocument* document = parser.releaseDocument();
+ Q_ASSERT( document );
+
+ m_document = static_cast<GeoDataDocument*>( document );
+ m_document->setFileName( m_filepath );
+
+ file.close();
+
+ qDebug() << "newGeoDataDocumentAdded" << m_filepath;
+
+ emit newGeoDataDocumentAdded( m_document );
+}
+
+void FileLoader::importKmlFromData()
+{
+ GeoDataParser parser( GeoData_KML );
+
+ QByteArray ba( m_contents.toUtf8() );
+ QBuffer buffer( &ba );
+ buffer.open( QIODevice::ReadOnly );
+
+ if ( !parser.read( &buffer ) ) {
+ qWarning( "Could not parse buffer!" );
+ return;
+ }
+ GeoDocument* document = parser.releaseDocument();
+ Q_ASSERT( document );
+
+ m_document = static_cast<GeoDataDocument*>( document );
+ m_document->setFileName( m_filepath );
+
+ buffer.close();
+
+ qDebug() << "newGeoDataDocumentAdded" << m_filepath;
+
+ emit newGeoDataDocumentAdded( m_document );
+}
+
+bool FileLoader::loadFile( const QString &filename )
+{
+ QFile file( filename );
+ file.open( QIODevice::ReadOnly );
+ QDataStream in( &file );
+
+ // Read and check the header
+ quint32 magic;
+ in >> magic;
+ if ( magic != MarbleMagicNumber ) {
+ qDebug( "Bad file format!" );
+ return false;
+ }
+
+ // Read the version
+ qint32 version;
+ in >> version;
+ if ( version < 014 ) {
+ qDebug( "Bad file - too old!" );
+ return false;
+ }
+ /*
+ if (version > 002) {
+ qDebug( "Bad file - too new!" );
+ return;
+ }
+ */
+ m_document = new GeoDataDocument();
+
+ m_document->setFileName( m_filepath );
+
+ in.setVersion( QDataStream::Qt_4_2 );
+
+ // Read the data itself
+ // Use double to provide a single cache file format across architectures
+ double lon;
+ double lat;
+ double alt;
+ double area;
+
+ QString tmpstr;
+ qint64 tmpint64;
+
+ while ( !in.atEnd() ) {
+ GeoDataPlacemark mark;
+ in >> tmpstr;
+ mark.setName( tmpstr );
+ in >> lon >> lat >> alt;
+ mark.setCoordinate( (qreal)(lon), (qreal)(lat), (qreal)(alt) );
+ in >> tmpstr;
+ mark.setRole( tmpstr.at(0) );
+ in >> tmpstr;
+ mark.setDescription( tmpstr );
+ in >> tmpstr;
+ mark.setCountryCode( tmpstr );
+ in >> area;
+ mark.setArea( (qreal)(area) );
+ in >> tmpint64;
+ mark.setPopulation( tmpint64 );
+
+ m_document->append( mark );
+ }
+
+ m_document->setVisible( false );
+ return true;
+}
+
+#include "FileLoader.moc"
+} // namespace Marble
diff --git a/src/lib/FileLoader.h b/src/lib/FileLoader.h
new file mode 100644
index 0000000..2d2bc22
--- /dev/null
+++ b/src/lib/FileLoader.h
@@ -0,0 +1,48 @@
+//
+// This file is part of the Marble Desktop 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 2008 Patrick Spendrin <ps_ml at gmx.de>
+//
+#ifndef FILELOADER_H
+#define FILELOADER_H
+
+#include <QtCore/QThread>
+#include <QtCore/QString>
+
+namespace Marble
+{
+
+class GeoDataDocument;
+
+class FileLoader : public QThread
+{
+ Q_OBJECT
+ public:
+ FileLoader( QObject* parent, const QString& file );
+ FileLoader( QObject* parent, const QString& contents, const QString& name );
+ virtual ~FileLoader();
+
+ void run();
+ QString path() const;
+
+ Q_SIGNALS:
+ void fileLoaderFailed( FileLoader* );
+ void newGeoDataDocumentAdded( GeoDataDocument* );
+ private:
+ void importKml( const QString& filename );
+ void importKmlFromData();
+ bool loadFile(const QString &filename );
+ void saveFile();
+
+ QString m_filepath;
+ QString m_contents;
+ GeoDataDocument *m_document;
+};
+
+} // namespace Marble
+
+#endif // FILELOADER_H
diff --git a/src/lib/FileManager.cpp b/src/lib/FileManager.cpp
new file mode 100644
index 0000000..0b70218
--- /dev/null
+++ b/src/lib/FileManager.cpp
@@ -0,0 +1,219 @@
+//
+// This file is part of the Marble Desktop 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 2006-2007 Torsten Rahn <tackat at kde.org>"
+// Copyright 2007 Inge Wallin <ingwa at kde.org>"
+//
+
+#include "FileManager.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+
+#include "FileLoader.h"
+#include "FileViewModel.h"
+#include "KmlFileViewItem.h"
+#include "MarbleDataFacade.h"
+#include "MarbleGeometryModel.h"
+
+#include "GeoDataDocument.h"
+
+
+using namespace Marble;
+
+namespace Marble
+{
+class FileManagerPrivate
+{
+ public:
+ FileManagerPrivate( )
+ : m_datafacade( 0 )
+ {
+ }
+
+ MarbleDataFacade* m_datafacade;
+ QList<FileLoader*> m_loaderList;
+ QStringList m_pathList;
+ QList < AbstractFileViewItem* > m_fileItemList;
+};
+}
+
+FileManager::FileManager( QObject *parent )
+ : QObject( parent )
+ , d( new FileManagerPrivate() )
+{
+}
+
+
+FileManager::~FileManager()
+{
+ foreach( FileLoader *loader, d->m_loaderList ) {
+ if ( loader ) {
+ loader->wait();
+ }
+ }
+
+ foreach( AbstractFileViewItem *file, d->m_fileItemList)
+ {
+ delete file;
+ }
+
+ delete d;
+}
+
+void FileManager::setDataFacade( MarbleDataFacade *facade )
+{
+ d->m_datafacade = facade;
+// d->m_datafacade->fileViewModel()->setFileManager(this);
+}
+
+MarbleDataFacade *FileManager::dataFacade()
+{
+ return d->m_datafacade;
+}
+
+QStringList FileManager::containers() const
+{
+ QStringList retList;
+ for( int line = 0; line < d->m_fileItemList.count(); ++line ) {
+ retList << d->m_fileItemList.at( line )->name();
+ }
+ return retList + d->m_pathList;
+}
+
+QString FileManager::toRegularName( QString name )
+{
+ return name.remove(".kml").remove(".cache");
+}
+
+void FileManager::addFile( const QString& filepath )
+{
+ if( ! containers().contains( toRegularName( filepath ) ) ) {
+ qDebug() << "adding container:" << toRegularName( filepath );
+ FileLoader* loader = new FileLoader( this, filepath );
+ appendLoader( loader );
+ d->m_pathList.append( toRegularName( filepath ) );
+ }
+}
+
+void FileManager::addData( const QString &name, const QString &data )
+{
+ FileLoader* loader = new FileLoader( this, data, name );
+ appendLoader( loader );
+}
+
+void FileManager::appendLoader( FileLoader *loader )
+{
+ connect ( loader, SIGNAL( fileLoaderFailed( FileLoader* ) ),
+ this, SLOT( cleanupLoader( FileLoader* ) ) );
+
+ connect ( loader, SIGNAL( newGeoDataDocumentAdded( GeoDataDocument* ) ),
+ this, SLOT( addGeoDataDocument( GeoDataDocument* ) ) );
+
+ d->m_loaderList.append( loader );
+ loader->start();
+}
+
+void FileManager::removeFile( const QString& key )
+{
+ for( int i = 0; i < d->m_fileItemList.size(); ++i )
+ {
+ if( toRegularName( key ) == toRegularName( d->m_fileItemList.at(i)->name() ) ) {
+ closeFile(i);
+ break;
+ }
+ }
+}
+
+void FileManager::addFile ( AbstractFileViewItem * item )
+{
+ qDebug() << "FileManager::addFile";
+ d->m_fileItemList.append( item );
+ emit fileAdded(d->m_fileItemList.indexOf( item ) );
+}
+
+void FileManager::saveFile( int index )
+{
+ if (index < d->m_fileItemList.size() )
+ {
+ d->m_fileItemList.at( index )->saveFile();
+ }
+}
+
+void FileManager::closeFile( int index )
+{
+ qDebug() << "FileManager::closeFile";
+ if (index < d->m_fileItemList.size() )
+ {
+ d->m_fileItemList.at( index )->closeFile( indexStart( index ));
+ delete d->m_fileItemList.at( index );
+ d->m_fileItemList.removeAt( index );
+ emit fileRemoved( index );
+ }
+}
+
+int FileManager::size() const
+{
+ return d->m_fileItemList.size();
+}
+
+AbstractFileViewItem * FileManager::at( int index )
+{
+ if (index < d->m_fileItemList.size() )
+ {
+ return d->m_fileItemList.at( index );
+ }
+ return 0;
+}
+
+void FileManager::addGeoDataDocument( GeoDataDocument* document )
+{
+ Q_UNUSED( document );
+// KmlFileViewItem* item = new KmlFileViewItem( *this, *document );
+// addFile( item );
+//
+// // now get the document that will be preserved throughout the life time
+// GeoDataDocument* doc = item->document();
+// // remove the hashes in front of the styles.
+// QVector<GeoDataFeature>::Iterator end = doc->end();
+// QVector<GeoDataFeature>::Iterator itr = doc->begin();
+// for ( ; itr != end; ++itr ) {
+// // use *itr (or itr.value()) here
+// QString styleUrl = itr->styleUrl().remove('#');
+// itr->setStyle( &doc->style( styleUrl ) );
+// }
+//
+// // do not set this file if it only contains points
+// if( doc->isVisible() && d->m_datafacade->geometryModel() )
+// d->m_datafacade->geometryModel()->setGeoDataRoot( doc );
+// emit geoDataDocumentAdded( *doc );
+//
+// if( d->m_loaderList.isEmpty() ) {
+// emit finalize();
+// }
+}
+
+void FileManager::cleanupLoader( FileLoader* loader )
+{
+ d->m_loaderList.removeAll( loader );
+ if ( loader->isFinished() ) {
+ d->m_pathList.removeAll( loader->path() );
+ delete loader;
+ }
+}
+
+int FileManager::indexStart( int index )
+{
+ int start = 0;
+ for( int i = 0; i < index; i++ ) {
+ start += d->m_fileItemList.at( i )->size();
+ }
+ return start;
+}
+
+#include "FileManager.moc"
diff --git a/src/lib/FileManager.h b/src/lib/FileManager.h
new file mode 100644
index 0000000..2b86f37
--- /dev/null
+++ b/src/lib/FileManager.h
@@ -0,0 +1,118 @@
+//
+// This file is part of the Marble Desktop 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 2006-2007 Torsten Rahn <tackat at kde.org>"
+// Copyright 2007 Inge Wallin <ingwa at kde.org>"
+//
+
+
+#ifndef FILEMANAGER_H
+#define FILEMANAGER_H
+
+#include <QtCore/QList>
+#include <QtCore/QObject>
+#include <QtCore/QString>
+
+namespace Marble
+{
+
+class AbstractFileViewItem;
+class FileManagerPrivate;
+class GeoDataDocument;
+class MarbleDataFacade;
+class FileLoader;
+
+/**
+ * This class is responsible for loading the
+ * different files into Geodata model.
+ *
+ * The loaded data are accessible via
+ * various models in the DataFacade.
+ */
+class FileManager : public QObject
+{
+ friend class MarblePlacemarkModel;
+ Q_OBJECT
+
+ public:
+ /**
+ * Creates a new file manager.
+ *
+ * @param parent The parent object.
+ */
+ explicit FileManager( QObject *parent = 0 );
+
+ /**
+ * Destroys the file manager.
+ */
+ ~FileManager();
+
+ /**
+ * Sets the DataFacade from which the models can be accessed.
+ */
+ void setDataFacade ( MarbleDataFacade *facade );
+
+ MarbleDataFacade *dataFacade ();
+
+ /**
+ * return a list containing all containers that have been queued for loading or that are
+ * loaded already
+ */
+ QStringList containers() const;
+
+ /**
+ * Loads a new file into the manager.
+ */
+ void addFile( const QString &fileName );
+
+ /**
+ * removes an existing file from the manager
+ */
+ void removeFile( const QString &fileName );
+
+ /**
+ * add Data containing KML code as string
+ */
+ void addData( const QString &name, const QString &data );
+
+ void addFile( AbstractFileViewItem *item );
+ void saveFile( int index );
+ void closeFile( int index );
+
+ int size() const;
+ AbstractFileViewItem *at( int index );
+
+
+ Q_SIGNALS:
+ void geoDataDocumentAdded( GeoDataDocument &document );
+ void fileAdded( int index );
+ void fileRemoved( int index );
+ void finalize();
+
+ private Q_SLOTS:
+ void addGeoDataDocument( GeoDataDocument *document );
+ void cleanupLoader( FileLoader *loader );
+
+ private:
+
+ int indexStart( int index );
+
+ void appendLoader( FileLoader *loader );
+
+ /**
+ * internal helper function which returns the regular name of a kml or cache file
+ */
+ static QString toRegularName( QString name );
+
+ Q_DISABLE_COPY( FileManager )
+
+ FileManagerPrivate *const d;
+};
+
+}
+
+#endif // FILEMANAGER_H
diff --git a/src/lib/MarbleModel.cpp b/src/lib/MarbleModel.cpp
index 03e7d41..057eaec 100644
--- a/src/lib/MarbleModel.cpp
+++ b/src/lib/MarbleModel.cpp
@@ -58,6 +58,7 @@
#include "MarblePlacemarkModel.h"
#include "MarbleGeometryModel.h"
#include "MergedLayerDecorator.h"
+#include "FileManager.h"
#include "PlacemarkManager.h"
#include "PlacemarkLayout.h"
#include "PlacemarkPainter.h"
@@ -87,6 +88,7 @@ class MarbleModelPrivate
m_layerManager( 0 ),
m_downloadManager( new HttpDownloadManager( QUrl(), new FileStoragePolicy(
MarbleDirs::localPath() ))),
+ m_fileManager( 0 ),
m_placemarkmanager( 0 )
{
}
@@ -117,6 +119,7 @@ class MarbleModelPrivate
static VectorComposer *m_veccomposer; // FIXME: Make not a pointer.
// Places on the map
+ FileManager *m_fileManager;
PlacemarkManager *m_placemarkmanager;
PlacemarkLayout *m_placemarkLayout;
QSortFilterProxyModel *m_popSortModel;
@@ -164,7 +167,8 @@ MarbleModel::MarbleModel( QObject *parent )
in setMapTheme if the theme being loaded does need it. If the theme
doesn't need it, it's left as is. */
}
-
+ d->m_fileManager = new FileManager();
+ d->m_fileManager->setDataFacade(d->m_dataFacade);
d->m_placemarkmanager = new PlacemarkManager();
d->m_placemarkmanager->setDataFacade(d->m_dataFacade);
@@ -245,6 +249,7 @@ MarbleModel::~MarbleModel()
}
delete d->m_popSortModel;
delete d->m_placemarkmanager;
+ delete d->m_fileManager;
delete d->m_gpsLayer;
delete d->m_mapTheme;
delete d->m_timer;
--
1.6.3.3
More information about the Marble-devel
mailing list