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

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 - Date 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 void AlbumManager::scanDAlbums()
0023 {
0024     d->scanDAlbumsTimer->stop();
0025 
0026     if (d->dateListJob)
0027     {
0028         disconnect(d->dateListJob, nullptr, this, nullptr);
0029 
0030         d->dateListJob->cancel();
0031         d->dateListJob = nullptr;
0032     }
0033 
0034     DatesDBJobInfo jInfo;
0035     jInfo.setFoldersJob();
0036     d->dateListJob = DBJobsManager::instance()->startDatesJobThread(jInfo);
0037 
0038     connect(d->dateListJob, SIGNAL(finished()),
0039             this, SLOT(slotDatesJobResult()));
0040 
0041     connect(d->dateListJob, SIGNAL(foldersData(QHash<QDateTime,int>)),
0042             this, SLOT(slotDatesJobData(QHash<QDateTime,int>)));
0043 }
0044 
0045 AlbumList AlbumManager::allDAlbums() const
0046 {
0047     AlbumList list;
0048 
0049     if (d->rootDAlbum)
0050     {
0051         list.append(d->rootDAlbum);
0052     }
0053 
0054     AlbumIterator it(d->rootDAlbum);
0055 
0056     while (it.current())
0057     {
0058         list.append(*it);
0059         ++it;
0060     }
0061 
0062     return list;
0063 }
0064 
0065 DAlbum* AlbumManager::findDAlbum(int id) const
0066 {
0067     if (!d->rootDAlbum)
0068     {
0069         return nullptr;
0070     }
0071 
0072     int gid = d->rootDAlbum->globalID() + id;
0073 
0074     return static_cast<DAlbum*>((d->allAlbumsIdHash.value(gid)));
0075 }
0076 
0077 QMap<YearMonth, int> AlbumManager::getDAlbumsCount() const
0078 {
0079     return d->dAlbumsCount;
0080 }
0081 
0082 void AlbumManager::slotDatesJobResult()
0083 {
0084     if (!d->dateListJob)
0085     {
0086         return;
0087     }
0088 
0089     if (d->dateListJob->hasErrors())
0090     {
0091         qCWarning(DIGIKAM_GENERAL_LOG) << "Failed to list dates";
0092 
0093         // Pop-up a message about the error.
0094 
0095         DNotificationWrapper(QString(), d->dateListJob->errorsList().first(),
0096                              nullptr, i18n("digiKam"));
0097     }
0098 
0099     d->dateListJob = nullptr;
0100 
0101     Q_EMIT signalAllDAlbumsLoaded();
0102 }
0103 
0104 void AlbumManager::slotDatesJobData(const QHash<QDateTime, int>& datesStatHash)
0105 {
0106     if (datesStatHash.isEmpty() || !d->rootDAlbum)
0107     {
0108         return;
0109     }
0110 
0111     // insert all the DAlbums into a qmap for quick access
0112 
0113     QMap<QDate, DAlbum*> mAlbumMap;
0114     QMap<int, DAlbum*>   yAlbumMap;
0115 
0116     AlbumIterator it(d->rootDAlbum);
0117 
0118     while (it.current())
0119     {
0120         DAlbum* const a = (DAlbum*)(*it);
0121 
0122         if (a->range() == DAlbum::Month)
0123         {
0124             mAlbumMap.insert(a->date(), a);
0125         }
0126         else
0127         {
0128             yAlbumMap.insert(a->date().year(), a);
0129         }
0130 
0131         ++it;
0132     }
0133 
0134     QMap<YearMonth, int> yearMonthMap;
0135 
0136     for (QHash<QDateTime, int>::const_iterator it3 = datesStatHash.constBegin() ;
0137          it3 != datesStatHash.constEnd() ; ++it3)
0138     {
0139         YearMonth yearMonth = YearMonth(it3.key().date().year(), it3.key().date().month());
0140 
0141         QMap<YearMonth, int>::iterator it2 = yearMonthMap.find(yearMonth);
0142 
0143         if (it2 == yearMonthMap.end())
0144         {
0145             yearMonthMap.insert(yearMonth, *it3);
0146         }
0147         else
0148         {
0149             *it2 += *it3;
0150         }
0151     }
0152 
0153     int year, month;
0154 
0155     for (QMap<YearMonth, int>::const_iterator it4 = yearMonthMap.constBegin() ;
0156          it4 != yearMonthMap.constEnd() ; ++it4)
0157     {
0158         year  = it4.key().first;
0159         month = it4.key().second;
0160 
0161         QDate md(year, month, 1);
0162 
0163         // Do we already have this Month album
0164 
0165         if (mAlbumMap.contains(md))
0166         {
0167             // already there. remove Month album from map
0168 
0169             mAlbumMap.remove(md);
0170 
0171             if (yAlbumMap.contains(year))
0172             {
0173                 // already there. remove from map
0174 
0175                 yAlbumMap.remove(year);
0176             }
0177 
0178             continue;
0179         }
0180 
0181         // Check if Year Album already exist.
0182 
0183         DAlbum* yAlbum = nullptr;
0184         AlbumIterator it5(d->rootDAlbum);
0185 
0186         while (it5.current())
0187         {
0188             DAlbum* const a = (DAlbum*)(*it5);
0189 
0190             if ((a->date() == QDate(year, 1, 1)) && (a->range() == DAlbum::Year))
0191             {
0192                 yAlbum = a;
0193                 break;
0194             }
0195 
0196             ++it5;
0197         }
0198 
0199         // If no, create Year album.
0200 
0201         if (!yAlbum)
0202         {
0203             yAlbum = new DAlbum(QDate(year, 1, 1), false, DAlbum::Year);
0204             Q_EMIT signalAlbumAboutToBeAdded(yAlbum, d->rootDAlbum, d->rootDAlbum->lastChild());
0205             yAlbum->setParent(d->rootDAlbum);
0206             d->allAlbumsIdHash.insert(yAlbum->globalID(), yAlbum);
0207             Q_EMIT signalAlbumAdded(yAlbum);
0208         }
0209 
0210         // Create Month album
0211 
0212         DAlbum* const mAlbum = new DAlbum(md);
0213 
0214         Q_EMIT signalAlbumAboutToBeAdded(mAlbum, yAlbum, yAlbum->lastChild());
0215 
0216         mAlbum->setParent(yAlbum);
0217         d->allAlbumsIdHash.insert(mAlbum->globalID(), mAlbum);
0218 
0219         Q_EMIT signalAlbumAdded(mAlbum);
0220     }
0221 
0222     // Now the items contained in the maps are the ones which
0223     // have been deleted.
0224 
0225     for (QMap<QDate, DAlbum*>::const_iterator it6 = mAlbumMap.constBegin() ;
0226          it6 != mAlbumMap.constEnd() ; ++it6)
0227     {
0228         DAlbum* const album = it6.value();
0229         Q_EMIT signalAlbumAboutToBeDeleted(album);
0230         d->allAlbumsIdHash.remove(album->globalID());
0231 
0232         Q_EMIT signalAlbumDeleted(album);
0233 
0234         quintptr deletedAlbum = reinterpret_cast<quintptr>(album);
0235         delete album;
0236 
0237         Q_EMIT signalAlbumHasBeenDeleted(deletedAlbum);
0238     }
0239 
0240     for (QMap<int, DAlbum*>::const_iterator it7 = yAlbumMap.constBegin() ;
0241          it7 != yAlbumMap.constEnd() ; ++it7)
0242     {
0243         DAlbum* const album = it7.value();
0244         Q_EMIT signalAlbumAboutToBeDeleted(album);
0245         d->allAlbumsIdHash.remove(album->globalID());
0246 
0247         Q_EMIT signalAlbumDeleted(album);
0248 
0249         quintptr deletedAlbum = reinterpret_cast<quintptr>(album);
0250         delete album;
0251 
0252         Q_EMIT signalAlbumHasBeenDeleted(deletedAlbum);
0253     }
0254 
0255     d->dAlbumsCount = yearMonthMap;
0256 
0257     Q_EMIT signalDAlbumsDirty(yearMonthMap);
0258     Q_EMIT signalDatesHashDirty(datesStatHash);
0259 }
0260 
0261 void AlbumManager::scanDAlbumsScheduled()
0262 {
0263     // Avoid a cycle of killing a job which takes longer than the timer interval
0264 
0265     if (d->dateListJob)
0266     {
0267         d->scanDAlbumsTimer->start();
0268         return;
0269     }
0270 
0271     scanDAlbums();
0272 }
0273 
0274 } // namespace Digikam