1 /* ============================================================
2 *
3 * This file is a part of KDE project
4 *
5 *
6 * Date : 2005-17-26
7 * Description : a kipi plugin to export images to Facebook web service
8 *
9 * Copyright (C) 2005-2008 by Vardhman Jain <vardhman at gmail dot com>
10 * Copyright (C) 2008-2018 by Gilles Caulier <caulier dot gilles at gmail dot com>
11 * Copyright (C) 2008-2009 by Luka Renko <lure at kubuntu dot org>
12 *
13 * This program is free software; you can redistribute it
14 * and/or modify it under the terms of the GNU General
15 * Public License as published by the Free Software Foundation;
16 * either version 2, or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * ============================================================ */
24
25 #include "fbwindow.h"
26
27 // Qt includes
28
29 #include <QWindow>
30 #include <QComboBox>
31 #include <QMenu>
32 #include <QFileInfo>
33 #include <QCheckBox>
34 #include <QCloseEvent>
35 #include <QSpinBox>
36 #include <QMessageBox>
37 #include <QPointer>
38
39 // KDE includes
40
41 #include <kconfig.h>
42 #include <klocalizedstring.h>
43 #include <kwindowconfig.h>
44
45 // Libkipi includes
46
47 #include <KIPI/Interface>
48
49 // Local includes
50
51 #include "kipiplugins_debug.h"
52 #include "kpimageslist.h"
53 #include "kpaboutdata.h"
54 #include "kpimageinfo.h"
55 #include "kpversion.h"
56 #include "kpprogresswidget.h"
57 #include "fbitem.h"
58 #include "fbtalker.h"
59 #include "fbwidget.h"
60 #include "fbalbum.h"
61
62 namespace KIPIFacebookPlugin
63 {
64
65 class FbWindow::Private
66 {
67 public:
68
Private(QWidget * const widget,KIPI::Interface * const iface)69 Private(QWidget* const widget, KIPI::Interface* const iface)
70 {
71 m_widget = new FbWidget(widget, iface, QString::fromLatin1("Facebook"));
72 m_imgList = m_widget->imagesList();
73 m_progressBar = m_widget->progressBar();
74 m_changeUserBtn = m_widget->getChangeUserBtn();
75 m_albumsCoB = m_widget->getAlbumsCoB();
76 m_newAlbumBtn = m_widget->getNewAlbmBtn();
77 m_reloadAlbumsBtn = m_widget->getReloadBtn();
78 m_resizeChB = m_widget->getResizeCheckBox();
79 m_dimensionSpB = m_widget->getDimensionSpB();
80 m_imageQualitySpB = m_widget->getImgQualitySpB();
81 }
82
83 FbWidget* m_widget;
84 KPImagesList* m_imgList;
85 QPushButton* m_changeUserBtn;
86 QComboBox* m_albumsCoB;
87 QPushButton* m_newAlbumBtn;
88 QPushButton* m_reloadAlbumsBtn;
89 QCheckBox* m_resizeChB;
90 QSpinBox* m_dimensionSpB;
91 QSpinBox* m_imageQualitySpB;
92 KPProgressWidget* m_progressBar;
93 };
94
95
FbWindow(const QString & tmpFolder,QWidget * const)96 FbWindow::FbWindow(const QString& tmpFolder, QWidget* const /*parent*/)
97 : KPToolDialog(nullptr),
98 d(new Private(this, iface()))
99 {
100 m_tmpPath.clear();
101 m_tmpDir = tmpFolder;
102 m_imagesCount = 0;
103 m_imagesTotal = 0;
104
105 setMainWidget(d->m_widget);
106 setWindowIcon(QIcon::fromTheme(QString::fromLatin1("kipi-facebook")));
107 setModal(false);
108
109 setWindowTitle(i18n("Export to Facebook Web Service"));
110
111 startButton()->setText(i18n("Start Upload"));
112 startButton()->setToolTip(i18n("Start upload to Facebook web service"));
113
114 d->m_widget->setMinimumSize(700, 500);
115 // ------------------------------------------------------------------------
116
117 connect(d->m_imgList, SIGNAL(signalImageListChanged()),
118 this, SLOT(slotImageListChanged()));
119
120 connect(d->m_changeUserBtn, SIGNAL(clicked()),
121 this, SLOT(slotUserChangeRequest()));
122
123 connect(d->m_newAlbumBtn, SIGNAL(clicked()),
124 this, SLOT(slotNewAlbumRequest()));
125
126 connect(d->m_widget, SIGNAL(reloadAlbums(long long)),
127 this, SLOT(slotReloadAlbumsRequest(long long)));
128
129 connect(startButton(), SIGNAL(clicked()),
130 this, SLOT(slotStartTransfer()));
131
132 connect(this, SIGNAL(finished(int)),
133 this, SLOT(slotFinished()));
134
135 connect(this, SIGNAL(cancelClicked()),
136 this, SLOT(slotCancelClicked()));
137
138 // ------------------------------------------------------------------------
139
140 KPAboutData* about = new KPAboutData(ki18n("Facebook Export"),
141 ki18n("A tool to export image collection "
142 "to/from Facebook web service."),
143 ki18n("(c) 2005-2008, Vardhman Jain\n"
144 "(c) 2008-2012, Gilles Caulier\n"
145 "(c) 2008-2009, Luka Renko"));
146
147 about->addAuthor(ki18n("Luka Renko").toString(),
148 ki18n("Author and maintainer").toString(),
149 QString::fromLatin1("lure at kubuntu dot org"));
150
151 about->setHandbookEntry(QString::fromLatin1("tool-facebookexport"));
152 setAboutData(about);
153
154 // ------------------------------------------------------------------------
155
156 m_albumDlg = new FbNewAlbum(this, QString::fromLatin1("Facebook"));
157
158 // ------------------------------------------------------------------------
159
160 m_talker = new FbTalker(this);
161
162 connect(m_talker, SIGNAL(signalBusy(bool)),
163 this, SLOT(slotBusy(bool)));
164
165 connect(m_talker, SIGNAL(signalLoginProgress(int,int,QString)),
166 this, SLOT(slotLoginProgress(int,int,QString)));
167
168 connect(m_talker, SIGNAL(signalLoginDone(int,QString)),
169 this, SLOT(slotLoginDone(int,QString)));
170
171 connect(m_talker, SIGNAL(signalAddPhotoDone(int,QString)),
172 this, SLOT(slotAddPhotoDone(int,QString)));
173
174 connect(m_talker, SIGNAL(signalCreateAlbumDone(int,QString,QString)),
175 this, SLOT(slotCreateAlbumDone(int,QString,QString)));
176
177 connect(m_talker, SIGNAL(signalListAlbumsDone(int,QString,QList<FbAlbum>)),
178 this, SLOT(slotListAlbumsDone(int,QString,QList<FbAlbum>)));
179
180 connect(d->m_progressBar, SIGNAL(signalProgressCanceled()),
181 this, SLOT(slotStopAndCloseProgressBar()));
182
183 // ------------------------------------------------------------------------
184
185 readSettings();
186
187 qCDebug(KIPIPLUGINS_LOG) << "Calling Login method";
188 buttonStateChange(m_talker->loggedIn());
189 authenticate();
190 }
191
~FbWindow()192 FbWindow::~FbWindow()
193 {
194 delete m_albumDlg;
195 delete m_talker;
196 delete d;
197 }
198
slotStopAndCloseProgressBar()199 void FbWindow::slotStopAndCloseProgressBar()
200 {
201 // Cancel the operation
202 slotCancelClicked();
203
204 // Write settings and tidy up
205 slotFinished();
206
207 // Close the dialog
208 reject();
209 }
210
slotFinished()211 void FbWindow::slotFinished()
212 {
213 writeSettings();
214 d->m_imgList->listView()->clear();
215 d->m_progressBar->progressCompleted();
216 }
217
slotCancelClicked()218 void FbWindow::slotCancelClicked()
219 {
220 setRejectButtonMode(QDialogButtonBox::Close);
221 m_talker->cancel();
222 m_transferQueue.clear();
223 d->m_imgList->cancelProcess();
224 d->m_progressBar->hide();
225 d->m_progressBar->progressCompleted();
226 }
227
reactivate()228 void FbWindow::reactivate()
229 {
230 d->m_imgList->loadImagesFromCurrentSelection();
231 show();
232 }
233
closeEvent(QCloseEvent * e)234 void FbWindow::closeEvent(QCloseEvent* e)
235 {
236 if (!e)
237 {
238 return;
239 }
240
241 slotFinished();
242 e->accept();
243 }
244
readSettings()245 void FbWindow::readSettings()
246 {
247 KConfig config(QString::fromLatin1("kipirc"));
248 KConfigGroup grp = config.group("Facebook Settings");
249 m_accessToken = grp.readEntry("Access Token");
250 m_sessionExpires = grp.readEntry("Session Expires", 0);
251
252 if (m_accessToken.isEmpty())
253 {
254 m_sessionKey = grp.readEntry("Session Key");
255 m_sessionSecret = grp.readEntry("Session Secret");
256 }
257
258 m_currentAlbumID = grp.readEntry("Current Album", QString());
259
260 if (grp.readEntry("Resize", false))
261 {
262 d->m_resizeChB->setChecked(true);
263 d->m_dimensionSpB->setEnabled(true);
264 d->m_imageQualitySpB->setEnabled(true);
265 }
266 else
267 {
268 d->m_resizeChB->setChecked(false);
269 d->m_dimensionSpB->setEnabled(false);
270 d->m_imageQualitySpB->setEnabled(false);
271 }
272
273 d->m_dimensionSpB->setValue(grp.readEntry("Maximum Width", 604));
274 d->m_imageQualitySpB->setValue(grp.readEntry("Image Quality", 85));
275
276 winId();
277 KConfigGroup dialogGroup = config.group("Facebook Export Dialog");
278 KWindowConfig::restoreWindowSize(windowHandle(), dialogGroup);
279 resize(windowHandle()->size());
280 }
281
writeSettings()282 void FbWindow::writeSettings()
283 {
284 KConfig config(QString::fromLatin1("kipirc"));
285 KConfigGroup grp = config.group("Facebook Settings");
286 grp.writeEntry("Access Token", m_accessToken);
287
288 /* If we have both access token and session key, then we have just converted one into the other. */
289 if (! m_accessToken.isEmpty())
290 {
291 if (! m_sessionKey.isEmpty())
292 {
293 grp.deleteEntry("Session Key");
294 }
295
296 if (! m_sessionSecret.isEmpty())
297 {
298 grp.deleteEntry("Session Secret");
299 }
300 }
301
302 grp.writeEntry("Session Expires", m_sessionExpires);
303 grp.writeEntry("Current Album", m_currentAlbumID);
304 grp.writeEntry("Resize", d->m_resizeChB->isChecked());
305 grp.writeEntry("Maximum Width", d->m_dimensionSpB->value());
306 grp.writeEntry("Image Quality", d->m_imageQualitySpB->value());
307
308 KConfigGroup dialogGroup = config.group("Facebook Export Dialog");
309 KWindowConfig::saveWindowSize(windowHandle(), dialogGroup);
310
311 config.sync();
312 }
313
authenticate()314 void FbWindow::authenticate()
315 {
316 setRejectButtonMode(QDialogButtonBox::Cancel);
317 d->m_progressBar->show();
318 d->m_progressBar->setFormat(QString::fromLatin1(""));
319
320 // Converting old world session keys into OAuth2 tokens
321 if (! m_sessionKey.isEmpty() && m_accessToken.isEmpty())
322 {
323 qCDebug(KIPIPLUGINS_LOG) << "Exchanging session tokens to OAuth";
324 m_talker->exchangeSession(m_sessionKey);
325 }
326 else
327 {
328 qCDebug(KIPIPLUGINS_LOG) << "Calling Login method";
329 m_talker->authenticate(m_accessToken, m_sessionExpires);
330 }
331 }
332
slotLoginProgress(int step,int maxStep,const QString & label)333 void FbWindow::slotLoginProgress(int step, int maxStep, const QString& label)
334 {
335 KIPIPlugins::KPProgressWidget* const progressBar = d->m_progressBar;
336
337 if (!label.isEmpty())
338 {
339 progressBar->setFormat(label);
340 }
341
342 if (maxStep > 0)
343 {
344 progressBar->setMaximum(maxStep);
345 }
346
347 progressBar->setValue(step);
348 }
349
slotLoginDone(int errCode,const QString & errMsg)350 void FbWindow::slotLoginDone(int errCode, const QString& errMsg)
351 {
352 setRejectButtonMode(QDialogButtonBox::Close);
353 d->m_progressBar->hide();
354
355 buttonStateChange(m_talker->loggedIn());
356 FbUser user = m_talker->getUser();
357 setProfileAID(user.id);
358 d->m_widget->updateLabels(user.name, user.profileURL);
359 d->m_albumsCoB->clear();
360
361 d->m_albumsCoB->addItem(i18n("<auto create>"), QString());
362
363 m_accessToken = m_talker->getAccessToken();
364 m_sessionExpires = m_talker->getSessionExpires();
365
366 if (errCode == 0 && m_talker->loggedIn())
367 {
368 m_talker->listAlbums(); // get albums to fill combo box
369 }
370 else
371 {
372 QMessageBox::critical(this, QString(), i18n("Facebook Call Failed: %1\n", errMsg));
373 }
374 }
375
slotListAlbumsDone(int errCode,const QString & errMsg,const QList<FbAlbum> & albumsList)376 void FbWindow::slotListAlbumsDone(int errCode, const QString& errMsg, const QList<FbAlbum>& albumsList)
377 {
378
379 QString albumDebug = QString::fromLatin1("");
380 foreach(const FbAlbum &album, albumsList)
381 {
382 albumDebug.append(QString::fromLatin1("%1: %2\n").arg(album.id).arg(album.title));
383 }
384
385 qCDebug(KIPIPLUGINS_LOG) << "Received albums (errCode = " << errCode << ", errMsg = "
386 << errMsg << "): " << albumDebug;
387
388 if (errCode != 0)
389 {
390 QMessageBox::critical(this, QString(), i18n("Facebook Call Failed: %1\n", errMsg));
391 return;
392 }
393
394 d->m_albumsCoB->clear();
395 d->m_albumsCoB->addItem(i18n("<auto create>"), QString());
396
397 for (int i = 0; i < albumsList.size(); ++i)
398 {
399 QString albumIcon;
400
401 switch (albumsList.at(i).privacy)
402 {
403 case FB_ME:
404 albumIcon = QString::fromLatin1("secure-card");
405 break;
406
407 case FB_FRIENDS:
408 albumIcon = QString::fromLatin1("user-identity");
409 break;
410
411 case FB_FRIENDS_OF_FRIENDS:
412 albumIcon = QString::fromLatin1("system-users");
413 break;
414
415 case FB_NETWORKS:
416 albumIcon = QString::fromLatin1("network-workgroup");
417 break;
418
419 case FB_EVERYONE:
420 albumIcon = QString::fromLatin1("folder-html");
421 break;
422
423 case FB_CUSTOM:
424 albumIcon = QString::fromLatin1("configure");
425 break;
426 }
427
428 d->m_albumsCoB->addItem(
429 QIcon::fromTheme(albumIcon),
430 albumsList.at(i).title,
431 albumsList.at(i).id);
432
433 if (m_currentAlbumID == albumsList.at(i).id)
434 {
435 d->m_albumsCoB->setCurrentIndex(i + 1);
436 }
437 }
438 }
439
buttonStateChange(bool state)440 void FbWindow::buttonStateChange(bool state)
441 {
442 d->m_newAlbumBtn->setEnabled(state);
443 d->m_reloadAlbumsBtn->setEnabled(state);
444 startButton()->setEnabled(state);
445 }
446
slotBusy(bool val)447 void FbWindow::slotBusy(bool val)
448 {
449 if (val)
450 {
451 setCursor(Qt::WaitCursor);
452 d->m_changeUserBtn->setEnabled(false);
453 buttonStateChange(false);
454 }
455 else
456 {
457 setCursor(Qt::ArrowCursor);
458 d->m_changeUserBtn->setEnabled(true);
459 buttonStateChange(m_talker->loggedIn());
460 }
461 }
462
slotUserChangeRequest()463 void FbWindow::slotUserChangeRequest()
464 {
465 qCDebug(KIPIPLUGINS_LOG) << "Slot Change User Request";
466
467 if (m_talker->loggedIn())
468 {
469 m_talker->logout();
470 QMessageBox warn(QMessageBox::Warning,
471 i18n("Warning"),
472 i18n("After you have been logged out in the browser, "
473 "click \"Continue\" to authenticate for another account"),
474 QMessageBox::Yes | QMessageBox::No);
475
476 (warn.button(QMessageBox::Yes))->setText(i18n("Continue"));
477 (warn.button(QMessageBox::No))->setText(i18n("Cancel"));
478
479 if (warn.exec() == QMessageBox::Yes)
480 {
481 m_accessToken.clear();
482 m_sessionExpires = 0;
483 }
484 else
485 return;
486 }
487
488 authenticate();
489 }
490
slotReloadAlbumsRequest(long long userID)491 void FbWindow::slotReloadAlbumsRequest(long long userID)
492 {
493 qCDebug(KIPIPLUGINS_LOG) << "Reload Albums Request for UID:" << userID;
494
495 if (userID == 0)
496 {
497 FbUser user = m_talker->getUser();
498 setProfileAID(user.id);
499 m_talker->listAlbums(); // re-get albums from current user
500 }
501 else
502 {
503 setProfileAID(userID);
504 m_talker->listAlbums(userID); // re-get albums for friend
505 }
506 }
507
slotNewAlbumRequest()508 void FbWindow::slotNewAlbumRequest()
509 {
510 qCDebug(KIPIPLUGINS_LOG) << "Slot New Album Request";
511
512 if (m_albumDlg->exec() == QDialog::Accepted)
513 {
514 qCDebug(KIPIPLUGINS_LOG) << "Calling New Album method";
515 FbAlbum newAlbum;
516 m_albumDlg->getAlbumProperties(newAlbum);
517 m_talker->createAlbum(newAlbum);
518 }
519 }
520
slotStartTransfer()521 void FbWindow::slotStartTransfer()
522 {
523 qCDebug(KIPIPLUGINS_LOG) << "slotStartTransfer invoked";
524
525 d->m_imgList->clearProcessedStatus();
526 m_transferQueue = d->m_imgList->imageUrls();
527
528 if (m_transferQueue.isEmpty())
529 {
530 return;
531 }
532
533 m_currentAlbumID = d->m_albumsCoB->itemData(d->m_albumsCoB->currentIndex()).toString();
534 qCDebug(KIPIPLUGINS_LOG) << "upload request got album id from widget: " << m_currentAlbumID;
535 m_imagesTotal = m_transferQueue.count();
536 m_imagesCount = 0;
537
538 setRejectButtonMode(QDialogButtonBox::Cancel);
539 d->m_progressBar->setFormat(i18n("%v / %m"));
540 d->m_progressBar->setMaximum(m_imagesTotal);
541 d->m_progressBar->setValue(0);
542 d->m_progressBar->show();
543 d->m_progressBar->progressScheduled(i18n("Facebook export"), true, true);
544 d->m_progressBar->progressThumbnailChanged(QIcon(QLatin1String(":/icons/kipi-icon.svg")).pixmap(22, 22));
545
546 uploadNextPhoto();
547 }
548
setProfileAID(long long userID)549 void FbWindow::setProfileAID(long long userID)
550 {
551 // store AID of Profile Photos album
552 // http://wiki.developers.facebook.com/index.php/Profile_archive_album
553 m_profileAID = QString::number((userID << 32)
554 + (-3 & 0xFFFFFFFF));
555 }
556
getImageCaption(const QString & fileName)557 QString FbWindow::getImageCaption(const QString& fileName)
558 {
559 KPImageInfo info(QUrl::fromLocalFile(fileName));
560 // Facebook doesn't support image titles. Include it in descriptions if needed.
561 QStringList descriptions = QStringList() << info.title() << info.description();
562 descriptions.removeAll(QString::fromLatin1(""));
563 return descriptions.join(QString::fromLatin1("\n\n"));
564 }
565
prepareImageForUpload(const QString & imgPath,QString & caption)566 bool FbWindow::prepareImageForUpload(const QString& imgPath, QString& caption)
567 {
568 QImage image;
569
570 if (iface())
571 {
572 image = iface()->preview(QUrl::fromLocalFile(imgPath));
573 }
574
575 if (image.isNull())
576 {
577 image.load(imgPath);
578 }
579
580 if (image.isNull())
581 {
582 return false;
583 }
584
585 // get temporary file name
586 m_tmpPath = m_tmpDir + QFileInfo(imgPath).baseName().trimmed() + QString::fromLatin1(".jpg");
587
588 // rescale image if requested
589 int maxDim = d->m_dimensionSpB->value();
590
591 if (d->m_resizeChB->isChecked()
592 && (image.width() > maxDim || image.height() > maxDim))
593 {
594 qCDebug(KIPIPLUGINS_LOG) << "Resizing to " << maxDim;
595 image = image.scaled(maxDim, maxDim, Qt::KeepAspectRatio,
596 Qt::SmoothTransformation);
597 }
598
599 qCDebug(KIPIPLUGINS_LOG) << "Saving to temp file: " << m_tmpPath;
600 image.save(m_tmpPath, "JPEG", d->m_imageQualitySpB->value());
601
602 // copy meta data to temporary image
603
604 if (iface())
605 {
606 QPointer<MetadataProcessor> meta = iface()->createMetadataProcessor();
607
608 if (meta && meta->load(QUrl::fromLocalFile(imgPath)))
609 {
610 caption = getImageCaption(imgPath);
611 meta->setImageDimensions(image.size());
612 meta->setImageOrientation(MetadataProcessor::NORMAL);
613 meta->setImageProgramId(QString::fromLatin1("Kipi-plugins"), kipipluginsVersion());
614 meta->save(QUrl::fromLocalFile(m_tmpPath), true);
615 }
616 else
617 {
618 caption.clear();
619 }
620 }
621
622 return true;
623 }
624
uploadNextPhoto()625 void FbWindow::uploadNextPhoto()
626 {
627 if (m_transferQueue.isEmpty())
628 {
629 setRejectButtonMode(QDialogButtonBox::Close);
630 d->m_progressBar->hide();
631 d->m_progressBar->progressCompleted();
632 return;
633 }
634
635 d->m_imgList->processing(m_transferQueue.first());
636 QString imgPath = m_transferQueue.first().toLocalFile();
637
638 d->m_progressBar->setMaximum(m_imagesTotal);
639 d->m_progressBar->setValue(m_imagesCount);
640
641 QString caption;
642 bool res;
643
644 if (d->m_resizeChB->isChecked())
645 {
646 if (!prepareImageForUpload(imgPath, caption))
647 {
648 slotAddPhotoDone(666, i18n("Cannot open file"));
649 return;
650 }
651
652 res = m_talker->addPhoto(m_tmpPath, m_currentAlbumID, caption);
653 }
654 else
655 {
656 caption = getImageCaption(imgPath);
657 m_tmpPath.clear();
658 res = m_talker->addPhoto(imgPath, m_currentAlbumID, caption);
659 }
660
661 if (!res)
662 {
663 slotAddPhotoDone(666, i18n("Cannot open file"));
664 return;
665 }
666 }
667
slotAddPhotoDone(int errCode,const QString & errMsg)668 void FbWindow::slotAddPhotoDone(int errCode, const QString& errMsg)
669 {
670 // Remove temporary file if it was used
671 if (!m_tmpPath.isEmpty())
672 {
673 QFile::remove(m_tmpPath);
674 m_tmpPath.clear();
675 }
676
677 d->m_imgList->processed(m_transferQueue.first(), (errCode == 0));
678
679 if (errCode == 0)
680 {
681 m_transferQueue.pop_front();
682 m_imagesCount++;
683 }
684 else
685 {
686 if (QMessageBox::question(this, i18n("Uploading Failed"),
687 i18n("Failed to upload photo into Facebook: %1\n"
688 "Do you want to continue?", errMsg))
689 != QMessageBox::Yes)
690 {
691 setRejectButtonMode(QDialogButtonBox::Close);
692 d->m_progressBar->hide();
693 d->m_progressBar->progressCompleted();
694 m_transferQueue.clear();
695 return;
696 }
697 }
698
699 uploadNextPhoto();
700 }
701
slotCreateAlbumDone(int errCode,const QString & errMsg,const QString & newAlbumID)702 void FbWindow::slotCreateAlbumDone(int errCode, const QString& errMsg, const QString& newAlbumID)
703 {
704 if (errCode != 0)
705 {
706 QMessageBox::critical(this, QString(), i18n("Facebook Call Failed: %1", errMsg));
707 return;
708 }
709
710 // reload album list and automatically select new album
711 m_currentAlbumID = newAlbumID;
712 m_talker->listAlbums();
713 }
714
slotImageListChanged()715 void FbWindow::slotImageListChanged()
716 {
717 startButton()->setEnabled(!(d->m_imgList->imageUrls().isEmpty()));
718 }
719
720 } // namespace KIPIFacebookPlugin
721