1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2006-30-08
7  * Description : batch thumbnails generator
8  *
9  * Copyright (C) 2006-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
10  * Copyright (C) 2012      by Andi Clemens <andi dot clemens at gmail dot com>
11  *
12  * This program is free software; you can redistribute it
13  * and/or modify it under the terms of the GNU General
14  * Public License as published by the Free Software Foundation;
15  * either version 2, or (at your option)
16  * any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * ============================================================ */
24 
25 #include "thumbsgenerator.h"
26 
27 // Qt includes
28 
29 #include <QApplication>
30 #include <QString>
31 #include <QTimer>
32 #include <QDir>
33 #include <QFileInfo>
34 #include <QPixmap>
35 
36 // KDE includes
37 
38 #include <klocalizedstring.h>
39 
40 // Local includes
41 
42 #include "coredb.h"
43 #include "coredbalbuminfo.h"
44 #include "albummanager.h"
45 #include "applicationsettings.h"
46 #include "coredbaccess.h"
47 #include "iteminfo.h"
48 #include "thumbsdbaccess.h"
49 #include "thumbsdb.h"
50 #include "maintenancethread.h"
51 #include "digikam_config.h"
52 
53 namespace Digikam
54 {
55 
56 class Q_DECL_HIDDEN ThumbsGenerator::Private
57 {
58 public:
59 
Private()60     explicit Private()
61       : rebuildAll(true),
62         thread(nullptr)
63     {
64     }
65 
66     bool               rebuildAll;
67 
68     AlbumList          albumList;
69 
70     QStringList        allPicturesPath;
71 
72     MaintenanceThread* thread;
73 };
74 
ThumbsGenerator(const bool rebuildAll,const AlbumList & list,ProgressItem * const parent)75 ThumbsGenerator::ThumbsGenerator(const bool rebuildAll, const AlbumList& list, ProgressItem* const parent)
76     : MaintenanceTool(QLatin1String("ThumbsGenerator"), parent),
77       d(new Private)
78 {
79     d->albumList = list;
80     init(rebuildAll);
81 }
82 
ThumbsGenerator(const bool rebuildAll,int albumId,ProgressItem * const parent)83 ThumbsGenerator::ThumbsGenerator(const bool rebuildAll, int albumId, ProgressItem* const parent)
84     : MaintenanceTool(QLatin1String("ThumbsGenerator"), parent),
85       d(new Private)
86 {
87     d->albumList.append(AlbumManager::instance()->findPAlbum(albumId));
88     init(rebuildAll);
89 }
90 
~ThumbsGenerator()91 ThumbsGenerator::~ThumbsGenerator()
92 {
93     delete d;
94 }
95 
init(const bool rebuildAll)96 void ThumbsGenerator::init(const bool rebuildAll)
97 {
98     setLabel(i18n("Thumbs"));
99     ProgressManager::addProgressItem(this);
100 
101     d->rebuildAll = rebuildAll;
102     d->thread     = new MaintenanceThread(this);
103 
104     connect(d->thread, SIGNAL(signalCompleted()),
105             this, SLOT(slotDone()));
106 
107     connect(d->thread, SIGNAL(signalAdvance(QImage)),
108             this, SLOT(slotAdvance(QImage)));
109 }
110 
setUseMultiCoreCPU(bool b)111 void ThumbsGenerator::setUseMultiCoreCPU(bool b)
112 {
113     d->thread->setUseMultiCore(b);
114 }
115 
slotCancel()116 void ThumbsGenerator::slotCancel()
117 {
118     d->thread->cancel();
119     MaintenanceTool::slotCancel();
120 }
121 
slotStart()122 void ThumbsGenerator::slotStart()
123 {
124     MaintenanceTool::slotStart();
125 
126     QApplication::setOverrideCursor(Qt::WaitCursor);
127 
128     if (d->albumList.isEmpty())
129     {
130         d->albumList = AlbumManager::instance()->allPAlbums();
131     }
132 
133     for (AlbumList::const_iterator it = d->albumList.constBegin();
134          !canceled() && (it != d->albumList.constEnd()); ++it)
135     {
136         if (!(*it))
137         {
138             continue;
139         }
140 
141         if ((*it)->type() == Album::PHYSICAL)
142         {
143             d->allPicturesPath += CoreDbAccess().db()->getItemURLsInAlbum((*it)->id());
144         }
145         else if ((*it)->type() == Album::TAG)
146         {
147             d->allPicturesPath += CoreDbAccess().db()->getItemURLsInTag((*it)->id());
148         }
149     }
150 
151     if (!d->rebuildAll)
152     {
153         QHash<QString, int> filePaths = ThumbsDbAccess().db()->getFilePathsWithThumbnail();
154         QStringList::iterator it      = d->allPicturesPath.begin();
155 
156         while (it != d->allPicturesPath.end())
157         {
158             if (filePaths.contains(*it))
159             {
160                 it = d->allPicturesPath.erase(it);
161             }
162             else
163             {
164                 ++it;
165             }
166         }
167     }
168 
169     // remove non-image or video files from the list
170     QStringList::iterator it = d->allPicturesPath.begin();
171 
172     while (it != d->allPicturesPath.end())
173     {
174         ItemInfo info = ItemInfo::fromLocalFile(*it);
175 
176         if ((info.category() != DatabaseItem::Image) &&
177             (info.category() != DatabaseItem::Video) &&
178             (info.category() != DatabaseItem::Audio))
179         {
180             it = d->allPicturesPath.erase(it);
181         }
182         else
183         {
184             ++it;
185         }
186     }
187 
188     QApplication::restoreOverrideCursor();
189 
190     if (d->allPicturesPath.isEmpty())
191     {
192         slotDone();
193         return;
194     }
195 
196     setTotalItems(d->allPicturesPath.count());
197 
198     d->thread->generateThumbs(d->allPicturesPath);
199     d->thread->start();
200 }
201 
slotAdvance(const QImage & img)202 void ThumbsGenerator::slotAdvance(const QImage& img)
203 {
204     setThumbnail(QPixmap::fromImage(img));
205     advance(1);
206 }
207 
208 } // namespace Digikam
209