File indexing completed on 2025-01-19 03:53:47

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2017-05-06
0007  * Description : interface to database information for shared tools.
0008  *
0009  * SPDX-FileCopyrightText: 2017-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText: 2019-2020 by Minh Nghia Duong <minhnghiaduong997 at gmail dot com>
0011  * SPDX-FileCopyrightText: 2017      by Mario Frank <mario dot frank at uni minus potsdam dot de>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #include "dbinfoiface.h"
0018 
0019 // Qt includes
0020 
0021 #include <QDir>
0022 #include <QStandardPaths>
0023 
0024 // Local includes
0025 
0026 #include "albumselecttabs.h"
0027 #include "album.h"
0028 #include "albummodel.h"
0029 #include "albummanager.h"
0030 #include "albumfiltermodel.h"
0031 #include "albumselectwidget.h"
0032 #include "albumparser.h"
0033 #include "coredb.h"
0034 #include "collectionmanager.h"
0035 #include "coredbnamefilter.h"
0036 #include "collectionscanner.h"
0037 #include "digikamapp.h"
0038 #include "digikam_debug.h"
0039 #include "itemattributeswatch.h"
0040 #include "itemiconview.h"
0041 #include "itemcomments.h"
0042 #include "itemcopyright.h"
0043 #include "iteminfo.h"
0044 #include "photoinfocontainer.h"
0045 #include "videoinfocontainer.h"
0046 #include "itemposition.h"
0047 #include "itemsortsettings.h"
0048 #include "coredbsearchxml.h"
0049 #include "itemlister.h"
0050 #include "itemlisterreceiver.h"
0051 #include "dio.h"
0052 #include "disjointmetadata.h"
0053 #include "fileactionmngr.h"
0054 #include "tagsactionmngr.h"
0055 #include "setup.h"
0056 
0057 #ifdef HAVE_GEOLOCATION
0058 #   include "itemgps.h"
0059 #endif
0060 
0061 namespace Digikam
0062 {
0063 
0064 class Q_DECL_HIDDEN DBInfoIface::Private
0065 {
0066 public:
0067 
0068     explicit Private()
0069       : albumManager    (AlbumManager::instance()),
0070         albumsChooser   (nullptr),
0071         albumSelector   (nullptr),
0072         operationType   (ApplicationSettings::Unspecified),
0073         withGroupedIsSet(false),
0074         withGrouped     (false)
0075     {
0076     }
0077 
0078     AlbumManager*                      albumManager;
0079     AlbumSelectTabs*                   albumsChooser;
0080     AlbumSelectWidget*                 albumSelector;
0081 
0082     QList<QUrl>                        itemUrls;
0083 
0084     ApplicationSettings::OperationType operationType;
0085     bool                               withGroupedIsSet;
0086     bool                               withGrouped;
0087 
0088 public:
0089 
0090     /**
0091      * get the images from the Physical album in database and return the items found.
0092      */
0093     QList<QUrl> imagesFromPAlbum(PAlbum* const album) const
0094     {
0095         // get the images from the database and return the items found
0096 
0097         CoreDB::ItemSortOrder sortOrder = CoreDB::NoItemSorting;
0098 
0099         switch (ApplicationSettings::instance()->getImageSortOrder())
0100         {
0101             default:
0102             case ItemSortSettings::SortByFileName:
0103             {
0104                 sortOrder = CoreDB::ByItemName;
0105                 break;
0106             }
0107 
0108             case ItemSortSettings::SortByFilePath:
0109             {
0110                 sortOrder = CoreDB::ByItemPath;
0111                 break;
0112             }
0113 
0114             case ItemSortSettings::SortByCreationDate:
0115             {
0116                 sortOrder = CoreDB::ByItemDate;
0117                 break;
0118             }
0119 
0120             case ItemSortSettings::SortByRating:
0121             {
0122                 sortOrder = CoreDB::ByItemRating;
0123                 break;
0124             }
0125 
0126             // NOTE: ByISize not supported
0127         }
0128 
0129         QStringList list = CoreDbAccess().db()->getItemURLsInAlbum(album->id(), sortOrder);
0130         QList<QUrl> urlList;
0131         CoreDbNameFilter nameFilter(ApplicationSettings::instance()->getAllFileFilter());
0132 
0133         for (QStringList::const_iterator it = list.constBegin() ; it != list.constEnd() ; ++it)
0134         {
0135             if (nameFilter.matches(*it))
0136             {
0137                 urlList << QUrl::fromLocalFile(*it);
0138             }
0139         }
0140 
0141         return urlList;
0142     }
0143 
0144     /**
0145      * get the images from the Tags album in database and return the items found.
0146      */
0147     QList<QUrl> imagesFromTAlbum(TAlbum* const album) const
0148     {
0149         QStringList list = CoreDbAccess().db()->getItemURLsInTag(album->id());
0150         QList<QUrl> urlList;
0151         CoreDbNameFilter nameFilter(ApplicationSettings::instance()->getAllFileFilter());
0152 
0153         for (QStringList::const_iterator it = list.constBegin() ; it != list.constEnd() ; ++it)
0154         {
0155             if (nameFilter.matches(*it))
0156             {
0157                 urlList << QUrl::fromLocalFile(*it);
0158             }
0159         }
0160 
0161         return urlList;
0162     }
0163 
0164     /**
0165      * get the images from the search album in database and return the items found.
0166      */
0167     QList<QUrl> imagesFromSAlbum(SAlbum* const album) const
0168     {
0169         QList<QUrl> urlList;
0170         CoreDbNameFilter nameFilter(ApplicationSettings::instance()->getAllFileFilter());
0171 
0172         if (album->isDuplicatesSearch())
0173         {
0174             // duplicates search album -> get the id list from the query
0175 
0176             SearchXmlReader reader(album->query());
0177             reader.readToFirstField();
0178 
0179             // Get the defined image ids.
0180 
0181             QList<int> list;
0182             list << reader.valueToIntList();
0183 
0184             Q_FOREACH (int imageId, list)
0185             {
0186                 ItemInfo imageInfo(imageId);
0187                 if (imageInfo.isVisible())
0188                 {
0189                     // if the image is visible, i.e. existent and not deleted,
0190                     // add the url if the name filter matches
0191 
0192                     QUrl imageUrl = imageInfo.fileUrl();
0193 /*
0194                     qCDebug(DIGIKAM_GENERAL_LOG) << "Duplicates search Image url "
0195                                                  << imageUrl.toString();
0196 */
0197                     if (nameFilter.matches(imageUrl.toString()))
0198                     {
0199                         urlList << imageUrl;
0200                     }
0201                 }
0202             }
0203         }
0204         else
0205         {
0206             // If we do not have a duplicates search, we use the image lister to get the images.
0207 
0208             ItemLister lister;
0209             lister.setListOnlyAvailable(true);
0210 
0211             ItemListerValueListReceiver receiver;
0212 
0213             if (album->searchType() == DatabaseSearch::HaarSearch)
0214             {
0215                 lister.listHaarSearch(&receiver, album->query());
0216             }
0217             else
0218             {
0219                 lister.listSearch(&receiver, album->query(), 0, -1);
0220             }
0221 
0222             if (!receiver.hasError)
0223             {
0224                 // if there were no error, fetch and process the results.
0225 
0226                 Q_FOREACH (const ItemListerRecord &record, receiver.records)
0227                 {
0228                     ItemInfo imageInfo(record);
0229                     QUrl imageUrl = imageInfo.fileUrl();
0230 /*
0231                     qCDebug(DIGIKAM_GENERAL_LOG) << "Fuzzy/other search Image url "
0232                                                  << imageUrl.toString();
0233 */
0234                     if (nameFilter.matches(imageUrl.toString()))
0235                     {
0236                         urlList << imageUrl;
0237                     }
0238                 }
0239             }
0240         }
0241 
0242         return urlList;
0243     }
0244 
0245     /**
0246      * Remove grouped images if user chose/chooses to.
0247      */
0248     QList<QUrl> resolveGroupsFromAlbums(const QList<QUrl>& urlList)
0249     {
0250         QList<QUrl> lst = urlList;
0251 
0252         if (!(withGroupedIsSet && withGrouped))
0253         {
0254             Q_FOREACH (const QUrl& url, urlList)
0255             {
0256                 ItemInfo info = ItemInfo::fromUrl(url);
0257 
0258                 if (info.hasGroupedImages())
0259                 {
0260                     if (!withGroupedIsSet)
0261                     {
0262                         withGroupedIsSet = true;
0263                         withGrouped      = ApplicationSettings::instance()->askGroupingOperateOnAll(operationType);
0264 
0265                         if (withGrouped)
0266                         {
0267                             break;
0268                         }
0269                     }
0270 
0271                     Q_FOREACH (const ItemInfo& i, info.groupedImages())
0272                     {
0273                         lst.removeOne(i.fileUrl());
0274                     }
0275                 }
0276             }
0277         }
0278 
0279         return lst;
0280     }
0281 
0282     bool includeGroupedFromSelected()
0283     {
0284         if (withGroupedIsSet)
0285         {
0286             return withGrouped;
0287         }
0288 
0289         withGroupedIsSet = true;
0290         withGrouped      = DigikamApp::instance()->view()->selectedNeedGroupResolving(operationType);
0291 
0292         return withGrouped;
0293     }
0294 };
0295 
0296 DBInfoIface::DBInfoIface(QObject* const parent, const QList<QUrl>& lst,
0297                          const ApplicationSettings::OperationType type)
0298     : DInfoInterface(parent),
0299       d             (new Private)
0300 {
0301     setObjectName(QLatin1String("DBInfoIface"));
0302     d->itemUrls      = lst;
0303     d->operationType = type;
0304 
0305     // forward signal to DPluginAction of Digikam
0306 
0307     connect(TagsActionMngr::defaultManager(), SIGNAL(signalShortcutPressed(QString,int)),
0308             this, SIGNAL(signalShortcutPressed(QString,int)));
0309 }
0310 
0311 DBInfoIface::~DBInfoIface()
0312 {
0313     delete d;
0314 }
0315 
0316 void DBInfoIface::slotDateTimeForUrl(const QUrl& url, const QDateTime& dt, bool updModDate)
0317 {
0318     ItemInfo info = ItemInfo::fromUrl(url);
0319 
0320     if (!info.isNull())
0321     {
0322         info.setDateTime(dt);
0323 
0324         if (updModDate)
0325         {
0326             info.setModDateTime(dt);
0327         }
0328     }
0329 
0330     ItemAttributesWatch::instance()->fileMetadataChanged(url);
0331 }
0332 
0333 void DBInfoIface::slotMetadataChangedForUrl(const QUrl& url)
0334 {
0335     // Refresh Database with new metadata from file.
0336 
0337     CollectionScanner scanner;
0338 
0339     scanner.scanFile(url.toLocalFile(), CollectionScanner::Rescan);
0340     ItemAttributesWatch::instance()->fileMetadataChanged(url);
0341 }
0342 
0343 void DBInfoIface::parseAlbumItemsRecursive()
0344 {
0345     Album* const currAlbum = d->albumManager->currentAlbums().constFirst();
0346 
0347     if (currAlbum)
0348     {
0349         AlbumParser* const parser = new AlbumParser(currAlbum);
0350 
0351         connect(parser, SIGNAL(signalComplete(QList<QUrl>)),
0352                 this, SIGNAL(signalAlbumItemsRecursiveCompleted(QList<QUrl>)));
0353 
0354         parser->run();
0355     }
0356 }
0357 
0358 QList<QUrl> DBInfoIface::currentAlbumItems() const
0359 {
0360     if (!d->itemUrls.isEmpty())
0361     {
0362         return d->itemUrls;
0363     }
0364 
0365     if (d->albumManager->currentAlbums().isEmpty())
0366     {
0367         return QList<QUrl>();
0368     }
0369 
0370     QList<QUrl> imageList = DigikamApp::instance()->view()->allUrls(d->includeGroupedFromSelected());
0371 
0372     if (imageList.isEmpty())
0373     {
0374         Album* const currAlbum = d->albumManager->currentAlbums().constFirst();
0375         imageList              = d->resolveGroupsFromAlbums(albumItems(currAlbum));
0376     }
0377 
0378     return imageList;
0379 }
0380 
0381 QList<QUrl> DBInfoIface::currentSelectedItems() const
0382 {
0383     if (!d->itemUrls.isEmpty())
0384     {
0385         return d->itemUrls;
0386     }
0387 
0388     return DigikamApp::instance()->view()->selectedUrls(d->includeGroupedFromSelected());
0389 }
0390 
0391 QList<QUrl> DBInfoIface::allAlbumItems() const
0392 {
0393     QList<QUrl> imageList;
0394 
0395     const AlbumList palbumList = d->albumManager->allPAlbums();
0396 
0397     for (AlbumList::ConstIterator it = palbumList.constBegin() ;
0398          it != palbumList.constEnd() ; ++it)
0399     {
0400         // don't add the root album
0401 
0402         if ((*it)->isRoot())
0403         {
0404             continue;
0405         }
0406 
0407         PAlbum* const p = dynamic_cast<PAlbum*>(*it);
0408 
0409         if (p)
0410         {
0411             imageList.append(d->imagesFromPAlbum(p));
0412         }
0413     }
0414 
0415     return imageList;
0416 }
0417 
0418 DBInfoIface::DInfoMap DBInfoIface::albumInfo(int gid) const
0419 {
0420     Album* const a = d->albumManager->findAlbum(gid);
0421 
0422     if (!a)
0423     {
0424         return DInfoMap();
0425     }
0426 
0427     DInfoMap map;
0428     map.insert(QLatin1String("title"), a->title());
0429 
0430     PAlbum* const p = dynamic_cast<PAlbum*>(a);
0431 
0432     if (p)
0433     {
0434         map.insert(QLatin1String("caption"),   p->caption());
0435         map.insert(QLatin1String("date"),      p->date());
0436         map.insert(QLatin1String("path"),      p->folderPath());
0437         map.insert(QLatin1String("albumpath"), p->albumPath());
0438     }
0439 
0440     return map;
0441 }
0442 
0443 DBInfoIface::DInfoMap DBInfoIface::itemInfo(const QUrl& url) const
0444 {
0445     DInfoMap map;
0446 
0447     ItemInfo info = ItemInfo::fromUrl(url);
0448 
0449     if (!info.isNull())
0450     {
0451         map.insert(QLatin1String("name"),               info.name());
0452         map.insert(QLatin1String("title"),              info.title());
0453         map.insert(QLatin1String("albumid"),            info.albumId());
0454         map.insert(QLatin1String("comment"),            info.comment());
0455         map.insert(QLatin1String("orientation"),        info.orientation());
0456         map.insert(QLatin1String("datetime"),           info.dateTime());
0457         map.insert(QLatin1String("rating"),             info.rating());
0458         map.insert(QLatin1String("colorlabel"),         info.colorLabel());
0459         map.insert(QLatin1String("picklabel"),          info.pickLabel());
0460         map.insert(QLatin1String("filesize"),           info.fileSize());
0461         map.insert(QLatin1String("dimensions"),         info.dimensions());
0462 
0463         // Get digiKam Tags Path list of picture from database.
0464         // Ex.: "City/Paris/Monuments/Notre Dame"
0465 
0466         QList<int> tagIds            = info.tagIds();
0467         QStringList tagspath         = AlbumManager::instance()->tagPaths(tagIds, false);
0468         map.insert(QLatin1String("tagspath"),           tagspath);
0469 
0470         // Get digiKam Tags name (keywords) list of picture from database.
0471         // Ex.: "Notre Dame"
0472 
0473         QStringList tags             = AlbumManager::instance()->tagNames(tagIds);
0474         map.insert(QLatin1String("keywords"),           tags);
0475 
0476         // Get GPS location of picture from database.
0477 
0478         ItemPosition pos             = info.imagePosition();
0479 
0480         if (!pos.isEmpty())
0481         {
0482             map.insert(QLatin1String("latitude"),       pos.latitudeNumber());
0483             map.insert(QLatin1String("longitude"),      pos.longitudeNumber());
0484             map.insert(QLatin1String("altitude"),       pos.altitude());
0485         }
0486 
0487         // Get Copyright information of picture from database.
0488 
0489         ItemCopyright rights         = info.imageCopyright();
0490         map.insert(QLatin1String("creators"),           rights.creator());
0491         map.insert(QLatin1String("credit"),             rights.credit());
0492         map.insert(QLatin1String("rights"),             rights.rights());
0493         map.insert(QLatin1String("source"),             rights.source());
0494 
0495         PhotoInfoContainer photoInfo = info.photoInfoContainer();
0496         map.insert(QLatin1String("lens"),               photoInfo.lens);
0497         map.insert(QLatin1String("make"),               photoInfo.make);
0498         map.insert(QLatin1String("model"),              photoInfo.model);
0499         map.insert(QLatin1String("exposuretime"),       photoInfo.exposureTime);
0500         map.insert(QLatin1String("sensitivity"),        photoInfo.sensitivity);
0501         map.insert(QLatin1String("aperture"),           photoInfo.aperture);
0502         map.insert(QLatin1String("focallength"),        photoInfo.focalLength);
0503         map.insert(QLatin1String("focalLength35mm"),    photoInfo.focalLength35mm);
0504 
0505         // TODO: add more video metadata as needed
0506 
0507         VideoInfoContainer videoInfo = info.videoInfoContainer();
0508         map.insert(QLatin1String("videocodec"),         videoInfo.videoCodec);
0509 
0510         // Get complex text containers.
0511 
0512         ItemComments comments = info.imageComments(CoreDbAccess());
0513         CaptionsMap titles    = comments.toCaptionsMap(DatabaseComment::Title);
0514         map.insert(QLatin1String("titles"),             QVariant::fromValue(titles));
0515         CaptionsMap captions  = comments.toCaptionsMap(DatabaseComment::Comment);
0516         map.insert(QLatin1String("captions"),           QVariant::fromValue(captions));
0517 
0518         Template tpl                      = info.metadataTemplate();
0519         MetaEngine::AltLangMap copyrights = tpl.copyright();
0520         map.insert(QLatin1String("copyrights"),         QVariant::fromValue(copyrights));
0521         MetaEngine::AltLangMap notices    = tpl.rightUsageTerms();
0522         map.insert(QLatin1String("copyrightnotices"),   QVariant::fromValue(notices));
0523 
0524         qCDebug(DIGIKAM_GENERAL_LOG) << "Database Info populated for" << url;
0525     }
0526     else
0527     {
0528         qCDebug(DIGIKAM_GENERAL_LOG) << "Database Info is NULL for" << url;
0529     }
0530 
0531     return map;
0532 }
0533 
0534 void DBInfoIface::setItemInfo(const QUrl& url, const DInfoMap& map)
0535 {
0536     ItemInfo info    = ItemInfo::fromUrl(url);
0537     QStringList keys = map.keys();
0538     DisjointMetadata hub;
0539     hub.load(info);
0540 
0541     qCDebug(DIGIKAM_GENERAL_LOG) << "DBInfoIface::setItemInfo() keys:" << keys;
0542 
0543     if (map.contains(QLatin1String("orientation")))
0544     {
0545         FileActionMngr::instance()->setExifOrientation(QList<ItemInfo>() << info,
0546                                                        map[QLatin1String("orientation")].toInt());
0547         keys.removeAll(QLatin1String("orientation"));
0548     }
0549 
0550     if (map.contains(QLatin1String("rating")))
0551     {
0552         hub.setRating(map[QLatin1String("rating")].toInt());
0553         keys.removeAll(QLatin1String("rating"));
0554     }
0555 
0556     if (map.contains(QLatin1String("colorlabel")))
0557     {
0558         hub.setColorLabel(map[QLatin1String("colorlabel")].toInt());
0559         keys.removeAll(QLatin1String("colorlabel"));
0560     }
0561 
0562     if (map.contains(QLatin1String("picklabel")))
0563     {
0564         hub.setPickLabel(map[QLatin1String("picklabel")].toInt());
0565         keys.removeAll(QLatin1String("picklabel"));
0566     }
0567 
0568     // NOTE: For now tag doesn't really exist anywhere else apart from digikam
0569     // therefore it's not really necessary to implement accessor method in InfoIface.
0570 
0571     if (map.contains(QLatin1String("tag")))
0572     {
0573         hub.setTag(map[QLatin1String("tag")].toInt());
0574         keys.removeAll(QLatin1String("tag"));
0575     }
0576 
0577     if (map.contains(QLatin1String("titles")))
0578     {
0579         hub.setTitles(qvariant_cast<CaptionsMap>(map[QLatin1String("titles")]));
0580         keys.removeAll(QLatin1String("titles"));
0581     }
0582 
0583     if (map.contains(QLatin1String("captions")))
0584     {
0585         hub.setComments(qvariant_cast<CaptionsMap>(map[QLatin1String("captions")]));
0586         keys.removeAll(QLatin1String("captions"));
0587     }
0588 
0589     Template tpl = hub.metadataTemplate();
0590 
0591     if (map.contains(QLatin1String("copyrights")))
0592     {
0593         tpl.setCopyright(qvariant_cast<MetaEngine::AltLangMap>(map[QLatin1String("copyrights")]));
0594         hub.setMetadataTemplate(tpl);
0595         keys.removeAll(QLatin1String("copyrights"));
0596     }
0597 
0598     if (map.contains(QLatin1String("copyrightnotices")))
0599     {
0600         tpl.setRightUsageTerms(qvariant_cast<MetaEngine::AltLangMap>(map[QLatin1String("copyrightnotices")]));
0601         hub.setMetadataTemplate(tpl);
0602         keys.removeAll(QLatin1String("copyrightnotices"));
0603     }
0604 
0605     if (!keys.isEmpty())
0606     {
0607         qCWarning(DIGIKAM_GENERAL_LOG) << "Keys not yet supported in DBInfoIface::setItemInfo():" << keys;
0608     }
0609 
0610     // We write to the database immediately because
0611     // the FileActionMngr writes with a delay.
0612 
0613     if (hub.write(info, DisjointMetadata::PartialWrite))
0614     {
0615         FileActionMngr::instance()->applyMetadata(QList<ItemInfo>() << info, hub);
0616     }
0617 }
0618 
0619 QList<QUrl> DBInfoIface::albumItems(Album* const album) const
0620 {
0621     if (!album)
0622     {
0623         return QList<QUrl>();
0624     }
0625 
0626     QList<QUrl> imageList;
0627 
0628     switch (album->type())
0629     {
0630         case Album::PHYSICAL:
0631         {
0632             PAlbum* const p = dynamic_cast<PAlbum*>(album);
0633 
0634             if (p)
0635             {
0636                 imageList = d->imagesFromPAlbum(p);
0637             }
0638 
0639             break;
0640         }
0641 
0642         case Album::TAG:
0643         {
0644             TAlbum* const p = dynamic_cast<TAlbum*>(album);
0645 
0646             if (p)
0647             {
0648                 imageList = d->imagesFromTAlbum(p);
0649             }
0650 
0651             break;
0652         }
0653 
0654         case Album::SEARCH:
0655         {
0656             SAlbum* const s = dynamic_cast<SAlbum*>(album);
0657 
0658             if (s)
0659             {
0660                 imageList = d->imagesFromSAlbum(s);
0661             }
0662 
0663             break;
0664         }
0665 
0666         default:
0667         {
0668             qCWarning(DIGIKAM_GENERAL_LOG) << "Unknown album type";
0669             break;
0670         }
0671     }
0672 
0673     return d->resolveGroupsFromAlbums(imageList);
0674 }
0675 
0676 QList<QUrl> DBInfoIface::albumItems(int id) const
0677 {
0678     return albumItems(d->albumManager->findAlbum(id));
0679 }
0680 
0681 QList<QUrl> DBInfoIface::albumsItems(const DAlbumIDs& lst) const
0682 {
0683     QList<QUrl> imageList;
0684 
0685     Q_FOREACH (int gid, lst)
0686     {
0687         imageList << albumItems(gid);
0688     }
0689 
0690     return d->resolveGroupsFromAlbums(imageList);
0691 }
0692 
0693 QWidget* DBInfoIface::albumChooser(QWidget* const parent) const
0694 {
0695     if (!d->albumsChooser)
0696     {
0697         d->albumsChooser = new AlbumSelectTabs(objectName(), parent);
0698     }
0699 
0700     connect(d->albumsChooser, SIGNAL(signalAlbumSelectionChanged()),
0701             this, SIGNAL(signalAlbumChooserSelectionChanged()));
0702 
0703     return d->albumsChooser;
0704 }
0705 
0706 DBInfoIface::DAlbumIDs DBInfoIface::albumChooserItems() const
0707 {
0708     if (!d->albumsChooser)
0709     {
0710         return DAlbumIDs();
0711     }
0712 
0713     AlbumList lst = d->albumsChooser->selectedAlbums();
0714     DAlbumIDs ids;
0715 
0716     Q_FOREACH (Album* const a, lst)
0717     {
0718         if (a)
0719         {
0720             ids << a->globalID();
0721         }
0722     }
0723 
0724     return ids;
0725 }
0726 
0727 bool DBInfoIface::supportAlbums() const
0728 {
0729     return true;
0730 }
0731 
0732 QWidget* DBInfoIface::uploadWidget(QWidget* const parent) const
0733 {
0734     if (!d->albumSelector)
0735     {
0736         d->albumSelector = new AlbumSelectWidget(parent);
0737 
0738         connect(d->albumSelector, SIGNAL(itemSelectionChanged()),
0739                 this, SIGNAL(signalUploadUrlChanged()));
0740     }
0741 
0742     return d->albumSelector;
0743 }
0744 
0745 QUrl DBInfoIface::uploadUrl() const
0746 {
0747     QUrl url;
0748 
0749     if (d->albumSelector)
0750     {
0751         PAlbum* const p = d->albumSelector->currentAlbum();
0752 
0753         if (p)
0754         {
0755             url = QUrl::fromLocalFile(p->folderPath());
0756         }
0757     }
0758 
0759     return url;
0760 }
0761 
0762 QUrl DBInfoIface::defaultUploadUrl() const
0763 {
0764     QUrl place       = QUrl::fromLocalFile(QDir::homePath());
0765     QStringList pics = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
0766 
0767     if (!pics.isEmpty())
0768     {
0769         place = QUrl::fromLocalFile(pics.first());
0770     }
0771 
0772     Album* const album = AlbumManager::instance()->currentAlbums().first();
0773 
0774     if (album->type() == Album::PHYSICAL)
0775     {
0776         PAlbum* const p = dynamic_cast<PAlbum*>(album);
0777 
0778         if (p)
0779         {
0780             place = QUrl::fromLocalFile(p->folderPath());
0781         }
0782     }
0783     else
0784     {
0785         QStringList cols = CollectionManager::instance()->allAvailableAlbumRootPaths();
0786 
0787         if (!cols.isEmpty())
0788         {
0789             place = QUrl::fromLocalFile(cols.first());
0790         }
0791     }
0792 
0793     return place;
0794 }
0795 
0796 QAbstractItemModel* DBInfoIface::tagFilterModel()
0797 {
0798     TagModel* const tagModel                    = new TagModel(AbstractAlbumModel::IgnoreRootAlbum, this);
0799     TagPropertiesFilterModel* const filterModel = new TagPropertiesFilterModel(this);
0800     filterModel->setSourceAlbumModel(tagModel);
0801     filterModel->sort(0);
0802 
0803     return filterModel;
0804 }
0805 
0806 #ifdef HAVE_GEOLOCATION
0807 
0808 QList<GPSItemContainer*> DBInfoIface::currentGPSItems() const
0809 {
0810     QList<GPSItemContainer*> items;
0811 
0812     Q_FOREACH (const QUrl& url, currentSelectedItems())
0813     {
0814         ItemInfo info = ItemInfo::fromUrl(url);
0815         items << new ItemGPS(info);
0816     }
0817 
0818     return items;
0819 }
0820 
0821 #endif
0822 
0823 QMap<QString, QString> DBInfoIface::passShortcutActionsToWidget(QWidget* const wdg) const
0824 {
0825     TagsActionMngr::defaultManager()->registerActionsToWidget(wdg);
0826 
0827     QMap<QString, QString> shortcutPrefixes;
0828     shortcutPrefixes.insert(QLatin1String("rating"),     TagsActionMngr::defaultManager()->ratingShortcutPrefix());
0829     shortcutPrefixes.insert(QLatin1String("tag"),        TagsActionMngr::defaultManager()->tagShortcutPrefix());
0830     shortcutPrefixes.insert(QLatin1String("picklabel"),  TagsActionMngr::defaultManager()->pickShortcutPrefix());
0831     shortcutPrefixes.insert(QLatin1String("colorlabel"), TagsActionMngr::defaultManager()->colorShortcutPrefix());
0832 
0833     return shortcutPrefixes;
0834 }
0835 
0836 void DBInfoIface::deleteImage(const QUrl& url)
0837 {
0838     ItemInfo info = ItemInfo::fromUrl(url);
0839 
0840     DIO::del(info, true);
0841 }
0842 
0843 void DBInfoIface::openSetupPage(SetupPage page)
0844 {
0845     switch (page)
0846     {
0847         case ExifToolPage:
0848         {
0849             if (Setup::execExifTool(nullptr))
0850             {
0851                 Q_EMIT signalSetupChanged();
0852             }
0853 
0854             break;
0855         }
0856 
0857         case ImageQualityPage:
0858         {
0859             if (Setup::execImageQualitySorter(nullptr))
0860             {
0861                 Q_EMIT signalSetupChanged();
0862             }
0863 
0864             break;
0865         }
0866 
0867         default:
0868         {
0869         }
0870     }
0871 }
0872 
0873 } // namespace Digikam
0874 
0875 #include "moc_dbinfoiface.cpp"