File indexing completed on 2025-01-19 03:53:09

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