File indexing completed on 2024-05-05 03:49:16

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2012 Dennis Nienhüser <nienhueser@kde.org>
0004 //
0005 
0006 #include "Bookmarks.h"
0007 
0008 #include "Planet.h"
0009 #include "MarbleQuickItem.h"
0010 #include "MarbleModel.h"
0011 #include "MarblePlacemarkModel.h"
0012 #include "BookmarkManager.h"
0013 #include "GeoDataDocument.h"
0014 #include "GeoDataPlacemark.h"
0015 #include "GeoDataFolder.h"
0016 #include "GeoDataTypes.h"
0017 #include "GeoDataExtendedData.h"
0018 #include "GeoDataTreeModel.h"
0019 #include "kdescendantsproxymodel.h"
0020 #include "osm/OsmPlacemarkData.h"
0021 
0022 
0023 namespace Marble {
0024 
0025 Bookmarks::Bookmarks( QObject* parent ) : QObject( parent ),
0026     m_marbleQuickItem( nullptr ), m_proxyModel( nullptr )
0027 {
0028     // nothing to do
0029 }
0030 
0031 MarbleQuickItem *Bookmarks::map()
0032 {
0033     return m_marbleQuickItem;
0034 }
0035 
0036 void Bookmarks::setMap( MarbleQuickItem* item )
0037 {
0038     m_marbleQuickItem = item;
0039     if (item) {
0040         connect(item->model()->bookmarkManager(), SIGNAL(bookmarksChanged()),
0041                 this, SLOT(updateBookmarkDocument()));
0042     }
0043     updateBookmarkDocument();
0044     emit modelChanged();
0045 }
0046 
0047 bool Bookmarks::isBookmark( qreal longitude, qreal latitude ) const
0048 {
0049     if ( !m_marbleQuickItem || !m_marbleQuickItem->model()->bookmarkManager() ) {
0050         return false;
0051     }
0052 
0053     Marble::BookmarkManager* manager = m_marbleQuickItem->model()->bookmarkManager();
0054     Marble::GeoDataDocument *bookmarks = manager->document();
0055     Marble::GeoDataCoordinates const compareTo( longitude, latitude, 0.0, Marble::GeoDataCoordinates::Degree );
0056 
0057     qreal planetRadius = m_marbleQuickItem->model()->planet()->radius();
0058     for( const Marble::GeoDataFolder* folder: bookmarks->folderList() ) {
0059         for( const Marble::GeoDataPlacemark * const placemark: folder->placemarkList() ) {
0060             if (placemark->coordinate().sphericalDistanceTo(compareTo) * planetRadius < 5) {
0061                 return true;
0062             }
0063         }
0064     }
0065 
0066     return false;
0067 }
0068 
0069 Placemark *Bookmarks::placemark(int row)
0070 {
0071     Placemark* placemark = new Placemark;
0072 
0073     QModelIndex index = model()->index(row, 0);
0074     GeoDataObject *object = model()->data(index, MarblePlacemarkModel::ObjectPointerRole ).value<GeoDataObject*>();
0075     if (GeoDataPlacemark *geoDataPlacemark = geodata_cast<GeoDataPlacemark>(object)) {
0076         placemark->setGeoDataPlacemark(*geoDataPlacemark);
0077     }
0078 
0079     return placemark;
0080 }
0081 
0082 void Bookmarks::addBookmark(Placemark *placemark, const QString &folderName )
0083 {
0084     if ( !m_marbleQuickItem || !m_marbleQuickItem->model()->bookmarkManager() ) {
0085         return;
0086     }
0087 
0088     Marble::BookmarkManager* manager = m_marbleQuickItem->model()->bookmarkManager();
0089     Marble::GeoDataDocument *bookmarks = manager->document();
0090     Marble::GeoDataContainer *target = nullptr;
0091     for( Marble::GeoDataFolder* const folder: bookmarks->folderList() ) {
0092         if ( folder->name() == folderName ) {
0093             target = folder;
0094             break;
0095         }
0096     }
0097 
0098     if ( !target ) {
0099         manager->addNewBookmarkFolder( bookmarks, folderName );
0100 
0101         for( Marble::GeoDataFolder* const folder: bookmarks->folderList() ) {
0102             if ( folder->name() == folderName ) {
0103                 target = folder;
0104                 break;
0105             }
0106         }
0107 
0108         Q_ASSERT( target );
0109     }
0110 
0111     Marble::GeoDataPlacemark bookmark = placemark->placemark();
0112     if (bookmark.name().isEmpty()) {
0113         bookmark.setName(placemark->address());
0114     }
0115     if (bookmark.name().isEmpty()) {
0116         bookmark.setName(bookmark.coordinate().toString(GeoDataCoordinates::Decimal).trimmed());
0117     }
0118     bookmark.clearOsmData();
0119     bookmark.setCoordinate(bookmark.coordinate()); // replace non-point geometries with their center
0120     manager->addBookmark( target, bookmark );
0121 }
0122 
0123 void Bookmarks::removeBookmark( qreal longitude, qreal latitude )
0124 {
0125     if ( !m_marbleQuickItem || !m_marbleQuickItem->model()->bookmarkManager() ) {
0126         return;
0127     }
0128 
0129     Marble::BookmarkManager* manager = m_marbleQuickItem->model()->bookmarkManager();
0130     Marble::GeoDataDocument *bookmarks = manager->document();
0131     Marble::GeoDataCoordinates const compareTo( longitude, latitude, 0.0, Marble::GeoDataCoordinates::Degree );
0132 
0133     qreal planetRadius = m_marbleQuickItem->model()->planet()->radius();
0134     for( const Marble::GeoDataFolder* folder: bookmarks->folderList() ) {
0135         for( Marble::GeoDataPlacemark * placemark: folder->placemarkList() ) {
0136             if (placemark->coordinate().sphericalDistanceTo(compareTo) * planetRadius < 5) {
0137                 manager->removeBookmark( placemark );
0138                 return;
0139             }
0140         }
0141     }
0142 }
0143 
0144 void Bookmarks::updateBookmarkDocument()
0145 {
0146     if (m_marbleQuickItem) {
0147         Marble::BookmarkManager* manager = m_marbleQuickItem->model()->bookmarkManager();
0148         m_treeModel.setRootDocument( manager->document() );
0149     }
0150 }
0151 
0152 BookmarksModel *Bookmarks::model()
0153 {
0154     if ( !m_proxyModel && m_marbleQuickItem && m_marbleQuickItem->model()->bookmarkManager() ) {
0155         KDescendantsProxyModel* flattener = new KDescendantsProxyModel( this );
0156         flattener->setSourceModel(&m_treeModel);
0157 
0158         m_proxyModel = new BookmarksModel( this );
0159         m_proxyModel->setFilterFixedString( Marble::GeoDataTypes::GeoDataPlacemarkType );
0160         m_proxyModel->setFilterKeyColumn( 1 );
0161         m_proxyModel->setSourceModel( flattener );
0162     }
0163 
0164     return m_proxyModel;
0165 }
0166 
0167 BookmarksModel::BookmarksModel( QObject *parent ) : QSortFilterProxyModel( parent )
0168 {
0169     connect( this, SIGNAL(layoutChanged()), this, SIGNAL(countChanged()) );
0170     connect( this, SIGNAL(modelReset()), this, SIGNAL(countChanged()) );
0171     connect( this, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SIGNAL(countChanged()) );
0172     connect( this, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SIGNAL(countChanged()) );
0173 }
0174 
0175 int BookmarksModel::count() const
0176 {
0177     return rowCount();
0178 }
0179 
0180 qreal BookmarksModel::longitude( int idx ) const
0181 {
0182     if ( idx >= 0 && idx < rowCount() ) {
0183         QVariant const value = data( index( idx, 0 ), Marble::MarblePlacemarkModel::CoordinateRole );
0184         Marble::GeoDataCoordinates const coordinates = value.value<Marble::GeoDataCoordinates>();
0185         return coordinates.longitude( Marble::GeoDataCoordinates::Degree );
0186     }
0187     return 0.0;
0188 }
0189 
0190 qreal BookmarksModel::latitude( int idx ) const
0191 {
0192     if ( idx >= 0 && idx < rowCount() ) {
0193         QVariant const value = data( index( idx, 0 ), Marble::MarblePlacemarkModel::CoordinateRole );
0194         Marble::GeoDataCoordinates const coordinates = value.value<Marble::GeoDataCoordinates>();
0195         return coordinates.latitude( Marble::GeoDataCoordinates::Degree );
0196     }
0197     return 0.0;
0198 }
0199 
0200 QString BookmarksModel::name( int idx ) const
0201 {
0202     if ( idx >= 0 && idx < rowCount() ) {
0203         return data( index( idx, 0 ) ).toString();
0204     }
0205     return QString();
0206 }
0207 
0208 }
0209 
0210 #include "moc_Bookmarks.cpp"