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("<none>"), 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("<none>"), 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