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

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2012-02-02
0007  * Description : a tool to export items to ImageShack web service
0008  *
0009  * SPDX-FileCopyrightText: 2012      by Dodon Victor <dodonvictor at gmail dot com>
0010  * SPDX-FileCopyrightText: 2013-2018 by Caulier Gilles <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "imageshackwindow.h"
0017 
0018 // Qt includes
0019 
0020 #include <QWindow>
0021 #include <QButtonGroup>
0022 #include <QCheckBox>
0023 #include <QCloseEvent>
0024 #include <QDialog>
0025 #include <QFileInfo>
0026 #include <QGridLayout>
0027 #include <QHBoxLayout>
0028 #include <QLineEdit>
0029 #include <QPointer>
0030 #include <QPushButton>
0031 #include <QRadioButton>
0032 #include <QSpinBox>
0033 #include <QVBoxLayout>
0034 #include <QApplication>
0035 #include <QIcon>
0036 #include <QMenu>
0037 #include <QComboBox>
0038 #include <QMessageBox>
0039 #include <QTimer>
0040 
0041 // KDE includes
0042 
0043 #include <klocalizedstring.h>
0044 #include <ksharedconfig.h>
0045 #include <kconfiggroup.h>
0046 
0047 // Local includes
0048 
0049 #include "digikam_debug.h"
0050 #include "imageshacksession.h"
0051 #include "imageshackwidget_p.h"
0052 #include "imageshacktalker.h"
0053 #include "dprogresswdg.h"
0054 #include "wslogindialog.h"
0055 #include "imageshacknewalbumdlg.h"
0056 
0057 namespace DigikamGenericImageShackPlugin
0058 {
0059 
0060 class Q_DECL_HIDDEN ImageShackWindow::Private
0061 {
0062 public:
0063 
0064     explicit Private()
0065     {
0066         imagesCount = 0;
0067         imagesTotal = 0;
0068         session     = nullptr;
0069         widget      = nullptr;
0070         talker      = nullptr;
0071         albumDlg    = nullptr;
0072         iface       = nullptr;
0073     }
0074 
0075     unsigned int           imagesCount;
0076     unsigned int           imagesTotal;
0077     QString                newAlbmTitle;
0078 
0079     QList<QUrl>            transferQueue;
0080 
0081     ImageShackSession*     session;
0082     ImageShackWidget*      widget;
0083     ImageShackTalker*      talker;
0084 
0085     ImageShackNewAlbumDlg* albumDlg;
0086 
0087     DInfoInterface*        iface;
0088 };
0089 
0090 ImageShackWindow::ImageShackWindow(DInfoInterface* const iface,
0091                                    QWidget* const /*parent*/)
0092     : WSToolDialog(nullptr, QLatin1String("ImageShack Dialog")),
0093       d(new Private)
0094 {
0095     d->session = new ImageShackSession();
0096     d->iface   = iface;
0097     d->widget  = new ImageShackWidget(this,
0098                                       d->session,
0099                                       d->iface,
0100                                       QLatin1String("ImageShack"));
0101     d->widget->setMinimumSize(700, 500);
0102 
0103     setMainWidget(d->widget);
0104     setWindowTitle(i18nc("@title:window", "Export to ImageShack"));
0105     setModal(false);
0106 
0107     d->albumDlg = new ImageShackNewAlbumDlg(this, QLatin1String("ImageShack"));
0108 
0109     connect(d->widget->d->chgRegCodeBtn, SIGNAL(clicked(bool)),
0110             this, SLOT(slotChangeRegistrantionCode()));
0111 
0112     startButton()->setText(i18nc("@action:button", "Upload"));
0113     startButton()->setToolTip(i18nc("@info:tooltip, button", "Start upload to ImageShack web service"));
0114     startButton()->setEnabled(false);
0115 
0116     connect(d->widget->d->imgList, SIGNAL(signalImageListChanged()),
0117             this, SLOT(slotImageListChanged()));
0118 
0119     // -----------------------------------------------------------
0120 
0121     connect(this, SIGNAL(signalBusy(bool)),
0122             this, SLOT(slotBusy(bool)));
0123 
0124     d->talker = new ImageShackTalker(d->session);
0125 
0126     connect(d->talker, SIGNAL(signalBusy(bool)),
0127             this, SLOT(slotBusy(bool)));
0128 
0129     connect(d->talker, SIGNAL(signalJobInProgress(int,int,QString)),
0130             this, SLOT(slotJobInProgress(int,int,QString)));
0131 
0132     connect(d->talker, SIGNAL(signalLoginDone(int,QString)),
0133             this, SLOT(slotLoginDone(int,QString)));
0134 
0135     connect(d->talker, SIGNAL(signalGetGalleriesDone(int,QString)),
0136             this, SLOT(slotGetGalleriesDone(int,QString)));
0137 
0138     connect(d->talker, SIGNAL(signalUpdateGalleries(QStringList,QStringList)),
0139             d->widget, SLOT(slotGetGalleries(QStringList,QStringList)));
0140 
0141     connect(d->talker, SIGNAL(signalAddPhotoDone(int,QString)),
0142             this, SLOT(slotAddPhotoDone(int,QString)));
0143 
0144     connect(d->widget, SIGNAL(signalReloadGalleries()),
0145             this, SLOT(slotGetGalleries()));
0146 
0147     connect(startButton(), SIGNAL(clicked()),
0148             this, SLOT(slotStartTransfer()));
0149 
0150     connect(this, SIGNAL(finished(int)),
0151             this, SLOT(slotFinished()));
0152 
0153     connect(this, SIGNAL(cancelClicked()),
0154             this, SLOT(slotCancelClicked()));
0155 
0156     connect(d->widget->getNewAlbmBtn(), SIGNAL(clicked()),
0157             this, SLOT(slotNewAlbumRequest()));
0158 
0159     readSettings();
0160 
0161     QTimer::singleShot(20, this, SLOT(authenticate()));
0162 }
0163 
0164 ImageShackWindow::~ImageShackWindow()
0165 {
0166     delete d->session;
0167     delete d;
0168 }
0169 
0170 void ImageShackWindow::slotImageListChanged()
0171 {
0172     startButton()->setEnabled(!d->widget->d->imgList->imageUrls().isEmpty());
0173 }
0174 
0175 void ImageShackWindow::slotFinished()
0176 {
0177     saveSettings();
0178     d->widget->d->progressBar->progressCompleted();
0179     d->widget->d->imgList->listView()->clear();
0180 }
0181 
0182 void ImageShackWindow::closeEvent(QCloseEvent* e)
0183 {
0184     if (!e)
0185     {
0186         return;
0187     }
0188 
0189     slotFinished();
0190     e->accept();
0191 }
0192 
0193 void ImageShackWindow::readSettings()
0194 {
0195     KSharedConfigPtr config = KSharedConfig::openConfig();
0196     KConfigGroup group      = config->group(QLatin1String("ImageShack Settings"));
0197 
0198     if (group.readEntry("Private", false))
0199     {
0200         d->widget->d->privateImagesChb->setChecked(true);
0201     }
0202 
0203     if (group.readEntry("Rembar", false))
0204     {
0205         d->widget->d->remBarChb->setChecked(true);
0206     }
0207     else
0208     {
0209         d->widget->d->remBarChb->setChecked(false);
0210     }
0211 }
0212 
0213 void ImageShackWindow::saveSettings()
0214 {
0215     KSharedConfigPtr config = KSharedConfig::openConfig();
0216     KConfigGroup group      = config->group(QLatin1String("ImageShack Settings"));
0217 
0218     group.writeEntry("Private", d->widget->d->privateImagesChb->isChecked());
0219     group.writeEntry("Rembar",  d->widget->d->remBarChb->isChecked());
0220 }
0221 
0222 void ImageShackWindow::slotStartTransfer()
0223 {
0224     d->widget->d->imgList->clearProcessedStatus();
0225     d->transferQueue = d->widget->d->imgList->imageUrls();
0226 
0227     if (d->transferQueue.isEmpty())
0228     {
0229         return;
0230     }
0231 
0232     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Transfer started!";
0233 
0234     d->imagesTotal = d->transferQueue.count();
0235     d->imagesCount = 0;
0236 
0237     d->widget->d->progressBar->setFormat(i18n("%v / %m"));
0238     d->widget->d->progressBar->setMaximum(d->imagesTotal);
0239     d->widget->d->progressBar->setValue(0);
0240     d->widget->d->progressBar->setVisible(true);
0241     d->widget->d->progressBar->progressScheduled(i18n("Image Shack Export"), false, true);
0242     d->widget->d->progressBar->progressThumbnailChanged(
0243         QIcon::fromTheme(QLatin1String("dk-imageshack")).pixmap(22, 22));
0244 
0245     uploadNextItem();
0246 }
0247 
0248 void ImageShackWindow::slotCancelClicked()
0249 {
0250     d->talker->cancel();
0251     d->transferQueue.clear();
0252     d->widget->d->imgList->cancelProcess();
0253     d->widget->d->progressBar->setVisible(false);
0254     d->widget->d->progressBar->progressCompleted();
0255 }
0256 
0257 void ImageShackWindow::slotChangeRegistrantionCode()
0258 {
0259     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Change registration code";
0260     authenticate();
0261 }
0262 
0263 void ImageShackWindow::authenticate()
0264 {
0265     Q_EMIT signalBusy(true);
0266     d->widget->progressBar()->show();
0267     d->widget->d->progressBar->setValue(0);
0268     d->widget->d->progressBar->setMaximum(4);
0269     d->widget->progressBar()->setFormat(i18n("Authenticating..."));
0270 
0271     WSLoginDialog* const dlg = new WSLoginDialog(this, QLatin1String("ImageShack"));
0272 
0273     if (dlg->exec() == QDialog::Accepted)
0274     {
0275         d->session->setEmail(dlg->login());
0276         d->session->setPassword(dlg->password());
0277         d->talker->authenticate();
0278     }
0279 }
0280 
0281 void ImageShackWindow::slotBusy(bool val)
0282 {
0283     if (val)
0284     {
0285         setCursor(Qt::WaitCursor);
0286         d->widget->d->chgRegCodeBtn->setEnabled(false);
0287         startButton()->setEnabled(false);
0288         setRejectButtonMode(QDialogButtonBox::Cancel);
0289     }
0290     else
0291     {
0292         setCursor(Qt::ArrowCursor);
0293         d->widget->d->chgRegCodeBtn->setEnabled(true);
0294         startButton()->setEnabled(d->session->loggedIn() &&
0295                                   !d->widget->imagesList()->imageUrls().isEmpty());
0296         setRejectButtonMode(QDialogButtonBox::Close);
0297     }
0298 }
0299 
0300 void ImageShackWindow::slotJobInProgress(int step, int maxStep, const QString& format)
0301 {
0302     if (maxStep > 0)
0303     {
0304         d->widget->d->progressBar->setMaximum(maxStep);
0305     }
0306 
0307     d->widget->d->progressBar->setValue(step);
0308 
0309     if (!format.isEmpty())
0310     {
0311         d->widget->d->progressBar->setFormat(format);
0312     }
0313 }
0314 
0315 void ImageShackWindow::slotLoginDone(int errCode, const QString& errMsg)
0316 {
0317     d->widget->updateLabels();
0318 
0319     if (!errCode && d->session->loggedIn())
0320     {
0321         d->session->saveSettings();
0322         startButton()->setEnabled(!d->widget->imagesList()->imageUrls().isEmpty());
0323         d->talker->getGalleries();
0324     }
0325     else
0326     {
0327         QMessageBox::critical(this, QString(), i18n("Login failed: %1\n", errMsg));
0328         startButton()->setEnabled(false);
0329         d->widget->d->progressBar->setVisible(false);
0330         slotBusy(false);
0331     }
0332 }
0333 
0334 void ImageShackWindow::slotGetGalleriesDone(int errCode, const QString& errMsg)
0335 {
0336     slotBusy(false);
0337     d->widget->d->progressBar->setVisible(false);
0338 
0339     if (errCode)
0340     {
0341         QMessageBox::critical(this, QString(), i18n("Failed to get galleries list: %1\n", errMsg));
0342     }
0343 }
0344 
0345 void ImageShackWindow::uploadNextItem()
0346 {
0347     if (d->transferQueue.isEmpty())
0348     {
0349         d->widget->d->progressBar->hide();
0350         return;
0351     }
0352 
0353     d->widget->d->imgList->processing(d->transferQueue.first());
0354     QString imgPath = d->transferQueue.first().toLocalFile();
0355 
0356     d->widget->d->progressBar->setMaximum(d->imagesTotal);
0357     d->widget->d->progressBar->setValue(d->imagesCount);
0358 
0359     QMap<QString, QString> opts;
0360 
0361     if (d->widget->d->privateImagesChb->isChecked())
0362     {
0363         opts[QLatin1String("public")] = QLatin1String("no");
0364     }
0365 
0366     if (d->widget->d->remBarChb->isChecked())
0367     {
0368         opts[QLatin1String("rembar")] = QLatin1String("yes");
0369     }
0370 
0371     // tags
0372     if (!d->widget->d->tagsFld->text().isEmpty())
0373     {
0374         QString str = d->widget->d->tagsFld->text();
0375         QStringList tagsList;
0376         tagsList = str.split(QRegularExpression(QLatin1String("\\W+")), QT_SKIP_EMPTY_PARTS);
0377         opts[QLatin1String("tags")] = tagsList.join(QLatin1Char(','));
0378     }
0379 
0380     opts[QLatin1String("auth_token")] = d->session->authToken();
0381 
0382     int gidx = d->widget->d->galleriesCob->currentIndex();
0383 
0384     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Album ID is "<< d->widget->d->galleriesCob->itemData(gidx).toString();
0385 
0386     switch (gidx)
0387     {
0388         case 0:
0389             d->talker->uploadItem(imgPath, opts);
0390             break;
0391         case 1:
0392             opts[QLatin1String("album")] = d->newAlbmTitle;
0393             d->talker->uploadItemToGallery(imgPath, d->newAlbmTitle, opts);
0394             break;
0395         default:
0396             opts[QLatin1String("album")] = d->widget->d->galleriesCob->itemData(gidx).toString();
0397             d->talker->uploadItemToGallery(imgPath, d->widget->d->galleriesCob->itemData(gidx).toString(), opts);
0398     }
0399 }
0400 
0401 void ImageShackWindow::slotAddPhotoDone(int errCode, const QString& errMsg)
0402 {
0403     d->widget->d->imgList->processed(d->transferQueue.first(), (errCode == 0));
0404 
0405     if (!errCode)
0406     {
0407         d->widget->imagesList()->removeItemByUrl(d->transferQueue.first());
0408         d->transferQueue.removeFirst();
0409         d->imagesCount++;
0410     }
0411     else
0412     {
0413         if (QMessageBox::question(this, i18nc("@title:window", "Uploading Failed"),
0414                                   i18n("Failed to upload photo into ImageShack: %1\n"
0415                                        "Do you want to continue?", errMsg))
0416             != QMessageBox::Yes)
0417         {
0418             d->widget->d->progressBar->setVisible(false);
0419             d->transferQueue.clear();
0420             return;
0421         }
0422     }
0423 
0424     uploadNextItem();
0425 }
0426 
0427 void ImageShackWindow::slotGetGalleries()
0428 {
0429     d->widget->d->progressBar->setVisible(true);
0430     d->talker->getGalleries();
0431 }
0432 
0433 void ImageShackWindow::slotNewAlbumRequest()
0434 {
0435     if (d->albumDlg->exec() == QDialog::Accepted)
0436     {
0437         d->newAlbmTitle = d->albumDlg->getAlbumTitle();
0438     }
0439 }
0440 
0441 } // namespace DigikamGenericImageShackPlugin
0442 
0443 #include "moc_imageshackwindow.cpp"