1 /* ============================================================
2  *
3  * This file is a part of KDE project
4  *
5  *
6  * Date        : 2005-17-06
7  * Description : a kipi plugin to import/export images to/from
8  *                SmugMug web service
9  *
10  * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot com>
11  * Copyright (C) 2008-2018 by Gilles Caulier <caulier dot gilles at gmail dot com>
12  * Copyright (C) 2008-2009 by Luka Renko <lure at kubuntu dot org>
13  *
14  * This program is free software; you can redistribute it
15  * and/or modify it under the terms of the GNU General
16  * Public License as published by the Free Software Foundation;
17  * either version 2, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * ============================================================ */
25 
26 #include "smugwindow.h"
27 
28 // Qt includes
29 
30 #include <QWindow>
31 #include <QFileInfo>
32 #include <QPointer>
33 #include <QSpinBox>
34 #include <QCheckBox>
35 #include <QGroupBox>
36 #include <QMenu>
37 #include <QComboBox>
38 #include <QPushButton>
39 #include <QMessageBox>
40 #include <QApplication>
41 
42 // KDE includes
43 
44 #include <kconfig.h>
45 #include <klocalizedstring.h>
46 #include <kwindowconfig.h>
47 
48 // Libkipi includes
49 
50 #include <KIPI/Interface>
51 #include <KIPI/UploadWidget>
52 #include <KIPI/PluginLoader>
53 
54 // Local includes
55 
56 #include "kipiplugins_debug.h"
57 #include "kpimageslist.h"
58 #include "kpaboutdata.h"
59 #include "kpimageinfo.h"
60 #include "kpversion.h"
61 #include "kpprogresswidget.h"
62 #include "smugitem.h"
63 #include "smugtalker.h"
64 #include "smugwidget.h"
65 #include "smugalbum.h"
66 
67 namespace KIPISmugPlugin
68 {
69 
SmugWindow(const QString & tmpFolder,bool import,QWidget * const)70 SmugWindow::SmugWindow(const QString& tmpFolder, bool import, QWidget* const /*parent*/)
71     : KPToolDialog(nullptr)
72 {
73     m_tmpPath.clear();
74     m_tmpDir      = tmpFolder;
75     m_import      = import;
76     m_imagesCount = 0;
77     m_imagesTotal = 0;
78     m_widget      = new SmugWidget(this, iface(), import);
79 
80     setMainWidget(m_widget);
81     setWindowIcon(QIcon::fromTheme(QString::fromLatin1("kipi-smugmug")));
82     setModal(false);
83 
84     if (import)
85     {
86         setWindowTitle(i18n("Import from SmugMug Web Service"));
87 
88         startButton()->setText(i18n("Start Download"));
89         startButton()->setToolTip(i18n("Start download from SmugMug web service"));
90 
91         m_widget->setMinimumSize(300, 400);
92     }
93     else
94     {
95         setWindowTitle(i18n("Export to SmugMug Web Service"));
96 
97         startButton()->setText(i18n("Start Upload"));
98         startButton()->setToolTip(i18n("Start upload to SmugMug web service"));
99 
100         m_widget->setMinimumSize(700, 500);
101     }
102 
103 
104     connect(m_widget, SIGNAL(signalUserChangeRequest(bool)),
105             this, SLOT(slotUserChangeRequest(bool)) );
106 
107     connect(m_widget->m_imgList, SIGNAL(signalImageListChanged()),
108             this, SLOT(slotImageListChanged()) );
109 
110     connect(m_widget->m_reloadAlbumsBtn, SIGNAL(clicked()),
111             this, SLOT(slotReloadAlbumsRequest()) );
112 
113     connect(m_widget->m_newAlbumBtn, SIGNAL(clicked()),
114             this, SLOT(slotNewAlbumRequest()) );
115 
116     connect(startButton(), &QPushButton::clicked,
117             this, &SmugWindow::slotStartTransfer);
118 
119     connect(this, &KPToolDialog::cancelClicked,
120             this, &SmugWindow::slotCancelClicked);
121 
122     connect(this, &QDialog::finished,
123             this, &SmugWindow::slotDialogFinished);
124 
125     // ------------------------------------------------------------------------
126 
127     KPAboutData* const about = new KPAboutData(ki18n("Smug Import/Export"),
128                                    ki18n("A tool to import/export image collections "
129                                          "from/to the SmugMug web service."),
130                                    ki18n("(c) 2005-2008, Vardhman Jain\n"
131                                          "(c) 2008-2012, Gilles Caulier\n"
132                                          "(c) 2008-2009, Luka Renko"));
133 
134     about->addAuthor(ki18n("Luka Renko").toString(),
135                      ki18n("Author and maintainer").toString(),
136                      QString::fromLatin1("lure at kubuntu dot org"));
137 
138     about->setHandbookEntry(QString::fromLatin1("tool-smugexport"));
139     setAboutData(about);
140 
141     // ------------------------------------------------------------------------
142 
143     m_loginDlg  = new KPLoginDialog(this,
144                                     i18n("<qt>Enter the <b>email address</b> and <b>password</b> for your "
145                                          "<a href=\"http://www.smugmug.com\">SmugMug</a> account</qt>"));
146 
147     // ------------------------------------------------------------------------
148 
149     m_albumDlg  = new SmugNewAlbum(this);
150 
151     connect(m_albumDlg->m_categCoB, SIGNAL(currentIndexChanged(int)),
152             this, SLOT(slotCategorySelectionChanged(int)) );
153 
154     connect(m_albumDlg->m_templateCoB, SIGNAL(currentIndexChanged(int)),
155             this, SLOT(slotTemplateSelectionChanged(int)) );
156 
157     // ------------------------------------------------------------------------
158 
159     m_talker = new SmugTalker(this);
160 
161     connect(m_talker, SIGNAL(signalBusy(bool)),
162             this, SLOT(slotBusy(bool)));
163 
164     connect(m_talker, SIGNAL(signalLoginProgress(int,int,QString)),
165             this, SLOT(slotLoginProgress(int,int,QString)));
166 
167     connect(m_talker, SIGNAL(signalLoginDone(int,QString)),
168             this, SLOT(slotLoginDone(int,QString)));
169 
170     connect(m_talker, SIGNAL(signalAddPhotoDone(int,QString)),
171             this, SLOT(slotAddPhotoDone(int,QString)));
172 
173     connect(m_talker, SIGNAL(signalGetPhotoDone(int,QString,QByteArray)),
174             this, SLOT(slotGetPhotoDone(int,QString,QByteArray)));
175 
176     connect(m_talker, SIGNAL(signalCreateAlbumDone(int,QString,qint64,QString)),
177             this, SLOT(slotCreateAlbumDone(int,QString,qint64,QString)));
178 
179     connect(m_talker, SIGNAL(signalListAlbumsDone(int,QString,QList<SmugAlbum>)),
180             this, SLOT(slotListAlbumsDone(int,QString,QList<SmugAlbum>)));
181 
182     connect(m_talker, SIGNAL(signalListPhotosDone(int,QString,QList<SmugPhoto>)),
183             this, SLOT(slotListPhotosDone(int,QString,QList<SmugPhoto>)));
184 
185     connect(m_talker, SIGNAL(signalListAlbumTmplDone(int,QString,QList<SmugAlbumTmpl>)),
186             this, SLOT(slotListAlbumTmplDone(int,QString,QList<SmugAlbumTmpl>)));
187 
188     connect(m_talker, SIGNAL(signalListCategoriesDone(int,QString,QList<SmugCategory>)),
189             this, SLOT(slotListCategoriesDone(int,QString,QList<SmugCategory>)));
190 
191     connect(m_talker, SIGNAL(signalListSubCategoriesDone(int,QString,QList<SmugCategory>)),
192             this, SLOT(slotListSubCategoriesDone(int,QString,QList<SmugCategory>)));
193 
194     connect(m_widget->progressBar(), SIGNAL(signalProgressCanceled()),
195             this, SLOT(slotStopAndCloseProgressBar()));
196 
197     // ------------------------------------------------------------------------
198 
199     readSettings();
200 
201     qCDebug(KIPIPLUGINS_LOG) << "Calling Login method";
202     buttonStateChange(m_talker->loggedIn());
203 
204 
205     if (m_import)
206     {
207         // if no e-mail, switch to anonymous login
208         if (m_anonymousImport || m_email.isEmpty())
209         {
210             m_anonymousImport = true;
211             authenticate();
212         }
213         else
214             authenticate(m_email, m_password);
215         m_widget->setAnonymous(m_anonymousImport);
216     }
217     else
218     {
219         // export cannot login anonymously: pop-up login window`
220         if (m_email.isEmpty())
221             slotUserChangeRequest(false);
222         else
223             authenticate(m_email, m_password);
224     }
225 }
226 
~SmugWindow()227 SmugWindow::~SmugWindow()
228 {
229     delete m_talker;
230 }
231 
closeEvent(QCloseEvent * e)232 void SmugWindow::closeEvent(QCloseEvent* e)
233 {
234     if (!e)
235     {
236         return;
237     }
238 
239     slotDialogFinished();
240     e->accept();
241 }
242 
slotDialogFinished()243 void SmugWindow::slotDialogFinished()
244 {
245     slotCancelClicked();
246 
247     if (m_talker->loggedIn())
248         m_talker->logout();
249 
250     writeSettings();
251     m_widget->imagesList()->listView()->clear();
252 }
253 
setUiInProgressState(bool inProgress)254 void SmugWindow::setUiInProgressState(bool inProgress)
255 {
256     setRejectButtonMode(inProgress ? QDialogButtonBox::Cancel : QDialogButtonBox::Close);
257 
258     if (inProgress)
259     {
260         m_widget->progressBar()->show();
261     }
262     else
263     {
264         m_widget->progressBar()->hide();
265         m_widget->progressBar()->progressCompleted();
266     }
267 }
268 
slotCancelClicked()269 void SmugWindow::slotCancelClicked()
270 {
271     m_talker->cancel();
272     m_transferQueue.clear();
273     m_widget->m_imgList->cancelProcess();
274     setUiInProgressState(false);
275 }
276 
slotStopAndCloseProgressBar()277 void SmugWindow::slotStopAndCloseProgressBar()
278 {
279     slotCancelClicked();
280 
281     writeSettings();
282     m_widget->imagesList()->listView()->clear();
283     reject();
284 }
285 
reactivate()286 void SmugWindow::reactivate()
287 {
288     m_widget->imagesList()->loadImagesFromCurrentSelection();
289     show();
290 }
291 
authenticate(const QString & email,const QString & password)292 void SmugWindow::authenticate(const QString& email, const QString& password)
293 {
294     setUiInProgressState(true);
295     m_widget->progressBar()->setFormat(QString());
296 
297     m_talker->login(email, password);
298 }
299 
readSettings()300 void SmugWindow::readSettings()
301 {
302     KConfig config(QString::fromLatin1("kipirc"));
303     KConfigGroup grp  = config.group("Smug Settings");
304     m_anonymousImport = grp.readEntry("AnonymousImport", true);
305     m_email           = grp.readEntry("Email");
306     m_password        = grp.readEntry("Password");
307     m_currentAlbumID  = grp.readEntry("Current Album", -1);
308     m_currentAlbumKey = grp.readEntry("Current Key", -1);
309 
310     if (grp.readEntry("Resize", false))
311     {
312         m_widget->m_resizeChB->setChecked(true);
313         m_widget->m_dimensionSpB->setEnabled(true);
314         m_widget->m_imageQualitySpB->setEnabled(true);
315     }
316     else
317     {
318         m_widget->m_resizeChB->setChecked(false);
319         m_widget->m_dimensionSpB->setEnabled(false);
320         m_widget->m_imageQualitySpB->setEnabled(false);
321     }
322 
323     m_widget->m_dimensionSpB->setValue(grp.readEntry("Maximum Width", 1600));
324     m_widget->m_imageQualitySpB->setValue(grp.readEntry("Image Quality", 85));
325 
326     if (m_import)
327     {
328         winId();
329         KConfigGroup dialogGroup = config.group("Smug Import Dialog");
330         KWindowConfig::restoreWindowSize(windowHandle(), dialogGroup);
331         resize(windowHandle()->size());
332     }
333     else
334     {
335         winId();
336         KConfigGroup dialogGroup = config.group("Smug Export Dialog");
337         KWindowConfig::restoreWindowSize(windowHandle(), dialogGroup);
338         resize(windowHandle()->size());
339     }
340 }
341 
writeSettings()342 void SmugWindow::writeSettings()
343 {
344     KConfig config(QString::fromLatin1("kipirc"));
345     KConfigGroup grp = config.group("Smug Settings");
346     grp.writeEntry("AnonymousImport", m_anonymousImport);
347     grp.writeEntry("Email",           m_email);
348     grp.writeEntry("Password",        m_password);
349     grp.writeEntry("Current Album",   m_currentAlbumID);
350     grp.writeEntry("Current Key",     m_currentAlbumKey);
351     grp.writeEntry("Resize",          m_widget->m_resizeChB->isChecked());
352     grp.writeEntry("Maximum Width",   m_widget->m_dimensionSpB->value());
353     grp.writeEntry("Image Quality",   m_widget->m_imageQualitySpB->value());
354 
355     if (m_import)
356     {
357         KConfigGroup dialogGroup = config.group("Smug Import Dialog");
358         KWindowConfig::saveWindowSize(windowHandle(), dialogGroup);
359     }
360     else
361     {
362         KConfigGroup dialogGroup = config.group("Smug Export Dialog");
363         KWindowConfig::saveWindowSize(windowHandle(), dialogGroup);
364     }
365 
366     config.sync();
367 }
368 
slotLoginProgress(int step,int maxStep,const QString & label)369 void SmugWindow::slotLoginProgress(int step, int maxStep, const QString &label)
370 {
371     KPProgressWidget* progressBar = m_widget->progressBar();
372 
373     if (!label.isEmpty())
374         progressBar->setFormat(label);
375 
376     if (maxStep > 0)
377         progressBar->setMaximum(maxStep);
378 
379     progressBar->setValue(step);
380 }
381 
slotLoginDone(int errCode,const QString & errMsg)382 void SmugWindow::slotLoginDone(int errCode, const QString &errMsg)
383 {
384     setUiInProgressState(false);
385 
386     buttonStateChange(m_talker->loggedIn());
387     SmugUser user = m_talker->getUser();
388     m_widget->updateLabels(user.email, user.displayName, user.nickName);
389     m_widget->m_albumsCoB->clear();
390 
391     if (errCode == 0 && m_talker->loggedIn())
392     {
393         if (m_import)
394         {
395             m_anonymousImport = m_widget->isAnonymous();
396             // anonymous: list albums after login only if nick is not empty
397             QString nick = m_widget->getNickName();
398 
399             if (!nick.isEmpty() || !m_anonymousImport)
400             {
401                 m_talker->listAlbums(nick);
402             }
403         }
404         else
405         {
406             // get albums from current user
407             m_talker->listAlbums();
408         }
409     }
410     else
411     {
412         QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("SmugMug Call Failed: %1\n", errMsg));
413     }
414 }
415 
slotListAlbumsDone(int errCode,const QString & errMsg,const QList<SmugAlbum> & albumsList)416 void SmugWindow::slotListAlbumsDone(int errCode, const QString &errMsg,
417                                     const QList <SmugAlbum>& albumsList)
418 {
419     if (errCode != 0)
420     {
421         QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("SmugMug Call Failed: %1\n", errMsg));
422         return;
423     }
424 
425     m_widget->m_albumsCoB->clear();
426 
427     for (int i = 0; i < albumsList.size(); ++i)
428     {
429         QString albumIcon;
430 
431         if (!albumsList.at(i).password.isEmpty())
432             albumIcon = QString::fromLatin1("folder-locked");
433         else if (albumsList.at(i).isPublic)
434             albumIcon = QString::fromLatin1("folder-image");
435         else
436             albumIcon = QString::fromLatin1("folder");
437 
438         QString data = QString::fromLatin1("%1:%2").arg(albumsList.at(i).id).arg(albumsList.at(i).key);
439         m_widget->m_albumsCoB->addItem(QIcon::fromTheme(albumIcon), albumsList.at(i).title, data);
440 
441         if (m_currentAlbumID == albumsList.at(i).id)
442             m_widget->m_albumsCoB->setCurrentIndex(i);
443     }
444 }
445 
slotListPhotosDone(int errCode,const QString & errMsg,const QList<SmugPhoto> & photosList)446 void SmugWindow::slotListPhotosDone(int errCode, const QString &errMsg,
447                                     const QList <SmugPhoto>& photosList)
448 {
449     if (errCode != 0)
450     {
451         QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("SmugMug Call Failed: %1\n", errMsg));
452         return;
453     }
454 
455     m_transferQueue.clear();
456 
457     for (int i = 0; i < photosList.size(); ++i)
458     {
459         m_transferQueue.push_back(QUrl::fromLocalFile(photosList.at(i).originalURL));
460     }
461 
462     if (m_transferQueue.isEmpty())
463         return;
464 
465     m_imagesTotal = m_transferQueue.count();
466     m_imagesCount = 0;
467 
468     m_widget->progressBar()->setMaximum(m_imagesTotal);
469     m_widget->progressBar()->setValue(0);
470 
471     // start download with first photo in queue
472     downloadNextPhoto();
473 }
474 
slotListAlbumTmplDone(int errCode,const QString & errMsg,const QList<SmugAlbumTmpl> & albumTList)475 void SmugWindow::slotListAlbumTmplDone(int errCode, const QString &errMsg,
476                                        const QList <SmugAlbumTmpl>& albumTList)
477 {
478     // always put at least default <none> subcategory
479     m_albumDlg->m_templateCoB->clear();
480     m_albumDlg->m_templateCoB->addItem(i18n("&lt;none&gt;"), 0);
481 
482     if (errCode != 0)
483     {
484         QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("SmugMug Call Failed: %1\n", errMsg));
485         return;
486     }
487 
488     for (int i = 0; i < albumTList.size(); ++i)
489     {
490         QString albumIcon;
491 
492         if (!albumTList.at(i).password.isEmpty())
493             albumIcon = QString::fromLatin1("folder-locked");
494         else if (albumTList.at(i).isPublic)
495             albumIcon = QString::fromLatin1("folder-image");
496         else
497             albumIcon = QString::fromLatin1("folder");
498 
499         m_albumDlg->m_templateCoB->addItem(QIcon::fromTheme(albumIcon), albumTList.at(i).name, albumTList.at(i).id);
500 
501         if (m_currentTmplID == albumTList.at(i).id)
502             m_albumDlg->m_templateCoB->setCurrentIndex(i+1);
503     }
504 
505     m_currentTmplID = m_albumDlg->m_templateCoB->itemData(m_albumDlg->m_templateCoB->currentIndex()).toLongLong();
506 
507     // now fill in categories
508     m_talker->listCategories();
509 }
510 
slotListCategoriesDone(int errCode,const QString & errMsg,const QList<SmugCategory> & categoriesList)511 void SmugWindow::slotListCategoriesDone(int errCode, const QString& errMsg,
512                                         const QList <SmugCategory>& categoriesList)
513 {
514     if (errCode != 0)
515     {
516         QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("SmugMug Call Failed: %1\n", errMsg));
517         return;
518     }
519 
520     m_albumDlg->m_categCoB->clear();
521 
522     for (int i = 0; i < categoriesList.size(); ++i)
523     {
524         m_albumDlg->m_categCoB->addItem(
525             categoriesList.at(i).name,
526             categoriesList.at(i).id);
527 
528         if (m_currentCategoryID == categoriesList.at(i).id)
529             m_albumDlg->m_categCoB->setCurrentIndex(i);
530     }
531 
532     m_currentCategoryID = m_albumDlg->m_categCoB->itemData(
533                           m_albumDlg->m_categCoB->currentIndex()).toLongLong();
534     m_talker->listSubCategories(m_currentCategoryID);
535 }
536 
slotListSubCategoriesDone(int errCode,const QString & errMsg,const QList<SmugCategory> & categoriesList)537 void SmugWindow::slotListSubCategoriesDone(int errCode, const QString &errMsg,
538                                               const QList <SmugCategory>& categoriesList)
539 {
540     // always put at least default <none> subcategory
541     m_albumDlg->m_subCategCoB->clear();
542     m_albumDlg->m_subCategCoB->addItem(i18n("&lt;none&gt;"), 0);
543 
544     if (errCode != 0)
545     {
546         QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("SmugMug Call Failed: %1\n", errMsg));
547         return;
548     }
549 
550     for (int i = 0; i < categoriesList.size(); ++i)
551     {
552         m_albumDlg->m_subCategCoB->addItem(
553             categoriesList.at(i).name,
554             categoriesList.at(i).id);
555     }
556 }
557 
slotTemplateSelectionChanged(int index)558 void SmugWindow::slotTemplateSelectionChanged(int index)
559 {
560     if (index < 0)
561         return;
562 
563     m_currentTmplID = m_albumDlg->m_templateCoB->itemData(index).toLongLong();
564 
565     // if template is selected, then disable Security & Privacy
566     m_albumDlg->m_privBox->setEnabled(m_currentTmplID == 0);
567 }
568 
slotCategorySelectionChanged(int index)569 void SmugWindow::slotCategorySelectionChanged(int index)
570 {
571     if (index < 0)
572         return;
573 
574     // subcategories are per category -> reload
575     m_currentCategoryID = m_albumDlg->m_categCoB->itemData(index).toLongLong();
576     m_talker->listSubCategories(m_currentCategoryID);
577 }
578 
buttonStateChange(bool state)579 void SmugWindow::buttonStateChange(bool state)
580 {
581     m_widget->m_newAlbumBtn->setEnabled(state);
582     m_widget->m_reloadAlbumsBtn->setEnabled(state);
583     startButton()->setEnabled(state);
584 }
585 
slotBusy(bool val)586 void SmugWindow::slotBusy(bool val)
587 {
588     if (val)
589     {
590         setCursor(Qt::WaitCursor);
591         m_widget->m_changeUserBtn->setEnabled(false);
592         buttonStateChange(false);
593     }
594     else
595     {
596         setCursor(Qt::ArrowCursor);
597         m_widget->m_changeUserBtn->setEnabled(!m_widget->isAnonymous());
598         buttonStateChange(m_talker->loggedIn());
599     }
600 }
601 
slotUserChangeRequest(bool anonymous)602 void SmugWindow::slotUserChangeRequest(bool anonymous)
603 {
604     qCDebug(KIPIPLUGINS_LOG) << "Slot Change User Request";
605 
606     if (m_talker->loggedIn())
607         m_talker->logout();
608 
609     if (anonymous)
610     {
611         authenticate();
612     }
613     else
614     {
615         // fill in current email and password
616         m_loginDlg->setLogin(m_email);
617         m_loginDlg->setPassword(m_password);
618 
619         if (m_loginDlg->exec())
620         {
621             m_email    = m_loginDlg->login();
622             m_password = m_loginDlg->password();
623             authenticate(m_email, m_password);
624         }
625     }
626 }
627 
slotReloadAlbumsRequest()628 void SmugWindow::slotReloadAlbumsRequest()
629 {
630     if (m_import)
631     {
632         m_talker->listAlbums(m_widget->getNickName());
633     }
634     else
635     {
636         // get albums for current user
637         m_talker->listAlbums();
638     }
639 }
640 
slotNewAlbumRequest()641 void SmugWindow::slotNewAlbumRequest()
642 {
643     qCDebug(KIPIPLUGINS_LOG) << "Slot New Album Request";
644 
645     // get list of album templates from SmugMug to fill in dialog
646     m_talker->listAlbumTmpl();
647 
648     if (m_albumDlg->exec() == QDialog::Accepted)
649     {
650         qCDebug(KIPIPLUGINS_LOG) << "Calling New Album method";
651         m_currentTmplID = m_albumDlg->m_templateCoB->itemData(
652                         m_albumDlg->m_templateCoB->currentIndex()).toLongLong();
653         m_currentCategoryID = m_albumDlg->m_categCoB->itemData(
654                         m_albumDlg->m_categCoB->currentIndex()).toLongLong();
655 
656         SmugAlbum newAlbum;
657         m_albumDlg->getAlbumProperties(newAlbum);
658         m_talker->createAlbum(newAlbum);
659     }
660 }
661 
slotStartTransfer()662 void SmugWindow::slotStartTransfer()
663 {
664     qCDebug(KIPIPLUGINS_LOG) << "slotStartTransfer invoked";
665 
666     if (m_import)
667     {
668         m_widget->progressBar()->setFormat(i18n("%v / %m"));
669         m_widget->progressBar()->setMaximum(0);
670         m_widget->progressBar()->setValue(0);
671         m_widget->progressBar()->progressScheduled(i18n("Smug Import"), true, true);
672         m_widget->progressBar()->progressThumbnailChanged(
673             QIcon(QLatin1String(":/icons/kipi-icon.svg")).pixmap(22, 22));
674         setUiInProgressState(true);
675 
676         // list photos of the album, then start download
677         QString dataStr = m_widget->m_albumsCoB->itemData(m_widget->m_albumsCoB->currentIndex()).toString();
678         int colonIdx = dataStr.indexOf(QLatin1Char(':'));
679         qint64 albumID = dataStr.left(colonIdx).toLongLong();
680         QString albumKey = dataStr.right(dataStr.length() - colonIdx - 1);
681         m_talker->listPhotos(albumID, albumKey,
682                              m_widget->getAlbumPassword(),
683                              m_widget->getSitePassword());
684     }
685     else
686     {
687         m_widget->m_imgList->clearProcessedStatus();
688         m_transferQueue = m_widget->m_imgList->imageUrls();
689 
690         if (m_transferQueue.isEmpty())
691             return;
692 
693         QString data = m_widget->m_albumsCoB->itemData(m_widget->m_albumsCoB->currentIndex()).toString();
694         int colonIdx = data.indexOf(QLatin1Char(':'));
695         m_currentAlbumID = data.left(colonIdx).toLongLong();
696         m_currentAlbumKey = data.right(data.length() - colonIdx - 1);
697 
698         m_imagesTotal = m_transferQueue.count();
699         m_imagesCount = 0;
700 
701         m_widget->progressBar()->setFormat(i18n("%v / %m"));
702         m_widget->progressBar()->setMaximum(m_imagesTotal);
703         m_widget->progressBar()->setValue(0);
704         m_widget->progressBar()->progressScheduled(i18n("Smug Export"), true, true);
705         m_widget->progressBar()->progressThumbnailChanged(QIcon(QLatin1String(":/icons/kipi-icon.svg")).pixmap(22, 22));
706         setUiInProgressState(true);
707 
708         qCDebug(KIPIPLUGINS_LOG) << "m_currentAlbumID" << m_currentAlbumID;
709         uploadNextPhoto();
710         qCDebug(KIPIPLUGINS_LOG) << "slotStartTransfer done";
711     }
712 }
713 
prepareImageForUpload(const QString & imgPath)714 bool SmugWindow::prepareImageForUpload(const QString& imgPath)
715 {
716     QImage image;
717 
718     if (iface())
719     {
720         image = iface()->preview(QUrl::fromLocalFile(imgPath));
721     }
722 
723     if (image.isNull())
724     {
725        image.load(imgPath);
726     }
727 
728     if (image.isNull())
729     {
730         return false;
731     }
732 
733     // get temporary file name
734     m_tmpPath  = m_tmpDir + QFileInfo(imgPath).baseName().trimmed() + QString::fromLatin1(".jpg");
735 
736     // rescale image if requested
737     int maxDim = m_widget->m_dimensionSpB->value();
738 
739     if (m_widget->m_resizeChB->isChecked() &&
740         (image.width() > maxDim || image.height() > maxDim))
741     {
742         qCDebug(KIPIPLUGINS_LOG) << "Resizing to " << maxDim;
743         image = image.scaled(maxDim, maxDim, Qt::KeepAspectRatio,
744                                              Qt::SmoothTransformation);
745     }
746 
747     qCDebug(KIPIPLUGINS_LOG) << "Saving to temp file: " << m_tmpPath;
748     image.save(m_tmpPath, "JPEG", m_widget->m_imageQualitySpB->value());
749 
750     // copy meta-data to temporary image
751     if (iface())
752     {
753         QPointer<MetadataProcessor> meta = iface()->createMetadataProcessor();
754 
755         if (meta && meta->load(QUrl::fromLocalFile(imgPath)))
756         {
757             meta->setImageDimensions(image.size());
758             meta->setImageOrientation(MetadataProcessor::NORMAL);
759             meta->setImageProgramId(QString::fromLatin1("Kipi-plugins"), kipipluginsVersion());
760             meta->save(QUrl::fromLocalFile(m_tmpPath), true);
761         }
762     }
763 
764     return true;
765 }
766 
uploadNextPhoto()767 void SmugWindow::uploadNextPhoto()
768 {
769     if (m_transferQueue.isEmpty())
770     {
771         setUiInProgressState(false);
772         return;
773     }
774 
775     m_widget->m_imgList->processing(m_transferQueue.first());
776 
777     QUrl imgPath = m_transferQueue.first();
778     KPImageInfo info(imgPath);
779 
780     m_widget->progressBar()->setMaximum(m_imagesTotal);
781     m_widget->progressBar()->setValue(m_imagesCount);
782 
783     bool res;
784 
785     if (m_widget->m_resizeChB->isChecked())
786     {
787         if (!prepareImageForUpload(imgPath.toLocalFile()))
788         {
789             slotAddPhotoDone(666, i18n("Cannot open file"));
790             return;
791         }
792 
793         res = m_talker->addPhoto(m_tmpPath, m_currentAlbumID, m_currentAlbumKey, info.description());
794     }
795     else
796     {
797         m_tmpPath.clear();
798         res = m_talker->addPhoto(imgPath.toLocalFile(), m_currentAlbumID, m_currentAlbumKey, info.description());
799     }
800 
801     if (!res)
802     {
803         slotAddPhotoDone(666, i18n("Cannot open file"));
804         return;
805     }
806 }
807 
slotAddPhotoDone(int errCode,const QString & errMsg)808 void SmugWindow::slotAddPhotoDone(int errCode, const QString& errMsg)
809 {
810     // Remove temporary file if it was used
811     if (!m_tmpPath.isEmpty())
812     {
813         QFile::remove(m_tmpPath);
814         m_tmpPath.clear();
815     }
816 
817     m_widget->m_imgList->processed(m_transferQueue.first(), (errCode == 0));
818 
819     if (errCode == 0)
820     {
821         m_transferQueue.pop_front();
822         m_imagesCount++;
823     }
824     else
825     {
826         if (QMessageBox::question(this, i18n("Uploading Failed"),
827                               i18n("Failed to upload photo to SmugMug."
828                                    "\n%1\n"
829                                    "Do you want to continue?", errMsg))
830             != QMessageBox::Yes)
831         {
832             setUiInProgressState(false);
833             m_transferQueue.clear();
834             return;
835         }
836     }
837 
838     uploadNextPhoto();
839 }
840 
downloadNextPhoto()841 void SmugWindow::downloadNextPhoto()
842 {
843     if (m_transferQueue.isEmpty())
844     {
845         setUiInProgressState(false);
846         return;
847     }
848 
849     m_widget->progressBar()->setMaximum(m_imagesTotal);
850     m_widget->progressBar()->setValue(m_imagesCount);
851 
852     QString imgPath = m_transferQueue.first().url();
853 
854     m_talker->getPhoto(imgPath);
855 }
856 
slotGetPhotoDone(int errCode,const QString & errMsg,const QByteArray & photoData)857 void SmugWindow::slotGetPhotoDone(int errCode, const QString& errMsg,
858                                   const QByteArray& photoData)
859 {
860     QString imgPath = m_widget->getDestinationPath() + QLatin1Char('/')
861                       + m_transferQueue.first().fileName();
862 
863     if (errCode == 0)
864     {
865         QString errText;
866         QFile imgFile(imgPath);
867 
868         if (!imgFile.open(QIODevice::WriteOnly))
869         {
870             errText = imgFile.errorString();
871         }
872         else if (imgFile.write(photoData) != photoData.size())
873         {
874             errText = imgFile.errorString();
875         }
876         else
877         {
878             imgFile.close();
879         }
880 
881         if (errText.isEmpty())
882         {
883             m_transferQueue.pop_front();
884             m_imagesCount++;
885         }
886         else
887         {
888             if (QMessageBox::question(this, i18n("Processing Failed"),
889                                       i18n("Failed to save photo: %1\n"
890                                            "Do you want to continue?", errText))
891                 != QMessageBox::Yes)
892             {
893                 m_transferQueue.clear();
894                 setUiInProgressState(false);
895                 return;
896             }
897         }
898     }
899     else
900     {
901         if (QMessageBox::question(this, i18n("Processing Failed"),
902                                   i18n("Failed to download photo: %1\n"
903                                        "Do you want to continue?", errMsg))
904                 != QMessageBox::Yes)
905         {
906             m_transferQueue.clear();
907             setUiInProgressState(false);
908             return;
909         }
910     }
911 
912     downloadNextPhoto();
913 }
914 
slotCreateAlbumDone(int errCode,const QString & errMsg,qint64 newAlbumID,const QString & newAlbumKey)915 void SmugWindow::slotCreateAlbumDone(int errCode, const QString& errMsg,
916                                      qint64 newAlbumID, const QString& newAlbumKey)
917 {
918     if (errCode != 0)
919     {
920         QMessageBox::critical(QApplication::activeWindow(), i18n("Error"), i18n("SmugMug Call Failed: %1\n", errMsg));
921         return;
922     }
923 
924     // reload album list and automatically select new album
925     m_currentAlbumID  = newAlbumID;
926     m_currentAlbumKey = newAlbumKey;
927     m_talker->listAlbums();
928 }
929 
slotImageListChanged()930 void SmugWindow::slotImageListChanged()
931 {
932     startButton()->setEnabled(!(m_widget->m_imgList->imageUrls().isEmpty()));
933 }
934 
935 } // namespace KIPISmugPlugin
936