[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