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

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2013-11-18
0007  * Description : a tool to export images to Dropbox web service
0008  *
0009  * SPDX-FileCopyrightText: 2013      by Pankaj Kumar <me at panks dot me>
0010  * SPDX-FileCopyrightText: 2013-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 "dbwindow.h"
0017 
0018 // Qt includes
0019 
0020 #include <QWindow>
0021 #include <QSpinBox>
0022 #include <QCheckBox>
0023 #include <QMessageBox>
0024 #include <QCloseEvent>
0025 
0026 // KDE includes
0027 
0028 #include <klocalizedstring.h>
0029 #include <ksharedconfig.h>
0030 #include <kconfiggroup.h>
0031 
0032 // Local includes
0033 
0034 #include "digikam_debug.h"
0035 #include "ditemslist.h"
0036 #include "digikam_version.h"
0037 #include "dbtalker.h"
0038 #include "dbitem.h"
0039 #include "dbnewalbumdlg.h"
0040 #include "dbwidget.h"
0041 
0042 namespace DigikamGenericDropBoxPlugin
0043 {
0044 
0045 class Q_DECL_HIDDEN DBWindow::Private
0046 {
0047 public:
0048 
0049     explicit Private()
0050     {
0051         imagesCount = 0;
0052         imagesTotal = 0;
0053         widget      = nullptr;
0054         albumDlg    = nullptr;
0055         talker      = nullptr;
0056     }
0057 
0058     unsigned int   imagesCount;
0059     unsigned int   imagesTotal;
0060 
0061     DBWidget*      widget;
0062     DBNewAlbumDlg* albumDlg;
0063     DBTalker*      talker;
0064 
0065     QString        currentAlbumName;
0066     QList<QUrl>    transferQueue;
0067 };
0068 
0069 DBWindow::DBWindow(DInfoInterface* const iface, QWidget* const /*parent*/)
0070     : WSToolDialog(nullptr, QLatin1String("Dropbox Export Dialog")),
0071       d           (new Private)
0072 {
0073     d->widget   = new DBWidget(this, iface, QLatin1String("Dropbox"));
0074     d->widget->imagesList()->setIface(iface);
0075 
0076     setMainWidget(d->widget);
0077     setModal(false);
0078     setWindowTitle(i18nc("@title:window", "Export to Dropbox"));
0079 
0080     startButton()->setText(i18nc("@action:button", "Start Upload"));
0081     startButton()->setToolTip(i18nc("@info:tooltip, button", "Start upload to Dropbox"));
0082 
0083     d->widget->setMinimumSize(700, 500);
0084 
0085     connect(d->widget->imagesList(), SIGNAL(signalImageListChanged()),
0086             this, SLOT(slotImageListChanged()));
0087 
0088     connect(d->widget->getChangeUserBtn(), SIGNAL(clicked()),
0089             this, SLOT(slotUserChangeRequest()));
0090 
0091     connect(d->widget->getNewAlbmBtn(), SIGNAL(clicked()),
0092             this, SLOT(slotNewAlbumRequest()));
0093 
0094     connect(d->widget->getReloadBtn(), SIGNAL(clicked()),
0095             this, SLOT(slotReloadAlbumsRequest()));
0096 
0097     connect(startButton(), SIGNAL(clicked()),
0098             this, SLOT(slotStartTransfer()));
0099 
0100     d->albumDlg = new DBNewAlbumDlg(this, QLatin1String("Dropbox"));
0101 
0102     d->talker   = new DBTalker(this);
0103 
0104     connect(d->talker, SIGNAL(signalBusy(bool)),
0105             this, SLOT(slotBusy(bool)));
0106 
0107     connect(d->talker, SIGNAL(signalLinkingFailed()),
0108             this, SLOT(slotSignalLinkingFailed()));
0109 
0110     connect(d->talker, SIGNAL(signalLinkingSucceeded()),
0111             this, SLOT(slotSignalLinkingSucceeded()));
0112 
0113     connect(d->talker, SIGNAL(signalSetUserName(QString)),
0114             this, SLOT(slotSetUserName(QString)));
0115 
0116     connect(d->talker, SIGNAL(signalListAlbumsFailed(QString)),
0117             this, SLOT(slotListAlbumsFailed(QString)));
0118 
0119     connect(d->talker, SIGNAL(signalListAlbumsDone(QList<QPair<QString,QString> >)),    // krazy:exclude=normalize
0120             this, SLOT(slotListAlbumsDone(QList<QPair<QString,QString> >)));            // krazy:exclude=normalize
0121 
0122     connect(d->talker, SIGNAL(signalCreateFolderFailed(QString)),
0123             this, SLOT(slotCreateFolderFailed(QString)));
0124 
0125     connect(d->talker, SIGNAL(signalCreateFolderSucceeded()),
0126             this, SLOT(slotCreateFolderSucceeded()));
0127 
0128     connect(d->talker, SIGNAL(signalAddPhotoFailed(QString)),
0129             this, SLOT(slotAddPhotoFailed(QString)));
0130 
0131     connect(d->talker, SIGNAL(signalAddPhotoSucceeded()),
0132             this, SLOT(slotAddPhotoSucceeded()));
0133 
0134     connect(this, SIGNAL(finished(int)),
0135             this, SLOT(slotFinished()));
0136 
0137     readSettings();
0138     buttonStateChange(false);
0139 
0140     d->talker->link();
0141 }
0142 
0143 DBWindow::~DBWindow()
0144 {
0145     delete d->talker;
0146     delete d;
0147 }
0148 
0149 void DBWindow::setItemsList(const QList<QUrl>& urls)
0150 {
0151     d->widget->imagesList()->slotAddImages(urls);
0152 }
0153 
0154 void DBWindow::reactivate()
0155 {
0156     d->widget->imagesList()->loadImagesFromCurrentSelection();
0157     d->widget->progressBar()->hide();
0158 
0159     show();
0160 }
0161 
0162 void DBWindow::readSettings()
0163 {
0164     KSharedConfigPtr config = KSharedConfig::openConfig();
0165     KConfigGroup grp        = config->group(QLatin1String("Dropbox Settings"));
0166     d->currentAlbumName     = grp.readEntry("Current Album", QString());
0167 
0168     if (grp.readEntry("Resize", false))
0169     {
0170         d->widget->getResizeCheckBox()->setChecked(true);
0171         d->widget->getDimensionSpB()->setEnabled(true);
0172     }
0173     else
0174     {
0175         d->widget->getResizeCheckBox()->setChecked(false);
0176         d->widget->getDimensionSpB()->setEnabled(false);
0177     }
0178 
0179     d->widget->getOriginalCheckBox()->setChecked(grp.readEntry("Upload Original", false));
0180     d->widget->getDimensionSpB()->setValue(grp.readEntry("Maximum Width",         1600));
0181     d->widget->getImgQualitySpB()->setValue(grp.readEntry("Image Quality",        90));
0182 }
0183 
0184 void DBWindow::writeSettings()
0185 {
0186     KSharedConfigPtr config = KSharedConfig::openConfig();
0187     KConfigGroup grp        = config->group(QLatin1String("Dropbox Settings"));
0188 
0189     grp.writeEntry("Current Album",   d->currentAlbumName);
0190     grp.writeEntry("Resize",          d->widget->getResizeCheckBox()->isChecked());
0191     grp.writeEntry("Upload Original", d->widget->getOriginalCheckBox()->isChecked());
0192     grp.writeEntry("Maximum Width",   d->widget->getDimensionSpB()->value());
0193     grp.writeEntry("Image Quality",   d->widget->getImgQualitySpB()->value());
0194 }
0195 
0196 void DBWindow::slotSetUserName(const QString& msg)
0197 {
0198     d->widget->updateLabels(msg, QLatin1String(""));
0199 }
0200 
0201 void DBWindow::slotListAlbumsDone(const QList<QPair<QString, QString> >& list)
0202 {
0203     d->widget->getAlbumsCoB()->clear();
0204     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "slotListAlbumsDone:" << list.size();
0205 
0206     for (int i = 0 ; i < list.size() ; ++i)
0207     {
0208         d->widget->getAlbumsCoB()->addItem(
0209         QIcon::fromTheme(QLatin1String("system-users")),
0210         list.value(i).second, list.value(i).first);
0211 
0212         if (d->currentAlbumName == list.value(i).first)
0213         {
0214             d->widget->getAlbumsCoB()->setCurrentIndex(i);
0215         }
0216     }
0217 
0218     buttonStateChange(true);
0219     d->talker->getUserName();
0220 }
0221 
0222 void DBWindow::slotBusy(bool val)
0223 {
0224     if (val)
0225     {
0226         setCursor(Qt::WaitCursor);
0227         d->widget->getChangeUserBtn()->setEnabled(false);
0228         buttonStateChange(false);
0229     }
0230     else
0231     {
0232         setCursor(Qt::ArrowCursor);
0233         d->widget->getChangeUserBtn()->setEnabled(true);
0234         buttonStateChange(true);
0235     }
0236 }
0237 
0238 void DBWindow::slotStartTransfer()
0239 {
0240     d->widget->imagesList()->clearProcessedStatus();
0241 
0242     if (d->widget->imagesList()->imageUrls().isEmpty())
0243     {
0244         QMessageBox::critical(this, i18nc("@title:window", "Error"),
0245                               i18n("No image selected. Please select which images should be uploaded."));
0246         return;
0247     }
0248 
0249     if (!(d->talker->authenticated()))
0250     {
0251         if (QMessageBox::question(this, i18nc("@title:window", "Login Failed"),
0252                                   i18n("Authentication failed. Do you want to try again?"))
0253             == QMessageBox::Yes)
0254         {
0255             d->talker->link();
0256             return;
0257         }
0258         else
0259         {
0260             return;
0261         }
0262     }
0263 
0264     d->transferQueue = d->widget->imagesList()->imageUrls();
0265 
0266     if (d->transferQueue.isEmpty())
0267     {
0268         return;
0269     }
0270 
0271     d->currentAlbumName = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString();
0272 
0273     d->imagesTotal = d->transferQueue.count();
0274     d->imagesCount = 0;
0275 
0276     d->widget->progressBar()->setFormat(i18n("%v / %m"));
0277     d->widget->progressBar()->setMaximum(d->imagesTotal);
0278     d->widget->progressBar()->setValue(0);
0279     d->widget->progressBar()->show();
0280     d->widget->progressBar()->progressScheduled(i18n("Dropbox export"), true, true);
0281     d->widget->progressBar()->progressThumbnailChanged(
0282         QIcon::fromTheme(QLatin1String("dk-dropbox")).pixmap(22, 22));
0283 
0284     uploadNextPhoto();
0285 }
0286 
0287 void DBWindow::uploadNextPhoto()
0288 {
0289     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "uploadNextPhoto:" << d->transferQueue.count();
0290 
0291     if (d->transferQueue.isEmpty())
0292     {
0293         qCDebug(DIGIKAM_WEBSERVICES_LOG) << "empty";
0294         d->widget->progressBar()->progressCompleted();
0295         return;
0296     }
0297 
0298     QString imgPath = d->transferQueue.first().toLocalFile();
0299     QString temp    = d->currentAlbumName + QLatin1Char('/');
0300 
0301     bool res = d->talker->addPhoto(imgPath,
0302                                    temp,
0303                                    d->widget->getOriginalCheckBox()->isChecked(),
0304                                    d->widget->getResizeCheckBox()->isChecked(),
0305                                    d->widget->getDimensionSpB()->value(),
0306                                    d->widget->getImgQualitySpB()->value());
0307 
0308     if (!res)
0309     {
0310         slotAddPhotoFailed(QLatin1String(""));
0311         return;
0312     }
0313 }
0314 
0315 void DBWindow::slotAddPhotoFailed(const QString& msg)
0316 {
0317     if (QMessageBox::question(this, i18nc("@title:window", "Uploading Failed"),
0318                               i18n("Failed to upload photo to Dropbox."
0319                                    "\n%1\n"
0320                                    "Do you want to continue?", msg))
0321         != QMessageBox::Yes)
0322     {
0323         d->transferQueue.clear();
0324         d->widget->progressBar()->hide();
0325     }
0326     else
0327     {
0328         d->transferQueue.removeFirst();
0329         d->imagesTotal--;
0330         d->widget->progressBar()->setMaximum(d->imagesTotal);
0331         d->widget->progressBar()->setValue(d->imagesCount);
0332         uploadNextPhoto();
0333     }
0334 }
0335 
0336 void DBWindow::slotAddPhotoSucceeded()
0337 {
0338     // Remove photo uploaded from the list
0339     d->widget->imagesList()->removeItemByUrl(d->transferQueue.first());
0340     d->transferQueue.removeFirst();
0341     d->imagesCount++;
0342     d->widget->progressBar()->setMaximum(d->imagesTotal);
0343     d->widget->progressBar()->setValue(d->imagesCount);
0344     uploadNextPhoto();
0345 }
0346 
0347 void DBWindow::slotImageListChanged()
0348 {
0349     startButton()->setEnabled(!(d->widget->imagesList()->imageUrls().isEmpty()));
0350 }
0351 
0352 void DBWindow::slotNewAlbumRequest()
0353 {
0354     if (d->albumDlg->exec() == QDialog::Accepted)
0355     {
0356         DBFolder newFolder;
0357         d->albumDlg->getFolderTitle(newFolder);
0358         qCDebug(DIGIKAM_WEBSERVICES_LOG) << "slotNewAlbumRequest:" << newFolder.title;
0359         d->currentAlbumName = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString();
0360         d->currentAlbumName = d->currentAlbumName + newFolder.title;
0361         d->talker->createFolder(d->currentAlbumName);
0362     }
0363 }
0364 
0365 void DBWindow::slotReloadAlbumsRequest()
0366 {
0367     d->talker->listFolders();
0368 }
0369 
0370 void DBWindow::slotSignalLinkingFailed()
0371 {
0372     slotSetUserName(QLatin1String(""));
0373     d->widget->getAlbumsCoB()->clear();
0374 
0375     if (QMessageBox::question(this, i18nc("@title:window", "Login Failed"),
0376                               i18n("Authentication failed. Do you want to try again?"))
0377         == QMessageBox::Yes)
0378     {
0379         d->talker->link();
0380     }
0381 }
0382 
0383 void DBWindow::slotSignalLinkingSucceeded()
0384 {
0385     d->talker->listFolders();
0386 }
0387 
0388 void DBWindow::slotListAlbumsFailed(const QString& msg)
0389 {
0390     QMessageBox::critical(this, QString(), i18n("Dropbox call failed:\n%1", msg));
0391 }
0392 
0393 void DBWindow::slotCreateFolderFailed(const QString& msg)
0394 {
0395     QMessageBox::critical(this, QString(), i18n("Dropbox call failed:\n%1", msg));
0396 }
0397 
0398 void DBWindow::slotCreateFolderSucceeded()
0399 {
0400     d->talker->listFolders();
0401 }
0402 
0403 void DBWindow::slotTransferCancel()
0404 {
0405     d->transferQueue.clear();
0406     d->widget->progressBar()->hide();
0407     d->talker->cancel();
0408 }
0409 
0410 void DBWindow::slotUserChangeRequest()
0411 {
0412     slotSetUserName(QLatin1String(""));
0413     d->widget->getAlbumsCoB()->clear();
0414     d->talker->unLink();
0415     d->talker->link();
0416 }
0417 
0418 void DBWindow::buttonStateChange(bool state)
0419 {
0420     d->widget->getNewAlbmBtn()->setEnabled(state);
0421     d->widget->getReloadBtn()->setEnabled(state);
0422     startButton()->setEnabled(state);
0423 }
0424 
0425 void DBWindow::slotFinished()
0426 {
0427     writeSettings();
0428     d->widget->imagesList()->listView()->clear();
0429 }
0430 
0431 void DBWindow::closeEvent(QCloseEvent* e)
0432 {
0433     if (!e)
0434     {
0435         return;
0436     }
0437 
0438     slotFinished();
0439     e->accept();
0440 }
0441 
0442 } // namespace DigikamGenericDropBoxPlugin
0443 
0444 #include "moc_dbwindow.cpp"