diff --git a/NEWS b/NEWS index edf6f2d3a5..c4b9998b0b 100644 --- a/NEWS +++ b/NEWS @@ -1,29 +1,29 @@ ***************************************************************************************************** digiKam 5.9.0 - Release date: 2018-02-25 NEW FEATURES: General : Libraw updated to last 0.18.7. BUGFIXES FROM BUGZILLA: 001 ==> 388977 - Error during upgrading core database schema from v8 to v9. 002 ==> 388867 - problem migrating databaseschema from 8 to 9. 003 ==> 388824 - UpdateSchemaFromV7ToV9 fails due to foreign key contraint in 5.8.0-01. 004 ==> 389042 - Auto-rotation/flip Images delete face tags. 005 ==> 337243 - Tool-Tips ignoring custom font size setting. 006 ==> 388320 - Selecting print layout does not stay selected. 007 ==> 389246 - Single click confirmation of suggested face tag. 008 ==> 389208 - Request addition of "Lens" to Tool-Tips (Icon Items). 009 ==> 389342 - Tags are copied although moving of file fails because file with the same name already exists in target location. 010 ==> 389420 - Thumbnails diminishing in size after switching Views. 011 ==> 389493 - Collection browse dialog should be consistent with other browse dialogs on KDE. 012 ==> 389512 - Timeline Thumbnails Not Shown. 013 ==> 389651 - Custom font size is not applied until you enter and exit the settings menu. 014 ==> 388345 - AppImage MySQL connection issues. 015 ==> 389827 - Ignores albums selection. 016 ==> 389835 - Incorrect DateTime manipulation if timestamp is before unix epoch time. 017 ==> 390121 - Thumbnail size is too small. 018 ==> 390136 - digiKam crashes when launching scan and recognize faces. -019 ==> - +019 ==> 390325 - Segmentation fault - QMutex::lock(). +020 ==> diff --git a/utilities/maintenance/databasetask.cpp b/utilities/maintenance/databasetask.cpp index 746884b869..840b165863 100644 --- a/utilities/maintenance/databasetask.cpp +++ b/utilities/maintenance/databasetask.cpp @@ -1,456 +1,452 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2017-01-29 * Description : Thread actions task for database cleanup. * * Copyright (C) 2017 by Mario Frank * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "databasetask.h" // Qt includes #include // Local includes #include "digikam_debug.h" #include "imageinfo.h" #include "thumbsdb.h" #include "thumbsdbaccess.h" #include "coredb.h" #include "coredbaccess.h" #include "recognitiondatabase.h" #include "facetagseditor.h" #include "maintenancedata.h" namespace Digikam { class DatabaseTask::Private { public: - Private(): - scanThumbsDb(false), - scanRecognitionDb(false), - cancel(false), - mode(Mode::Unknown), - data(0) + Private() + : scanThumbsDb(false), + scanRecognitionDb(false), + mode(Mode::Unknown), + data(0) { } QString objectIdentification; bool scanThumbsDb; bool scanRecognitionDb; - bool cancel; Mode mode; MaintenanceData* data; }; // ------------------------------------------------------- DatabaseTask::DatabaseTask() : ActionJob(), d(new Private) { } DatabaseTask::~DatabaseTask() { - slotCancel(); - + cancel(); delete d; } void DatabaseTask::computeDatabaseJunk(bool thumbsDb, bool facesDb) { d->scanThumbsDb = thumbsDb; d->scanRecognitionDb = facesDb; } void DatabaseTask::setMode(Mode mode) { d->mode = mode; } -void DatabaseTask::setMaintenanceData(MaintenanceData* data) +void DatabaseTask::setMaintenanceData(MaintenanceData* const data) { d->data = data; } void DatabaseTask::slotCancel() { - d->cancel = true; } void DatabaseTask::run() { - if (d->cancel) + if (m_cancel) { return; } emit signalStarted(); QThread::sleep(1); if (d->mode == Mode::ShrinkDatabases) { qCDebug(DIGIKAM_GENERAL_LOG) << "Shrinking databases"; if (CoreDbAccess().db()->integrityCheck()) { CoreDbAccess().db()->vacuum(); if (!CoreDbAccess().db()->integrityCheck()) { qCWarning(DIGIKAM_DATABASE_LOG) << "Integrity check for core DB failed after vacuum. Something went wrong."; // Signal that the database was vacuumed but failed the integrity check afterwards. emit signalFinished(true,false); } else { qCDebug(DIGIKAM_DATABASE_LOG) << "Finished vacuuming of core DB. Integrity check after vacuuming was positive."; emit signalFinished(true,true); } } else { qCWarning(DIGIKAM_DATABASE_LOG) << "Integrity check for core DB failed. Will not vacuum."; // Signal that the integrity check failed and thus the vacuum was skipped emit signalFinished(false,false); } QThread::sleep(1); - if (d->cancel) + if (m_cancel) { return; } if (ThumbsDbAccess::isInitialized()) { if (ThumbsDbAccess().db()->integrityCheck()) { ThumbsDbAccess().db()->vacuum(); if (!ThumbsDbAccess().db()->integrityCheck()) { qCWarning(DIGIKAM_DATABASE_LOG) << "Integrity check for thumbnails DB failed after vacuum. Something went wrong."; // Signal that the database was vacuumed but failed the integrity check afterwards. emit signalFinished(true,false); } else { qCDebug(DIGIKAM_DATABASE_LOG) << "Finished vacuuming of thumbnails DB. Integrity check after vacuuming was positive."; emit signalFinished(true,true); } } else { qCWarning(DIGIKAM_DATABASE_LOG) << "Integrity check for thumbnails DB failed. Will not vacuum."; // Signal that the integrity check failed and thus the vacuum was skipped emit signalFinished(false,false); } } else { qCWarning(DIGIKAM_DATABASE_LOG) << "Thumbnails DB is not initialised. Will not vacuum."; emit signalFinished(false,false); } QThread::sleep(1); - if (d->cancel) + if (m_cancel) { return; } if (RecognitionDatabase().integrityCheck()) { RecognitionDatabase().vacuum(); if (!RecognitionDatabase().integrityCheck()) { qCWarning(DIGIKAM_DATABASE_LOG) << "Integrity check for recognition DB failed after vacuum. Something went wrong."; // Signal that the database was vacuumed but failed the integrity check afterwards. emit signalFinished(true,false); } else { qCDebug(DIGIKAM_DATABASE_LOG) << "Finished vacuuming of recognition DB. Integrity check after vacuuming was positive."; emit signalFinished(true,true); } } else { qCWarning(DIGIKAM_DATABASE_LOG) << "Integrity check for recognition DB failed. Will not vacuum."; // Signal that the integrity check failed and thus the vacuum was skipped emit signalFinished(false,false); } QThread::sleep(1); } else if (d->mode == Mode::ComputeDatabaseJunk) { QList staleImageIds; QList staleThumbIds; QList staleIdentities; int additionalItemsToProcess = 0; // Get the count of image entries in DB to delete. staleImageIds = CoreDbAccess().db()->getImageIds(DatabaseItem::Status::Obsolete); // get the count of items to process for thumbnails cleanup it enabled. if (d->scanThumbsDb && ThumbsDbAccess::isInitialized()) { additionalItemsToProcess += CoreDbAccess().db()->getAllItems().size(); } // get the count of items to process for identities cleanup it enabled. if (d->scanRecognitionDb) { additionalItemsToProcess += RecognitionDatabase().allIdentities().size(); } if (additionalItemsToProcess > 0) { emit signalAddItemsToProcess(additionalItemsToProcess); } emit signalFinished(); // Get the stale thumbnail paths. if (d->scanThumbsDb && ThumbsDbAccess::isInitialized()) { // Thumbnails should be deleted, if the following conditions hold: // 1) The file path to which the thumb is assigned does not lead to an item // 2) The unique hash and file size are not used in core db for an item. // 3) The custom identifier does not exist in core db for an item. // OR // The thumbnail is stale, i.e. no thumbs db table references it. QSet thumbIds = ThumbsDbAccess().db()->findAll().toSet(); // Get all items, i.e. images, videos, ... QList items = CoreDbAccess().db()->getAllItems(); FaceTagsEditor editor; foreach(qlonglong item, items) { - if (d->cancel) + if (m_cancel) { return; } ImageInfo info(item); if (!info.isNull()) { QString hash = CoreDbAccess().db()->getImagesFields(item,DatabaseFields::ImagesField::UniqueHash).first().toString(); qlonglong fileSize = info.fileSize(); bool removed = false; // Remove the id that is found by the file path. Finding the id -1 does no harm removed = thumbIds.remove(ThumbsDbAccess().db()->findByFilePath(info.filePath()).id); if (!removed) { // Remove the id that is found by the hash and file size. Finding the id -1 does no harm thumbIds.remove(ThumbsDbAccess().db()->findByHash(hash,fileSize).id); } // Add the custom identifier. // get all faces for the image and generate the custom identifiers QUrl url; url.setScheme(QLatin1String("detail")); url.setPath(info.filePath()); QList faces = editor.databaseFaces(item); foreach(FaceTagsIface face, faces) { QRect rect = face.region().toRect(); QString r = QString::fromLatin1("%1,%2-%3x%4").arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height()); QUrlQuery q(url); // Remove the previous query if existent. q.removeQueryItem(QLatin1String("rect")); q.addQueryItem(QLatin1String("rect"), r); url.setQuery(q); //qCDebug(DIGIKAM_GENERAL_LOG) << "URL: " << url.toString(); // Remove the id that is found by the custom identifyer. Finding the id -1 does no harm thumbIds.remove(ThumbsDbAccess().db()->findByCustomIdentifier(url.toString()).id); } } // Signal that this item was processed. emit signalFinished(); } // The remaining thumbnail ids should be used to remove them since they are stale. staleThumbIds = thumbIds.toList(); // Signal that the database was processed. emit signalFinished(); } - if (d->cancel) + if (m_cancel) { return; } // Get the stale face identities. if (d->scanRecognitionDb) { QList properties = CoreDbAccess().db()->getTagProperties(TagPropertyName::faceEngineUuid()); QSet uuidSet; foreach(TagProperty prop, properties) { uuidSet << prop.value; } QList identities = RecognitionDatabase().allIdentities(); // Get all identitites to remove. Don't remove now in order to make sure no side effects occur. foreach(Identity identity, identities) { QString value = identity.attribute(QLatin1String("uuid")); if (!value.isEmpty() && !uuidSet.contains(value)) { staleIdentities << identity; } // Signal that this identity was processed. emit signalFinished(); } // Signal that the database was processed. emit signalFinished(); } emit signalData(staleImageIds,staleThumbIds,staleIdentities); } else if (d->mode == Mode::CleanCoreDb) { // While we have data (using this as check for non-null) while (d->data) { - if (d->cancel) + if (m_cancel) { return; } qlonglong imageId = d->data->getImageId(); if (imageId == -1) { break; } CoreDbAccess().db()->deleteItem(imageId); CoreDbAccess().db()->removeImagePropertyByName(QLatin1String("similarityTo_")+QString::number(imageId)); emit signalFinished(); } } else if (d->mode == Mode::CleanThumbsDb) { BdEngineBackend::QueryState lastQueryState = BdEngineBackend::ConnectionError; // Connect to the database lastQueryState = ThumbsDbAccess().backend()->beginTransaction(); if (BdEngineBackend::NoErrors == lastQueryState) { // Start removing. // While we have data (using this as check for non-null) while (d->data) { - if (d->cancel) + if (m_cancel) { return; } int thumbId = d->data->getThumbnailId(); if (thumbId == -1) { break; } lastQueryState = ThumbsDbAccess().db()->remove(thumbId); emit signalFinished(); } // Check for errors. if (BdEngineBackend::NoErrors == lastQueryState) { // Commit the removel if everything was fine. lastQueryState = ThumbsDbAccess().backend()->commitTransaction(); if (BdEngineBackend::NoErrors != lastQueryState) { qCWarning(DIGIKAM_THUMBSDB_LOG) << "Could not commit the removal of " << d->objectIdentification << " due to error "; } } else { qCWarning(DIGIKAM_THUMBSDB_LOG) << "Could not start the removal of " << d->objectIdentification << " due to error "; } } else { qCWarning(DIGIKAM_THUMBSDB_LOG) << "Could not begin the transaction for the removal of " << d->objectIdentification << " due to error "; } } else if (d->mode == Mode::CleanRecognitionDb) { // While we have data (using this as check for non-null) while (d->data) { - if (d->cancel) + if (m_cancel) { return; } Identity identity = d->data->getIdentity(); if (identity.isNull()) { break; } RecognitionDatabase().deleteIdentity(identity); emit signalFinished(); } } emit signalDone(); } } // namespace Digikam diff --git a/utilities/maintenance/databasetask.h b/utilities/maintenance/databasetask.h index cd06820dd8..45aae1d852 100644 --- a/utilities/maintenance/databasetask.h +++ b/utilities/maintenance/databasetask.h @@ -1,98 +1,98 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2017-01-29 * Description : Thread actions task for database cleanup. * * Copyright (C) 2017 by Mario Frank * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DATABASE_TASK_H #define DATABASE_TASK_H // Local includes #include "actionthreadbase.h" namespace Digikam { class Identity; } namespace Digikam { class LoadingDescription; class MaintenanceData; class DatabaseTask : public ActionJob { Q_OBJECT public: enum Mode{ Unknown, ComputeDatabaseJunk, CleanCoreDb, CleanThumbsDb, CleanRecognitionDb, ShrinkDatabases }; explicit DatabaseTask(); virtual ~DatabaseTask(); void setMode(Mode mode); - void setMaintenanceData(MaintenanceData* data=0); + void setMaintenanceData(MaintenanceData* const data=0); void computeDatabaseJunk(bool thumbsDb=false, bool facesDb=false); Q_SIGNALS: void signalFinished(); void signalFinished(bool done, bool errorFree); void signalData(const QList& staleImageIds, const QList& staleThumbIds, const QList& staleIdentities); void signalStarted(); /** * Signal to emit the count of additional items to process. */ void signalAddItemsToProcess(int count); public Q_SLOTS: void slotCancel(); protected: void run(); private: class Private; Private* const d; }; } // namespace Digikam #endif // DATABASE_TASK_H diff --git a/utilities/maintenance/fingerprintstask.cpp b/utilities/maintenance/fingerprintstask.cpp index 5cfba0fdf6..16dadf614d 100644 --- a/utilities/maintenance/fingerprintstask.cpp +++ b/utilities/maintenance/fingerprintstask.cpp @@ -1,111 +1,107 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2013-08-14 * Description : Thread actions task for finger-prints generator. * * Copyright (C) 2013-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "fingerprintstask.h" // Qt includes #include // Local includes #include "digikam_debug.h" #include "dimg.h" #include "haar.h" #include "haariface.h" #include "previewloadthread.h" #include "maintenancedata.h" namespace Digikam { class FingerprintsTask::Private { public: - Private() : - cancel(false), - data(0) + Private() + : data(0) { } - bool cancel; - MaintenanceData* data; }; // ------------------------------------------------------- FingerprintsTask::FingerprintsTask() : ActionJob(), d(new Private) { } FingerprintsTask::~FingerprintsTask() { - slotCancel(); + cancel(); delete d; } -void FingerprintsTask::setMaintenanceData(MaintenanceData* data) +void FingerprintsTask::setMaintenanceData(MaintenanceData* const data) { d->data = data; } -void FingerprintsTask::slotCancel() -{ - d->cancel = true; -} - void FingerprintsTask::run() { // While we have data (using this as check for non-null) while (d->data) { - if (d->cancel) + if (m_cancel) + { return; + } QString path = d->data->getImagePath(); if (path.isEmpty()) + { break; + } qCDebug(DIGIKAM_GENERAL_LOG) << "Updating fingerprints for file: " << path ; DImg dimg = PreviewLoadThread::loadFastSynchronously(path, HaarIface::preferredSize()); if (!dimg.isNull()) { // compute Haar fingerprint and store it to DB HaarIface haarIface; haarIface.indexImage(path, dimg); } QImage qimg = dimg.smoothScale(22, 22, Qt::KeepAspectRatio).copyQImage(); emit signalFinished(qimg); } emit signalDone(); } } // namespace Digikam diff --git a/utilities/maintenance/fingerprintstask.h b/utilities/maintenance/fingerprintstask.h index 93175dee79..529ebbe4a8 100644 --- a/utilities/maintenance/fingerprintstask.h +++ b/utilities/maintenance/fingerprintstask.h @@ -1,74 +1,70 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2013-08-14 * Description : Thread actions task for finger-prints generator. * * Copyright (C) 2013-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef FINGERPRINTS_TASK_H #define FINGERPRINTS_TASK_H // Qt includes #include #include // Local includes #include "actionthreadbase.h" namespace Digikam { class LoadingDescription; class MaintenanceData; class DImg; class FingerprintsTask : public ActionJob { Q_OBJECT public: FingerprintsTask(); ~FingerprintsTask(); - void setMaintenanceData(MaintenanceData* data=0); + void setMaintenanceData(MaintenanceData* const data=0); Q_SIGNALS: void signalFinished(const QImage&); -public Q_SLOTS: - - void slotCancel(); - protected: void run(); private: class Private; Private* const d; }; } // namespace Digikam #endif /* FINGERPRINTS_TASK_H */ diff --git a/utilities/maintenance/imagequalitytask.cpp b/utilities/maintenance/imagequalitytask.cpp index dd3d3c58de..8b98eb4dcd 100644 --- a/utilities/maintenance/imagequalitytask.cpp +++ b/utilities/maintenance/imagequalitytask.cpp @@ -1,139 +1,138 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2013-08-19 * Description : Thread actions task for image quality sorter. * * Copyright (C) 2013-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "imagequalitytask.h" // Local includes #include "digikam_debug.h" #include "dimg.h" #include "previewloadthread.h" #include "imagequalitysettings.h" #include "imgqsort.h" #include "imageinfo.h" #include "maintenancedata.h" namespace Digikam { class ImageQualityTask::Private { public: - Private() : - cancel(false), - imgqsort(0), - data(0) + Private() + : imgqsort(0), + data(0) { } - bool cancel; ImageQualitySettings quality; ImgQSort* imgqsort; MaintenanceData* data; }; // ------------------------------------------------------- ImageQualityTask::ImageQualityTask() : ActionJob(), d(new Private) { } ImageQualityTask::~ImageQualityTask() { slotCancel(); + cancel(); delete d; } void ImageQualityTask::setQuality(const ImageQualitySettings& quality) { d->quality = quality; } -void ImageQualityTask::setMaintenanceData(MaintenanceData* data) +void ImageQualityTask::setMaintenanceData(MaintenanceData* const data) { d->data = data; } void ImageQualityTask::slotCancel() { - d->cancel = true; - if (d->imgqsort) { d->imgqsort->cancelAnalyse(); } } void ImageQualityTask::run() { // While we have data (using this as check for non-null) while (d->data) { - if (d->cancel) + if (m_cancel) { return; } QString path = d->data->getImagePath(); if (path.isEmpty()) + { break; + } // Get item preview to perform quality analysis. No need to load whole image, this will be slower. // TODO : check if 1024 pixels size is enough to get suitable Quality results. DImg dimg = PreviewLoadThread::loadFastSynchronously(path, 1024); - if (!dimg.isNull() && !d->cancel) + if (!dimg.isNull() && !m_cancel) { // TODO : run here Quality analysis backend and store Pick Label result to DB. // Backend Input : d->quality as Quality analysis settings, // dimg as reduced size image data to parse, // path as file path to patch DB properties. // Result : Backend must scan Quality of image depending of settings and compute a Quality estimation accordingly. // Finaly, using file path, DB Pick Label properties must be assigned through ImageInfo interface. // Warning : All code here will run in a separated thread and must be re-entrant/thread-safe. Only pure computation // must be processed. GUI calls are prohibited. ImageInfo and DImg can be used safety in thread. PickLabel pick; d->imgqsort = new ImgQSort(dimg, d->quality, &pick); d->imgqsort->startAnalyse(); ImageInfo info = ImageInfo::fromLocalFile(path); info.setPickLabel(pick); delete d->imgqsort; //delete image data after setting label d->imgqsort = 0; } // Dispatch progress to Progress Manager QImage qimg = dimg.smoothScale(22, 22, Qt::KeepAspectRatio).copyQImage(); emit signalFinished(qimg); } emit signalDone(); } } // namespace Digikam diff --git a/utilities/maintenance/imagequalitytask.h b/utilities/maintenance/imagequalitytask.h index 9b74861501..25b6dfb2c0 100644 --- a/utilities/maintenance/imagequalitytask.h +++ b/utilities/maintenance/imagequalitytask.h @@ -1,73 +1,73 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2013-08-19 * Description : Thread actions task for image quality sorter. * * Copyright (C) 2013-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef IMAGEQUALITYTASK_H #define IMAGEQUALITYTASK_H // Qt includes #include // Local includes #include "actionthreadbase.h" namespace Digikam { class ImageQualitySettings; class MaintenanceData; class ImageQualityTask : public ActionJob { Q_OBJECT public: ImageQualityTask(); ~ImageQualityTask(); void setQuality(const ImageQualitySettings& quality); - void setMaintenanceData(MaintenanceData* data=0); + void setMaintenanceData(MaintenanceData* const data=0); Q_SIGNALS: void signalFinished(const QImage&); public Q_SLOTS: void slotCancel(); protected: void run(); private: class Private; Private* const d; }; } // namespace Digikam #endif /* IMAGEQUALITYTASK_H */ diff --git a/utilities/maintenance/maintenancethread.cpp b/utilities/maintenance/maintenancethread.cpp index 789722dc16..e36a0e1e57 100644 --- a/utilities/maintenance/maintenancethread.cpp +++ b/utilities/maintenance/maintenancethread.cpp @@ -1,341 +1,317 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2013-08-09 * Description : Thread actions manager for maintenance tools. * * Copyright (C) 2013-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "maintenancethread.h" // Qt includes #include #include // Local includes #include "digikam_debug.h" #include "metadatatask.h" #include "thumbstask.h" #include "fingerprintstask.h" #include "imagequalitytask.h" #include "imagequalitysettings.h" #include "databasetask.h" #include "maintenancedata.h" namespace Digikam { MaintenanceThread::MaintenanceThread(QObject* const parent) : ActionThreadBase(parent), data(new MaintenanceData) { connect(this, SIGNAL(finished()), this, SLOT(slotThreadFinished())); } MaintenanceThread::~MaintenanceThread() { cancel(); wait(); delete data; } void MaintenanceThread::setUseMultiCore(const bool b) { if (!b) { setMaximumNumberOfThreads(1); } else { defaultMaximumNumberOfThreads(); //setMaximumNumberOfThreads(qMax( maximumNumberOfThreads() / 2, 1)); } } void MaintenanceThread::syncMetadata(const ImageInfoList& items, MetadataSynchronizer::SyncDirection dir, bool tagsOnly) { ActionJobCollection collection; data->setImageInfos(items); for (int i = 1; i <= maximumNumberOfThreads(); i++) { MetadataTask* const t = new MetadataTask(); t->setTagsOnly(tagsOnly); t->setDirection(dir); t->setMaintenanceData(data); connect(t, SIGNAL(signalFinished(QImage)), this, SIGNAL(signalAdvance(QImage))); - connect(this, SIGNAL(signalCanceled()), - t, SLOT(slotCancel()), Qt::QueuedConnection); - collection.insert(t, 0); qCDebug(DIGIKAM_GENERAL_LOG) << "Creating a metadata task for synchronizing metadata"; } appendJobs(collection); } void MaintenanceThread::generateThumbs(const QStringList& paths) { ActionJobCollection collection; data->setImagePaths(paths); for (int i = 1; i <= maximumNumberOfThreads(); i++) { ThumbsTask* const t = new ThumbsTask(); t->setMaintenanceData(data); connect(t, SIGNAL(signalFinished(QImage)), this, SIGNAL(signalAdvance(QImage))); - connect(this, SIGNAL(signalCanceled()), - t, SLOT(slotCancel()), Qt::QueuedConnection); - collection.insert(t, 0); qCDebug(DIGIKAM_GENERAL_LOG) << "Creating a thumbnails task for generating thumbnails"; } appendJobs(collection); } void MaintenanceThread::generateFingerprints(const QStringList& paths) { ActionJobCollection collection; data->setImagePaths(paths); for (int i = 1; i <= (maximumNumberOfThreads()); i++) { FingerprintsTask* const t = new FingerprintsTask(); t->setMaintenanceData(data); connect(t, SIGNAL(signalFinished(QImage)), - this, SIGNAL(signalAdvance(QImage))); - - connect(this, SIGNAL(signalCanceled()), - t, SLOT(slotCancel()), Qt::QueuedConnection); + this, SIGNAL(signalAdvance(QImage))); collection.insert(t, 0); qCDebug(DIGIKAM_GENERAL_LOG) << "Creating a fingerprints task for generating fingerprints";// for items with a chunk size of " << chunk.size(); } appendJobs(collection); } void MaintenanceThread::sortByImageQuality(const QStringList& paths, const ImageQualitySettings& quality) { ActionJobCollection collection; data->setImagePaths(paths); for (int i = 1; i <= maximumNumberOfThreads(); i++) { ImageQualityTask* const t = new ImageQualityTask(); t->setQuality(quality); t->setMaintenanceData(data); connect(t, SIGNAL(signalFinished(QImage)), this, SIGNAL(signalAdvance(QImage))); connect(this, SIGNAL(signalCanceled()), t, SLOT(slotCancel()), Qt::QueuedConnection); collection.insert(t, 0); qCDebug(DIGIKAM_GENERAL_LOG) << "Creating a image quality task for sorting items."; } appendJobs(collection); } void MaintenanceThread::computeDatabaseJunk(bool thumbsDb, bool facesDb) { ActionJobCollection collection; DatabaseTask* const t = new DatabaseTask(); t->setMode(DatabaseTask::Mode::ComputeDatabaseJunk); t->computeDatabaseJunk(thumbsDb, facesDb); connect(t, SIGNAL(signalFinished()), - this, SIGNAL(signalAdvance())); + this, SIGNAL(signalAdvance())); connect(t,SIGNAL(signalAddItemsToProcess(int)), this, SIGNAL(signalAddItemsToProcess(int))); connect(t,SIGNAL(signalData(QList,QList,QList)), this, SIGNAL(signalData(QList,QList,QList))); - connect(this, SIGNAL(signalCanceled()), - t, SLOT(slotCancel()), Qt::QueuedConnection); - collection.insert(t, 0); appendJobs(collection); } void MaintenanceThread::cleanCoreDb(const QList& imageIds) { ActionJobCollection collection; data->setImageIds(imageIds); for (int i = 1; i <= maximumNumberOfThreads(); i++) { DatabaseTask* const t = new DatabaseTask(); t->setMaintenanceData(data); t->setMode(DatabaseTask::Mode::CleanCoreDb); connect(t, SIGNAL(signalFinished()), this, SIGNAL(signalAdvance())); - connect(this, SIGNAL(signalCanceled()), - t, SLOT(slotCancel()), Qt::QueuedConnection); - collection.insert(t, 0); qCDebug(DIGIKAM_GENERAL_LOG) << "Creating a database task for removing stale items."; } appendJobs(collection); } void MaintenanceThread::cleanThumbsDb(const QList& thumbnailIds) { ActionJobCollection collection; data->setThumbnailIds(thumbnailIds); for (int i = 1; i <= maximumNumberOfThreads(); i++) { DatabaseTask* const t = new DatabaseTask(); t->setMaintenanceData(data); t->setMode(DatabaseTask::Mode::CleanThumbsDb); connect(t, SIGNAL(signalFinished()), this, SIGNAL(signalAdvance())); - connect(this, SIGNAL(signalCanceled()), - t, SLOT(slotCancel()), Qt::QueuedConnection); - collection.insert(t, 0); qCDebug(DIGIKAM_GENERAL_LOG) << "Creating a database task for removing stale thumbnails."; } appendJobs(collection); } void MaintenanceThread::cleanFacesDb(const QList& staleIdentities) { ActionJobCollection collection; data->setIdentities(staleIdentities); for (int i = 1; i <= maximumNumberOfThreads(); i++) { DatabaseTask* const t = new DatabaseTask(); t->setMaintenanceData(data); t->setMode(DatabaseTask::Mode::CleanRecognitionDb); connect(t, SIGNAL(signalFinished()), this, SIGNAL(signalAdvance())); - connect(this, SIGNAL(signalCanceled()), - t, SLOT(slotCancel()), Qt::QueuedConnection); - collection.insert(t, 0); qCDebug(DIGIKAM_GENERAL_LOG) << "Creating a database task for removing stale identities."; } appendJobs(collection); } void MaintenanceThread::shrinkDatabases() { ActionJobCollection collection; DatabaseTask* const t = new DatabaseTask(); t->setMode(DatabaseTask::Mode::ShrinkDatabases); connect(t, SIGNAL(signalStarted()), this, SIGNAL(signalStarted())); connect(t, SIGNAL(signalFinished(bool,bool)), this, SIGNAL(signalFinished(bool,bool))); - connect(this, SIGNAL(signalCanceled()), - t, SLOT(slotCancel()), Qt::QueuedConnection); - collection.insert(t, 0); appendJobs(collection); } void MaintenanceThread::cancel() { if (isRunning()) { emit signalCanceled(); } ActionThreadBase::cancel(); } void MaintenanceThread::slotThreadFinished() { if (isEmpty()) { qCDebug(DIGIKAM_GENERAL_LOG) << "List of Pending Jobs is empty"; emit signalCompleted(); } } /* int MaintenanceThread::getChunkSize(int elementCount) { int chunkSize = elementCount; if (maximumNumberOfThreads() > 1) { chunkSize = elementCount / (maximumNumberOfThreads() - 1); } // add a factor to the chunk size (do it dynamically depending on free mem?) chunkSize = chunkSize * 0.5; return chunkSize; } */ } // namespace Digikam diff --git a/utilities/maintenance/metadatatask.cpp b/utilities/maintenance/metadatatask.cpp index 323891e465..d58ad40f1c 100644 --- a/utilities/maintenance/metadatatask.cpp +++ b/utilities/maintenance/metadatatask.cpp @@ -1,137 +1,130 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2013-08-09 * Description : Thread actions task for metadata synchronizer. * * Copyright (C) 2013-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "metadatatask.h" // Local includes #include "collectionscanner.h" #include "metadatahub.h" #include "digikam_debug.h" #include "maintenancedata.h" namespace Digikam { class MetadataTask::Private { public: - Private() : - cancel(false), - tagsOnly(false), - direction(MetadataSynchronizer::WriteFromDatabaseToFile), - data(0) + Private() + : tagsOnly(false), + direction(MetadataSynchronizer::WriteFromDatabaseToFile), + data(0) { } - bool cancel; bool tagsOnly; MetadataSynchronizer::SyncDirection direction; MaintenanceData* data; }; // ------------------------------------------------------- MetadataTask::MetadataTask() : ActionJob(), d(new Private) { } MetadataTask::~MetadataTask() { - slotCancel(); + cancel(); delete d; } void MetadataTask::setTagsOnly(bool value) { d->tagsOnly = value; } void MetadataTask::setDirection(MetadataSynchronizer::SyncDirection dir) { d->direction = dir; } -void MetadataTask::setMaintenanceData(MaintenanceData* data) +void MetadataTask::setMaintenanceData(MaintenanceData* const data) { d->data = data; } -void MetadataTask::slotCancel() -{ - d->cancel = true; -} - void MetadataTask::run() { // While we have data (using this as check for non-null) while (d->data) { + if (m_cancel) + { + return; + } + ImageInfo item = d->data->getImageInfo(); // If the item is null, we are done. if (item.isNull()) { break; } - if (d->cancel) - { - return; - } - if (d->direction == MetadataSynchronizer::WriteFromDatabaseToFile) { MetadataHub fileHub; // read in from database fileHub.load(item); // write out to file DMetadata if (d->tagsOnly) { fileHub.writeTags(item.filePath()); } else { fileHub.write(item.filePath(), MetadataHub::WRITE_ALL, true); } } else // MetadataSynchronizer::ReadFromFileToDatabase { CollectionScanner scanner; scanner.scanFile(item, CollectionScanner::Rescan); } emit signalFinished(QImage()); } emit signalDone(); } } // namespace Digikam diff --git a/utilities/maintenance/metadatatask.h b/utilities/maintenance/metadatatask.h index 22cd8d2f6d..0c6a44d97b 100644 --- a/utilities/maintenance/metadatatask.h +++ b/utilities/maintenance/metadatatask.h @@ -1,75 +1,71 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2013-08-09 * Description : Thread actions task for metadata synchronizer. * * Copyright (C) 2013-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef METADATA_TASK_H #define METADATA_TASK_H // Qt includes #include // Local includes #include "actionthreadbase.h" #include "imageinfo.h" #include "metadatasynchronizer.h" namespace Digikam { class MaintenanceData; class MetadataTask : public ActionJob { Q_OBJECT public: MetadataTask(); ~MetadataTask(); void setTagsOnly(bool value); void setDirection(MetadataSynchronizer::SyncDirection dir); - void setMaintenanceData(MaintenanceData* data=0); + void setMaintenanceData(MaintenanceData* const data=0); Q_SIGNALS: void signalFinished(const QImage&); -public Q_SLOTS: - - void slotCancel(); - protected: void run(); private: class Private; Private* const d; }; } // namespace Digikam #endif /* METADATA_TASK_H */ diff --git a/utilities/maintenance/thumbstask.cpp b/utilities/maintenance/thumbstask.cpp index 8138030501..a7a92171f0 100644 --- a/utilities/maintenance/thumbstask.cpp +++ b/utilities/maintenance/thumbstask.cpp @@ -1,120 +1,117 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2013-08-14 * Description : Thread actions task for thumbs generator. * * Copyright (C) 2013-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "thumbstask.h" // Qt includes #include // Local includes #include "digikam_debug.h" #include "thumbnailloadthread.h" #include "thumbnailsize.h" #include "maintenancedata.h" namespace Digikam { class ThumbsTask::Private { public: Private() - : cancel(false),catcher(0), data(0) + : catcher(0), + data(0) { } - bool cancel; - ThumbnailImageCatcher* catcher; MaintenanceData* data; }; // ------------------------------------------------------- ThumbsTask::ThumbsTask() : ActionJob(), d(new Private) { ThumbnailLoadThread* const thread = new ThumbnailLoadThread; thread->setPixmapRequested(false); thread->setThumbnailSize(ThumbnailLoadThread::maximumThumbnailSize()); d->catcher = new ThumbnailImageCatcher(thread, this); } ThumbsTask::~ThumbsTask() { - slotCancel(); + cancel(); + + d->catcher->setActive(false); + d->catcher->thread()->stopAllTasks(); delete d->catcher->thread(); delete d->catcher; delete d; } -void ThumbsTask::setMaintenanceData(MaintenanceData* data) +void ThumbsTask::setMaintenanceData(MaintenanceData* const data) { d->data = data; } -void ThumbsTask::slotCancel() -{ - d->catcher->thread()->stopAllTasks(); - d->catcher->cancel(); - d->cancel = true; -} - void ThumbsTask::run() { d->catcher->setActive(true); // While we have data (using this as check for non-null) while (d->data) { - if (d->cancel) + if (m_cancel) { + d->catcher->setActive(false); + d->catcher->thread()->stopAllTasks(); return; } QString path = d->data->getImagePath(); if (path.isEmpty()) { break; } // TODO Should be improved by some update procedure d->catcher->thread()->deleteThumbnail(path); d->catcher->thread()->find(ThumbnailIdentifier(path)); d->catcher->enqueue(); QList images = d->catcher->waitForThumbnails(); emit signalFinished(images.first()); } emit signalDone(); d->catcher->setActive(false); } } // namespace Digikam diff --git a/utilities/maintenance/thumbstask.h b/utilities/maintenance/thumbstask.h index e6ddba6c36..964573bfcf 100644 --- a/utilities/maintenance/thumbstask.h +++ b/utilities/maintenance/thumbstask.h @@ -1,72 +1,68 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2013-08-14 * Description : Thread actions task for thumbs generator. * * Copyright (C) 2013-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef THUMBS_TASK_H #define THUMBS_TASK_H // Qt includes #include // Local includes #include "actionthreadbase.h" namespace Digikam { class LoadingDescription; class MaintenanceData; class ThumbsTask : public ActionJob { Q_OBJECT public: ThumbsTask(); ~ThumbsTask(); - void setMaintenanceData(MaintenanceData* data=0); + void setMaintenanceData(MaintenanceData* const data=0); Q_SIGNALS: void signalFinished(const QImage&); -public Q_SLOTS: - - void slotCancel(); - protected: void run(); private: class Private; Private* const d; }; } // namespace Digikam #endif /* THUMBS_TASK_H */