Marble

BookmarkManager.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2010 Gaurav Gupta <1989.gaurav@googlemail.com>
4// SPDX-FileCopyrightText: 2012 Thibaut Gridel <tgridel@free.fr>
5//
6
7#include "BookmarkManager.h"
8#include "BookmarkManager_p.h"
9#include "GeoDataParser.h"
10#include "GeoDataContainer.h"
11#include "GeoDataDocument.h"
12#include "GeoDataFolder.h"
13#include "GeoDataPlacemark.h"
14#include "GeoDataTreeModel.h"
15#include "GeoDataDocumentWriter.h"
16#include "GeoDataIconStyle.h"
17#include "KmlElementDictionary.h"
18#include "MarbleDebug.h"
19#include "MarbleDirs.h"
20#include "StyleBuilder.h"
21#include <QFile>
22
23namespace Marble
24{
25
26BookmarkManagerPrivate::BookmarkManagerPrivate( GeoDataTreeModel *treeModel ) :
27 m_treeModel( treeModel ),
28 m_bookmarkDocument( nullptr ),
29 m_bookmarkFileRelativePath( "bookmarks/bookmarks.kml" ),
30 m_styleBuilder(nullptr)
31{
32 resetBookmarkDocument();
33}
34
35BookmarkManagerPrivate::~BookmarkManagerPrivate()
36{
37 Q_ASSERT( m_bookmarkDocument && "BookmarkManagerPrivate::m_bookmarkDocument is 0. Please report a Marble bug at https://bugs.kde.org" );
38 if ( m_bookmarkDocument )
39 {
40 m_treeModel->removeDocument( m_bookmarkDocument );
41 }
42 delete m_bookmarkDocument;
43}
44
45void BookmarkManagerPrivate::resetBookmarkDocument()
46{
47 if ( m_bookmarkDocument ) {
48 m_treeModel->removeDocument( m_bookmarkDocument );
49 delete m_bookmarkDocument;
50 }
51
52 GeoDataFolder* folder = new GeoDataFolder;
53 folder->setName( QObject::tr( "Default" ) );
54
55 m_bookmarkDocument = new GeoDataDocument;
56 m_bookmarkDocument->setDocumentRole( BookmarkDocument );
57 m_bookmarkDocument->setName( QObject::tr("Bookmarks") );
58 m_bookmarkDocument->append( folder );
59 m_treeModel->addDocument( m_bookmarkDocument );
60}
61
62void BookmarkManagerPrivate::setVisualCategory( GeoDataContainer *container ) {
63 for( GeoDataFolder* folder: container->folderList() ) {
64 setVisualCategory( folder );
65 }
66 for( GeoDataPlacemark* placemark: container->placemarkList() ) {
67 placemark->setVisualCategory(GeoDataPlacemark::Bookmark);
68 placemark->setZoomLevel( 1 );
69 }
70
71}
72
73BookmarkManager::BookmarkManager( GeoDataTreeModel *treeModel, QObject *parent ) :
74 QObject( parent ),
75 d( new BookmarkManagerPrivate( treeModel ) )
76{
77}
78
79BookmarkManager::~BookmarkManager()
80{
81 delete d;
82}
83
84QString BookmarkManager::bookmarkFile() const
85{
86 return MarbleDirs::path( d->m_bookmarkFileRelativePath );
87}
88
89bool BookmarkManager::loadFile( const QString &relativeFilePath )
90{
91 d->m_bookmarkFileRelativePath = relativeFilePath;
92 QString absoluteFilePath = bookmarkFile();
93
94 mDebug() << "Loading Bookmark File:" << absoluteFilePath;
95
96 if (absoluteFilePath.isEmpty())
97 return false;
98
99 if ( relativeFilePath.isNull() )
100 return false;
101
102 GeoDataDocument *document = openFile( absoluteFilePath );
103 bool recover = false;
104 if ( !document ) {
105 mDebug() << "Could not parse file" << absoluteFilePath;
106 mDebug() << "This could be caused by a previous broken bookmark file. Trying to recover.";
107 /** @todo: Remove this workaround and return false around Marble 1.4 */
108 recover = true;
109 // return false;
110 }
111
112 d->m_treeModel->removeDocument( d->m_bookmarkDocument );
113 delete d->m_bookmarkDocument;
114 d->m_bookmarkDocument = document;
115
116 if ( recover ) {
117 d->resetBookmarkDocument();
118 updateBookmarkFile();
119 } else {
120 Q_ASSERT( d->m_bookmarkDocument && "d->m_bookmarkDocument is 0 but must not be. Please report a bug at https://bugs.kde.org" );
121 d->m_treeModel->addDocument( d->m_bookmarkDocument );
122 }
123 ensureDefaultFolder();
124
125 emit bookmarksChanged();
126 return true;
127}
128
129void BookmarkManager::addBookmark( GeoDataContainer *container, const GeoDataPlacemark &placemark )
130{
131 GeoDataPlacemark *bookmark = new GeoDataPlacemark( placemark );
132 bookmark->setVisualCategory(GeoDataPlacemark::Bookmark);
133 bookmark->setZoomLevel( 1 );
134 if (bookmark->name().isEmpty()) {
135 bookmark->setName(bookmark->coordinate().toString(GeoDataCoordinates::Decimal).trimmed());
136 }
137 if (d->m_styleBuilder && bookmark->style()->iconStyle().iconPath().isEmpty()) {
138 StyleParameters style;
139 style.placemark = bookmark;
140 bookmark->setStyle(GeoDataStyle::Ptr(new GeoDataStyle(*d->m_styleBuilder->createStyle(style))));
141 }
142 d->m_treeModel->addFeature( container, bookmark );
143
144 updateBookmarkFile();
145}
146
147void BookmarkManager::updateBookmark( GeoDataPlacemark *bookmark )
148{
149 d->m_treeModel->updateFeature( bookmark );
150}
151
152void BookmarkManager::removeBookmark( GeoDataPlacemark *bookmark )
153{
154 d->m_treeModel->removeFeature( bookmark );
155 delete bookmark;
156 updateBookmarkFile();
157}
158
159GeoDataPlacemark* BookmarkManager::bookmarkAt(GeoDataContainer *container, const GeoDataCoordinates &coordinate)
160{
161 for ( GeoDataFolder *folder: container->folderList() ) {
162 GeoDataPlacemark *placemark = bookmarkAt(folder, coordinate);
163 if ( placemark )
164 return placemark;
165 }
166
167 for ( GeoDataPlacemark *placemark: container->placemarkList() ) {
168 if ( placemark->coordinate() == coordinate )
169 return placemark;
170 }
171
172 return Q_NULLPTR;
173}
174
175GeoDataDocument * BookmarkManager::document()
176{
177 return d->m_bookmarkDocument;
178}
179
180const GeoDataDocument * BookmarkManager::document() const
181{
182 return d->m_bookmarkDocument;
183}
184
185bool BookmarkManager::showBookmarks() const
186{
187 return d->m_bookmarkDocument->isVisible();
188}
189
190void BookmarkManager::setShowBookmarks( bool visible )
191{
192 d->m_bookmarkDocument->setVisible( visible );
193 d->m_treeModel->updateFeature( d->m_bookmarkDocument );
194}
195
196QVector<GeoDataFolder*> BookmarkManager::folders() const
197{
198 return d->m_bookmarkDocument->folderList();
199}
200
201GeoDataFolder* BookmarkManager::addNewBookmarkFolder( GeoDataContainer *container, const QString &name )
202{
203 //If name is empty string
204 if ( name.isEmpty() ) {
205 mDebug() << "Folder with empty name is not acceptable, please give it another name" ;
206 return Q_NULLPTR;
207 }
208
209 //If folder with same name already exist
210 QVector<GeoDataFolder*> folderList = container->folderList();
211
214 for ( ; i != end; ++i ) {
215 if ( name == ( *i )->name() ) {
216 mDebug() << "Folder with same name already exist, please give it another name";
217 return *i;
218 }
219 }
220
221 GeoDataFolder *bookmarkFolder = new GeoDataFolder();
222 bookmarkFolder->setName( name );
223
224 d->m_treeModel->addFeature( container, bookmarkFolder );
225 updateBookmarkFile();
226
227 return bookmarkFolder;
228}
229
230void BookmarkManager::renameBookmarkFolder( GeoDataFolder *folder, const QString &name )
231{
232 folder->setName( name );
233 d->m_treeModel->updateFeature( folder );
234}
235
236void BookmarkManager::removeBookmarkFolder( GeoDataFolder *folder )
237{
238 d->m_treeModel->removeFeature( folder );
239 delete folder;
240}
241
242void BookmarkManager::ensureDefaultFolder()
243{
244 if ( d->m_bookmarkDocument->size() == 0 ) {
245 addNewBookmarkFolder( d->m_bookmarkDocument, tr("Default") );
246 }
247}
248
249void BookmarkManager::removeAllBookmarks()
250{
251 d->resetBookmarkDocument();
252 updateBookmarkFile();
253}
254
255void BookmarkManager::setStyleBuilder(const StyleBuilder *styleBuilder)
256{
257 d->m_styleBuilder = styleBuilder;
258}
259
260bool BookmarkManager::updateBookmarkFile()
261{
262 const QString absoluteLocalFilePath = MarbleDirs::localPath() + QLatin1Char('/') + d->m_bookmarkFileRelativePath;
263
264 if ( ! d->m_bookmarkFileRelativePath.isNull() ) {
265 QFile file( absoluteLocalFilePath );
266 if ( !file.exists() ) {
267 // Extracting directory of file : for bookmarks it will be MarbleDirs::localPath()+/bookmarks/
268 QFileInfo fileInfo( absoluteLocalFilePath );
269 QString directoryPath = fileInfo.path();
270
271 //Creating all directories, which doesn't exist
272 QDir directory( MarbleDirs::localPath() );
273 directory.mkpath( directoryPath );
274 }
275
276 if (!GeoDataDocumentWriter::write(absoluteLocalFilePath, *d->m_bookmarkDocument)) {
277 mDebug() << "Could not write the bookmarks file" << absoluteLocalFilePath;
278 file.close();
279 return false;
280 }
281 emit bookmarksChanged();
282 file.close();
283 return true;
284 }
285 return false;
286}
287
288GeoDataDocument* BookmarkManager::openFile( const QString &fileName )
289{
290 GeoDataParser parser( GeoData_KML );
291 QFile file( fileName );
292
293 if ( !file.exists() ) {
294 return nullptr;
295 }
296
297 if ( !file.open( QIODevice::ReadOnly ) || !parser.read( &file ) ) {
298 mDebug() << "Could not open/parse file" << fileName;
299 return nullptr;
300 }
301
302 GeoDataDocument *result = dynamic_cast<GeoDataDocument*>( parser.releaseDocument() );
303 if ( !result ) {
304 return nullptr;
305 }
306
307 result->setDocumentRole( BookmarkDocument );
308 for( GeoDataFolder* folder: result->folderList() ) {
309 BookmarkManagerPrivate::setVisualCategory( folder );
310 }
311
312 return result;
313}
314
315}
316
317#include "moc_BookmarkManager.cpp"
A base class that can hold GeoDataFeatures.
QVector< GeoDataFolder * > folderList() const
A convenience function that returns all folders in this container.
QVector< GeoDataPlacemark * > placemarkList() const
A convenience function that returns all placemarks in this container.
A 3d point representation.
QString toString() const
return a string representation of the coordinate this is a convenience function which uses the defaul...
A container for Features, Styles and in the future Schemas.
void setStyle(const QSharedPointer< GeoDataStyle > &style)
Sets the style of the placemark.
QString name() const
The name of the feature.
void setZoomLevel(int index)
Sets the popularity index of the placemark.
QSharedPointer< const GeoDataStyle > style() const
Return the style assigned to the placemark, or a default style if none has been set.
void setName(const QString &value)
Set a new name for this feature.
bool isVisible() const
Return whether this feature is visible or not.
A container that is used to arrange other GeoDataFeatures.
a class representing a point of interest on the map
void setVisualCategory(GeoDataVisualCategory index)
Sets the symbol category of the placemark.
GeoDataCoordinates coordinate(const QDateTime &dateTime=QDateTime(), bool *iconAtCoordinates=nullptr) const
Return the coordinates of the placemark at time dateTime as a GeoDataCoordinates.
an addressable style group
Binds a QML item to a specific geodetic location in screen coordinates.
const_iterator constBegin() const const
const_iterator constEnd() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isEmpty() const const
bool isNull() const const
QString trimmed() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:18:16 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.