1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2008-05-30
7 * Description : GPS search sidebar tab contents.
8 *
9 * Copyright (C) 2008-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10 * Copyright (C) 2009 by Johannes Wienke <languitar at semipol dot de>
11 * Copyright (C) 2010-2011 by Michael G. Hansen <mike at mghansen dot de>
12 * Copyright (C) 2014 by Mohamed_Anwer <m_dot_anwer at gmx dot com>
13 *
14 * This program is free software; you can redistribute it
15 * and/or modify it under the terms of the GNU General
16 * Public License as published by the Free Software Foundation;
17 * either version 2, or (at your option)
18 * any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * ============================================================ */
26
27 #include "gpssearchview.h"
28
29 // Qt includes
30
31 #include <QLabel>
32 #include <QLayout>
33 #include <QPushButton>
34 #include <QSplitter>
35 #include <QToolButton>
36 #include <QTimer>
37 #include <QMenu>
38 #include <QActionGroup>
39 #include <QAction>
40 #include <QApplication>
41 #include <QStyle>
42 #include <QLineEdit>
43 #include <QInputDialog>
44 #include <QIcon>
45
46 // KDE includes
47
48 #include <klocalizedstring.h>
49 #include <kconfiggroup.h>
50
51 // Local includes
52
53 #include "digikam_debug.h"
54 #include "searchtreeview.h"
55 #include "editablesearchtreeview.h"
56 #include "iteminfojob.h"
57 #include "coredbsearchxml.h"
58 #include "gpsmarkertiler.h"
59 #include "gpsiteminfosorter.h"
60 #include "searchtextbardb.h"
61
62 namespace Digikam
63 {
64
65 class Q_DECL_HIDDEN GPSSearchView::Private
66 {
67
68 public:
69
Private()70 explicit Private()
71 : saveBtn (nullptr),
72 nameEdit (nullptr),
73 imageInfoJob (),
74 searchGPSBar (nullptr),
75 searchTreeView (nullptr),
76 splitter (nullptr),
77 mapSearchWidget (nullptr),
78 gpsMarkerTiler (nullptr),
79 imageAlbumModel (nullptr),
80 imageFilterModel (nullptr),
81 selectionModel (nullptr),
82 searchModel (nullptr),
83 sortOrderOptionsHelper (nullptr)
84 {
85 }
86
87 static const QString configSplitterStateEntry;
88 QToolButton* saveBtn;
89 QLineEdit* nameEdit;
90 ItemInfoJob imageInfoJob;
91 SearchTextBarDb* searchGPSBar;
92 EditableSearchTreeView* searchTreeView;
93 QSplitter* splitter;
94 MapWidget* mapSearchWidget;
95 GPSMarkerTiler* gpsMarkerTiler;
96 ItemAlbumModel* imageAlbumModel;
97 ItemFilterModel* imageFilterModel;
98 QItemSelectionModel* selectionModel;
99 SearchModel* searchModel;
100 GPSItemInfoSorter* sortOrderOptionsHelper;
101 QString nonGeonlocatedItemsXml;
102 };
103
104 const QString GPSSearchView::Private::configSplitterStateEntry(QLatin1String("SplitterState"));
105
106 /**
107 * @brief Constructor
108 * @param parent the parent object.
109 * @param searchModel The model that stores the searches.
110 * @param imageFilterModel The image model used by displaying the selected images on map.
111 * @param itemSelectionModel The selection model corresponding to the imageFilterModel.
112 */
GPSSearchView(QWidget * const parent,SearchModel * const searchModel,SearchModificationHelper * const searchModificationHelper,ItemFilterModel * const imageFilterModel,QItemSelectionModel * const itemSelectionModel)113 GPSSearchView::GPSSearchView(QWidget* const parent,
114 SearchModel* const searchModel,
115 SearchModificationHelper* const searchModificationHelper,
116 ItemFilterModel* const imageFilterModel,
117 QItemSelectionModel* const itemSelectionModel)
118 : QWidget (parent),
119 StateSavingObject(this),
120 d (new Private)
121 {
122 setAttribute(Qt::WA_DeleteOnClose);
123
124 /// @todo Really?
125
126 setAcceptDrops(true);
127
128 d->imageAlbumModel = qobject_cast<ItemAlbumModel*>(imageFilterModel->sourceModel());
129 d->selectionModel = itemSelectionModel;
130 d->imageFilterModel = imageFilterModel;
131 d->searchModel = searchModel;
132
133 // ---------------------------------------------------------------
134
135 QVBoxLayout* const vlay = new QVBoxLayout(this);
136
137 QFrame* const mapPanel = new QFrame(this);
138 mapPanel->setMinimumWidth(256);
139 mapPanel->setMinimumHeight(256);
140 QVBoxLayout* const vlay2 = new QVBoxLayout(mapPanel);
141 d->mapSearchWidget = new MapWidget(mapPanel);
142 d->mapSearchWidget->setBackend(QLatin1String("marble"));
143 d->mapSearchWidget->setShowThumbnails(true);
144
145 d->gpsMarkerTiler = new GPSMarkerTiler(this, d->imageFilterModel, d->selectionModel);
146 d->mapSearchWidget->setGroupedModel(d->gpsMarkerTiler);
147
148 mapPanel->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
149 mapPanel->setLineWidth(style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
150
151 d->sortOrderOptionsHelper = new GPSItemInfoSorter(this);
152 d->sortOrderOptionsHelper->addToMapWidget(d->mapSearchWidget);
153
154 vlay2->addWidget(d->mapSearchWidget);
155 vlay2->setContentsMargins(QMargins());
156 vlay2->setSpacing(0);
157
158 // ---------------------------------------------------------------
159
160 DHBox* const hbox = new DHBox(this);
161 hbox->setContentsMargins(QMargins());
162 hbox->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
163
164 d->nameEdit = new QLineEdit(hbox);
165 d->nameEdit->setClearButtonEnabled(true);
166 d->nameEdit->setWhatsThis(i18n("Enter the name of the current map search to save in the "
167 "\"Map Searches\" view."));
168
169 d->saveBtn = new QToolButton(hbox);
170 d->saveBtn->setIcon(QIcon::fromTheme(QLatin1String("document-save")));
171 d->saveBtn->setEnabled(false);
172 d->saveBtn->setToolTip(i18n("Save current map search to a new virtual album."));
173 d->saveBtn->setWhatsThis(i18n("If this button is pressed, the current map search "
174 "will be saved to a new search "
175 "virtual album using the name "
176 "set on the left side."));
177
178 // ---------------------------------------------------------------
179
180 d->searchTreeView = new EditableSearchTreeView(this, d->searchModel, searchModificationHelper);
181 d->searchTreeView->filteredModel()->setFilterSearchType(DatabaseSearch::MapSearch);
182 d->searchTreeView->filteredModel()->setListTemporarySearches(true);
183 d->searchTreeView->setAlbumManagerCurrentAlbum(true);
184 d->searchGPSBar = new SearchTextBarDb(this, QLatin1String("GPSSearchViewSearchGPSBar"));
185 d->searchGPSBar->setModel(d->searchTreeView->filteredModel(), AbstractAlbumModel::AlbumIdRole, AbstractAlbumModel::AlbumTitleRole);
186 d->searchGPSBar->setFilterModel(d->searchTreeView->albumFilterModel());
187
188 // ---------------------------------------------------------------
189
190 d->splitter = new QSplitter(Qt::Vertical, this);
191
192 QFrame* const frameTop = new QFrame(d->splitter);
193 QVBoxLayout* const vlayTop = new QVBoxLayout(frameTop);
194 vlayTop->addWidget(mapPanel);
195 vlayTop->addWidget(d->mapSearchWidget->getControlWidget());
196
197 d->mapSearchWidget->setAvailableMouseModes(MouseModePan |
198 MouseModeRegionSelection |
199 MouseModeZoomIntoGroup |
200 MouseModeRegionSelectionFromIcon |
201 MouseModeFilter |
202 MouseModeSelectThumbnail);
203
204 d->mapSearchWidget->setVisibleMouseModes(MouseModePan |
205 MouseModeZoomIntoGroup |
206 MouseModeFilter |
207 MouseModeSelectThumbnail);
208
209 /**
210 * construct a second row of control actions below the control widget
211 * @todo Should we still replace the icons of the actions with text as discussed during the sprint?
212 */
213 QWidget* const secondActionRow = new QWidget();
214 QHBoxLayout* const secondActionRowHBox = new QHBoxLayout();
215 secondActionRowHBox->setContentsMargins(QMargins());
216 secondActionRow->setLayout(secondActionRowHBox);
217
218 QLabel* const secondActionRowLabel = new QLabel(i18n("Search by area:"));
219 secondActionRowHBox->addWidget(secondActionRowLabel);
220
221 QToolButton* const tbRegionSelection = new QToolButton(secondActionRow);
222 tbRegionSelection->setDefaultAction(d->mapSearchWidget->getControlAction(QLatin1String("mousemode-regionselectionmode")));
223 secondActionRowHBox->addWidget(tbRegionSelection);
224
225 QToolButton* const tbRegionFromIcon = new QToolButton(secondActionRow);
226 tbRegionFromIcon->setDefaultAction(d->mapSearchWidget->getControlAction(QLatin1String("mousemode-regionselectionfromiconmode")));
227 secondActionRowHBox->addWidget(tbRegionFromIcon);
228
229 QToolButton* const tbClearRegionSelection = new QToolButton(secondActionRow);
230 tbClearRegionSelection->setDefaultAction(d->mapSearchWidget->getControlAction(QLatin1String("mousemode-removecurrentregionselection")));
231 secondActionRowHBox->addWidget(tbClearRegionSelection);
232
233 secondActionRowHBox->addStretch(10);
234 vlayTop->addWidget(secondActionRow);
235
236 // end of the second action row
237
238 // Show Non Geolocated Items row
239
240 QWidget* const nonGeolocatedActionRow = new QWidget();
241 QVBoxLayout* const thirdActionRowVBox = new QVBoxLayout();
242 thirdActionRowVBox->setContentsMargins(QMargins());
243 nonGeolocatedActionRow->setLayout(thirdActionRowVBox);
244
245 QPushButton* const nonGeolocatedBtn = new QPushButton(nonGeolocatedActionRow);
246 nonGeolocatedBtn->setText(i18n("Show Non-Geolocated Items"));
247 nonGeolocatedBtn->setIcon(QIcon::fromTheme(QLatin1String("emblem-unmounted")));
248 thirdActionRowVBox->addWidget(nonGeolocatedBtn);
249
250 thirdActionRowVBox->addStretch(10);
251 vlayTop->addWidget(nonGeolocatedActionRow);
252
253 // end of the third action row
254
255 vlayTop->addWidget(hbox);
256 vlayTop->setStretchFactor(mapPanel, 10);
257 vlayTop->setContentsMargins(QMargins());
258 vlayTop->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
259 QFrame* const frameBottom = new QFrame(d->splitter);
260 QVBoxLayout* const vlayBottom = new QVBoxLayout(frameBottom);
261 vlayBottom->addWidget(d->searchTreeView);
262 vlayBottom->addWidget(d->searchGPSBar);
263 vlayBottom->setContentsMargins(QMargins());
264 vlayBottom->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));
265
266 d->splitter->addWidget(frameTop);
267 d->splitter->addWidget(frameBottom);
268
269 // ---------------------------------------------------------------
270
271 vlay->addWidget(d->splitter);
272
273 // ---------------------------------------------------------------
274
275 connect(d->searchTreeView, SIGNAL(currentAlbumChanged(Album*)),
276 this, SLOT(slotAlbumSelected(Album*)));
277
278 connect(d->saveBtn, SIGNAL(clicked()),
279 this, SLOT(slotSaveGPSSAlbum()));
280
281 connect(d->nameEdit, SIGNAL(textChanged(QString)),
282 this, SLOT(slotCheckNameEditGPSConditions()));
283
284 connect(d->nameEdit, SIGNAL(returnPressed()),
285 d->saveBtn, SLOT(animateClick()));
286
287 connect(d->mapSearchWidget, SIGNAL(signalRegionSelectionChanged()),
288 this, SLOT(slotRegionSelectionChanged()));
289
290 connect(d->gpsMarkerTiler, SIGNAL(signalModelFilteredImages(QList<qlonglong>)),
291 this, SLOT(slotMapSoloItems(QList<qlonglong>)));
292
293 connect(d->mapSearchWidget, SIGNAL(signalRemoveCurrentFilter()),
294 this, SLOT(slotRemoveCurrentFilter()));
295
296 connect(nonGeolocatedBtn, SIGNAL(clicked()),
297 d->mapSearchWidget->getControlAction(QLatin1String("mousemode-removecurrentregionselection")), SIGNAL(triggered()));
298
299 connect(nonGeolocatedBtn, SIGNAL(clicked()),
300 this, SLOT(showNonGeolocatedItems()));
301
302 // ---------------------------------------------------------------
303
304 slotCheckNameEditGPSConditions();
305 }
306
~GPSSearchView()307 GPSSearchView::~GPSSearchView()
308 {
309 delete d;
310 }
311
setConfigGroup(const KConfigGroup & group)312 void GPSSearchView::setConfigGroup(const KConfigGroup& group)
313 {
314 StateSavingObject::setConfigGroup(group);
315 d->searchTreeView->setConfigGroup(group);
316 }
317
doLoadState()318 void GPSSearchView::doLoadState()
319 {
320 KConfigGroup group = getConfigGroup();
321
322 if (group.hasKey(entryName(d->configSplitterStateEntry)))
323 {
324 const QByteArray splitterState = QByteArray::fromBase64(group.readEntry(entryName(d->configSplitterStateEntry), QByteArray()));
325
326 if (!splitterState.isEmpty())
327 {
328 d->splitter->restoreState(splitterState);
329 }
330 }
331
332 d->sortOrderOptionsHelper->setSortOptions(GPSItemInfoSorter::SortOptions(group.readEntry(entryName(QLatin1String("Sort Order")), int(d->sortOrderOptionsHelper->getSortOptions()))));
333
334 const KConfigGroup groupMapWidget = KConfigGroup(&group, entryName(QLatin1String("GPSSearch Map Widget")));
335
336 d->mapSearchWidget->readSettingsFromGroup(&groupMapWidget);
337
338 d->searchTreeView->loadState();
339
340 AlbumManager::instance()->clearCurrentAlbums();
341
342 d->searchTreeView->clearSelection();
343 }
344
doSaveState()345 void GPSSearchView::doSaveState()
346 {
347 KConfigGroup group = getConfigGroup();
348
349 group.writeEntry(entryName(d->configSplitterStateEntry), d->splitter->saveState().toBase64());
350 group.writeEntry(entryName(QLatin1String("Sort Order")), int(d->sortOrderOptionsHelper->getSortOptions()));
351
352 KConfigGroup groupMapWidget = KConfigGroup(&group, entryName(QLatin1String("GPSSearch Map Widget")));
353 d->mapSearchWidget->saveSettingsToGroup(&groupMapWidget);
354 d->searchTreeView->saveState();
355
356 group.sync();
357 }
358
359 /**
360 * @brief Sets the widget active or inactive.
361 *
362 * Called when the GPSSearch tab becomes the current/not current tab.
363 *
364 * @param state When true, the widget is enabled.
365 */
setActive(bool state)366 void GPSSearchView::setActive(bool state)
367 {
368 if (!state)
369 {
370 // make sure we reset the custom filters set by the map:
371
372 emit signalMapSoloItems(QList<qlonglong>(), QLatin1String("gpssearch"));
373 d->mapSearchWidget->setActive(false);
374 }
375 else
376 {
377 d->mapSearchWidget->setActive(true);
378
379 if (d->searchTreeView->currentAlbum())
380 {
381 AlbumManager::instance()->setCurrentAlbums(QList<Album*>() << d->searchTreeView->currentAlbum());
382 }
383
384 slotClearImages();
385 }
386 }
387
changeAlbumFromHistory(SAlbum * const album)388 void GPSSearchView::changeAlbumFromHistory(SAlbum* const album)
389 {
390 d->searchTreeView->setCurrentAlbums(QList<Album*>() << album);
391 }
392
393 /**
394 * This slot saves the current album.
395 */
slotSaveGPSSAlbum()396 void GPSSearchView::slotSaveGPSSAlbum()
397 {
398 QString name = d->nameEdit->text();
399
400 if (!checkName(name))
401 {
402 return;
403 }
404
405 createNewGPSSearchAlbum(name);
406 }
407
408 /**
409 * This slot is called when a new selection is made. It creates a new Search Album.
410 */
slotRegionSelectionChanged()411 void GPSSearchView::slotRegionSelectionChanged()
412 {
413 const GeoCoordinates::Pair newRegionSelection = d->mapSearchWidget->getRegionSelection();
414 const bool haveRegionSelection = newRegionSelection.first.hasCoordinates();
415
416 if (haveRegionSelection)
417 {
418 slotCheckNameEditGPSConditions();
419 createNewGPSSearchAlbum(SAlbum::getTemporaryTitle(DatabaseSearch::MapSearch));
420 }
421 else
422 {
423 // reset the search rectangle of the temporary album:
424
425 createNewGPSSearchAlbum(SAlbum::getTemporaryTitle(DatabaseSearch::MapSearch));
426 d->gpsMarkerTiler->removeCurrentRegionSelection();
427 d->searchTreeView->clearSelection();
428 slotClearImages();
429 }
430
431 // also remove any filters which may have been there
432
433 slotRemoveCurrentFilter();
434
435 slotRefreshMap();
436 }
437
438 /**
439 * @brief This function creates a new Search Album.
440 * @param name The name of the new album.
441 */
createNewGPSSearchAlbum(const QString & name)442 void GPSSearchView::createNewGPSSearchAlbum(const QString& name)
443 {
444 /*
445 AlbumManager::instance()->clearCurrentAlbums();
446 */
447 // We query the database here
448
449 const GeoCoordinates::Pair coordinates = d->mapSearchWidget->getRegionSelection();
450 const bool haveCoordinates = coordinates.first.hasCoordinates();
451
452 if (haveCoordinates)
453 {
454 d->gpsMarkerTiler->setRegionSelection(coordinates);
455 }
456
457 // NOTE: coordinates as lon1, lat1, lon2, lat2 (or West, North, East, South)
458 // as left/top, right/bottom rectangle.
459
460 QList<qreal> coordinatesList = QList<qreal>() <<
461 coordinates.first.lon() << coordinates.first.lat() <<
462 coordinates.second.lon() << coordinates.second.lat();
463
464 if (!haveCoordinates)
465 {
466 /// @todo We need to create a search album with invalid coordinates
467
468 coordinatesList.clear();
469 coordinatesList << -200 << -200 << -200 << -200;
470 }
471
472 qCDebug(DIGIKAM_GENERAL_LOG) << "West, North, East, South: " << coordinatesList;
473
474 SearchXmlWriter writer;
475 writer.writeGroup();
476 writer.writeField(QLatin1String("position"), SearchXml::Inside);
477 writer.writeAttribute(QLatin1String("type"), QLatin1String("rectangle"));
478 writer.writeValue(coordinatesList);
479 writer.finishField();
480 writer.finishGroup();
481
482 SAlbum* const salbum = AlbumManager::instance()->createSAlbum(name, DatabaseSearch::MapSearch, writer.xml());
483 AlbumManager::instance()->setCurrentAlbums(QList<Album*>() << salbum);
484 d->imageInfoJob.allItemsFromAlbum(salbum);
485 d->searchTreeView->setCurrentAlbums(QList<Album*>() << salbum);
486 d->imageAlbumModel->openAlbum(QList<Album*>() << salbum);
487 }
488
489 /**
490 * @brief An album is selected in the saved searches list.
491 * @param a This album will be selected.
492 */
slotAlbumSelected(Album * a)493 void GPSSearchView::slotAlbumSelected(Album* a)
494 {
495 /// @todo This re-sets the region selection unwantedly...
496
497 SAlbum* const salbum = dynamic_cast<SAlbum*>(a);
498
499 if (!salbum)
500 {
501 return;
502 }
503
504 SearchXmlReader reader(salbum->query());
505 reader.readToFirstField();
506 QStringRef type = reader.attributes().value(QLatin1String("type"));
507
508 if (type == QLatin1String("rectangle"))
509 {
510 const QList<double> list = reader.valueToDoubleList();
511
512 const GeoCoordinates::Pair coordinates(
513 GeoCoordinates(list.at(1), list.at(0)),
514 GeoCoordinates(list.at(3), list.at(2))
515 );
516
517 /// @todo Currently, invalid coordinates are stored as -200:
518
519 if (list.at(1) != -200)
520 {
521 d->mapSearchWidget->setRegionSelection(coordinates);
522 d->gpsMarkerTiler->setRegionSelection(coordinates);
523 }
524 else
525 {
526 d->mapSearchWidget->clearRegionSelection();
527 d->gpsMarkerTiler->removeCurrentRegionSelection();
528 }
529
530 slotCheckNameEditGPSConditions();
531 }
532
533 d->imageInfoJob.allItemsFromAlbum(salbum);
534 }
535
536 /**
537 * @brief Checks whether the newly added search name already exists.
538 * @param name The name of the current search.
539 */
checkName(QString & name)540 bool GPSSearchView::checkName(QString& name)
541 {
542 bool checked = checkAlbum(name);
543
544 while (!checked)
545 {
546 QString label = i18n("Search name already exists.\n"
547 "Please enter a new name:");
548 bool ok;
549 QString newTitle = QInputDialog::getText(this,
550 i18n("Name exists"),
551 label,
552 QLineEdit::Normal,
553 name,
554 &ok);
555
556 if (!ok)
557 {
558 return false;
559 }
560
561 name = newTitle;
562 checked = checkAlbum(name);
563 }
564
565 return true;
566 }
567
568 /**
569 * @brief Checks whether the newly added album name already exists.
570 * @param name The name of the album.
571 */
checkAlbum(const QString & name) const572 bool GPSSearchView::checkAlbum(const QString& name) const
573 {
574 const AlbumList list = AlbumManager::instance()->allSAlbums();
575
576 for (AlbumList::ConstIterator it = list.constBegin() ; it != list.constEnd() ; ++it)
577 {
578 const SAlbum* const album = (SAlbum*)(*it);
579
580 if (album->title() == name)
581 {
582 return false;
583 }
584 }
585
586 return true;
587 }
588
589 /**
590 * @brief Remove the current filter.
591 */
slotRemoveCurrentFilter()592 void GPSSearchView::slotRemoveCurrentFilter()
593 {
594 d->gpsMarkerTiler->setPositiveFilterIsActive(false);
595 const QList<qlonglong> emptyIdList;
596 emit signalMapSoloItems(emptyIdList, QLatin1String("gpssearch"));
597 slotRefreshMap();
598 d->mapSearchWidget->slotUpdateActionsEnabled();
599 }
600
601 /**
602 * @brief Enable or disable the album saving controls.
603 */
slotCheckNameEditGPSConditions()604 void GPSSearchView::slotCheckNameEditGPSConditions()
605 {
606 if (d->mapSearchWidget->getRegionSelection().first.hasCoordinates())
607 {
608 d->nameEdit->setEnabled(true);
609
610 if (!d->nameEdit->text().isEmpty())
611 {
612 d->saveBtn->setEnabled(true);
613 }
614 }
615 else
616 {
617 d->nameEdit->setEnabled(false);
618 d->saveBtn->setEnabled(false);
619 }
620 }
621
622 /**
623 * @brief Slot which gets called when the user makes items 'solo' on the map
624 * @param gpsList List of GPSInfos which are 'solo'
625 */
slotMapSoloItems(const QList<qlonglong> & idList)626 void GPSSearchView::slotMapSoloItems(const QList<qlonglong>& idList)
627 {
628 emit signalMapSoloItems(idList, QLatin1String("gpssearch"));
629 d->mapSearchWidget->slotUpdateActionsEnabled();
630 }
631
showNonGeolocatedItems()632 void GPSSearchView::showNonGeolocatedItems()
633 {
634 if (d->nonGeonlocatedItemsXml.isEmpty())
635 {
636 SearchXmlWriter writer;
637 writer.setFieldOperator((SearchXml::standardFieldOperator()));
638 writer.writeGroup();
639 writer.writeField(QLatin1String("nogps"), SearchXml::Equal);
640 writer.finishField();
641 writer.finishGroup();
642 writer.finish();
643 d->nonGeonlocatedItemsXml = writer.xml();
644 }
645
646 QString title = SAlbum::getTemporaryTitle(DatabaseSearch::MapSearch);
647 SAlbum* album = AlbumManager::instance()->findSAlbum(title);
648
649 int id;
650
651 if (album)
652 {
653 id = album->id();
654 CoreDbAccess().db()->updateSearch(id, DatabaseSearch::AdvancedSearch,
655 SAlbum::getTemporaryTitle(DatabaseSearch::AdvancedSearch),
656 d->nonGeonlocatedItemsXml);
657 }
658 else
659 {
660 id = CoreDbAccess().db()->addSearch(DatabaseSearch::AdvancedSearch,
661 SAlbum::getTemporaryTitle(DatabaseSearch::AdvancedSearch),
662 d->nonGeonlocatedItemsXml);
663 }
664
665 album = new SAlbum(i18n("Non Geo-located Items"), id);
666
667 if (album)
668 {
669 AlbumManager::instance()->setCurrentAlbums(QList<Album*>() << album);
670 }
671 }
672
673
slotRefreshMap()674 void GPSSearchView::slotRefreshMap()
675 {
676 d->mapSearchWidget->refreshMap();
677 }
678
slotClearImages()679 void GPSSearchView::slotClearImages()
680 {
681 if (d->mapSearchWidget->getActiveState())
682 {
683 d->imageAlbumModel->clearItemInfos();
684 }
685 }
686
687 } // namespace Digikam
688