File indexing completed on 2025-01-05 03:58:35

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2006-09-19
0007  * Description : Track file loading and managing
0008  *
0009  * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText: 2010-2014 by Michael G. Hansen <mike at mghansen dot de>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "trackmanager.h"
0017 
0018 // Qt includes
0019 
0020 #include <QtConcurrentMap>
0021 #include <QFuture>
0022 #include <QFutureWatcher>
0023 
0024 // local includes
0025 
0026 #include "trackreader.h"
0027 
0028 namespace Digikam
0029 {
0030 
0031 // TrackManager::TrackPoint ---------------------------------------------------
0032 
0033 bool TrackManager::TrackPoint::EarlierThan(const TrackPoint& a, const TrackPoint& b)
0034 {
0035     return (a.dateTime < b.dateTime);
0036 }
0037 
0038 // TrackManager ---------------------------------------------------------------
0039 
0040 class Q_DECL_HIDDEN TrackManager::Private
0041 {
0042 public:
0043 
0044     explicit Private()
0045       : trackLoadFutureWatcher(nullptr),
0046         trackLoadFuture       (),
0047         trackList             (),
0048         loadErrorFiles        (),
0049         nextTrackId           (1),
0050         nextTrackColor        (0),
0051         visibility            (true)
0052     {
0053     }
0054 
0055     QFutureWatcher<TrackReader::TrackReadResult>* trackLoadFutureWatcher;
0056     QFuture<TrackReader::TrackReadResult>         trackLoadFuture;
0057     TrackManager::Track::List                     trackPendingList;
0058     TrackManager::Track::List                     trackList;
0059     QList<QPair<QUrl, QString> >                  loadErrorFiles;
0060 
0061     Id                                            nextTrackId;
0062     int                                           nextTrackColor;
0063     bool                                          visibility;
0064 };
0065 
0066 TrackManager::TrackManager(QObject* const parent)
0067     : QObject(parent),
0068       d      (new Private)
0069 {
0070 }
0071 
0072 TrackManager::~TrackManager()
0073 {
0074 }
0075 
0076 bool TrackManager::getVisibility() const
0077 {
0078     return d->visibility;
0079 }
0080 
0081 void TrackManager::setVisibility(const bool value)
0082 {
0083     if (d->visibility == value)
0084     {
0085         return;
0086     }
0087 
0088     d->visibility = value;
0089 
0090     Q_EMIT signalVisibilityChanged(value);
0091 }
0092 
0093 void TrackManager::clear()
0094 {
0095     /// @TODO send a signal
0096 
0097     d->trackList.clear();
0098     d->nextTrackColor = 0;
0099 }
0100 
0101 const TrackManager::Track& TrackManager::getTrack(const int index) const
0102 {
0103     return d->trackList.at(index);
0104 }
0105 
0106 void TrackManager::loadTrackFiles(const QList<QUrl>& urls)
0107 {
0108     d->trackLoadFutureWatcher = new QFutureWatcher<TrackReader::TrackReadResult>(this);
0109 
0110     connect(d->trackLoadFutureWatcher, SIGNAL(resultsReadyAt(int,int)),
0111             this, SLOT(slotTrackFilesReadyAt(int,int)));
0112 
0113     connect(d->trackLoadFutureWatcher, SIGNAL(finished()),
0114             this, SLOT(slotTrackFilesFinished()));
0115 
0116     d->trackLoadFuture = QtConcurrent::mapped(urls, TrackReader::loadTrackFile);
0117     d->trackLoadFutureWatcher->setFuture(d->trackLoadFuture);
0118 
0119     // results are reported to slotTrackFilesReadyAt
0120 }
0121 
0122 void TrackManager::slotTrackFilesReadyAt(int beginIndex, int endIndex)
0123 {
0124 /*
0125     const int nFilesBefore = d->trackList.count();
0126 */
0127     // note that endIndex is exclusive!
0128 
0129     for (int i = beginIndex ; i < endIndex ; ++i)
0130     {
0131         const TrackReader::TrackReadResult nextFile = d->trackLoadFuture.resultAt(i);
0132 
0133         if (nextFile.isValid)
0134         {
0135             Track nextTrack = nextFile.track;
0136             nextTrack.id    = getNextFreeTrackId();
0137             nextTrack.color = getNextFreeTrackColor();
0138             d->trackPendingList << nextTrack;
0139         }
0140         else
0141         {
0142             d->loadErrorFiles << QPair<QUrl, QString>(nextFile.track.url, nextFile.loadError);
0143         }
0144     }
0145 }
0146 
0147 void TrackManager::slotTrackFilesFinished()
0148 {
0149     d->trackLoadFutureWatcher->deleteLater();
0150 
0151     d->trackList << d->trackPendingList;
0152     QList<TrackChanges> trackChanges;
0153 
0154     Q_FOREACH (const Track& track, d->trackPendingList)
0155     {
0156         trackChanges << TrackChanges(track.id, ChangeAdd);
0157     }
0158 
0159     d->trackPendingList.clear();
0160 
0161     Q_EMIT signalAllTrackFilesReady();
0162     Q_EMIT signalTracksChanged(trackChanges);
0163 }
0164 
0165 TrackManager::Track::List TrackManager::getTrackList() const
0166 {
0167     return d->trackList;
0168 }
0169 
0170 int TrackManager::trackCount() const
0171 {
0172     return d->trackList.count();
0173 }
0174 
0175 QList<QPair<QUrl, QString> > TrackManager::readLoadErrors()
0176 {
0177     const QList<QPair<QUrl, QString> > result = d->loadErrorFiles;
0178     d->loadErrorFiles.clear();
0179 
0180     return result;
0181 }
0182 
0183 quint64 TrackManager::getNextFreeTrackId()
0184 {
0185     const quint64 nextId = d->nextTrackId;
0186     ++(d->nextTrackId);
0187 
0188     return nextId;
0189 }
0190 
0191 TrackManager::Track TrackManager::getTrackById(const quint64 trackId) const
0192 {
0193     Q_FOREACH (const Track& track, d->trackList)
0194     {
0195         if (track.id == trackId)
0196         {   // cppcheck-suppress useStlAlgorithm
0197             return track;
0198         }
0199     }
0200 
0201     return TrackManager::Track();
0202 }
0203 
0204 QColor TrackManager::getNextFreeTrackColor()
0205 {
0206     QList<QColor> colorList;
0207     colorList << Qt::red << Qt::blue << Qt::green << Qt::magenta;
0208 
0209     const QColor nextColor = colorList.at(d->nextTrackColor);
0210     ++(d->nextTrackColor);
0211 
0212     if (d->nextTrackColor >= colorList.count())
0213     {
0214         d->nextTrackColor = 0;
0215     }
0216 
0217     return nextColor;
0218 }
0219 
0220 } // namespace Digikam
0221 
0222 #include "moc_trackmanager.cpp"