File indexing completed on 2024-04-21 03:49:28
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2010 Gaurav Gupta <1989.gaurav@googlemail.com> 0004 // SPDX-FileCopyrightText: 2012 Thibaut Gridel <tgridel@free.fr> 0005 // 0006 0007 #include "BookmarkManager.h" 0008 #include "BookmarkManager_p.h" 0009 #include "GeoDataParser.h" 0010 #include "GeoDataContainer.h" 0011 #include "GeoDataDocument.h" 0012 #include "GeoDataFolder.h" 0013 #include "GeoDataPlacemark.h" 0014 #include "GeoDataTreeModel.h" 0015 #include "GeoDataDocumentWriter.h" 0016 #include "GeoDataIconStyle.h" 0017 #include "KmlElementDictionary.h" 0018 #include "MarbleDebug.h" 0019 #include "MarbleDirs.h" 0020 #include "StyleBuilder.h" 0021 #include <QFile> 0022 0023 namespace Marble 0024 { 0025 0026 BookmarkManagerPrivate::BookmarkManagerPrivate( GeoDataTreeModel *treeModel ) : 0027 m_treeModel( treeModel ), 0028 m_bookmarkDocument( nullptr ), 0029 m_bookmarkFileRelativePath( "bookmarks/bookmarks.kml" ), 0030 m_styleBuilder(nullptr) 0031 { 0032 resetBookmarkDocument(); 0033 } 0034 0035 BookmarkManagerPrivate::~BookmarkManagerPrivate() 0036 { 0037 Q_ASSERT( m_bookmarkDocument && "BookmarkManagerPrivate::m_bookmarkDocument is 0. Please report a Marble bug at https://bugs.kde.org" ); 0038 if ( m_bookmarkDocument ) 0039 { 0040 m_treeModel->removeDocument( m_bookmarkDocument ); 0041 } 0042 delete m_bookmarkDocument; 0043 } 0044 0045 void BookmarkManagerPrivate::resetBookmarkDocument() 0046 { 0047 if ( m_bookmarkDocument ) { 0048 m_treeModel->removeDocument( m_bookmarkDocument ); 0049 delete m_bookmarkDocument; 0050 } 0051 0052 GeoDataFolder* folder = new GeoDataFolder; 0053 folder->setName( QObject::tr( "Default" ) ); 0054 0055 m_bookmarkDocument = new GeoDataDocument; 0056 m_bookmarkDocument->setDocumentRole( BookmarkDocument ); 0057 m_bookmarkDocument->setName( QObject::tr("Bookmarks") ); 0058 m_bookmarkDocument->append( folder ); 0059 m_treeModel->addDocument( m_bookmarkDocument ); 0060 } 0061 0062 void BookmarkManagerPrivate::setVisualCategory( GeoDataContainer *container ) { 0063 for( GeoDataFolder* folder: container->folderList() ) { 0064 setVisualCategory( folder ); 0065 } 0066 for( GeoDataPlacemark* placemark: container->placemarkList() ) { 0067 placemark->setVisualCategory(GeoDataPlacemark::Bookmark); 0068 placemark->setZoomLevel( 1 ); 0069 } 0070 0071 } 0072 0073 BookmarkManager::BookmarkManager( GeoDataTreeModel *treeModel, QObject *parent ) : 0074 QObject( parent ), 0075 d( new BookmarkManagerPrivate( treeModel ) ) 0076 { 0077 } 0078 0079 BookmarkManager::~BookmarkManager() 0080 { 0081 delete d; 0082 } 0083 0084 QString BookmarkManager::bookmarkFile() const 0085 { 0086 return MarbleDirs::path( d->m_bookmarkFileRelativePath ); 0087 } 0088 0089 bool BookmarkManager::loadFile( const QString &relativeFilePath ) 0090 { 0091 d->m_bookmarkFileRelativePath = relativeFilePath; 0092 QString absoluteFilePath = bookmarkFile(); 0093 0094 mDebug() << "Loading Bookmark File:" << absoluteFilePath; 0095 0096 if (absoluteFilePath.isEmpty()) 0097 return false; 0098 0099 if ( relativeFilePath.isNull() ) 0100 return false; 0101 0102 GeoDataDocument *document = openFile( absoluteFilePath ); 0103 bool recover = false; 0104 if ( !document ) { 0105 mDebug() << "Could not parse file" << absoluteFilePath; 0106 mDebug() << "This could be caused by a previous broken bookmark file. Trying to recover."; 0107 /** @todo: Remove this workaround and return false around Marble 1.4 */ 0108 recover = true; 0109 // return false; 0110 } 0111 0112 d->m_treeModel->removeDocument( d->m_bookmarkDocument ); 0113 delete d->m_bookmarkDocument; 0114 d->m_bookmarkDocument = document; 0115 0116 if ( recover ) { 0117 d->resetBookmarkDocument(); 0118 updateBookmarkFile(); 0119 } else { 0120 Q_ASSERT( d->m_bookmarkDocument && "d->m_bookmarkDocument is 0 but must not be. Please report a bug at https://bugs.kde.org" ); 0121 d->m_treeModel->addDocument( d->m_bookmarkDocument ); 0122 } 0123 ensureDefaultFolder(); 0124 0125 emit bookmarksChanged(); 0126 return true; 0127 } 0128 0129 void BookmarkManager::addBookmark( GeoDataContainer *container, const GeoDataPlacemark &placemark ) 0130 { 0131 GeoDataPlacemark *bookmark = new GeoDataPlacemark( placemark ); 0132 bookmark->setVisualCategory(GeoDataPlacemark::Bookmark); 0133 bookmark->setZoomLevel( 1 ); 0134 if (bookmark->name().isEmpty()) { 0135 bookmark->setName(bookmark->coordinate().toString(GeoDataCoordinates::Decimal).trimmed()); 0136 } 0137 if (d->m_styleBuilder && bookmark->style()->iconStyle().iconPath().isEmpty()) { 0138 StyleParameters style; 0139 style.placemark = bookmark; 0140 bookmark->setStyle(GeoDataStyle::Ptr(new GeoDataStyle(*d->m_styleBuilder->createStyle(style)))); 0141 } 0142 d->m_treeModel->addFeature( container, bookmark ); 0143 0144 updateBookmarkFile(); 0145 } 0146 0147 void BookmarkManager::updateBookmark( GeoDataPlacemark *bookmark ) 0148 { 0149 d->m_treeModel->updateFeature( bookmark ); 0150 } 0151 0152 void BookmarkManager::removeBookmark( GeoDataPlacemark *bookmark ) 0153 { 0154 d->m_treeModel->removeFeature( bookmark ); 0155 delete bookmark; 0156 updateBookmarkFile(); 0157 } 0158 0159 GeoDataPlacemark* BookmarkManager::bookmarkAt(GeoDataContainer *container, const GeoDataCoordinates &coordinate) 0160 { 0161 for ( GeoDataFolder *folder: container->folderList() ) { 0162 GeoDataPlacemark *placemark = bookmarkAt(folder, coordinate); 0163 if ( placemark ) 0164 return placemark; 0165 } 0166 0167 for ( GeoDataPlacemark *placemark: container->placemarkList() ) { 0168 if ( placemark->coordinate() == coordinate ) 0169 return placemark; 0170 } 0171 0172 return Q_NULLPTR; 0173 } 0174 0175 GeoDataDocument * BookmarkManager::document() 0176 { 0177 return d->m_bookmarkDocument; 0178 } 0179 0180 const GeoDataDocument * BookmarkManager::document() const 0181 { 0182 return d->m_bookmarkDocument; 0183 } 0184 0185 bool BookmarkManager::showBookmarks() const 0186 { 0187 return d->m_bookmarkDocument->isVisible(); 0188 } 0189 0190 void BookmarkManager::setShowBookmarks( bool visible ) 0191 { 0192 d->m_bookmarkDocument->setVisible( visible ); 0193 d->m_treeModel->updateFeature( d->m_bookmarkDocument ); 0194 } 0195 0196 QVector<GeoDataFolder*> BookmarkManager::folders() const 0197 { 0198 return d->m_bookmarkDocument->folderList(); 0199 } 0200 0201 GeoDataFolder* BookmarkManager::addNewBookmarkFolder( GeoDataContainer *container, const QString &name ) 0202 { 0203 //If name is empty string 0204 if ( name.isEmpty() ) { 0205 mDebug() << "Folder with empty name is not acceptable, please give it another name" ; 0206 return Q_NULLPTR; 0207 } 0208 0209 //If folder with same name already exist 0210 QVector<GeoDataFolder*> folderList = container->folderList(); 0211 0212 QVector<GeoDataFolder*>::const_iterator i = folderList.constBegin(); 0213 QVector<GeoDataFolder*>::const_iterator end = folderList.constEnd(); 0214 for ( ; i != end; ++i ) { 0215 if ( name == ( *i )->name() ) { 0216 mDebug() << "Folder with same name already exist, please give it another name"; 0217 return *i; 0218 } 0219 } 0220 0221 GeoDataFolder *bookmarkFolder = new GeoDataFolder(); 0222 bookmarkFolder->setName( name ); 0223 0224 d->m_treeModel->addFeature( container, bookmarkFolder ); 0225 updateBookmarkFile(); 0226 0227 return bookmarkFolder; 0228 } 0229 0230 void BookmarkManager::renameBookmarkFolder( GeoDataFolder *folder, const QString &name ) 0231 { 0232 folder->setName( name ); 0233 d->m_treeModel->updateFeature( folder ); 0234 } 0235 0236 void BookmarkManager::removeBookmarkFolder( GeoDataFolder *folder ) 0237 { 0238 d->m_treeModel->removeFeature( folder ); 0239 delete folder; 0240 } 0241 0242 void BookmarkManager::ensureDefaultFolder() 0243 { 0244 if ( d->m_bookmarkDocument->size() == 0 ) { 0245 addNewBookmarkFolder( d->m_bookmarkDocument, tr("Default") ); 0246 } 0247 } 0248 0249 void BookmarkManager::removeAllBookmarks() 0250 { 0251 d->resetBookmarkDocument(); 0252 updateBookmarkFile(); 0253 } 0254 0255 void BookmarkManager::setStyleBuilder(const StyleBuilder *styleBuilder) 0256 { 0257 d->m_styleBuilder = styleBuilder; 0258 } 0259 0260 bool BookmarkManager::updateBookmarkFile() 0261 { 0262 const QString absoluteLocalFilePath = MarbleDirs::localPath() + QLatin1Char('/') + d->m_bookmarkFileRelativePath; 0263 0264 if ( ! d->m_bookmarkFileRelativePath.isNull() ) { 0265 QFile file( absoluteLocalFilePath ); 0266 if ( !file.exists() ) { 0267 // Extracting directory of file : for bookmarks it will be MarbleDirs::localPath()+/bookmarks/ 0268 QFileInfo fileInfo( absoluteLocalFilePath ); 0269 QString directoryPath = fileInfo.path(); 0270 0271 //Creating all directories, which doesn't exist 0272 QDir directory( MarbleDirs::localPath() ); 0273 directory.mkpath( directoryPath ); 0274 } 0275 0276 if (!GeoDataDocumentWriter::write(absoluteLocalFilePath, *d->m_bookmarkDocument)) { 0277 mDebug() << "Could not write the bookmarks file" << absoluteLocalFilePath; 0278 file.close(); 0279 return false; 0280 } 0281 emit bookmarksChanged(); 0282 file.close(); 0283 return true; 0284 } 0285 return false; 0286 } 0287 0288 GeoDataDocument* BookmarkManager::openFile( const QString &fileName ) 0289 { 0290 GeoDataParser parser( GeoData_KML ); 0291 QFile file( fileName ); 0292 0293 if ( !file.exists() ) { 0294 return nullptr; 0295 } 0296 0297 if ( !file.open( QIODevice::ReadOnly ) || !parser.read( &file ) ) { 0298 mDebug() << "Could not open/parse file" << fileName; 0299 return nullptr; 0300 } 0301 0302 GeoDataDocument *result = dynamic_cast<GeoDataDocument*>( parser.releaseDocument() ); 0303 if ( !result ) { 0304 return nullptr; 0305 } 0306 0307 result->setDocumentRole( BookmarkDocument ); 0308 for( GeoDataFolder* folder: result->folderList() ) { 0309 BookmarkManagerPrivate::setVisualCategory( folder ); 0310 } 0311 0312 return result; 0313 } 0314 0315 } 0316 0317 #include "moc_BookmarkManager.cpp"