35 #include <QSortFilterProxyModel>
36 #include <QFileDialog>
37 #include <QMessageBox>
38 #include <QItemSelectionModel>
56 class BookmarkManagerDialogPrivate {
58 BookmarkManagerDialog *m_parent;
60 BookmarkManager *m_manager;
62 GeoDataTreeModel* m_treeModel;
64 QSortFilterProxyModel *m_folderFilterModel;
66 QPersistentModelIndex m_selectedFolder;
68 BranchFilterProxyModel *m_branchFilterModel;
70 BookmarkManagerDialogPrivate( BookmarkManagerDialog* parent, BookmarkManager* manager );
72 void initializeFoldersView( GeoDataTreeModel* treeModel );
74 void initializeBookmarksView( GeoDataTreeModel* treeModel );
76 void handleFolderSelection(
const QModelIndex &index );
78 void updateButtonState();
88 void deleteBookmark();
90 void discardChanges();
92 QModelIndex bookmarkTreeIndex(
const QModelIndex &bookmark )
const;
94 QModelIndex folderTreeIndex(
const QModelIndex &index )
const;
95 GeoDataContainer* selectedFolder();
97 void selectFolder(
const QString &name = QString(),
const QModelIndex &index = QModelIndex() );
100 BookmarkManagerDialogPrivate::BookmarkManagerDialogPrivate( BookmarkManagerDialog* parent, BookmarkManager* manager ) :
101 m_parent( parent ), m_manager( manager ), m_treeModel( 0 ), m_folderFilterModel( 0 ), m_branchFilterModel( 0 )
108 void BookmarkManagerDialogPrivate::handleFolderSelection(
const QModelIndex &index )
110 if( !index.isValid() ) {
113 Q_ASSERT( index.isValid() );
114 Q_ASSERT( index.model() == m_folderFilterModel );
115 if( m_selectedFolder.isValid() &&
116 m_parent->foldersTreeView->selectionModel()->selectedIndexes().contains( m_selectedFolder ) ) {
117 m_selectedFolder = QModelIndex();
118 m_parent->foldersTreeView->selectionModel()->clear();
121 m_selectedFolder = index;
122 m_branchFilterModel->setBranchIndex( m_treeModel, folderTreeIndex( index ) );
123 m_parent->bookmarksListView->setRootIndex(
124 m_branchFilterModel->mapFromSource( folderTreeIndex( index ) ) );
125 m_parent->bookmarksListView->selectionModel()->clear();
129 void BookmarkManagerDialogPrivate::updateButtonState()
131 bool const hasFolderSelection = !m_parent->foldersTreeView->selectionModel()->selectedIndexes().isEmpty();
132 m_parent->renameFolderButton->setEnabled( hasFolderSelection );
133 m_parent->removeFolderButton->setEnabled( hasFolderSelection );
135 bool const hasBookmarkSelection = !m_parent->bookmarksListView->selectionModel()->selectedIndexes().isEmpty();
136 m_parent->editBookmarkButton->setEnabled( hasBookmarkSelection );
137 m_parent->removeBookmarkButton->setEnabled( hasBookmarkSelection );
140 void BookmarkManagerDialogPrivate::addNewFolder()
142 QPointer<NewBookmarkFolderDialog> dialog =
new NewBookmarkFolderDialog( m_parent );
143 if ( dialog->exec() == QDialog::Accepted && !dialog->folderName().isEmpty() ) {
144 m_manager->addNewBookmarkFolder( selectedFolder(), dialog->folderName() );
145 selectFolder( dialog->folderName(), m_selectedFolder );
150 void BookmarkManagerDialogPrivate::renameFolder()
152 GeoDataFolder *folder =
dynamic_cast<GeoDataFolder*
>(selectedFolder());
154 QPointer<NewBookmarkFolderDialog> dialog =
new NewBookmarkFolderDialog( m_parent );
155 dialog->setFolderName( folder->name() );
156 QPersistentModelIndex parentIndex = m_selectedFolder.parent();
157 if ( dialog->exec() == QDialog::Accepted ) {
158 m_manager->renameBookmarkFolder( folder, dialog->folderName() );
160 selectFolder( dialog->folderName(), parentIndex );
165 void BookmarkManagerDialogPrivate::deleteFolder()
167 GeoDataFolder *folder =
dynamic_cast<GeoDataFolder*
>(selectedFolder());
169 if ( folder->size() > 0 ) {
170 QString
const text = QObject::tr(
"The folder %1 is not empty. Removing it will delete all bookmarks it contains. Are you sure you want to delete the folder?" ).arg( folder->name() );
171 if ( QMessageBox::question( m_parent, QObject::tr(
"Remove Folder - Marble"), text, QMessageBox::Yes, QMessageBox::No ) != QMessageBox::Yes) {
177 QString parent =
static_cast<GeoDataContainer*
>(folder->parent())->name();
178 QPersistentModelIndex greatParentIndex = m_selectedFolder.parent().parent();
179 m_manager->removeBookmarkFolder( folder );
180 selectFolder( parent, greatParentIndex);
184 void BookmarkManagerDialogPrivate::editBookmark()
186 QModelIndexList selection = m_parent->bookmarksListView->selectionModel()->selectedIndexes();
187 if ( selection.size() == 1 ) {
188 QModelIndex index = m_branchFilterModel->mapToSource( selection.first() );
189 Q_ASSERT( index.isValid() );
192 GeoDataPlacemark* bookmark =
dynamic_cast<GeoDataPlacemark*
>( object );
197 Q_ASSERT( bookmark );
198 QModelIndex treeIndex = index;
199 Q_ASSERT( treeIndex.isValid() );
200 QModelIndex folderIndex = treeIndex.parent();
201 Q_ASSERT( folderIndex.isValid() );
203 Q_ASSERT( folderObject );
204 GeoDataFolder* folder =
dynamic_cast<GeoDataFolder*
>( folderObject );
207 QPointer<EditBookmarkDialog> dialog =
new EditBookmarkDialog( m_manager, m_parent );
208 dialog->setName( bookmark->name() );
209 if ( bookmark->lookAt() ) {
210 dialog->setRange( bookmark->lookAt()->range() );
212 dialog->setCoordinates( bookmark->coordinate() );
213 dialog->setDescription( bookmark->description() );
214 dialog->setFolderName( folder->name() );
215 if ( dialog->exec() == QDialog::Accepted ) {
216 bookmark->setName( dialog->name() );
217 bookmark->setDescription( dialog->description() );
218 bookmark->setCoordinate( dialog->coordinates() );
219 if ( bookmark->lookAt() ) {
220 bookmark->lookAt()->setCoordinates( dialog->coordinates() );
221 bookmark->lookAt()->setRange( dialog->range() );
222 }
else if ( dialog->range() ) {
223 GeoDataLookAt *lookat =
new GeoDataLookAt;
224 lookat->setCoordinates( dialog->coordinates() );
225 lookat->setRange( dialog->range() );
226 bookmark->setAbstractView( lookat );
228 m_manager->updateBookmark( bookmark );
230 if (folder->name() != dialog->folder()->name() ) {
231 GeoDataPlacemark newBookmark( *bookmark );
232 m_manager->removeBookmark( bookmark );
233 m_manager->addBookmark( dialog->folder(), newBookmark );
240 void BookmarkManagerDialogPrivate::deleteBookmark()
242 QModelIndexList selection = m_parent->bookmarksListView->selectionModel()->selectedIndexes();
243 if ( selection.size() == 1 ) {
244 QModelIndex bookmarkIndex = m_branchFilterModel->mapToSource( selection.first() );
245 GeoDataFolder* folder =
dynamic_cast<GeoDataFolder*
>( selectedFolder() );
247 GeoDataPlacemark* bookmark =
dynamic_cast<GeoDataPlacemark*
>( folder->child( bookmarkIndex.row() ) );
249 m_manager->removeBookmark( bookmark );
255 void BookmarkManagerDialogPrivate::discardChanges()
257 m_manager->loadFile(
"bookmarks/bookmarks.kml" );
261 void BookmarkManagerDialogPrivate::selectFolder(
const QString &name,
const QModelIndex &parent )
263 if ( parent.isValid() ) {
264 Q_ASSERT( parent.model() == m_folderFilterModel );
267 if ( name.isEmpty() ) {
268 QModelIndex documentTreeIndex = m_treeModel->index( m_parent->bookmarkDocument() );
269 QModelIndex folderFilterIndex = m_folderFilterModel->mapFromSource( documentTreeIndex );
270 Q_ASSERT( folderFilterIndex.isValid() );
271 m_parent->foldersTreeView->setCurrentIndex( folderFilterIndex );
272 handleFolderSelection( folderFilterIndex );
276 for (
int i=0; i < m_folderFilterModel->rowCount( parent ); ++i ) {
277 QModelIndex childIndex = m_folderFilterModel->index( i, 0, parent );
278 if ( childIndex.data().toString() == name
279 && m_selectedFolder != childIndex ) {
280 m_parent->foldersTreeView->setCurrentIndex( childIndex );
281 handleFolderSelection( childIndex );
284 if ( m_folderFilterModel->hasChildren( childIndex ) ) {
285 selectFolder( name, childIndex );
290 QModelIndex BookmarkManagerDialogPrivate::folderTreeIndex(
const QModelIndex &index )
const
292 Q_ASSERT( index.isValid() );
293 Q_ASSERT( index.model() == m_folderFilterModel );
294 QModelIndex
const treeModelIndex = m_folderFilterModel->mapToSource( index );
295 Q_ASSERT( treeModelIndex.isValid() );
296 Q_ASSERT( treeModelIndex.model() == m_treeModel );
297 return treeModelIndex;
300 GeoDataContainer *BookmarkManagerDialogPrivate::selectedFolder()
302 if( m_selectedFolder.isValid() ) {
305 GeoDataContainer* container =
dynamic_cast<GeoDataContainer*
>( object );
306 Q_ASSERT( container );
309 return m_parent->bookmarkDocument();
313 void BookmarkManagerDialogPrivate::initializeFoldersView( GeoDataTreeModel* treeModel )
315 m_folderFilterModel =
new QSortFilterProxyModel( m_parent );
316 m_folderFilterModel->setFilterKeyColumn( 1 );
320 m_folderFilterModel->setFilterRegExp( regexp );
321 m_folderFilterModel->setSourceModel( treeModel );
323 m_parent->foldersTreeView->setModel( m_folderFilterModel );
324 m_parent->foldersTreeView->setEditTriggers( QAbstractItemView::NoEditTriggers );
325 m_parent->foldersTreeView->setHeaderHidden(
true );
326 for (
int i=1; i<m_treeModel->columnCount(); ++i ) {
327 m_parent->foldersTreeView->hideColumn( i );
329 m_parent->foldersTreeView->setRootIndex( m_folderFilterModel->mapFromSource(
330 m_treeModel->index( m_parent->bookmarkDocument() )));
332 m_parent->connect( m_parent->foldersTreeView,
333 SIGNAL(clicked(QModelIndex)),
334 m_parent, SLOT(handleFolderSelection(QModelIndex)) );
335 m_parent->connect( m_parent->foldersTreeView->selectionModel(),
336 SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
337 m_parent, SLOT(updateButtonState()) );
338 m_parent->connect( m_parent->renameFolderButton, SIGNAL(clicked(
bool)),
339 m_parent, SLOT(renameFolder()) );
340 m_parent->connect( m_parent->newFolderButton, SIGNAL(clicked(
bool)),
341 m_parent, SLOT(addNewFolder()) );
342 m_parent->connect( m_parent->removeFolderButton, SIGNAL(clicked(
bool)),
343 m_parent, SLOT(deleteFolder()) );
346 void BookmarkManagerDialogPrivate::initializeBookmarksView( GeoDataTreeModel* treeModel )
348 m_branchFilterModel =
new BranchFilterProxyModel( m_parent );
349 m_branchFilterModel->setSourceModel( treeModel );
351 m_parent->bookmarksListView->setModel( m_branchFilterModel );
352 m_parent->bookmarksListView->setEditTriggers( QAbstractItemView::NoEditTriggers );
354 m_parent->connect( m_parent->bookmarksListView->selectionModel(),
355 SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
356 m_parent, SLOT(updateButtonState()) );
357 m_parent->connect( m_parent->editBookmarkButton, SIGNAL(clicked(
bool)),
358 m_parent, SLOT(editBookmark()) );
359 m_parent->connect( m_parent->removeBookmarkButton, SIGNAL(clicked(
bool)),
360 m_parent, SLOT(deleteBookmark()) );
365 d( new BookmarkManagerDialogPrivate( this, model->bookmarkManager() ) )
369 importButton->setVisible( !smallScreen );
370 exportButton->setVisible( !smallScreen );
371 foldersLabel->setVisible( !smallScreen );
372 bookmarkLabel->setVisible( !smallScreen );
376 d->initializeFoldersView( d->m_treeModel );
377 d->initializeBookmarksView( d->m_treeModel );
378 d->updateButtonState();
380 connect(
this, SIGNAL(accepted()), SLOT(saveBookmarks()) );
381 connect(
this, SIGNAL(rejected()), SLOT(discardChanges()) );
382 connect( exportButton, SIGNAL(clicked()),
this, SLOT(exportBookmarks()) );
383 connect( importButton, SIGNAL(clicked()),
this, SLOT(importBookmarks()) );
393 void BookmarkManagerDialog::saveBookmarks()
395 d->m_manager->updateBookmarkFile();
398 void BookmarkManagerDialog::exportBookmarks()
400 QString fileName = QFileDialog::getSaveFileName(
this, tr(
"Export Bookmarks" ),
401 QDir::homePath(), tr(
"KML files (*.kml)" ) );
403 if ( !fileName.isEmpty() ) {
404 QFile file( fileName );
406 writer.setDocumentType(
"http://earth.google.com/kml/2.2" );
408 if ( !file.open( QIODevice::ReadWrite ) || !writer.write( &file, bookmarkDocument() ) ) {
409 mDebug() <<
"Could not write the bookmarks file" << fileName;
410 QString
const text = tr(
"Unable to save bookmarks. Please check that the file is writable." );
411 QMessageBox::warning(
this, tr(
"Bookmark Export - Marble" ), text );
416 void BookmarkManagerDialog::importBookmarks()
418 QString
const file = QFileDialog::getOpenFileName(
this, tr(
"Import Bookmarks - Marble" ),
419 QDir::homePath(), tr(
"KML Files (*.kml)" ) );
420 if ( file.isEmpty() ) {
424 GeoDataDocument *
import = BookmarkManager::openFile( file );
426 QString
const text = tr(
"The file %1 cannot be opened as a KML file." ).arg( file );
427 QMessageBox::warning(
this, tr(
"Bookmark Import - Marble" ), text );
431 GeoDataDocument* current = bookmarkDocument();
433 bool replaceAll =
false;
434 bool skipAll =
false;
435 foreach( GeoDataFolder* newFolder, import->folderList() ) {
436 foreach( GeoDataPlacemark* newPlacemark, newFolder->placemarkList() ) {
437 bool added = skipAll;
438 foreach( GeoDataFolder* existingFolder, current->folderList() ) {
439 for(
int i=0; i<existingFolder->size() && !added; ++i ) {
440 GeoDataPlacemark* existingPlacemark =
dynamic_cast<GeoDataPlacemark*
>( existingFolder->child( i ) );
441 if ( existingPlacemark && existingPlacemark->coordinate() == newPlacemark->coordinate() ) {
448 if ( existingPlacemark->name() == newPlacemark->name() &&
449 existingPlacemark->description() == newPlacemark->description() ) {
454 QMessageBox messageBox(
this );
455 QString
const intro = tr(
"The file contains a bookmark that already exists among your Bookmarks." );
456 QString
const newBookmark = tr(
"Imported bookmark" );
457 QString
const existingBookmark = tr(
"Existing bookmark" );
458 QString
const question = tr(
"Do you want to replace the existing bookmark with the imported one?" );
459 QString html =
"<p>%1</p><table><tr><td>%2</td><td><b>%3 / %4</b></td></tr>";
460 html +=
"<tr><td>%5</td><td><b>%6 / %7</b></td></tr></table><p>%8</p>";
461 html = html.arg( intro ).arg( existingBookmark ).arg( existingFolder->name() );
462 html = html.arg( existingPlacemark->name() ).arg( newBookmark ).arg( newFolder->name() );
463 html = html.arg( newPlacemark->name() ).arg( question );
464 messageBox.setText( html );
466 QAbstractButton *replaceButton = messageBox.addButton(tr(
"Replace" ), QMessageBox::ActionRole );
467 QAbstractButton *replaceAllButton = messageBox.addButton(tr(
"Replace All" ), QMessageBox::ActionRole );
468 QAbstractButton *skipButton = messageBox.addButton(tr(
"Skip" ), QMessageBox::ActionRole );
469 QAbstractButton *skipAllButton = messageBox.addButton(tr(
"Skip All" ), QMessageBox::ActionRole );
470 messageBox.addButton(tr(
"Cancel" ), QMessageBox::RejectRole );
471 messageBox.setIcon( QMessageBox::Question );
476 if ( messageBox.clickedButton() == replaceAllButton ) {
478 }
else if ( messageBox.clickedButton() == skipAllButton ) {
481 }
else if ( messageBox.clickedButton() == skipButton ) {
484 }
else if ( messageBox.clickedButton() != replaceButton ) {
488 if ( messageBox.clickedButton() == replaceButton || replaceAll ) {
489 d->m_manager->removeBookmark( existingPlacemark );
490 d->m_manager->addBookmark( newFolder, *newPlacemark );
491 mDebug() <<
"Placemark " << newPlacemark->name() <<
" replaces " << existingPlacemark->name();
500 d->m_manager->addBookmark( newFolder, *newPlacemark );
508 GeoDataDocument* BookmarkManagerDialog::bookmarkDocument()
510 return d->m_manager->document();
515 buttonBox->setVisible( visible );
517 disconnect(
this, SIGNAL(rejected()),
this, SLOT(discardChanges()) );
518 connect(
this, SIGNAL(rejected()), SLOT(saveBookmarks()) );
524 #include "BookmarkManagerDialog.moc"
GeoDataTreeModel * treeModel()
Return the list of Placemarks as a QAbstractItemModel *.
This file contains the headers for MarbleModel.
const char * GeoDataDocumentType
The pointer to a specific object.
void setButtonBoxVisible(bool visible)
~BookmarkManagerDialog()
Destructor.
const char * GeoDataFolderType
static MarbleGlobal * getInstance()
The data model (not based on QAbstractModel) for a MarbleWidget.
Profiles profiles() const
BookmarkManagerDialog(MarbleModel *model, QWidget *parent=0)
Constructor.
QDebug mDebug()
a function to replace qDebug() in Marble library code