1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <tackat@kde.org>
4 // SPDX-FileCopyrightText: 2007 Inge Wallin <ingwa@kde.org>
5 //
6
7 #include "FileManager.h"
8
9 #include <QFileInfo>
10 #include <QElapsedTimer>
11
12 #include "FileLoader.h"
13 #include "MarbleDebug.h"
14 #include "MarbleModel.h"
15 #include "GeoDataTreeModel.h"
16
17 #include "GeoDataLatLonAltBox.h"
18 #include "GeoDataStyle.h"
19
20
21 using namespace Marble;
22
23 namespace Marble
24 {
25 class FileManagerPrivate
26 {
27 public:
FileManagerPrivate(GeoDataTreeModel * treeModel,const PluginManager * pluginManager,FileManager * parent)28 FileManagerPrivate( GeoDataTreeModel *treeModel, const PluginManager *pluginManager, FileManager* parent ) :
29 q( parent ),
30 m_treeModel( treeModel ),
31 m_pluginManager( pluginManager )
32 {
33 }
34
~FileManagerPrivate()35 ~FileManagerPrivate()
36 {
37 for ( FileLoader *loader: m_loaderList ) {
38 if ( loader ) {
39 loader->wait();
40 }
41 }
42 }
43
44 void appendLoader( FileLoader *loader );
45 void closeFile( const QString &key );
46 void cleanupLoader( FileLoader *loader );
47
48 FileManager *const q;
49 GeoDataTreeModel *const m_treeModel;
50 const PluginManager *const m_pluginManager;
51
52 QList<FileLoader*> m_loaderList;
53 QHash < QString, GeoDataDocument* > m_fileItemHash;
54 GeoDataLatLonBox m_latLonBox;
55 QElapsedTimer m_timer;
56 };
57 }
58
FileManager(GeoDataTreeModel * treeModel,const PluginManager * pluginManager,QObject * parent)59 FileManager::FileManager( GeoDataTreeModel *treeModel, const PluginManager *pluginManager, QObject *parent )
60 : QObject( parent )
61 , d( new FileManagerPrivate( treeModel, pluginManager, this ) )
62 {
63 }
64
65
~FileManager()66 FileManager::~FileManager()
67 {
68 delete d;
69 }
70
addFile(const QString & filepath,const QString & property,const GeoDataStyle::Ptr & style,DocumentRole role,int renderOrder,bool recenter)71 void FileManager::addFile( const QString& filepath, const QString& property, const GeoDataStyle::Ptr &style, DocumentRole role, int renderOrder, bool recenter )
72 {
73 if( d->m_fileItemHash.contains( filepath ) ) {
74 return; // already loaded
75 }
76
77 for ( const FileLoader *loader: d->m_loaderList ) {
78 if ( loader->path() == filepath )
79 return; // currently loading
80 }
81
82 mDebug() << "adding container:" << filepath;
83 mDebug() << "Starting placemark loading timer";
84 d->m_timer.start();
85 FileLoader* loader = new FileLoader( this, d->m_pluginManager, recenter, filepath, property, style, role, renderOrder );
86 d->appendLoader( loader );
87 }
88
addData(const QString & name,const QString & data,DocumentRole role)89 void FileManager::addData( const QString &name, const QString &data, DocumentRole role )
90 {
91 FileLoader* loader = new FileLoader( this, d->m_pluginManager, data, name, role );
92 d->appendLoader( loader );
93 }
94
appendLoader(FileLoader * loader)95 void FileManagerPrivate::appendLoader( FileLoader *loader )
96 {
97 QObject::connect( loader, SIGNAL(loaderFinished(FileLoader*)),
98 q, SLOT(cleanupLoader(FileLoader*)) );
99
100 m_loaderList.append( loader );
101 loader->start();
102 }
103
removeFile(const QString & key)104 void FileManager::removeFile( const QString& key )
105 {
106 for ( FileLoader *loader: d->m_loaderList ) {
107 if ( loader->path() == key ) {
108 disconnect( loader, nullptr, this, nullptr );
109 loader->wait();
110 d->m_loaderList.removeAll( loader );
111 delete loader->document();
112 return;
113 }
114 }
115
116 if( d->m_fileItemHash.contains( key ) ) {
117 d->closeFile( key );
118 }
119
120 mDebug() << "could not identify " << key;
121 }
122
closeFile(const QString & key)123 void FileManagerPrivate::closeFile( const QString& key )
124 {
125 mDebug() << "FileManager::closeFile " << key;
126 if( m_fileItemHash.contains( key ) ) {
127 GeoDataDocument *doc = m_fileItemHash.value( key );
128 m_treeModel->removeDocument( doc );
129 emit q->fileRemoved( key );
130 delete doc;
131 m_fileItemHash.remove( key );
132 }
133 }
134
closeFile(const GeoDataDocument * document)135 void FileManager::closeFile( const GeoDataDocument *document )
136 {
137 QHash < QString, GeoDataDocument* >::iterator itpoint = d->m_fileItemHash.begin();
138 QHash < QString, GeoDataDocument* >::iterator const endpoint = d->m_fileItemHash.end();
139 for (; itpoint != endpoint; ++itpoint ) {
140 if( d->m_fileItemHash.value( itpoint.key() ) == document ) {
141 d->closeFile( itpoint.key() );
142 return;
143 }
144 }
145 }
146
size() const147 int FileManager::size() const
148 {
149 return d->m_fileItemHash.size();
150 }
151
at(const QString & key)152 GeoDataDocument * FileManager::at( const QString &key )
153 {
154 if ( d->m_fileItemHash.contains( key ) ) {
155 return d->m_fileItemHash.value( key );
156 }
157 return nullptr;
158 }
159
pendingFiles() const160 int FileManager::pendingFiles() const
161 {
162 return d->m_loaderList.size();
163 }
164
cleanupLoader(FileLoader * loader)165 void FileManagerPrivate::cleanupLoader( FileLoader* loader )
166 {
167 GeoDataDocument *doc = loader->document();
168 m_loaderList.removeAll( loader );
169 if ( loader->isFinished() ) {
170 if ( doc ) {
171 if ( doc->name().isEmpty() && !doc->fileName().isEmpty() )
172 {
173 QFileInfo file( doc->fileName() );
174 doc->setName( file.baseName() );
175 }
176 m_treeModel->addDocument( doc );
177 m_fileItemHash.insert( loader->path(), doc );
178 emit q->fileAdded( loader->path() );
179 if( loader->recenter() ) {
180 m_latLonBox |= doc->latLonAltBox();
181 }
182 }
183 if ( !loader->error().isEmpty() ) {
184 qWarning() << "Failed to parse" << loader->path() << loader->error();
185 emit q->fileError(loader->path(), loader->error());
186 }
187 delete loader;
188 }
189 if ( m_loaderList.isEmpty() )
190 {
191 mDebug() << "Finished loading all placemarks " << m_timer.elapsed();
192
193 if ( !m_latLonBox.isEmpty() ) {
194 emit q->centeredDocument( m_latLonBox );
195 }
196 m_latLonBox.clear();
197 }
198 }
199
200 #include "moc_FileManager.cpp"
201