File indexing completed on 2025-01-05 03:53:08

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2011-05-23
0007  * Description : a tool to create panorama by fusion of several images.
0008  *
0009  * SPDX-FileCopyrightText: 2011-2016 by Benjamin Girault <benjamin dot girault at gmail dot com>
0010  * SPDX-FileCopyrightText: 2009-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 "panomanager.h"
0017 
0018 // Qt includes
0019 
0020 #include <QFile>
0021 #include <QSharedPointer>
0022 
0023 // KDE includes
0024 
0025 #include <ksharedconfig.h>
0026 #include <kconfiggroup.h>
0027 
0028 // Local includes
0029 
0030 #include "digikam_debug.h"
0031 #include "panowizard.h"
0032 #include "panoactionthread.h"
0033 #include "autooptimiserbinary.h"
0034 #include "cpcleanbinary.h"
0035 #include "cpfindbinary.h"
0036 #include "enblendbinary.h"
0037 #include "makebinary.h"
0038 #include "nonabinary.h"
0039 #include "panomodifybinary.h"
0040 #include "pto2mkbinary.h"
0041 #include "huginexecutorbinary.h"
0042 #include "ptofile.h"
0043 
0044 namespace DigikamGenericPanoramaPlugin
0045 {
0046 
0047 class Q_DECL_HIDDEN PanoManager::Private
0048 {
0049 public:
0050 
0051     explicit Private()
0052       : basePtoData                 (nullptr),
0053         cpFindPtoData               (nullptr),
0054         cpCleanPtoData              (nullptr),
0055         autoOptimisePtoData         (nullptr),
0056         viewAndCropOptimisePtoData  (nullptr),
0057         previewPtoData              (nullptr),
0058         panoPtoData                 (nullptr),
0059         hugin2015                   (false),
0060         thread                      (nullptr),
0061         plugin                      (nullptr),
0062         wizard                      (nullptr),
0063         config                      (KSharedConfig::openConfig()),
0064         group                       (config->group(QLatin1String("Panorama Settings")))
0065     {
0066         gPano    = group.readEntry("GPano", false);
0067 /*
0068         hdr      = group.readEntry("HDR", false);
0069 */
0070         fileType = (PanoramaFileType) group.readEntry("File Type", (int) JPEG);
0071     }
0072 
0073     ~Private()
0074     {
0075 /*
0076         group.writeEntry("HDR", hdr);
0077 */
0078         group.writeEntry("GPano",     gPano);
0079         group.writeEntry("File Type", (int) fileType);
0080         config->sync();
0081     }
0082 
0083     QList<QUrl>                    inputUrls;
0084 
0085     QUrl                           basePtoUrl;
0086     QSharedPointer<PTOType>        basePtoData;
0087     QUrl                           cpFindPtoUrl;
0088     QSharedPointer<PTOType>        cpFindPtoData;
0089     QUrl                           cpCleanPtoUrl;
0090     QSharedPointer<PTOType>        cpCleanPtoData;
0091     QUrl                           autoOptimisePtoUrl;
0092     QSharedPointer<PTOType>        autoOptimisePtoData;
0093     QUrl                           viewAndCropOptimisePtoUrl;
0094     QSharedPointer<PTOType>        viewAndCropOptimisePtoData;
0095     QUrl                           previewPtoUrl;
0096     QSharedPointer<PTOType>        previewPtoData;
0097     QUrl                           panoPtoUrl;
0098     QSharedPointer<PTOType>        panoPtoData;
0099 
0100     QUrl                           previewMkUrl;
0101     QUrl                           previewUrl;
0102     QUrl                           mkUrl;
0103     QUrl                           panoUrl;
0104 
0105     bool                           hugin2015;
0106     bool                           gPano;
0107 /*
0108     bool                           hdr;
0109 */
0110 
0111     PanoramaFileType               fileType;
0112 
0113     PanoramaItemUrlsMap            preProcessedUrlsMap;
0114 
0115     PanoActionThread*              thread;
0116 
0117     DPlugin*                       plugin;
0118 
0119     AutoOptimiserBinary            autoOptimiserBinary;
0120     CPCleanBinary                  cpCleanBinary;
0121     CPFindBinary                   cpFindBinary;
0122     EnblendBinary                  enblendBinary;
0123     MakeBinary                     makeBinary;
0124     NonaBinary                     nonaBinary;
0125     PanoModifyBinary               panoModifyBinary;
0126     Pto2MkBinary                   pto2MkBinary;
0127     HuginExecutorBinary            huginExecutorBinary;
0128 
0129     PanoWizard*                    wizard;
0130 
0131 private:
0132 
0133     KSharedConfigPtr               config;
0134     KConfigGroup                   group;
0135 };
0136 
0137 QPointer<PanoManager> PanoManager::internalPtr = QPointer<PanoManager>();
0138 
0139 PanoManager::PanoManager(QObject* const parent)
0140     : QObject(parent),
0141       d      (new Private)
0142 {
0143     d->thread = new PanoActionThread(this);
0144 }
0145 
0146 PanoManager::~PanoManager()
0147 {
0148     delete d->thread;
0149     delete d->wizard;
0150     delete d;
0151 }
0152 
0153 PanoManager* PanoManager::instance()
0154 {
0155     if (PanoManager::internalPtr.isNull())
0156     {
0157         PanoManager::internalPtr = new PanoManager();
0158     }
0159 
0160     return PanoManager::internalPtr;
0161 }
0162 
0163 bool PanoManager::isCreated()
0164 {
0165     return (!internalPtr.isNull());
0166 }
0167 
0168 void PanoManager::checkForHugin2015()
0169 {
0170     if (d->autoOptimiserBinary.recheckDirectories())
0171     {
0172         d->hugin2015 = d->autoOptimiserBinary.versionIsRight(2015.0);
0173     }
0174 
0175     qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Hugin >= 2015.0 : " << d->hugin2015;
0176 }
0177 
0178 bool PanoManager::checkBinaries()
0179 {
0180     bool result = d->autoOptimiserBinary.recheckDirectories() &&
0181                   d->cpCleanBinary.recheckDirectories()       &&
0182                   d->cpFindBinary.recheckDirectories()        &&
0183                   d->enblendBinary.recheckDirectories()       &&
0184                   d->makeBinary.recheckDirectories()          &&
0185                   d->nonaBinary.recheckDirectories();
0186 
0187     if (result)
0188     {
0189         if (d->hugin2015)
0190         {
0191             qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Check for Hugin Executor";
0192             result = d->huginExecutorBinary.recheckDirectories();
0193         }
0194         else
0195         {
0196             qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Check for Hugin Pto2Mk";
0197             result = d->pto2MkBinary.recheckDirectories();
0198         }
0199     }
0200 
0201     return result;
0202 }
0203 
0204 bool PanoManager::hugin2015() const
0205 {
0206     return d->hugin2015;
0207 }
0208 
0209 void PanoManager::setGPano(bool gPano)
0210 {
0211     d->gPano = gPano;
0212 }
0213 
0214 bool PanoManager::gPano() const
0215 {
0216     return d->gPano;
0217 }
0218 
0219 /*
0220 void PanoManager::setHDR(bool hdr)
0221 {
0222     d->hdr = hdr;
0223 }
0224 
0225 bool PanoManager::hdr() const
0226 {
0227     return d->hdr;
0228 }
0229 */
0230 
0231 void PanoManager::setFileFormatJPEG()
0232 {
0233     d->fileType = JPEG;
0234 }
0235 
0236 void PanoManager::setFileFormatTIFF()
0237 {
0238     d->fileType = TIFF;
0239 }
0240 
0241 void PanoManager::setFileFormatHDR()
0242 {
0243     d->fileType = HDR;
0244 }
0245 
0246 PanoramaFileType PanoManager::format() const
0247 {
0248     return d->fileType;
0249 }
0250 
0251 AutoOptimiserBinary& PanoManager::autoOptimiserBinary() const
0252 {
0253     return d->autoOptimiserBinary;
0254 }
0255 
0256 CPCleanBinary& PanoManager::cpCleanBinary() const
0257 {
0258     return d->cpCleanBinary;
0259 }
0260 
0261 CPFindBinary& PanoManager::cpFindBinary() const
0262 {
0263     return d->cpFindBinary;
0264 }
0265 
0266 EnblendBinary& PanoManager::enblendBinary() const
0267 {
0268     return d->enblendBinary;
0269 }
0270 
0271 MakeBinary& PanoManager::makeBinary() const
0272 {
0273     return d->makeBinary;
0274 }
0275 
0276 NonaBinary& PanoManager::nonaBinary() const
0277 {
0278     return d->nonaBinary;
0279 }
0280 
0281 PanoModifyBinary& PanoManager::panoModifyBinary() const
0282 {
0283     return d->panoModifyBinary;
0284 }
0285 
0286 Pto2MkBinary& PanoManager::pto2MkBinary() const
0287 {
0288     return d->pto2MkBinary;
0289 }
0290 
0291 HuginExecutorBinary& PanoManager::huginExecutorBinary() const
0292 {
0293     return d->huginExecutorBinary;
0294 }
0295 
0296 QUrl& PanoManager::basePtoUrl() const
0297 {
0298     return d->basePtoUrl;
0299 }
0300 
0301 QSharedPointer<PTOType> PanoManager::basePtoData()
0302 {
0303     if (d->basePtoData.isNull())
0304     {
0305         PTOFile file(cpFindBinary().version());
0306         file.openFile(d->basePtoUrl.toLocalFile());
0307         d->basePtoData = QSharedPointer<PTOType>(file.getPTO());
0308 
0309         if (d->basePtoData.isNull())
0310         {
0311             d->basePtoData = QSharedPointer<PTOType>(new PTOType(cpFindBinary().version()));
0312         }
0313     }
0314 
0315     return d->basePtoData;
0316 }
0317 
0318 void PanoManager::resetBasePto()
0319 {
0320     d->basePtoData.clear();
0321 
0322     QFile pto(d->basePtoUrl.toLocalFile());
0323 
0324     if (pto.exists())
0325     {
0326         pto.remove();
0327     }
0328 
0329     d->basePtoUrl.clear();
0330 }
0331 
0332 QUrl& PanoManager::cpFindPtoUrl() const
0333 {
0334     return d->cpFindPtoUrl;
0335 }
0336 
0337 QSharedPointer<PTOType> PanoManager::cpFindPtoData()
0338 {
0339     if (d->cpFindPtoData.isNull())
0340     {
0341         PTOFile file(cpFindBinary().version());
0342         file.openFile(d->cpFindPtoUrl.toLocalFile());
0343         d->cpFindPtoData = QSharedPointer<PTOType>(file.getPTO());
0344 
0345         if (d->cpFindPtoData.isNull())
0346         {
0347             d->cpFindPtoData = QSharedPointer<PTOType>(new PTOType(cpFindBinary().version()));
0348         }
0349     }
0350 
0351     return d->cpFindPtoData;
0352 }
0353 
0354 void PanoManager::resetCpFindPto()
0355 {
0356     d->cpFindPtoData.clear();
0357 
0358     QFile pto(d->cpFindPtoUrl.toLocalFile());
0359 
0360     if (pto.exists())
0361     {
0362         pto.remove();
0363     }
0364 
0365     d->cpFindPtoUrl.clear();
0366 }
0367 
0368 QUrl& PanoManager::cpCleanPtoUrl() const
0369 {
0370     return d->cpCleanPtoUrl;
0371 }
0372 
0373 QSharedPointer<PTOType> PanoManager::cpCleanPtoData()
0374 {
0375     if (d->cpCleanPtoData.isNull())
0376     {
0377         PTOFile file(cpFindBinary().version());
0378         file.openFile(d->cpCleanPtoUrl.toLocalFile());
0379         d->cpCleanPtoData = QSharedPointer<PTOType>(file.getPTO());
0380 
0381         if (d->cpCleanPtoData.isNull())
0382         {
0383             d->cpCleanPtoData = QSharedPointer<PTOType>(new PTOType(cpFindBinary().version()));
0384         }
0385     }
0386 
0387     return d->cpCleanPtoData;
0388 }
0389 
0390 void PanoManager::resetCpCleanPto()
0391 {
0392     d->cpCleanPtoData.clear();
0393 
0394     QFile pto(d->cpCleanPtoUrl.toLocalFile());
0395 
0396     if (pto.exists())
0397     {
0398         pto.remove();
0399     }
0400 
0401     d->cpCleanPtoUrl.clear();
0402 }
0403 
0404 QUrl& PanoManager::autoOptimisePtoUrl() const
0405 {
0406     return d->autoOptimisePtoUrl;
0407 }
0408 
0409 QSharedPointer<PTOType> PanoManager::autoOptimisePtoData()
0410 {
0411     if (d->autoOptimisePtoData.isNull())
0412     {
0413         PTOFile file(cpFindBinary().version());
0414         file.openFile(d->autoOptimisePtoUrl.toLocalFile());
0415         d->autoOptimisePtoData = QSharedPointer<PTOType>(file.getPTO());
0416 
0417         if (d->autoOptimisePtoData.isNull())
0418         {
0419             d->autoOptimisePtoData = QSharedPointer<PTOType>(new PTOType(cpFindBinary().version()));
0420         }
0421     }
0422 
0423     return d->autoOptimisePtoData;
0424 }
0425 
0426 void PanoManager::resetAutoOptimisePto()
0427 {
0428     d->autoOptimisePtoData.clear();
0429 
0430     QFile pto(d->autoOptimisePtoUrl.toLocalFile());
0431 
0432     if (pto.exists())
0433     {
0434         pto.remove();
0435     }
0436 
0437     d->autoOptimisePtoUrl.clear();
0438 }
0439 
0440 QUrl& PanoManager::viewAndCropOptimisePtoUrl() const
0441 {
0442     return d->viewAndCropOptimisePtoUrl;
0443 }
0444 
0445 QSharedPointer<PTOType> PanoManager::viewAndCropOptimisePtoData()
0446 {
0447     if (d->viewAndCropOptimisePtoData.isNull())
0448     {
0449         PTOFile file(cpFindBinary().version());
0450         file.openFile(d->viewAndCropOptimisePtoUrl.toLocalFile());
0451         d->viewAndCropOptimisePtoData = QSharedPointer<PTOType>(file.getPTO());
0452 
0453         if (d->viewAndCropOptimisePtoData.isNull())
0454         {
0455             d->viewAndCropOptimisePtoData = QSharedPointer<PTOType>(new PTOType(cpFindBinary().version()));
0456         }
0457     }
0458 
0459     return d->viewAndCropOptimisePtoData;
0460 }
0461 
0462 void PanoManager::resetViewAndCropOptimisePto()
0463 {
0464     d->viewAndCropOptimisePtoData.clear();
0465 
0466     QFile pto(d->viewAndCropOptimisePtoUrl.toLocalFile());
0467 
0468     if (pto.exists())
0469     {
0470         pto.remove();
0471     }
0472 
0473     d->viewAndCropOptimisePtoUrl.clear();
0474 }
0475 
0476 QUrl& PanoManager::previewPtoUrl() const
0477 {
0478     return d->previewPtoUrl;
0479 }
0480 
0481 QSharedPointer<PTOType> PanoManager::previewPtoData()
0482 {
0483     if (d->previewPtoData.isNull())
0484     {
0485         PTOFile file(cpFindBinary().version());
0486         file.openFile(d->previewPtoUrl.toLocalFile());
0487         d->previewPtoData = QSharedPointer<PTOType>(file.getPTO());
0488 
0489         if (d->previewPtoData.isNull())
0490         {
0491             d->previewPtoData = QSharedPointer<PTOType>(new PTOType(cpFindBinary().version()));
0492         }
0493     }
0494 
0495     return d->previewPtoData;
0496 }
0497 
0498 void PanoManager::resetPreviewPto()
0499 {
0500     d->previewPtoData.clear();
0501 
0502     QFile pto(d->previewPtoUrl.toLocalFile());
0503 
0504     if (pto.exists())
0505     {
0506         pto.remove();
0507     }
0508 
0509     d->previewPtoUrl.clear();
0510 }
0511 
0512 QUrl& PanoManager::panoPtoUrl() const
0513 {
0514     return d->panoPtoUrl;
0515 }
0516 
0517 QSharedPointer<PTOType> PanoManager::panoPtoData()
0518 {
0519     if (d->panoPtoData.isNull())
0520     {
0521         PTOFile file(cpFindBinary().version());
0522         file.openFile(d->panoPtoUrl.toLocalFile());
0523         d->panoPtoData = QSharedPointer<PTOType>(file.getPTO());
0524 
0525         if (d->panoPtoData.isNull())
0526         {
0527             d->panoPtoData = QSharedPointer<PTOType>(new PTOType(cpFindBinary().version()));
0528         }
0529     }
0530 
0531     return d->panoPtoData;
0532 }
0533 
0534 void PanoManager::resetPanoPto()
0535 {
0536     d->panoPtoData.clear();
0537 
0538     QFile pto(d->panoPtoUrl.toLocalFile());
0539 
0540     if (pto.exists())
0541     {
0542         pto.remove();
0543     }
0544 
0545     d->panoPtoUrl.clear();
0546 }
0547 
0548 QUrl& PanoManager::previewMkUrl() const
0549 {
0550     return d->previewMkUrl;
0551 }
0552 
0553 void PanoManager::resetPreviewMkUrl()
0554 {
0555     QFile pto(d->previewMkUrl.toLocalFile());
0556 
0557     if (pto.exists())
0558     {
0559         pto.remove();
0560     }
0561 
0562     d->previewMkUrl.clear();
0563 }
0564 
0565 QUrl& PanoManager::previewUrl() const
0566 {
0567     return d->previewUrl;
0568 }
0569 
0570 void PanoManager::resetPreviewUrl()
0571 {
0572     QFile pto(d->previewUrl.toLocalFile());
0573 
0574     if (pto.exists())
0575     {
0576         pto.remove();
0577     }
0578 
0579     d->previewUrl.clear();
0580 }
0581 
0582 QUrl& PanoManager::mkUrl() const
0583 {
0584     return d->mkUrl;
0585 }
0586 
0587 void PanoManager::resetMkUrl()
0588 {
0589     QFile pto(d->mkUrl.toLocalFile());
0590 
0591     if (pto.exists())
0592     {
0593         pto.remove();
0594     }
0595 
0596     d->mkUrl.clear();
0597 }
0598 
0599 QUrl& PanoManager::panoUrl() const
0600 {
0601     return d->panoUrl;
0602 }
0603 
0604 void PanoManager::resetPanoUrl()
0605 {
0606     QFile pto(d->panoUrl.toLocalFile());
0607 
0608     if (pto.exists())
0609     {
0610         pto.remove();
0611     }
0612 
0613     d->panoUrl.clear();
0614 }
0615 
0616 void PanoManager::setItemsList(const QList<QUrl>& urls)
0617 {
0618     d->inputUrls = urls;
0619 }
0620 
0621 QList<QUrl>& PanoManager::itemsList() const
0622 {
0623     return d->inputUrls;
0624 }
0625 
0626 void PanoManager::setPlugin(DPlugin* const plugin)
0627 {
0628     d->plugin = plugin;
0629 }
0630 
0631 void PanoManager::setPreProcessedMap(const PanoramaItemUrlsMap& urls)
0632 {
0633     d->preProcessedUrlsMap = urls;
0634 }
0635 
0636 PanoramaItemUrlsMap& PanoManager::preProcessedMap() const
0637 {
0638     return d->preProcessedUrlsMap;
0639 }
0640 
0641 PanoActionThread* PanoManager::thread() const
0642 {
0643     return d->thread;
0644 }
0645 
0646 void PanoManager::run()
0647 {
0648     startWizard();
0649 }
0650 
0651 void PanoManager::startWizard()
0652 {
0653     if (d->wizard && (d->wizard->isMinimized() || !d->wizard->isHidden()))
0654     {
0655         d->wizard->showNormal();        // krazy:exclude=qmethods
0656         d->wizard->activateWindow();
0657         d->wizard->raise();
0658     }
0659     else
0660     {
0661         delete d->wizard;
0662 
0663         d->wizard = new PanoWizard(this);
0664         d->wizard->setPlugin(d->plugin);
0665         d->wizard->show();
0666     }
0667 }
0668 
0669 } // namespace DigikamGenericPanoramaPlugin
0670 
0671 #include "moc_panomanager.cpp"