File indexing completed on 2025-01-05 03:53:24
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2018-05-20 0007 * Description : a tool to export images to Box web service 0008 * 0009 * SPDX-FileCopyrightText: 2018 by Tarek Talaat <tarektalaat93 at gmail dot com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #include "boxwindow.h" 0016 0017 // Qt includes 0018 0019 #include <QPointer> 0020 #include <QWindow> 0021 #include <QSpinBox> 0022 #include <QCheckBox> 0023 #include <QMessageBox> 0024 #include <QCloseEvent> 0025 0026 // KDE includes 0027 0028 #include <klocalizedstring.h> 0029 #include <ksharedconfig.h> 0030 #include <kconfiggroup.h> 0031 0032 // Local includes 0033 0034 #include "digikam_debug.h" 0035 #include "ditemslist.h" 0036 #include "digikam_version.h" 0037 #include "boxtalker.h" 0038 #include "boxitem.h" 0039 #include "boxnewalbumdlg.h" 0040 #include "boxwidget.h" 0041 0042 namespace DigikamGenericBoxPlugin 0043 { 0044 0045 class Q_DECL_HIDDEN BOXWindow::Private 0046 { 0047 public: 0048 0049 explicit Private() 0050 : imagesCount(0), 0051 imagesTotal(0), 0052 widget (nullptr), 0053 albumDlg (nullptr), 0054 talker (nullptr) 0055 { 0056 } 0057 0058 unsigned int imagesCount; 0059 unsigned int imagesTotal; 0060 0061 BOXWidget* widget; 0062 BOXNewAlbumDlg* albumDlg; 0063 BOXTalker* talker; 0064 0065 QString currentAlbumName; 0066 QList<QUrl> transferQueue; 0067 }; 0068 0069 BOXWindow::BOXWindow(DInfoInterface* const iface, 0070 QWidget* const /*parent*/) 0071 : WSToolDialog(nullptr, QLatin1String("Box Export Dialog")), 0072 d (new Private) 0073 { 0074 d->widget = new BOXWidget(this, iface, QLatin1String("Box")); 0075 0076 d->widget->imagesList()->setIface(iface); 0077 0078 setMainWidget(d->widget); 0079 setModal(false); 0080 setWindowTitle(i18nc("@title:window", "Export to Box")); 0081 0082 startButton()->setText(i18nc("@action:button", "Start Upload")); 0083 startButton()->setToolTip(i18nc("@info:tooltip, button", "Start upload to Box")); 0084 0085 d->widget->setMinimumSize(700, 500); 0086 0087 connect(d->widget->imagesList(), SIGNAL(signalImageListChanged()), 0088 this, SLOT(slotImageListChanged())); 0089 0090 connect(d->widget->getChangeUserBtn(), SIGNAL(clicked()), 0091 this, SLOT(slotUserChangeRequest())); 0092 0093 connect(d->widget->getNewAlbmBtn(), SIGNAL(clicked()), 0094 this, SLOT(slotNewAlbumRequest())); 0095 0096 connect(d->widget->getReloadBtn(), SIGNAL(clicked()), 0097 this, SLOT(slotReloadAlbumsRequest())); 0098 0099 connect(startButton(), SIGNAL(clicked()), 0100 this, SLOT(slotStartTransfer())); 0101 0102 d->albumDlg = new BOXNewAlbumDlg(this, QLatin1String("Box")); 0103 d->talker = new BOXTalker(this); 0104 0105 connect(d->talker,SIGNAL(signalBusy(bool)), 0106 this, SLOT(slotBusy(bool))); 0107 0108 connect(d->talker, SIGNAL(signalLinkingFailed()), 0109 this, SLOT(slotSignalLinkingFailed())); 0110 0111 connect(d->talker, SIGNAL(signalLinkingSucceeded()), 0112 this, SLOT(slotSignalLinkingSucceeded())); 0113 0114 connect(d->talker, SIGNAL(signalSetUserName(QString)), 0115 this, SLOT(slotSetUserName(QString))); 0116 0117 connect(d->talker, SIGNAL(signalListAlbumsFailed(QString)), 0118 this, SLOT(slotListAlbumsFailed(QString))); 0119 0120 connect(d->talker, SIGNAL(signalListAlbumsDone(QList<QPair<QString,QString> >)), // krazy:exclude=normalize 0121 this, SLOT(slotListAlbumsDone(QList<QPair<QString,QString> >))); // krazy:exclude=normalize 0122 0123 connect(d->talker, SIGNAL(signalCreateFolderFailed(QString)), 0124 this, SLOT(slotCreateFolderFailed(QString))); 0125 0126 connect(d->talker, SIGNAL(signalCreateFolderSucceeded()), 0127 this, SLOT(slotCreateFolderSucceeded())); 0128 0129 connect(d->talker, SIGNAL(signalAddPhotoFailed(QString)), 0130 this, SLOT(slotAddPhotoFailed(QString))); 0131 0132 connect(d->talker, SIGNAL(signalAddPhotoSucceeded()), 0133 this, SLOT(slotAddPhotoSucceeded())); 0134 0135 connect(this, SIGNAL(finished(int)), 0136 this, SLOT(slotFinished())); 0137 0138 readSettings(); 0139 buttonStateChange(false); 0140 0141 d->talker->link(); 0142 } 0143 0144 BOXWindow::~BOXWindow() 0145 { 0146 delete d->widget; 0147 delete d->albumDlg; 0148 delete d->talker; 0149 delete d; 0150 } 0151 0152 void BOXWindow::readSettings() 0153 { 0154 KSharedConfigPtr config = KSharedConfig::openConfig(); 0155 KConfigGroup grp = config->group(QLatin1String("Box Settings")); 0156 d->currentAlbumName = grp.readEntry("Current Album", QString()); 0157 0158 if (grp.readEntry("Resize", false)) 0159 { 0160 d->widget->getResizeCheckBox()->setChecked(true); 0161 d->widget->getDimensionSpB()->setEnabled(true); 0162 } 0163 else 0164 { 0165 d->widget->getResizeCheckBox()->setChecked(false); 0166 d->widget->getDimensionSpB()->setEnabled(false); 0167 } 0168 0169 d->widget->getDimensionSpB()->setValue(grp.readEntry("Maximum Width", 1600)); 0170 d->widget->getImgQualitySpB()->setValue(grp.readEntry("Image Quality", 90)); 0171 } 0172 0173 void BOXWindow::writeSettings() 0174 { 0175 KSharedConfigPtr config = KSharedConfig::openConfig(); 0176 KConfigGroup grp = config->group(QLatin1String("Box Settings")); 0177 0178 grp.writeEntry("Current Album", d->currentAlbumName); 0179 grp.writeEntry("Resize", d->widget->getResizeCheckBox()->isChecked()); 0180 grp.writeEntry("Maximum Width", d->widget->getDimensionSpB()->value()); 0181 grp.writeEntry("Image Quality", d->widget->getImgQualitySpB()->value()); 0182 } 0183 0184 void BOXWindow::reactivate() 0185 { 0186 d->widget->imagesList()->loadImagesFromCurrentSelection(); 0187 d->widget->progressBar()->hide(); 0188 0189 show(); 0190 } 0191 0192 void BOXWindow::setItemsList(const QList<QUrl>& urls) 0193 { 0194 d->widget->imagesList()->slotAddImages(urls); 0195 } 0196 0197 void BOXWindow::slotBusy(bool val) 0198 { 0199 if (val) 0200 { 0201 setCursor(Qt::WaitCursor); 0202 d->widget->getChangeUserBtn()->setEnabled(false); 0203 buttonStateChange(false); 0204 } 0205 else 0206 { 0207 setCursor(Qt::ArrowCursor); 0208 d->widget->getChangeUserBtn()->setEnabled(true); 0209 buttonStateChange(true); 0210 } 0211 } 0212 0213 void BOXWindow::slotSetUserName(const QString& msg) 0214 { 0215 d->widget->updateLabels(msg, QLatin1String("")); 0216 } 0217 0218 void BOXWindow::slotListAlbumsDone(const QList<QPair<QString,QString> >& list) 0219 { 0220 d->widget->getAlbumsCoB()->clear(); 0221 0222 for (int i = 0 ; i < list.size() ; ++i) 0223 { 0224 d->widget->getAlbumsCoB()->addItem( 0225 QIcon::fromTheme(QLatin1String("system-users")), 0226 list.value(i).second, list.value(i).second); 0227 0228 if (d->currentAlbumName == QString(list.value(i).second)) 0229 { 0230 d->widget->getAlbumsCoB()->setCurrentIndex(i); 0231 } 0232 } 0233 0234 buttonStateChange(true); 0235 d->talker->getUserName(); 0236 } 0237 0238 void BOXWindow::slotStartTransfer() 0239 { 0240 d->widget->imagesList()->clearProcessedStatus(); 0241 0242 if (d->widget->imagesList()->imageUrls().isEmpty()) 0243 { 0244 QMessageBox::critical(this, i18nc("@title:window", "Error"), 0245 i18nc("@info", "No image selected. Please select which images should be uploaded.")); 0246 return; 0247 } 0248 0249 if (!(d->talker->authenticated())) 0250 { 0251 QPointer<QMessageBox> warn = new QMessageBox(QMessageBox::Warning, 0252 i18nc("@title:window", "Warning"), 0253 i18nc("@info", "Authentication failed. Click \"Continue\" to authenticate."), 0254 QMessageBox::Yes | QMessageBox::No); 0255 0256 (warn->button(QMessageBox::Yes))->setText(i18nc("@action:button", "Continue")); 0257 (warn->button(QMessageBox::No))->setText(i18nc("@action:button", "Cancel")); 0258 0259 if (warn->exec() == QMessageBox::Yes) 0260 { 0261 d->talker->link(); 0262 delete warn; 0263 return; 0264 } 0265 else 0266 { 0267 delete warn; 0268 return; 0269 } 0270 } 0271 0272 d->transferQueue = d->widget->imagesList()->imageUrls(); 0273 0274 if (d->transferQueue.isEmpty()) 0275 { 0276 return; 0277 } 0278 0279 d->currentAlbumName = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString(); 0280 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "StartTransfer:" << d->currentAlbumName 0281 << "INDEX: " << d->widget->getAlbumsCoB()->currentIndex(); 0282 d->imagesTotal = d->transferQueue.count(); 0283 d->imagesCount = 0; 0284 0285 d->widget->progressBar()->setFormat(i18nc("@info: progress bar", "%v / %m")); 0286 d->widget->progressBar()->setMaximum(d->imagesTotal); 0287 d->widget->progressBar()->setValue(0); 0288 d->widget->progressBar()->show(); 0289 d->widget->progressBar()->progressScheduled(i18nc("@info", "Box export"), true, true); 0290 d->widget->progressBar()->progressThumbnailChanged( 0291 QIcon::fromTheme(QLatin1String("dk-box")).pixmap(22, 22)); 0292 0293 uploadNextPhoto(); 0294 } 0295 0296 void BOXWindow::uploadNextPhoto() 0297 { 0298 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "uploadNextPhoto:" << d->transferQueue.count(); 0299 0300 if (d->transferQueue.isEmpty()) 0301 { 0302 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "empty"; 0303 d->widget->progressBar()->progressCompleted(); 0304 return; 0305 } 0306 0307 QString imgPath = d->transferQueue.first().toLocalFile(); 0308 QString temp = d->currentAlbumName; 0309 0310 bool result = d->talker->addPhoto(imgPath, 0311 temp, 0312 d->widget->getResizeCheckBox()->isChecked(), 0313 d->widget->getDimensionSpB()->value(), 0314 d->widget->getImgQualitySpB()->value()); 0315 0316 if (!result) 0317 { 0318 slotAddPhotoFailed(QLatin1String("")); 0319 return; 0320 } 0321 } 0322 0323 void BOXWindow::slotAddPhotoFailed(const QString& msg) 0324 { 0325 if (QMessageBox::question(this, i18nc("@title:window", "Uploading Failed"), 0326 i18nc("@info", "Failed to upload photo to Box." 0327 "\n%1\n" 0328 "Do you want to continue?", msg)) 0329 != QMessageBox::Yes) 0330 { 0331 d->transferQueue.clear(); 0332 d->widget->progressBar()->hide(); 0333 } 0334 else 0335 { 0336 d->transferQueue.pop_front(); 0337 d->imagesTotal--; 0338 d->widget->progressBar()->setMaximum(d->imagesTotal); 0339 d->widget->progressBar()->setValue(d->imagesCount); 0340 uploadNextPhoto(); 0341 } 0342 } 0343 0344 void BOXWindow::slotAddPhotoSucceeded() 0345 { 0346 // Remove photo uploaded from the list 0347 0348 d->widget->imagesList()->removeItemByUrl(d->transferQueue.first()); 0349 d->transferQueue.pop_front(); 0350 d->imagesCount++; 0351 d->widget->progressBar()->setMaximum(d->imagesTotal); 0352 d->widget->progressBar()->setValue(d->imagesCount); 0353 uploadNextPhoto(); 0354 } 0355 0356 void BOXWindow::slotImageListChanged() 0357 { 0358 startButton()->setEnabled(!(d->widget->imagesList()->imageUrls().isEmpty())); 0359 } 0360 0361 void BOXWindow::slotNewAlbumRequest() 0362 { 0363 if (d->albumDlg->exec() == QDialog::Accepted) 0364 { 0365 BOXFolder newFolder; 0366 d->albumDlg->getFolderTitle(newFolder); 0367 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "slotNewAlbumRequest:" << newFolder.title; 0368 d->currentAlbumName = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString(); 0369 d->currentAlbumName = d->currentAlbumName + newFolder.title; 0370 d->talker->createFolder(d->currentAlbumName); 0371 } 0372 } 0373 0374 void BOXWindow::slotReloadAlbumsRequest() 0375 { 0376 d->talker->listFolders(); 0377 } 0378 0379 void BOXWindow::slotSignalLinkingFailed() 0380 { 0381 slotSetUserName(QLatin1String("")); 0382 d->widget->getAlbumsCoB()->clear(); 0383 0384 if (QMessageBox::question(this, i18nc("@title:window", "Login Failed"), 0385 i18nc("@info", "Authentication failed. Do you want to try again?")) 0386 == QMessageBox::Yes) 0387 { 0388 d->talker->link(); 0389 } 0390 } 0391 0392 void BOXWindow::slotSignalLinkingSucceeded() 0393 { 0394 slotBusy(false); 0395 d->talker->listFolders(); 0396 } 0397 0398 void BOXWindow::slotListAlbumsFailed(const QString& msg) 0399 { 0400 QMessageBox::critical(this, QString(), i18nc("@info", "Box call failed:\n%1", msg)); 0401 } 0402 0403 void BOXWindow::slotCreateFolderFailed(const QString& msg) 0404 { 0405 QMessageBox::critical(this, QString(), i18nc("@info", "Box call failed:\n%1", msg)); 0406 } 0407 0408 void BOXWindow::slotCreateFolderSucceeded() 0409 { 0410 d->talker->listFolders(); 0411 } 0412 0413 void BOXWindow::slotTransferCancel() 0414 { 0415 d->transferQueue.clear(); 0416 d->widget->progressBar()->hide(); 0417 d->talker->cancel(); 0418 } 0419 0420 void BOXWindow::slotUserChangeRequest() 0421 { 0422 slotSetUserName(QLatin1String("")); 0423 d->widget->getAlbumsCoB()->clear(); 0424 d->talker->unLink(); 0425 d->talker->link(); 0426 } 0427 0428 void BOXWindow::buttonStateChange(bool state) 0429 { 0430 d->widget->getNewAlbmBtn()->setEnabled(state); 0431 d->widget->getReloadBtn()->setEnabled(state); 0432 startButton()->setEnabled(state); 0433 } 0434 0435 void BOXWindow::slotFinished() 0436 { 0437 writeSettings(); 0438 d->widget->imagesList()->listView()->clear(); 0439 } 0440 0441 void BOXWindow::closeEvent(QCloseEvent* e) 0442 { 0443 if (!e) 0444 { 0445 return; 0446 } 0447 0448 slotFinished(); 0449 e->accept(); 0450 } 0451 0452 } // namespace DigikamGenericBoxPlugin 0453 0454 #include "moc_boxwindow.cpp"