File indexing completed on 2025-01-19 03:53:10
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 Pinterest 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 "pwindow.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 "ptalker.h" 0038 #include "pitem.h" 0039 #include "pnewalbumdlg.h" 0040 #include "pwidget.h" 0041 0042 namespace DigikamGenericPinterestPlugin 0043 { 0044 0045 class Q_DECL_HIDDEN PWindow::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 PWidget* widget; 0062 PNewAlbumDlg* albumDlg; 0063 PTalker* talker; 0064 0065 QString currentAlbumName; 0066 QList<QUrl> transferQueue; 0067 }; 0068 0069 PWindow::PWindow(DInfoInterface* const iface, 0070 QWidget* const /*parent*/) 0071 : WSToolDialog(nullptr, QLatin1String("Pinterest Export Dialog")), 0072 d (new Private) 0073 { 0074 d->widget = new PWidget(this, iface, QLatin1String("Pinterest")); 0075 0076 d->widget->imagesList()->setIface(iface); 0077 0078 setMainWidget(d->widget); 0079 setModal(false); 0080 setWindowTitle(i18nc("@title:window", "Export to Pinterest")); 0081 0082 startButton()->setText(i18nc("@action:button", "Start Upload")); 0083 startButton()->setToolTip(i18nc("@info:tooltip, button", "Start upload to Pinterest")); 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(slotNewBoardRequest())); 0095 0096 connect(d->widget->getReloadBtn(), SIGNAL(clicked()), 0097 this, SLOT(slotReloadBoardsRequest())); 0098 0099 connect(startButton(), SIGNAL(clicked()), 0100 this, SLOT(slotStartTransfer())); 0101 0102 d->albumDlg = new PNewAlbumDlg(this, QLatin1String("Pinterest")); 0103 d->talker = new PTalker(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(signalNetworkError()), 0112 this,SLOT(slotTransferCancel())); 0113 0114 connect(d->talker,SIGNAL(signalLinkingSucceeded()), 0115 this,SLOT(slotSignalLinkingSucceeded())); 0116 0117 connect(d->talker,SIGNAL(signalSetUserName(QString)), 0118 this,SLOT(slotSetUserName(QString))); 0119 0120 connect(d->talker,SIGNAL(signalListBoardsFailed(QString)), 0121 this,SLOT(slotListBoardsFailed(QString))); 0122 0123 connect(d->talker,SIGNAL(signalListBoardsDone(QList<QPair<QString,QString> >)), // krazy:exclude=normalize 0124 this,SLOT(slotListBoardsDone(QList<QPair<QString,QString> >))); // krazy:exclude=normalize 0125 0126 connect(d->talker,SIGNAL(signalCreateBoardFailed(QString)), 0127 this,SLOT(slotCreateBoardFailed(QString))); 0128 0129 connect(d->talker,SIGNAL(signalCreateBoardSucceeded()), 0130 this,SLOT(slotCreateBoardSucceeded())); 0131 0132 connect(d->talker,SIGNAL(signalAddPinFailed(QString)), 0133 this,SLOT(slotAddPinFailed(QString))); 0134 0135 connect(d->talker,SIGNAL(signalAddPinSucceeded()), 0136 this,SLOT(slotAddPinSucceeded())); 0137 0138 connect(this, SIGNAL(finished(int)), 0139 this, SLOT(slotFinished())); 0140 0141 readSettings(); 0142 buttonStateChange(false); 0143 0144 d->talker->readSettings(); 0145 } 0146 0147 PWindow::~PWindow() 0148 { 0149 delete d->widget; 0150 delete d->albumDlg; 0151 delete d->talker; 0152 delete d; 0153 } 0154 0155 void PWindow::readSettings() 0156 { 0157 KSharedConfigPtr config = KSharedConfig::openConfig(); 0158 KConfigGroup grp = config->group(QLatin1String("Pinterest Settings")); 0159 d->currentAlbumName = grp.readEntry("Current Album", QString()); 0160 0161 if (grp.readEntry("Resize", false)) 0162 { 0163 d->widget->getResizeCheckBox()->setChecked(true); 0164 d->widget->getDimensionSpB()->setEnabled(true); 0165 } 0166 else 0167 { 0168 d->widget->getResizeCheckBox()->setChecked(false); 0169 d->widget->getDimensionSpB()->setEnabled(false); 0170 } 0171 0172 d->widget->getDimensionSpB()->setValue(grp.readEntry("Maximum Width", 1600)); 0173 d->widget->getImgQualitySpB()->setValue(grp.readEntry("Image Quality", 90)); 0174 } 0175 0176 void PWindow::writeSettings() 0177 { 0178 KSharedConfigPtr config = KSharedConfig::openConfig(); 0179 KConfigGroup grp = config->group(QLatin1String("Pinterest Settings")); 0180 0181 grp.writeEntry("Current Album", d->currentAlbumName); 0182 grp.writeEntry("Resize", d->widget->getResizeCheckBox()->isChecked()); 0183 grp.writeEntry("Maximum Width", d->widget->getDimensionSpB()->value()); 0184 grp.writeEntry("Image Quality", d->widget->getImgQualitySpB()->value()); 0185 } 0186 0187 void PWindow::reactivate() 0188 { 0189 d->widget->imagesList()->loadImagesFromCurrentSelection(); 0190 d->widget->progressBar()->hide(); 0191 0192 show(); 0193 } 0194 0195 void PWindow::setItemsList(const QList<QUrl>& urls) 0196 { 0197 d->widget->imagesList()->slotAddImages(urls); 0198 } 0199 0200 void PWindow::slotBusy(bool val) 0201 { 0202 if (val) 0203 { 0204 setCursor(Qt::WaitCursor); 0205 d->widget->getChangeUserBtn()->setEnabled(false); 0206 buttonStateChange(false); 0207 } 0208 else 0209 { 0210 setCursor(Qt::ArrowCursor); 0211 d->widget->getChangeUserBtn()->setEnabled(true); 0212 buttonStateChange(true); 0213 } 0214 } 0215 0216 void PWindow::slotSetUserName(const QString& msg) 0217 { 0218 d->widget->updateLabels(msg, QLatin1String("")); 0219 } 0220 0221 void PWindow::slotListBoardsDone(const QList<QPair<QString,QString> >& list) 0222 { 0223 d->widget->getAlbumsCoB()->clear(); 0224 0225 for (int i = 0 ; i < list.size() ; ++i) 0226 { 0227 d->widget->getAlbumsCoB()->addItem( 0228 QIcon::fromTheme(QLatin1String("system-users")), 0229 list.value(i).second, list.value(i).first); 0230 0231 if (d->currentAlbumName == list.value(i).second) 0232 { 0233 d->widget->getAlbumsCoB()->setCurrentIndex(i); 0234 } 0235 } 0236 0237 buttonStateChange(true); 0238 d->talker->getUserName(); 0239 } 0240 0241 void PWindow::slotStartTransfer() 0242 { 0243 d->widget->imagesList()->clearProcessedStatus(); 0244 0245 if (d->widget->imagesList()->imageUrls().isEmpty()) 0246 { 0247 QMessageBox::critical(this, i18nc("@title:window", "Error"), 0248 i18n("No image selected. Please select which images should be uploaded.")); 0249 return; 0250 } 0251 0252 if (!(d->talker->authenticated())) 0253 { 0254 QPointer<QMessageBox> warn = new QMessageBox(QMessageBox::Warning, 0255 i18nc("@title:window", "Warning"), 0256 i18n("Authentication failed. Click \"Continue\" to authenticate."), 0257 QMessageBox::Yes | QMessageBox::No); 0258 0259 warn->button(QMessageBox::Yes)->setText(i18nc("@action:button", "Continue")); 0260 warn->button(QMessageBox::No)->setText(i18nc("@action:button", "Cancel")); 0261 0262 if (warn->exec() == QMessageBox::Yes) 0263 { 0264 d->talker->link(); 0265 delete warn; 0266 return; 0267 } 0268 else 0269 { 0270 delete warn; 0271 return; 0272 } 0273 } 0274 0275 d->transferQueue = d->widget->imagesList()->imageUrls(); 0276 0277 if (d->transferQueue.isEmpty()) 0278 { 0279 return; 0280 } 0281 0282 d->currentAlbumName = d->widget->getAlbumsCoB()->currentText(); 0283 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "StartTransfer:" << d->currentAlbumName 0284 << "INDEX:" << d->widget->getAlbumsCoB()->currentIndex(); 0285 d->imagesTotal = d->transferQueue.count(); 0286 d->imagesCount = 0; 0287 0288 d->widget->progressBar()->setFormat(i18n("%v / %m")); 0289 d->widget->progressBar()->setMaximum(d->imagesTotal); 0290 d->widget->progressBar()->setValue(0); 0291 d->widget->progressBar()->show(); 0292 d->widget->progressBar()->progressScheduled(i18n("Pinterest export"), true, true); 0293 d->widget->progressBar()->progressThumbnailChanged( 0294 QIcon::fromTheme(QLatin1String("dk-pinterest")).pixmap(22, 22)); 0295 0296 uploadNextPhoto(); 0297 } 0298 0299 void PWindow::uploadNextPhoto() 0300 { 0301 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "uploadNextPhoto:" << d->transferQueue.count(); 0302 0303 if (d->transferQueue.isEmpty()) 0304 { 0305 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "empty"; 0306 d->widget->progressBar()->progressCompleted(); 0307 return; 0308 } 0309 0310 QString imgPath = d->transferQueue.first().toLocalFile(); 0311 QString boardID = d->widget->getAlbumsCoB()->itemData(d->widget->getAlbumsCoB()->currentIndex()).toString(); 0312 0313 bool result = d->talker->addPin(imgPath, 0314 boardID, 0315 d->widget->getResizeCheckBox()->isChecked(), 0316 d->widget->getDimensionSpB()->value(), 0317 d->widget->getImgQualitySpB()->value()); 0318 0319 if (!result) 0320 { 0321 slotAddPinFailed(QLatin1String("")); 0322 return; 0323 } 0324 } 0325 0326 void PWindow::slotAddPinFailed(const QString& msg) 0327 { 0328 if (QMessageBox::question(this, i18nc("@title:window", "Uploading Failed"), 0329 i18n("Failed to upload photo to Pinterest." 0330 "\n%1\n" 0331 "Do you want to continue?", msg)) 0332 != QMessageBox::Yes) 0333 { 0334 d->transferQueue.clear(); 0335 d->widget->progressBar()->hide(); 0336 d->widget->progressBar()->progressCompleted(); 0337 } 0338 else 0339 { 0340 d->transferQueue.pop_front(); 0341 d->imagesTotal--; 0342 d->widget->progressBar()->setMaximum(d->imagesTotal); 0343 d->widget->progressBar()->setValue(d->imagesCount); 0344 uploadNextPhoto(); 0345 } 0346 } 0347 0348 void PWindow::slotAddPinSucceeded() 0349 { 0350 // Remove photo uploaded from the list 0351 0352 d->widget->imagesList()->removeItemByUrl(d->transferQueue.first()); 0353 d->transferQueue.pop_front(); 0354 d->imagesCount++; 0355 d->widget->progressBar()->setMaximum(d->imagesTotal); 0356 d->widget->progressBar()->setValue(d->imagesCount); 0357 uploadNextPhoto(); 0358 } 0359 0360 void PWindow::slotImageListChanged() 0361 { 0362 startButton()->setEnabled(!(d->widget->imagesList()->imageUrls().isEmpty())); 0363 } 0364 0365 void PWindow::slotNewBoardRequest() 0366 { 0367 if (d->albumDlg->exec() == QDialog::Accepted) 0368 { 0369 PFolder newFolder; 0370 d->albumDlg->getFolderTitle(newFolder); 0371 d->currentAlbumName = newFolder.title; 0372 d->talker->createBoard(d->currentAlbumName); 0373 } 0374 } 0375 0376 void PWindow::slotReloadBoardsRequest() 0377 { 0378 d->talker->listBoards(); 0379 } 0380 0381 void PWindow::slotSignalLinkingFailed() 0382 { 0383 slotSetUserName(QLatin1String("")); 0384 d->widget->getAlbumsCoB()->clear(); 0385 0386 if (QMessageBox::question(this, i18nc("@title:window", "Login Failed"), 0387 i18n("Authentication failed. Do you want to try again?")) 0388 == QMessageBox::Yes) 0389 { 0390 d->talker->link(); 0391 } 0392 } 0393 0394 void PWindow::slotSignalLinkingSucceeded() 0395 { 0396 d->talker->listBoards(); 0397 } 0398 0399 void PWindow::slotListBoardsFailed(const QString& msg) 0400 { 0401 QMessageBox::critical(this, QString(), i18n("Pinterest call failed:\n%1", msg)); 0402 } 0403 0404 void PWindow::slotCreateBoardFailed(const QString& msg) 0405 { 0406 QMessageBox::critical(this, QString(), i18n("Pinterest call failed:\n%1", msg)); 0407 } 0408 0409 void PWindow::slotCreateBoardSucceeded() 0410 { 0411 d->talker->listBoards(); 0412 } 0413 0414 void PWindow::slotTransferCancel() 0415 { 0416 d->talker->cancel(); 0417 d->transferQueue.clear(); 0418 d->widget->progressBar()->hide(); 0419 d->widget->progressBar()->progressCompleted(); 0420 } 0421 0422 void PWindow::slotUserChangeRequest() 0423 { 0424 slotSetUserName(QLatin1String("")); 0425 d->widget->getAlbumsCoB()->clear(); 0426 d->talker->unLink(); 0427 d->talker->link(); 0428 } 0429 0430 void PWindow::buttonStateChange(bool state) 0431 { 0432 d->widget->getNewAlbmBtn()->setEnabled(state); 0433 d->widget->getReloadBtn()->setEnabled(state); 0434 startButton()->setEnabled(state); 0435 } 0436 0437 void PWindow::slotFinished() 0438 { 0439 writeSettings(); 0440 slotTransferCancel(); 0441 d->widget->imagesList()->listView()->clear(); 0442 } 0443 0444 void PWindow::closeEvent(QCloseEvent* e) 0445 { 0446 if (!e) 0447 { 0448 return; 0449 } 0450 0451 slotFinished(); 0452 e->accept(); 0453 } 0454 0455 } // namespace DigikamGenericPinterestPlugin 0456 0457 #include "moc_pwindow.cpp"