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

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2004-06-15
0007  * Description : Albums manager interface - Search Album helpers.
0008  *
0009  * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText: 2006-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0011  * SPDX-FileCopyrightText: 2015      by Mohamed_Anwer <m_dot_anwer at gmx dot com>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #include "albummanager_p.h"
0018 
0019 namespace Digikam
0020 {
0021 
0022 AlbumList AlbumManager::allSAlbums() const
0023 {
0024     AlbumList list;
0025 
0026     if (d->rootSAlbum)
0027     {
0028         list.append(d->rootSAlbum);
0029     }
0030 
0031     AlbumIterator it(d->rootSAlbum);
0032 
0033     while (it.current())
0034     {
0035         list.append(*it);
0036         ++it;
0037     }
0038 
0039     return list;
0040 }
0041 
0042 void AlbumManager::scanSAlbums()
0043 {
0044     d->scanSAlbumsTimer->stop();
0045 
0046     // list SAlbums directly from the db
0047     // first insert all the current SAlbums into a map for quick lookup
0048 
0049     QMap<int, SAlbum*> oldSearches;
0050 
0051     AlbumIterator it(d->rootSAlbum);
0052 
0053     while (it.current())
0054     {
0055         SAlbum* const search      = (SAlbum*)(*it);
0056         oldSearches[search->id()] = search;
0057         ++it;
0058     }
0059 
0060     // scan db and get a list of all albums
0061 
0062     QList<SearchInfo> currentSearches = CoreDbAccess().db()->scanSearches();
0063     QList<SearchInfo> newSearches;
0064 
0065     // go through all the Albums and see which ones are already present
0066 
0067     Q_FOREACH (const SearchInfo& info, currentSearches)
0068     {
0069         if (oldSearches.contains(info.id))
0070         {
0071             SAlbum* const album = oldSearches[info.id];
0072 
0073             if ((info.name  != album->title())      ||
0074                 (info.type  != album->searchType()) ||
0075                 (info.query != album->query()))
0076             {
0077                 QString oldName = album->title();
0078 
0079                 album->setSearch(info.type, info.query);
0080                 album->setTitle(info.name);
0081 
0082                 if (oldName != album->title())
0083                 {
0084                     Q_EMIT signalAlbumRenamed(album);
0085                 }
0086 
0087                 Q_EMIT signalSearchUpdated(album);
0088             }
0089 
0090             oldSearches.remove(info.id);
0091         }
0092         else
0093         {
0094             newSearches << info;
0095         }
0096     }
0097 
0098     // remove old albums that have been deleted
0099 
0100     Q_FOREACH (SAlbum* const album, oldSearches)
0101     {
0102         Q_EMIT signalAlbumAboutToBeDeleted(album);
0103         d->allAlbumsIdHash.remove(album->globalID());
0104 
0105         Q_EMIT signalAlbumDeleted(album);
0106 
0107         quintptr deletedAlbum = reinterpret_cast<quintptr>(album);
0108         delete album;
0109 
0110         Q_EMIT signalAlbumHasBeenDeleted(deletedAlbum);
0111     }
0112 
0113     // add new albums
0114 
0115     Q_FOREACH (const SearchInfo& info, newSearches)
0116     {
0117         SAlbum* const album                   = new SAlbum(info.name, info.id);
0118         album->setSearch(info.type, info.query);
0119 
0120         Q_EMIT signalAlbumAboutToBeAdded(album, d->rootSAlbum, d->rootSAlbum->lastChild());
0121 
0122         album->setParent(d->rootSAlbum);
0123         d->allAlbumsIdHash[album->globalID()] = album;
0124 
0125         Q_EMIT signalAlbumAdded(album);
0126     }
0127 }
0128 
0129 SAlbum* AlbumManager::findSAlbum(int id) const
0130 {
0131     if (!d->rootSAlbum)
0132     {
0133         return nullptr;
0134     }
0135 
0136     int gid = d->rootSAlbum->globalID() + id;
0137 
0138     return (static_cast<SAlbum*>((d->allAlbumsIdHash.value(gid))));
0139 }
0140 
0141 SAlbum* AlbumManager::findSAlbum(const QString& name) const
0142 {
0143     for (Album* album = d->rootSAlbum->firstChild() ;
0144          album ; album = album->next())
0145     {
0146         if (album->title() == name)
0147         {
0148             return (dynamic_cast<SAlbum*>(album));
0149         }
0150     }
0151 
0152     return nullptr;
0153 }
0154 
0155 QList<SAlbum*> AlbumManager::findSAlbumsBySearchType(int searchType) const
0156 {
0157     QList<SAlbum*> albums;
0158 
0159     for (Album* album = d->rootSAlbum->firstChild() ;
0160          album ; album = album->next())
0161     {
0162         SAlbum* const sAlbum = dynamic_cast<SAlbum*>(album);
0163 
0164         if ((sAlbum) && (sAlbum->searchType() == searchType))
0165         {
0166             albums.append(sAlbum);
0167         }
0168     }
0169 
0170     return albums;
0171 }
0172 
0173 SAlbum* AlbumManager::createSAlbum(const QString& name,
0174                                    DatabaseSearch::Type type,
0175                                    const QString& query)
0176 {
0177     // first iterate through all the search albums and see if there's an existing
0178     // SAlbum with same name. (Remember, SAlbums are arranged in a flat list)
0179 
0180     SAlbum* album = findSAlbum(name);
0181     ChangingDB changing(d);
0182 
0183     if (album)
0184     {
0185         updateSAlbum(album, query, name, type);
0186         return album;
0187     }
0188 
0189     int id = CoreDbAccess().db()->addSearch(type, name, query);
0190 
0191     if (id == -1)
0192     {
0193         return nullptr;
0194     }
0195 
0196     album = new SAlbum(name, id);
0197     Q_EMIT signalAlbumAboutToBeAdded(album, d->rootSAlbum, d->rootSAlbum->lastChild());
0198     album->setSearch(type, query);
0199     album->setParent(d->rootSAlbum);
0200 
0201     d->allAlbumsIdHash.insert(album->globalID(), album);
0202 
0203     Q_EMIT signalAlbumAdded(album);
0204 
0205     return album;
0206 }
0207 
0208 bool AlbumManager::updateSAlbum(SAlbum* album,
0209                                 const QString& changedQuery,
0210                                 const QString& changedName,
0211                                 DatabaseSearch::Type type)
0212 {
0213     if (!album)
0214     {
0215         return false;
0216     }
0217 
0218     QString newName              = changedName.isNull()                    ? album->title()      : changedName;
0219     DatabaseSearch::Type newType = (type == DatabaseSearch::UndefinedType) ? album->searchType() : type;
0220 
0221     ChangingDB changing(d);
0222     CoreDbAccess().db()->updateSearch(album->id(), newType, newName, changedQuery);
0223 
0224     QString oldName              = album->title();
0225 
0226     album->setSearch(newType, changedQuery);
0227     album->setTitle(newName);
0228 
0229     if (oldName != album->title())
0230     {
0231         Q_EMIT signalAlbumRenamed(album);
0232     }
0233 
0234     if (!d->currentAlbums.isEmpty())
0235     {
0236         if (d->currentAlbums.first() == album)
0237         {
0238             Q_EMIT signalAlbumCurrentChanged(d->currentAlbums);
0239         }
0240     }
0241 
0242     return true;
0243 }
0244 
0245 bool AlbumManager::deleteSAlbum(SAlbum* album)
0246 {
0247     if (!album)
0248     {
0249         return false;
0250     }
0251 
0252     Q_EMIT signalAlbumAboutToBeDeleted(album);
0253 
0254     ChangingDB changing(d);
0255     CoreDbAccess().db()->deleteSearch(album->id());
0256 
0257     d->allAlbumsIdHash.remove(album->globalID());
0258 
0259     Q_EMIT signalAlbumDeleted(album);
0260 
0261     quintptr deletedAlbum = reinterpret_cast<quintptr>(album);
0262     delete album;
0263 
0264     Q_EMIT signalAlbumHasBeenDeleted(deletedAlbum);
0265 
0266     return true;
0267 }
0268 
0269 void AlbumManager::slotSearchChange(const SearchChangeset& changeset)
0270 {
0271     if (d->changingDB || !d->rootSAlbum)
0272     {
0273         return;
0274     }
0275 
0276     switch (changeset.operation())
0277     {
0278         case SearchChangeset::Added:
0279         case SearchChangeset::Deleted:
0280         {
0281             if (!d->scanSAlbumsTimer->isActive())
0282             {
0283                 d->scanSAlbumsTimer->start();
0284             }
0285 
0286             break;
0287         }
0288 
0289         case SearchChangeset::Changed:
0290         {
0291             if (!d->currentAlbums.isEmpty())
0292             {
0293                 Album* const currentAlbum = d->currentAlbums.first();
0294 
0295                 if (currentAlbum                            &&
0296                     (currentAlbum->type() == Album::SEARCH) &&
0297                     (currentAlbum->id()   == changeset.searchId()))
0298                 {
0299                     // the pointer is the same, but the contents changed
0300 
0301                     Q_EMIT signalAlbumCurrentChanged(d->currentAlbums);
0302                 }
0303             }
0304 
0305             break;
0306         }
0307 
0308         case SearchChangeset::Unknown:
0309         {
0310             break;
0311         }
0312     }
0313 }
0314 
0315 } // namespace Digikam