File indexing completed on 2024-04-21 03:49:32

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2010 Gaurav Gupta <1989.gaurav@googlemail.com>
0004 // SPDX-FileCopyrightText: 2011 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 // SPDX-FileCopyrightText: 2012 Thibaut Gridel <tgridel@free.fr>
0006 //
0007 
0008 #include "EditBookmarkDialog.h"
0009 #include "ui_EditBookmarkDialog.h"
0010 
0011 #include "BookmarkManager.h"
0012 #include "GeoDataLookAt.h"
0013 #include "GeoDataDocument.h"
0014 #include "GeoDataPlacemark.h"
0015 #include "GeoDataPoint.h"
0016 #include "GeoDataStyle.h"
0017 #include "GeoDataIconStyle.h"
0018 #include "GeoDataFolder.h"
0019 #include "GeoDataCoordinates.h"
0020 #include "GeoDataExtendedData.h"
0021 #include "GeoDataData.h"
0022 #include "MarbleDirs.h"
0023 #include "MarbleModel.h"
0024 #include "MarbleWidget.h"
0025 #include "NewBookmarkFolderDialog.h"
0026 #include "ReverseGeocodingRunnerManager.h"
0027 
0028 #include <QPointer>
0029 
0030 namespace Marble {
0031 
0032 class EditBookmarkDialogPrivate {
0033 public:
0034     MarbleWidget *m_widget;
0035     ReverseGeocodingRunnerManager* m_manager;
0036     BookmarkManager* m_bookmarkManager;
0037     GeoDataCoordinates m_bookmarkCoordinates;
0038     qreal m_range;
0039     Ui::UiEditBookmarkDialog m_ui;
0040 
0041     EditBookmarkDialogPrivate( EditBookmarkDialog* q, BookmarkManager *bookmarkManager );
0042 
0043     void initComboBox(const GeoDataContainer* const container , int level=0);
0044 
0045     void initialize();
0046 
0047     void setFolderName( const QString &name );
0048 
0049     static QString append( const QString &bookmark, const QString &text);
0050 
0051     void openNewFolderDialog();
0052 
0053     void retrieveGeocodeResult( const GeoDataCoordinates &coordinates, const GeoDataPlacemark &placemark);
0054 
0055     void updateCoordinates();
0056 
0057 private:
0058     EditBookmarkDialog* const q;
0059 };
0060 
0061 EditBookmarkDialogPrivate::EditBookmarkDialogPrivate( EditBookmarkDialog* q_, BookmarkManager *bookmarkManager ) :
0062         m_widget( nullptr ), m_manager( nullptr ), m_bookmarkManager( bookmarkManager ), m_range( 0 ), q( q_ )
0063 {
0064     // nothing to do
0065 }
0066 
0067 void EditBookmarkDialogPrivate::initialize()
0068 {
0069     m_ui.setupUi( q );
0070     bool const smallScreen = MarbleGlobal::getInstance()->profiles() & MarbleGlobal::SmallScreen;
0071     m_ui.m_header->setPositionVisible(!smallScreen);
0072     m_ui.m_header->setIdVisible( false );
0073     m_ui.m_header->setIconLink(MarbleDirs::path(QStringLiteral("bitmaps/bookmark.png")));
0074     QObject::connect( m_ui.m_newFolderButton, SIGNAL(clicked()), q, SLOT(openNewFolderDialog()) );
0075     QObject::connect( m_ui.m_header, SIGNAL(valueChanged()), q, SLOT(updateCoordinates()) );
0076 
0077     m_ui.m_folders->clear();
0078     initComboBox( m_bookmarkManager->document() );
0079 }
0080 
0081 void EditBookmarkDialogPrivate::initComboBox( const GeoDataContainer* const container, int level )
0082 {
0083     m_bookmarkManager->ensureDefaultFolder();
0084     for( GeoDataFolder *folder: container->folderList() ) {
0085         QVariant folderVariant;
0086         folderVariant.setValue(folder);
0087         QString name = QString(' ').repeated(4*level) + folder->name();
0088         m_ui.m_folders->addItem( name, folderVariant );
0089         if( !folder->folderList().isEmpty() ) {
0090             initComboBox( folder, level+1 );
0091         }
0092     }
0093 }
0094 
0095 void EditBookmarkDialogPrivate::setFolderName( const QString &name )
0096 {
0097     for ( int i=0; i<m_ui.m_folders->count(); ++i ) {
0098         if ( m_ui.m_folders->itemText( i ) == name ) {
0099             m_ui.m_folders->setCurrentIndex( i );
0100             return;
0101         }
0102     }
0103 }
0104 
0105 EditBookmarkDialog::EditBookmarkDialog( BookmarkManager *bookmarkManager, QWidget *parent )
0106     : QDialog( parent ), d( new EditBookmarkDialogPrivate( this, bookmarkManager ) )
0107 {
0108     d->initialize();
0109 }
0110 
0111 void EditBookmarkDialog::setCoordinates( const GeoDataCoordinates &coordinates )
0112 {
0113     d->m_bookmarkCoordinates = coordinates;
0114     QObject::disconnect( d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()) );
0115 
0116     if ( d->m_ui.m_header->name().isEmpty() ) {
0117         d->m_ui.m_header->setName( coordinates.toString() );
0118     }
0119 
0120     d->m_ui.m_header->setLongitude( coordinates.longitude(GeoDataCoordinates::Degree) );
0121     d->m_ui.m_header->setLatitude( coordinates.latitude(GeoDataCoordinates::Degree) );
0122     QObject::connect( d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()) );
0123 }
0124 
0125 void EditBookmarkDialog::setRange( qreal range ) {
0126     d->m_range = range;
0127 }
0128 
0129 void EditBookmarkDialog::setName( const QString &text )
0130 {
0131     QObject::disconnect( d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()) );
0132     d->m_ui.m_header->setName( text );
0133     d->m_ui.m_header->selectAll();
0134     QObject::connect( d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()) );
0135 }
0136 
0137 void EditBookmarkDialog::setDescription( const QString &text )
0138 {
0139     QObject::disconnect( d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()) );
0140     d->m_ui.m_description->setText( text );
0141     QObject::connect( d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()) );
0142 }
0143 
0144 void EditBookmarkDialog::setFolderName( const QString &name )
0145 {
0146     d->setFolderName( name );
0147 }
0148 
0149 void EditBookmarkDialog::setIconLink(const QString &iconLink)
0150 {
0151     QObject::disconnect( d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()) );
0152     d->m_ui.m_header->setIconLink( iconLink );
0153     QObject::connect( d->m_ui.m_header, SIGNAL(valueChanged()), this, SLOT(updateCoordinates()) );
0154 }
0155 
0156 void EditBookmarkDialog::setMarbleWidget( MarbleWidget* widget )
0157 {
0158     d->m_widget = widget;
0159     const AngleUnit defaultAngleUnit = d->m_widget->defaultAngleUnit();
0160     const GeoDataCoordinates::Notation notation =
0161         (defaultAngleUnit == DecimalDegree) ? GeoDataCoordinates::Decimal :
0162         (defaultAngleUnit == DMSDegree) ?     GeoDataCoordinates::DMS :
0163         /* else, UTM */                       GeoDataCoordinates::UTM;
0164     d->m_ui.m_header->setNotation(notation);
0165 
0166     d->m_manager = new ReverseGeocodingRunnerManager( d->m_widget->model(), this );
0167     QObject::connect( d->m_manager, SIGNAL(reverseGeocodingFinished(GeoDataCoordinates,GeoDataPlacemark)),
0168             this, SLOT(retrieveGeocodeResult(GeoDataCoordinates,GeoDataPlacemark)) );
0169 }
0170 
0171 void EditBookmarkDialog::setReverseGeocodeName()
0172 {
0173     if ( !d->m_manager ) {
0174         return;
0175     }
0176     //reverse geocode the bookmark point for better user experience
0177     d->m_manager->reverseGeocoding( d->m_bookmarkCoordinates );
0178 }
0179 
0180 EditBookmarkDialog::~EditBookmarkDialog()
0181 {
0182     delete d;
0183 }
0184 
0185 void EditBookmarkDialogPrivate::retrieveGeocodeResult( const GeoDataCoordinates &coordinates, const GeoDataPlacemark &placemark)
0186 {
0187     Q_UNUSED(coordinates)
0188     GeoDataExtendedData data = placemark.extendedData();
0189     QString bookmarkName;
0190     qreal distance = m_widget->distance() * KM2METER;
0191     //FIXME : Optimal logic for suggestion with distance consideration is required
0192 
0193     if( distance >= 3500 ) {
0194         bookmarkName = data.value(QStringLiteral("country")).value().toString();
0195     }
0196     else if( distance >= 200 ) {
0197         bookmarkName = append(data.value(QStringLiteral("city")).value().toString(),
0198                               data.value(QStringLiteral("state")).value().toString());
0199         bookmarkName = append(bookmarkName, data.value(QStringLiteral("country")).value().toString());
0200     }
0201     else {
0202         bookmarkName = append(data.value(QStringLiteral("road")).value().toString(),
0203                               data.value(QStringLiteral("city")).value().toString());
0204         bookmarkName = append(bookmarkName, data.value(QStringLiteral("country")).value().toString());
0205     }
0206 
0207     if( bookmarkName.isEmpty() ) {
0208         bookmarkName = placemark.address();
0209     }
0210 
0211     m_ui.m_header->setName( bookmarkName );
0212     m_ui.m_header->selectAll();
0213 }
0214 
0215 QString EditBookmarkDialogPrivate::append( const QString &bookmark, const QString &text)
0216 {
0217     if( bookmark.isEmpty() && text.isEmpty() ) {
0218         return "";
0219     }
0220     else if( bookmark.isEmpty() ) {
0221         return text;
0222     }
0223     else if( text.isEmpty() ) {
0224         return bookmark;
0225     }
0226     return bookmark + ", " + text;
0227 }
0228 
0229 void EditBookmarkDialogPrivate::openNewFolderDialog()
0230 {
0231     QPointer<NewBookmarkFolderDialog> dialog = new NewBookmarkFolderDialog( q );
0232     if ( dialog->exec() == QDialog::Accepted ) {
0233         m_bookmarkManager->addNewBookmarkFolder( m_bookmarkManager->document(), dialog->folderName() );
0234         m_ui.m_folders->clear();
0235         initComboBox( m_bookmarkManager->document() );
0236         setFolderName( dialog->folderName() );
0237     }
0238     delete dialog;
0239 }
0240 
0241 void EditBookmarkDialogPrivate::updateCoordinates()
0242 {
0243     m_bookmarkCoordinates.setLongitude( m_ui.m_header->longitude(), GeoDataCoordinates::Degree );
0244     m_bookmarkCoordinates.setLatitude( m_ui.m_header->latitude(), GeoDataCoordinates::Degree );
0245 }
0246 
0247 GeoDataPlacemark EditBookmarkDialog::bookmark() const
0248 {
0249     //Create a bookmark object
0250     GeoDataPlacemark bookmark;
0251     bookmark.setName( name() );
0252     bookmark.setDescription( description() );
0253     GeoDataStyle::Ptr newStyle(new GeoDataStyle( *bookmark.style() ));
0254     newStyle->iconStyle().setIconPath( iconLink() );
0255     bookmark.setStyle( newStyle );
0256     //allow for HTML in the description
0257     bookmark.setDescriptionCDATA( true );
0258     bookmark.setCoordinate( coordinates() );
0259     if ( d->m_range ) {
0260         GeoDataLookAt *lookat = new GeoDataLookAt;
0261         lookat->setCoordinates( coordinates() );
0262         lookat->setRange( range() );
0263         bookmark.setAbstractView( lookat );
0264     }
0265 
0266     bookmark.extendedData().addValue(GeoDataData(QStringLiteral("isBookmark"), true));
0267 
0268     if(d->m_widget != nullptr) {
0269         const QString celestialName = d->m_widget->model()->planetId();
0270         if (celestialName != QLatin1String("earth")) {
0271             bookmark.extendedData().addValue(GeoDataData(QStringLiteral("celestialBody"), celestialName));
0272         }
0273     }
0274 
0275     return bookmark;
0276 }
0277 
0278 QString EditBookmarkDialog::name() const
0279 {
0280     return d->m_ui.m_header->name();
0281 }
0282 
0283 GeoDataFolder *EditBookmarkDialog::folder() const
0284 {
0285     return qvariant_cast<GeoDataFolder*>(d->m_ui.m_folders->itemData(d->m_ui.m_folders->currentIndex()));
0286 }
0287 
0288 QString EditBookmarkDialog::description() const
0289 {
0290     return d->m_ui.m_description->toPlainText();
0291 }
0292 
0293 GeoDataCoordinates EditBookmarkDialog::coordinates() const
0294 {
0295     return d->m_bookmarkCoordinates;
0296 }
0297 
0298 qreal EditBookmarkDialog::range() const {
0299     return d->m_range;
0300 }
0301 
0302 QString EditBookmarkDialog::iconLink() const
0303 {
0304     return d->m_ui.m_header->iconLink();
0305 }
0306 
0307 }
0308 
0309 #include "moc_EditBookmarkDialog.cpp"