File indexing completed on 2025-01-19 03:57:51

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2014-10-17
0007  * Description : test for implementation of ditemslist api
0008  *
0009  * SPDX-FileCopyrightText: 2011-2012 by A Janardhan Reddy <annapareddyjanardhanreddy at gmail dot com>
0010  * SPDX-FileCopyrightText: 2011-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "ditemslist_gui.h"
0017 
0018 // Qt includes
0019 
0020 #include <QGridLayout>
0021 #include <QProgressBar>
0022 #include <QVBoxLayout>
0023 #include <QDialogButtonBox>
0024 #include <QApplication>
0025 #include <QImage>
0026 #include <QTransform>
0027 
0028 // Local includes
0029 
0030 #include "digikam_debug.h"
0031 #include "ditemslist.h"
0032 
0033 using namespace Digikam;
0034 
0035 class Q_DECL_HIDDEN Task : public ActionJob
0036 {
0037     Q_OBJECT
0038 
0039 public:
0040 
0041     Task(QObject* const parent = nullptr)
0042         : ActionJob(parent)
0043     {
0044     }
0045 
0046     QString errString;
0047     QUrl    fileUrl;
0048 
0049 protected:
0050 
0051     void run() override
0052     {
0053         Q_EMIT signalStarted();
0054 
0055         QImage src;
0056         QImage dst;
0057 
0058         if (m_cancel)
0059             return;
0060 
0061         Q_EMIT signalProgress(20);
0062 
0063         if (!src.load(fileUrl.toLocalFile()))
0064         {
0065             errString = QLatin1String("Loading image failed. Aborted...");
0066             return;
0067         }
0068 
0069         if (m_cancel)
0070             return;
0071 
0072         Q_EMIT signalProgress(40);
0073 
0074         QTransform transform;
0075         transform.rotate(90);
0076 
0077         if (m_cancel)
0078             return;
0079 
0080         Q_EMIT signalProgress(60);
0081 
0082         dst = src.transformed(transform);
0083 
0084         if (m_cancel)
0085             return;
0086 
0087         Q_EMIT signalProgress(80);
0088 
0089         if (!dst.save(fileUrl.toLocalFile()))
0090         {
0091             errString = QLatin1String("Saving image failed. Aborted...");
0092             return;
0093         }
0094 
0095         Q_EMIT signalDone();
0096     }
0097 };
0098 
0099 // ----------------------------------------------------------------------------------------------------
0100 
0101 ActionThread::ActionThread(QObject* const parent)
0102     : ActionThreadBase(parent)
0103 {
0104     setObjectName(QLatin1String("ActionThread"));
0105 }
0106 
0107 ActionThread::~ActionThread()
0108 {
0109 }
0110 
0111 void ActionThread::rotate(const QList<QUrl>& list)
0112 {
0113     ActionJobCollection collection;
0114 
0115     Q_FOREACH (const QUrl& url, list)
0116     {
0117         Task* const job = new Task();
0118         job->fileUrl    = url;
0119 
0120         connect(job, &Task::signalStarted,
0121                 this, &ActionThread::slotJobStarted);
0122 
0123         connect(job, &Task::signalProgress,
0124                 this, &ActionThread::slotJobProgress);
0125 
0126         connect(job, &Task::signalDone,
0127                 this, &ActionThread::slotJobDone);
0128 
0129         collection.insert(job, 0);
0130 
0131         qCDebug(DIGIKAM_TESTS_LOG) << "Appending file to process " << url;
0132     }
0133 
0134     appendJobs(collection);
0135 }
0136 
0137 void ActionThread::slotJobDone()
0138 {
0139     Task* const task = dynamic_cast<Task*>(sender());
0140     if (!task) return;
0141 
0142     if (task->errString.isEmpty())
0143     {
0144         Q_EMIT finished(task->fileUrl);
0145     }
0146     else
0147     {
0148         Q_EMIT failed(task->fileUrl, task->errString);
0149     }
0150 }
0151 
0152 void ActionThread::slotJobProgress(int p)
0153 {
0154     Task* const task = dynamic_cast<Task*>(sender());
0155     if (!task) return;
0156 
0157     Q_EMIT progress(task->fileUrl, p);
0158 }
0159 
0160 void ActionThread::slotJobStarted()
0161 {
0162     Task* const task = dynamic_cast<Task*>(sender());
0163     if (!task) return;
0164 
0165     Q_EMIT starting(task->fileUrl);
0166 }
0167 
0168 // ----------------------------------------------------------
0169 
0170 class Q_DECL_HIDDEN DItemsListTest::Private
0171 {
0172 public:
0173 
0174     explicit Private()
0175     {
0176         page        = nullptr;
0177         buttons     = nullptr;
0178         progressBar = nullptr;
0179         applyBtn    = nullptr;
0180         listView    = nullptr;
0181         thread      = nullptr;
0182     }
0183 
0184     QWidget*          page;
0185 
0186     QDialogButtonBox* buttons;
0187     QProgressBar*     progressBar;
0188     QPushButton*      applyBtn;
0189 
0190     DItemsList*      listView;
0191 
0192     ActionThread*     thread;
0193 };
0194 
0195 DItemsListTest::DItemsListTest(QWidget* const parent)
0196     : QDialog(parent),
0197       d      (new Private)
0198 {
0199     setWindowTitle(QString::fromUtf8("Rotate Images to 180 Degrees"));
0200 
0201     d->buttons               = new QDialogButtonBox(QDialogButtonBox::Apply |
0202                                                     QDialogButtonBox::Close, this);
0203 
0204     d->page                  = new QWidget(this);
0205     QVBoxLayout* const vbx   = new QVBoxLayout(this);
0206     vbx->addWidget(d->page);
0207     vbx->addWidget(d->buttons);
0208     setLayout(vbx);
0209     setModal(false);
0210 
0211     // -------------------
0212 
0213     QGridLayout* const mainLayout = new QGridLayout(d->page);
0214 
0215     d->listView                   = new DItemsList(d->page);
0216     d->listView->setControlButtonsPlacement(DItemsList::ControlButtonsRight);
0217 
0218     d->progressBar                = new QProgressBar(d->page);
0219     d->progressBar->setMaximumHeight(fontMetrics().height()+2);
0220 
0221     mainLayout->addWidget(d->listView,    0, 0, 1, 1);
0222     mainLayout->addWidget(d->progressBar, 1, 0, 1, 1);
0223     mainLayout->setRowStretch(0, 10);
0224 
0225     d->thread = new ActionThread(this);
0226 
0227     d->applyBtn = d->buttons->button(QDialogButtonBox::Apply);
0228     d->applyBtn->setText(QLatin1String("Rotate Items"));
0229 
0230     connect(d->applyBtn, &QPushButton::clicked,
0231             this, &DItemsListTest::slotStart);
0232 
0233     connect(d->buttons->button(QDialogButtonBox::Close), &QPushButton::clicked,
0234             this, &DItemsListTest::close);
0235 
0236     connect(d->thread, &ActionThread::starting,
0237             this, &DItemsListTest::slotStarting);
0238 
0239     connect(d->thread, &ActionThread::finished,
0240             this, &DItemsListTest::slotFinished);
0241 
0242     connect(d->thread, &ActionThread::failed,
0243             this, &DItemsListTest::slotFailed);
0244 }
0245 
0246 DItemsListTest::~DItemsListTest()
0247 {
0248     delete d;
0249 }
0250 
0251 void DItemsListTest::slotStart()
0252 {
0253     QList<QUrl> selectedImages = d->listView->imageUrls();
0254 
0255     if (selectedImages.isEmpty())
0256         return;
0257 
0258     qCDebug(DIGIKAM_TESTS_LOG) << selectedImages;
0259     d->progressBar->setMaximum(selectedImages.count());
0260     d->progressBar->setValue(0);
0261     d->applyBtn->setEnabled(false);
0262 
0263     // Rotate the selected images by 180 degrees
0264     // It can be converted to gray scale also, just change the function here
0265     d->thread->rotate(selectedImages);
0266     d->thread->start();
0267 }
0268 
0269 void DItemsListTest::slotStarting(const QUrl& url)
0270 {
0271     d->listView->processing(url);
0272 }
0273 
0274 void DItemsListTest::slotFinished(const QUrl& url)
0275 {
0276     d->listView->processed(url, true);
0277     d->progressBar->setValue(d->progressBar->value()+1);
0278     d->listView->updateThumbnail(url);
0279 }
0280 
0281 void DItemsListTest::slotFailed(const QUrl& url, const QString&)
0282 {
0283     d->listView->processed(url, false);
0284     d->progressBar->setValue(d->progressBar->value()+1);
0285 }
0286 
0287 int main(int argc, char* argv[])
0288 {
0289     QApplication app(argc, argv);
0290     DItemsListTest* const view = new DItemsListTest;
0291     view->show();
0292     app.exec();
0293     delete view;
0294     return 0;
0295 }
0296 
0297 #include "ditemslist_gui.moc"
0298 
0299 #include "moc_ditemslist_gui.cpp"