Marble

BookmarkManager.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2010 Gaurav Gupta <[email protected]>
4 // SPDX-FileCopyrightText: 2012 Thibaut Gridel <[email protected]>
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 
23 namespace Marble
24 {
25 
26 BookmarkManagerPrivate::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 
35 BookmarkManagerPrivate::~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 
45 void 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 
62 void 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 
73 BookmarkManager::BookmarkManager( GeoDataTreeModel *treeModel, QObject *parent ) :
74  QObject( parent ),
75  d( new BookmarkManagerPrivate( treeModel ) )
76 {
77 }
78 
79 BookmarkManager::~BookmarkManager()
80 {
81  delete d;
82 }
83 
85 {
86  return MarbleDirs::path( d->m_bookmarkFileRelativePath );
87 }
88 
89 bool BookmarkManager::loadFile( const QString &relativeFilePath )
90 {
91  d->m_bookmarkFileRelativePath = relativeFilePath;
92  QString absoluteFilePath = bookmarkFile();
93 
94  mDebug() << Q_FUNC_INFO << "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  }
124 
125  emit bookmarksChanged();
126  return true;
127 }
128 
130 {
131  GeoDataPlacemark *bookmark = new GeoDataPlacemark( placemark );
132  bookmark->setVisualCategory(GeoDataPlacemark::Bookmark);
133  bookmark->setZoomLevel( 1 );
134  if (bookmark->name().isEmpty()) {
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 
147 void BookmarkManager::updateBookmark( GeoDataPlacemark *bookmark )
148 {
149  d->m_treeModel->updateFeature( bookmark );
150 }
151 
152 void BookmarkManager::removeBookmark( GeoDataPlacemark *bookmark )
153 {
154  d->m_treeModel->removeFeature( bookmark );
155  delete bookmark;
156  updateBookmarkFile();
157 }
158 
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 
175 GeoDataDocument * BookmarkManager::document()
176 {
177  return d->m_bookmarkDocument;
178 }
179 
180 const GeoDataDocument * BookmarkManager::document() const
181 {
182  return d->m_bookmarkDocument;
183 }
184 
185 bool BookmarkManager::showBookmarks() const
186 {
187  return d->m_bookmarkDocument->isVisible();
188 }
189 
190 void BookmarkManager::setShowBookmarks( bool visible )
191 {
192  d->m_bookmarkDocument->setVisible( visible );
193  d->m_treeModel->updateFeature( d->m_bookmarkDocument );
194 }
195 
197 {
198  return d->m_bookmarkDocument->folderList();
199 }
200 
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 
230 void BookmarkManager::renameBookmarkFolder( GeoDataFolder *folder, const QString &name )
231 {
232  folder->setName( name );
233  d->m_treeModel->updateFeature( folder );
234 }
235 
236 void BookmarkManager::removeBookmarkFolder( GeoDataFolder *folder )
237 {
238  d->m_treeModel->removeFeature( folder );
239  delete folder;
240 }
241 
243 {
244  if ( d->m_bookmarkDocument->size() == 0 ) {
245  addNewBookmarkFolder( d->m_bookmarkDocument, tr("Default") );
246  }
247 }
248 
250 {
251  d->resetBookmarkDocument();
252  updateBookmarkFile();
253 }
254 
255 void BookmarkManager::setStyleBuilder(const StyleBuilder *styleBuilder)
256 {
257  d->m_styleBuilder = styleBuilder;
258 }
259 
260 bool 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 
288 GeoDataDocument* 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"
QString toString() const
return a string representation of the coordinate this is a convenience function which uses the defaul...
A 3d point representation.
bool isNull() const const
void addBookmark(GeoDataContainer *folder, const GeoDataPlacemark &bookmark)
add bookmark in a folder
QVector< GeoDataFolder * > folders() const
return Vector of folders
QString trimmed() const const
QString bookmarkFile() const
return bookmark file path
QVector::const_iterator constEnd() const const
GeoDataPlacemark * bookmarkAt(GeoDataContainer *container, const GeoDataCoordinates &coordinate)
checks all the bookmarks in container recursively and returns pointer to the one having the same coor...
void setName(const QString &value)
Set a new name for this feature.
void setVisualCategory(GeoDataVisualCategory index)
Sets the symbol category of the placemark.
A container that is used to arrange other GeoDataFeatures.
Definition: GeoDataFolder.h:33
static bool write(QIODevice *device, const GeoDataDocument &document, const QString &documentIdentifier)
Write the content of the given GeoDataDocument to the given I/O device.
void setZoomLevel(int index)
Sets the popularity index of the placemark.
QString name() const
The name of the feature.
bool isEmpty() const const
@ Decimal
"Decimal" notation (base-10)
GeoDataCoordinates coordinate(const QDateTime &dateTime=QDateTime(), bool *iconAtCoordinates=nullptr) const
Return the coordinates of the placemark at time dateTime as a GeoDataCoordinates.
A container for Features, Styles and in the future Schemas.
QVector< GeoDataPlacemark * > placemarkList() const
A convenience function that returns all placemarks in this container.
Binds a QML item to a specific geodetic location in screen coordinates.
void ensureDefaultFolder()
checks that there is at least one folder
a class representing a point of interest on the map
A base class that can hold GeoDataFeatures.
void setStyleBuilder(const StyleBuilder *styleBuilder)
void removeAllBookmarks()
remove all folders and bookmarks except default folder
void setStyle(const QSharedPointer< GeoDataStyle > &style)
Sets the style of the placemark.
QVector< GeoDataFolder * > folderList() const
A convenience function that returns all folders in this container.
QVector::const_iterator constBegin() const const
an addressable style group
Definition: GeoDataStyle.h:50
QString tr(const char *sourceText, const char *disambiguation, int n)
bool loadFile(const QString &relativeFilePath)
load bookmark file as GeoDataDocument and return true if loaded successfully else false
void bookmarksChanged()
One or more bookmarks were added or removed.
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:31
QSharedPointer< const GeoDataStyle > style() const
Return the style assigned to the placemark, or a default style if none has been set.
GeoDataFolder * addNewBookmarkFolder(GeoDataContainer *container, const QString &name)
add a folder
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Oct 4 2023 04:09:41 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.