1 /* ============================================================
2  *
3  * This file is a part of KDE project
4  *
5  *
6  * Date        : 2013-11-18
7  * Description : a kipi plugin to export images to Dropbox web service
8  *
9  * Copyright (C) 2013 by Pankaj Kumar <me at panks dot me>
10  *
11  * This program is free software; you can redistribute it
12  * and/or modify it under the terms of the GNU General
13  * Public License as published by the Free Software Foundation;
14  * either version 2, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * ============================================================ */
22 
23 #include "dbwindow.h"
24 
25 // Qt includes
26 
27 #include <QWindow>
28 #include <QSpinBox>
29 #include <QCheckBox>
30 #include <QMessageBox>
31 #include <QCloseEvent>
32 
33 // KDE includes
34 
35 #include <klocalizedstring.h>
36 #include <kconfig.h>
37 #include <kwindowconfig.h>
38 
39 // Libkipi includes
40 
41 #include <KIPI/Interface>
42 
43 // Local includes
44 
45 #include "kipiplugins_debug.h"
46 #include "kpimageslist.h"
47 #include "kpaboutdata.h"
48 #include "kpimageinfo.h"
49 #include "kpversion.h"
50 #include "kpprogresswidget.h"
51 #include "dbtalker.h"
52 #include "dbitem.h"
53 #include "dbalbum.h"
54 #include "dbwidget.h"
55 
56 namespace KIPIDropboxPlugin
57 {
58 
DBWindow(const QString & tmpFolder,QWidget * const)59 DBWindow::DBWindow(const QString& tmpFolder, QWidget* const /*parent*/)
60     : KPToolDialog(nullptr)
61 {
62     m_tmp         = tmpFolder;
63     m_imagesCount = 0;
64     m_imagesTotal = 0;
65 
66     m_widget      = new DropboxWidget(this, iface(), QLatin1String("Dropbox"));
67     setMainWidget(m_widget);
68     setWindowIcon(QIcon::fromTheme(QLatin1String("kipi-dropbox")));
69     setModal(false);
70     setWindowTitle(i18n("Export to Dropbox"));
71 
72     startButton()->setText(i18n("Start Upload"));
73     startButton()->setToolTip(i18n("Start upload to Dropbox"));
74 
75     m_widget->setMinimumSize(700, 500);
76 
77     connect(m_widget->imagesList(), SIGNAL(signalImageListChanged()),
78             this, SLOT(slotImageListChanged()));
79 
80     connect(m_widget->getChangeUserBtn(), SIGNAL(clicked()),
81             this, SLOT(slotUserChangeRequest()));
82 
83     connect(m_widget->getNewAlbmBtn(), SIGNAL(clicked()),
84             this, SLOT(slotNewAlbumRequest()));
85 
86     connect(m_widget->getReloadBtn(), SIGNAL(clicked()),
87             this, SLOT(slotReloadAlbumsRequest()));
88 
89     connect(startButton(), SIGNAL(clicked()),
90             this, SLOT(slotStartTransfer()));
91 
92     KPAboutData* const about = new KPAboutData(ki18n("Dropbox Export"),
93                                                ki18n("A tool to export images "
94                                                      "to Dropbox"),
95                                                ki18n("(c) 2013, Saurabh Patel"));
96 
97     about->addAuthor(ki18n("Saurabh Patel").toString(),
98                      ki18n("Author").toString(),
99                      QLatin1String("saurabhpatel7717 at gmail dot com"));
100 
101     about->setHandbookEntry(QLatin1String("tool-dropboxexport"));
102     setAboutData(about);
103 
104     //-------------------------------------------------------------------------
105 
106     m_albumDlg = new DBNewAlbum(this, QLatin1String("Dropbox"));
107 
108     //-------------------------------------------------------------------------
109 
110     m_talker   = new DBTalker(this);
111 
112     connect(m_talker,SIGNAL(signalBusy(bool)),
113             this,SLOT(slotBusy(bool)));
114 
115     connect(m_talker,SIGNAL(signalLinkingFailed()),
116             this,SLOT(slotSignalLinkingFailed()));
117 
118     connect(m_talker,SIGNAL(signalLinkingSucceeded()),
119             this,SLOT(slotSignalLinkingSucceeded()));
120 
121     connect(m_talker,SIGNAL(signalSetUserName(QString)),
122             this,SLOT(slotSetUserName(QString)));
123 
124     connect(m_talker,SIGNAL(signalListAlbumsFailed(QString)),
125             this,SLOT(slotListAlbumsFailed(QString)));
126 
127     connect(m_talker,SIGNAL(signalListAlbumsDone(QList<QPair<QString,QString> >)),
128             this,SLOT(slotListAlbumsDone(QList<QPair<QString,QString> >)));
129 
130     connect(m_talker,SIGNAL(signalCreateFolderFailed(QString)),
131             this,SLOT(slotCreateFolderFailed(QString)));
132 
133     connect(m_talker,SIGNAL(signalCreateFolderSucceeded()),
134             this,SLOT(slotCreateFolderSucceeded()));
135 
136     connect(m_talker,SIGNAL(signalAddPhotoFailed(QString)),
137             this,SLOT(slotAddPhotoFailed(QString)));
138 
139     connect(m_talker,SIGNAL(signalAddPhotoSucceeded()),
140             this,SLOT(slotAddPhotoSucceeded()));
141 
142     connect(this, SIGNAL(finished(int)),
143             this, SLOT(slotFinished()));
144 
145     readSettings();
146     buttonStateChange(false);
147 
148     m_talker->link();
149 }
150 
~DBWindow()151 DBWindow::~DBWindow()
152 {
153     delete m_widget;
154     delete m_albumDlg;
155     delete m_talker;
156 }
157 
reactivate()158 void DBWindow::reactivate()
159 {
160     m_widget->imagesList()->loadImagesFromCurrentSelection();
161     m_widget->progressBar()->hide();
162 
163     show();
164 }
165 
readSettings()166 void DBWindow::readSettings()
167 {
168     KConfig config(QLatin1String("kipirc"));
169     KConfigGroup grp   = config.group("Dropbox Settings");
170 
171     m_currentAlbumName = grp.readEntry("Current Album",QString());
172 
173     if (grp.readEntry("Resize", false))
174     {
175         m_widget->getResizeCheckBox()->setChecked(true);
176         m_widget->getDimensionSpB()->setEnabled(true);
177         m_widget->getImgQualitySpB()->setEnabled(true);
178     }
179     else
180     {
181         m_widget->getResizeCheckBox()->setChecked(false);
182         m_widget->getDimensionSpB()->setEnabled(false);
183         m_widget->getImgQualitySpB()->setEnabled(false);
184     }
185 
186     m_widget->getDimensionSpB()->setValue(grp.readEntry("Maximum Width",  1600));
187     m_widget->getImgQualitySpB()->setValue(grp.readEntry("Image Quality", 90));
188 
189     winId();
190     KConfigGroup dialogGroup = config.group("Dropbox Export Dialog");
191     KWindowConfig::restoreWindowSize(windowHandle(), dialogGroup);
192     resize(windowHandle()->size());
193 }
194 
writeSettings()195 void DBWindow::writeSettings()
196 {
197     KConfig config(QLatin1String("kipirc"));
198     KConfigGroup grp = config.group("Dropbox Settings");
199 
200     grp.writeEntry("Current Album", m_currentAlbumName);
201     grp.writeEntry("Resize",        m_widget->getResizeCheckBox()->isChecked());
202     grp.writeEntry("Maximum Width", m_widget->getDimensionSpB()->value());
203     grp.writeEntry("Image Quality", m_widget->getImgQualitySpB()->value());
204 
205     KConfigGroup dialogGroup = config.group("Dropbox Export Dialog");
206     KWindowConfig::saveWindowSize(windowHandle(), dialogGroup);
207 
208     config.sync();
209 }
210 
slotSetUserName(const QString & msg)211 void DBWindow::slotSetUserName(const QString& msg)
212 {
213     m_widget->updateLabels(msg, QLatin1String(""));
214 }
215 
slotListAlbumsDone(const QList<QPair<QString,QString>> & list)216 void DBWindow::slotListAlbumsDone(const QList<QPair<QString,QString> >& list)
217 {
218     m_widget->getAlbumsCoB()->clear();
219     qCDebug(KIPIPLUGINS_LOG) << "slotListAlbumsDone:" << list.size();
220 
221     for(int i = 0 ; i < list.size() ; i++)
222     {
223         m_widget->getAlbumsCoB()->addItem(
224         QIcon::fromTheme(QLatin1String("system-users")),
225         list.value(i).second, list.value(i).first);
226 
227         if (m_currentAlbumName == list.value(i).first)
228         {
229             m_widget->getAlbumsCoB()->setCurrentIndex(i);
230         }
231     }
232 
233     buttonStateChange(true);
234     m_talker->getUserName();
235 }
236 
slotBusy(bool val)237 void DBWindow::slotBusy(bool val)
238 {
239     if (val)
240     {
241         setCursor(Qt::WaitCursor);
242         m_widget->getChangeUserBtn()->setEnabled(false);
243         buttonStateChange(false);
244     }
245     else
246     {
247         setCursor(Qt::ArrowCursor);
248         m_widget->getChangeUserBtn()->setEnabled(true);
249         buttonStateChange(true);
250     }
251 }
252 
slotStartTransfer()253 void DBWindow::slotStartTransfer()
254 {
255     m_widget->imagesList()->clearProcessedStatus();
256 
257     if (m_widget->imagesList()->imageUrls().isEmpty())
258     {
259         QMessageBox::critical(this, i18nc("@title:window", "Error"),
260                               i18n("No image selected. Please select which images should be uploaded."));
261         return;
262     }
263 
264     if (!(m_talker->authenticated()))
265     {
266         if (QMessageBox::question(this, i18n("Login Failed"),
267                                   i18n("Authentication failed. Do you want to try again?"))
268             == QMessageBox::Yes)
269         {
270             m_talker->link();
271             return;
272         }
273         else
274         {
275             return;
276         }
277     }
278 
279     m_transferQueue = m_widget->imagesList()->imageUrls();
280 
281     if (m_transferQueue.isEmpty())
282     {
283         return;
284     }
285 
286     m_currentAlbumName = m_widget->getAlbumsCoB()->itemData(m_widget->getAlbumsCoB()->currentIndex()).toString();
287 
288     m_imagesTotal = m_transferQueue.count();
289     m_imagesCount = 0;
290 
291     m_widget->progressBar()->setFormat(i18n("%v / %m"));
292     m_widget->progressBar()->setMaximum(m_imagesTotal);
293     m_widget->progressBar()->setValue(0);
294     m_widget->progressBar()->show();
295     m_widget->progressBar()->progressScheduled(i18n("Dropbox export"), true, true);
296     m_widget->progressBar()->progressThumbnailChanged(
297         QIcon(QLatin1String(":/icons/kipi-icon.svg")).pixmap(22, 22));
298 
299     uploadNextPhoto();
300 }
301 
uploadNextPhoto()302 void DBWindow::uploadNextPhoto()
303 {
304     qCDebug(KIPIPLUGINS_LOG) << "uploadNextPhoto:" << m_transferQueue.count();
305 
306     if (m_transferQueue.isEmpty())
307     {
308         qCDebug(KIPIPLUGINS_LOG) << "empty";
309         m_widget->progressBar()->progressCompleted();
310         return;
311     }
312 
313     QString imgPath = m_transferQueue.first().toLocalFile();
314     QString temp = m_currentAlbumName + QLatin1String("/");
315 
316     bool res = m_talker->addPhoto(imgPath,temp,m_widget->getResizeCheckBox()->isChecked(),m_widget->getDimensionSpB()->value(),
317                                   m_widget->getImgQualitySpB()->value());
318 
319     if (!res)
320     {
321         slotAddPhotoFailed(QLatin1String(""));
322         return;
323     }
324 }
325 
slotAddPhotoFailed(const QString & msg)326 void DBWindow::slotAddPhotoFailed(const QString& msg)
327 {
328     if (QMessageBox::question(this, i18n("Uploading Failed"),
329                               i18n("Failed to upload photo to Dropbox."
330                                    "\n%1\n"
331                                    "Do you want to continue?", msg))
332         != QMessageBox::Yes)
333     {
334         m_transferQueue.clear();
335         m_widget->progressBar()->hide();
336     }
337     else
338     {
339         m_transferQueue.pop_front();
340         m_imagesTotal--;
341         m_widget->progressBar()->setMaximum(m_imagesTotal);
342         m_widget->progressBar()->setValue(m_imagesCount);
343         uploadNextPhoto();
344     }
345 }
346 
slotAddPhotoSucceeded()347 void DBWindow::slotAddPhotoSucceeded()
348 {
349     // Remove photo uploaded from the list
350     m_widget->imagesList()->removeItemByUrl(m_transferQueue.first());
351     m_transferQueue.pop_front();
352     m_imagesCount++;
353     m_widget->progressBar()->setMaximum(m_imagesTotal);
354     m_widget->progressBar()->setValue(m_imagesCount);
355     uploadNextPhoto();
356 }
357 
slotImageListChanged()358 void DBWindow::slotImageListChanged()
359 {
360     startButton()->setEnabled(!(m_widget->imagesList()->imageUrls().isEmpty()));
361 }
362 
slotNewAlbumRequest()363 void DBWindow::slotNewAlbumRequest()
364 {
365     if (m_albumDlg->exec() == QDialog::Accepted)
366     {
367         DBFolder newFolder;
368         m_albumDlg->getFolderTitle(newFolder);
369         qCDebug(KIPIPLUGINS_LOG) << "slotNewAlbumRequest:" << newFolder.title;
370         m_currentAlbumName = m_widget->getAlbumsCoB()->itemData(m_widget->getAlbumsCoB()->currentIndex()).toString();
371         QString temp = m_currentAlbumName + newFolder.title;
372         m_talker->createFolder(temp);
373     }
374 }
375 
slotReloadAlbumsRequest()376 void DBWindow::slotReloadAlbumsRequest()
377 {
378     m_talker->listFolders();
379 }
380 
slotSignalLinkingFailed()381 void DBWindow::slotSignalLinkingFailed()
382 {
383     slotSetUserName(QLatin1String(""));
384     m_widget->getAlbumsCoB()->clear();
385 
386     if (QMessageBox::question(this, i18n("Login Failed"),
387                               i18n("Authentication failed. Do you want to try again?"))
388         == QMessageBox::Yes)
389     {
390         m_talker->link();
391     }
392 }
393 
slotSignalLinkingSucceeded()394 void DBWindow::slotSignalLinkingSucceeded()
395 {
396     m_talker->listFolders();
397 }
398 
slotListAlbumsFailed(const QString & msg)399 void DBWindow::slotListAlbumsFailed(const QString& msg)
400 {
401     QMessageBox::critical(this, QString(), i18n("Dropbox call failed:\n%1", msg));
402 }
403 
slotCreateFolderFailed(const QString & msg)404 void DBWindow::slotCreateFolderFailed(const QString& msg)
405 {
406     QMessageBox::critical(this, QString(), i18n("Dropbox call failed:\n%1", msg));
407 }
408 
slotCreateFolderSucceeded()409 void DBWindow::slotCreateFolderSucceeded()
410 {
411     m_talker->listFolders();
412 }
413 
slotTransferCancel()414 void DBWindow::slotTransferCancel()
415 {
416     m_transferQueue.clear();
417     m_widget->progressBar()->hide();
418     m_talker->cancel();
419 }
420 
slotUserChangeRequest()421 void DBWindow::slotUserChangeRequest()
422 {
423     slotSetUserName(QLatin1String(""));
424     m_widget->getAlbumsCoB()->clear();
425     m_talker->unLink();
426     m_talker->link();
427 }
428 
buttonStateChange(bool state)429 void DBWindow::buttonStateChange(bool state)
430 {
431     m_widget->getNewAlbmBtn()->setEnabled(state);
432     m_widget->getReloadBtn()->setEnabled(state);
433     startButton()->setEnabled(state);
434 }
435 
slotFinished()436 void DBWindow::slotFinished()
437 {
438     writeSettings();
439     m_widget->imagesList()->listView()->clear();
440 }
441 
closeEvent(QCloseEvent * e)442 void DBWindow::closeEvent(QCloseEvent* e)
443 {
444     if (!e)
445     {
446         return;
447     }
448 
449     slotFinished();
450     e->accept();
451 }
452 
453 } // namespace KIPIDropboxPlugin
454