File indexing completed on 2025-01-05 03:53:42
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2011-04-12 0007 * Description : A tool to export items to Rajce web service 0008 * 0009 * SPDX-FileCopyrightText: 2011 by Lukas Krejci <krejci.l at centrum dot cz> 0010 * SPDX-FileCopyrightText: 2011-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "rajcewidget.h" 0017 0018 // Qt includes 0019 0020 #include <QLabel> 0021 #include <QSpinBox> 0022 #include <QCheckBox> 0023 #include <QGroupBox> 0024 #include <QButtonGroup> 0025 #include <QRadioButton> 0026 #include <QGridLayout> 0027 #include <QHBoxLayout> 0028 #include <QVBoxLayout> 0029 #include <QDialog> 0030 #include <QComboBox> 0031 #include <QApplication> 0032 #include <QStyle> 0033 0034 // KDE includes 0035 0036 #include <klocalizedstring.h> 0037 #include <ksharedconfig.h> 0038 #include <kconfiggroup.h> 0039 0040 // Local includes 0041 0042 #include "rajcetalker.h" 0043 #include "rajcenewalbumdlg.h" 0044 #include "rajcesession.h" 0045 #include "ditemslist.h" 0046 #include "wslogindialog.h" 0047 #include "dprogresswdg.h" 0048 0049 namespace DigikamGenericRajcePlugin 0050 { 0051 0052 class Q_DECL_HIDDEN RajceWidget::Private 0053 { 0054 public: 0055 0056 explicit Private() 0057 { 0058 headerLbl = nullptr; 0059 userNameLbl = nullptr; 0060 userName = nullptr; 0061 dimensionSpB = nullptr; 0062 imageQualitySpB = nullptr; 0063 albumsCoB = nullptr; 0064 newAlbumBtn = nullptr; 0065 reloadAlbumsBtn = nullptr; 0066 changeUserBtn = nullptr; 0067 iface = nullptr; 0068 imgList = nullptr; 0069 progressBar = nullptr; 0070 talker = nullptr; 0071 uploadingPhotos = false; 0072 lastLoggedInState = false; 0073 } 0074 0075 QLabel* headerLbl; 0076 QLabel* userNameLbl; 0077 QLabel* userName; 0078 0079 QSpinBox* dimensionSpB; 0080 QSpinBox* imageQualitySpB; 0081 0082 QComboBox* albumsCoB; 0083 0084 QPushButton* newAlbumBtn; 0085 QPushButton* reloadAlbumsBtn; 0086 QPushButton* changeUserBtn; 0087 0088 DInfoInterface* iface; 0089 DItemsList* imgList; 0090 DProgressWdg* progressBar; 0091 0092 RajceTalker* talker; 0093 0094 QList<QString> uploadQueue; 0095 QList<QString>::Iterator currentUploadImage; 0096 0097 bool uploadingPhotos; 0098 bool lastLoggedInState; 0099 QString currentAlbumName; 0100 }; 0101 0102 RajceWidget::RajceWidget(DInfoInterface* const iface, QWidget* const parent) 0103 : WSSettingsWidget(parent, iface, QLatin1String("Rajce.net")), 0104 d (new Private) 0105 { 0106 d->iface = iface; 0107 d->talker = new RajceTalker(this); 0108 d->albumsCoB = getAlbumsCoB(); 0109 d->dimensionSpB = getDimensionSpB(); 0110 d->imageQualitySpB = getImgQualitySpB(); 0111 d->newAlbumBtn = getNewAlbmBtn(); 0112 d->reloadAlbumsBtn = getReloadBtn(); 0113 d->progressBar = progressBar(); 0114 d->imgList = imagesList(); 0115 d->changeUserBtn = getChangeUserBtn(); 0116 0117 getUploadBox()->hide(); 0118 getSizeBox()->hide(); 0119 0120 this->updateLabels(); 0121 0122 // ------------------------------------------------------------------------ 0123 0124 connect(d->talker, SIGNAL(signalBusyStarted(uint)), 0125 this, SLOT(slotProgressStarted(uint))); 0126 0127 connect(d->talker, SIGNAL(signalBusyFinished(uint)), 0128 this, SLOT(slotProgressFinished(uint))); 0129 0130 connect(d->talker, SIGNAL(signalBusyProgress(uint,uint)), 0131 this, SLOT(slotProgressChanged(uint,uint))); 0132 0133 connect(d->changeUserBtn, SIGNAL(clicked()), 0134 this, SLOT(slotChangeUserClicked())); 0135 0136 connect(d->newAlbumBtn, SIGNAL(clicked()), 0137 this, SLOT(slotCreateAlbum())); 0138 0139 connect(d->reloadAlbumsBtn, SIGNAL(clicked()), 0140 this, SLOT(slotLoadAlbums())); 0141 0142 connect(d->albumsCoB, SIGNAL(currentTextChanged(QString)), 0143 this, SLOT(slotSelectedAlbumChanged(QString))); 0144 } 0145 0146 RajceWidget::~RajceWidget() 0147 { 0148 delete d; 0149 } 0150 0151 void RajceWidget::updateLabels(const QString&, const QString&) 0152 { 0153 bool loggedIn = !d->talker->session().sessionToken().isEmpty(); 0154 0155 if (loggedIn != d->lastLoggedInState) 0156 { 0157 d->lastLoggedInState = loggedIn; 0158 Q_EMIT signalLoginStatusChanged(loggedIn); 0159 } 0160 0161 QString username = loggedIn ? d->talker->session().username() : QLatin1String(""); 0162 QString nickname = loggedIn ? d->talker->session().nickname() : i18n("Not logged in"); 0163 0164 getUserNameLabel()->setText(QString::fromLatin1("<b>%2</b> <small>%1</small>").arg(username, nickname)); 0165 0166 QString link = loggedIn 0167 ? QString::fromLatin1("<b><h2><a href='http://") + d->talker->session().nickname() + 0168 QString::fromLatin1(".rajce.net'>" 0169 "<font color=\"#9ACD32\">Rajce.net</font>" 0170 "</a></h2></b>") 0171 : QString::fromLatin1("<b><h2><a href='https://www.rajce.net'>" 0172 "<font color=\"#9ACD32\">Rajce.net</font>" 0173 "</a></h2></b>"); 0174 0175 getHeaderLbl()->setText(link); 0176 0177 disconnect(d->albumsCoB, SIGNAL(currentTextChanged(QString)), 0178 this, SLOT(slotSelectedAlbumChanged(QString))); 0179 0180 d->albumsCoB->clear(); 0181 RajceAlbum album; 0182 int selIdx = 0; 0183 int i = 0; 0184 0185 Q_FOREACH (album, d->talker->session().albums()) 0186 { 0187 d->albumsCoB->addItem(album.name, QVariant::fromValue(album)); 0188 0189 if (d->currentAlbumName == album.name) 0190 { 0191 selIdx = i; 0192 } 0193 0194 ++i; 0195 } 0196 0197 if (!d->currentAlbumName.isEmpty()) 0198 { 0199 d->albumsCoB->setCurrentIndex(selIdx); 0200 } 0201 0202 connect(d->albumsCoB, SIGNAL(currentTextChanged(QString)), 0203 this, SLOT(slotSelectedAlbumChanged(QString))); 0204 0205 unsigned max = d->talker->session().maxHeight(); 0206 max = max > d->talker->session().maxWidth() ? max 0207 : d->talker->session().maxWidth(); 0208 d->dimensionSpB->setMaximum(max); 0209 0210 if (d->dimensionSpB->value() == 0) 0211 { 0212 d->dimensionSpB->setValue(max); 0213 } 0214 0215 d->newAlbumBtn->setEnabled(loggedIn); 0216 d->albumsCoB->setEnabled(loggedIn); 0217 d->reloadAlbumsBtn->setEnabled(loggedIn); 0218 d->dimensionSpB->setEnabled(loggedIn); 0219 d->imageQualitySpB->setEnabled(loggedIn); 0220 0221 if (d->talker->session().lastErrorCode() != 0) 0222 { 0223 d->progressBar->setVisible(true); 0224 0225 switch (d->talker->session().lastErrorCode()) 0226 { 0227 case UnknownError: d->progressBar->setFormat(i18n("Unknown error")); break; 0228 case InvalidCommand: d->progressBar->setFormat(i18n("Invalid command")); break; 0229 case InvalidCredentials: d->progressBar->setFormat(i18n("Invalid login name or password")); break; 0230 case InvalidSessionToken: d->progressBar->setFormat(i18n("Session expired")); break; 0231 case InvalidOrRepeatedColumnName: break; 0232 case InvalidAlbumId: d->progressBar->setFormat(i18n("Unknown album")); break; 0233 case AlbumDoesntExistOrNoPrivileges: d->progressBar->setFormat(i18n("Unknown album")); break; 0234 case InvalidAlbumToken: d->progressBar->setFormat(i18n("Failed to open album")); break; 0235 case AlbumNameEmpty: d->progressBar->setFormat(i18n("The album name cannot be empty")); break; 0236 case FailedToCreateAlbum: d->progressBar->setFormat(i18n("Failed to create album")); break; 0237 case AlbumDoesntExist: d->progressBar->setFormat(i18n("Album does not exist")); break; 0238 case UnknownApplication: break; 0239 case InvalidApplicationKey: break; 0240 case FileNotAttached: d->progressBar->setFormat(i18n("File upload failed")); break; 0241 case NewerVersionExists: break; 0242 case SavingFileFailed: d->progressBar->setFormat(i18n("File upload failed")); break; 0243 case UnsupportedFileExtension: d->progressBar->setFormat(i18n("Unsupported file extension")); break; 0244 case UnknownClientVersion: break; 0245 case NonexistentTarget: break; 0246 default: break; 0247 } 0248 0249 QPalette palette = d->progressBar->palette(); 0250 palette.setColor(QPalette::Active, QPalette::Window, Qt::darkRed); 0251 d->progressBar->setPalette(palette); 0252 } 0253 } 0254 0255 void RajceWidget::reactivate() 0256 { 0257 d->imgList->listView()->clear(); 0258 d->imgList->loadImagesFromCurrentSelection(); 0259 d->talker->clearLastError(); 0260 updateLabels(); 0261 } 0262 0263 void RajceWidget::slotProgressChanged(unsigned /*commandType*/, unsigned int percent) 0264 { 0265 if (d->uploadingPhotos) 0266 { 0267 unsigned idx = d->currentUploadImage - d->uploadQueue.begin() - 1; 0268 float perc = (float)idx / d->uploadQueue.size(); 0269 perc += (float)percent / 100 / d->uploadQueue.size(); 0270 percent = perc * 100; 0271 } 0272 0273 d->progressBar->setValue(percent); 0274 } 0275 0276 void RajceWidget::slotProgressFinished(unsigned) 0277 { 0278 if (d->uploadingPhotos) 0279 { 0280 unsigned idx = d->currentUploadImage - d->uploadQueue.begin(); 0281 float perc = (float)idx / d->uploadQueue.size(); 0282 0283 d->progressBar->setValue(perc * 100); 0284 } 0285 else 0286 { 0287 d->progressBar->setVisible(false); 0288 setEnabledWidgets(true); 0289 updateLabels(); 0290 } 0291 } 0292 0293 void RajceWidget::slotProgressStarted(unsigned commandType) 0294 { 0295 QString text; 0296 0297 switch (commandType) 0298 { 0299 case Login: text = i18n("Logging in %v%"); break; 0300 case Logout: text = i18n("Logging out %v%"); break; 0301 case ListAlbums: text = i18n("Loading albums %v%"); break; 0302 case CreateAlbum: text = i18n("Creating album %v%"); break; 0303 case OpenAlbum: text = i18n("Opening album %v%"); break; 0304 case CloseAlbum: text = i18n("Closing album %v%"); break; 0305 case AddPhoto: text = i18n("Adding photos %v%"); break; 0306 } 0307 0308 if (!d->uploadingPhotos) 0309 { 0310 d->progressBar->setValue(0); 0311 } 0312 0313 d->progressBar->setFormat(text); 0314 d->progressBar->setVisible(true); 0315 setEnabledWidgets(false); 0316 } 0317 0318 void RajceWidget::slotChangeUserClicked() 0319 { 0320 WSLoginDialog* const dlg = new WSLoginDialog(this, QLatin1String("Rajce.net")); 0321 0322 if (dlg->exec() == QDialog::Accepted) 0323 { 0324 d->talker->clearLastError(); 0325 0326 connect(d->talker, SIGNAL(signalBusyFinished(uint)), 0327 this, SLOT(slotLoadAlbums())); 0328 0329 d->talker->login(dlg->login(), dlg->password()); 0330 } 0331 0332 delete dlg; 0333 } 0334 0335 void RajceWidget::slotLoadAlbums() 0336 { 0337 disconnect(d->talker, SIGNAL(signalBusyFinished(uint)), 0338 this, SLOT(slotLoadAlbums())); 0339 0340 d->talker->loadAlbums(); 0341 } 0342 0343 void RajceWidget::slotCreateAlbum() 0344 { 0345 RajceNewAlbumDlg* const dlg = new RajceNewAlbumDlg(this); 0346 0347 if (dlg->exec() == QDialog::Accepted) 0348 { 0349 d->talker->clearLastError(); 0350 0351 connect(d->talker, SIGNAL(signalBusyFinished(uint)), 0352 this, SLOT(slotLoadAlbums())); 0353 0354 d->talker->createAlbum(dlg->albumName(), dlg->albumDescription(), dlg->albumVisible()); 0355 } 0356 0357 delete dlg; 0358 } 0359 0360 void RajceWidget::slotStartUpload() 0361 { 0362 d->talker->clearLastError(); 0363 setEnabledWidgets(false); 0364 0365 d->uploadQueue.clear(); 0366 0367 Q_FOREACH (const QUrl& image, d->imgList->imageUrls(true)) 0368 { 0369 QString imagePath = image.toLocalFile(); 0370 d->uploadQueue.append(imagePath); 0371 } 0372 0373 if (d->uploadQueue.isEmpty()) 0374 { 0375 setEnabledWidgets(true); 0376 return; 0377 } 0378 0379 connect(d->talker, SIGNAL(signalBusyFinished(uint)), 0380 this, SLOT(slotStartUploadAfterAlbumOpened())); 0381 0382 QString albumName = d->albumsCoB->currentText(); 0383 RajceAlbum album; 0384 0385 Q_FOREACH (RajceAlbum a, d->talker->session().albums()) 0386 { 0387 if (a.name == albumName) 0388 { // cppcheck-suppress useStlAlgorithm 0389 album = a; 0390 break; 0391 } 0392 } 0393 0394 if (album.name == albumName) 0395 { 0396 d->talker->openAlbum(album); 0397 } 0398 } 0399 0400 void RajceWidget::slotStartUploadAfterAlbumOpened() 0401 { 0402 disconnect(d->talker, SIGNAL(signalBusyFinished(uint)), 0403 this, SLOT(slotStartUploadAfterAlbumOpened())); 0404 0405 connect(d->talker, SIGNAL(signalBusyFinished(uint)), 0406 this, SLOT(slotUploadNext())); 0407 0408 d->uploadingPhotos = true; 0409 d->progressBar->setValue(0); 0410 slotProgressStarted(AddPhoto); 0411 d->currentUploadImage = d->uploadQueue.begin(); 0412 slotUploadNext(); 0413 } 0414 0415 void RajceWidget::slotCloseAlbum() 0416 { 0417 setEnabledWidgets(true); 0418 0419 disconnect(d->talker, SIGNAL(signalBusyFinished(uint)), 0420 this, SLOT(slotCloseAlbum())); 0421 0422 d->uploadQueue.clear(); 0423 d->progressBar->setVisible(false); 0424 0425 d->uploadingPhotos = false; 0426 } 0427 0428 void RajceWidget::slotUploadNext() 0429 { 0430 QList<QString>::Iterator tmp = d->currentUploadImage; 0431 0432 if (d->currentUploadImage == d->uploadQueue.end()) 0433 { 0434 d->imgList->processed(QUrl::fromLocalFile(*(--tmp)), (d->talker->session().lastErrorCode() == 0)); 0435 cancelUpload(); 0436 return; 0437 } 0438 0439 if (d->currentUploadImage != d->uploadQueue.begin()) 0440 { 0441 d->imgList->processed(QUrl::fromLocalFile(*(--tmp)), (d->talker->session().lastErrorCode() == 0)); 0442 } 0443 0444 d->imgList->processing(QUrl::fromLocalFile(*d->currentUploadImage)); 0445 0446 QString currentPhoto = *d->currentUploadImage; 0447 ++d->currentUploadImage; 0448 0449 unsigned dimension = d->dimensionSpB->value(); 0450 int jpgQuality = d->imageQualitySpB->value(); 0451 0452 d->talker->uploadPhoto(currentPhoto, dimension, jpgQuality); 0453 } 0454 0455 void RajceWidget::cancelUpload() 0456 { 0457 if (d->uploadingPhotos && d->currentUploadImage != d->uploadQueue.begin() && 0458 d->currentUploadImage != d->uploadQueue.end()) 0459 { 0460 d->imgList->processed(QUrl::fromLocalFile(*d->currentUploadImage), false); 0461 } 0462 0463 disconnect(d->talker, SIGNAL(signalBusyFinished(uint)), 0464 this, SLOT(slotUploadNext())); 0465 0466 connect(d->talker, SIGNAL(signalBusyFinished(uint)), 0467 this, SLOT(slotCloseAlbum())); 0468 0469 d->talker->cancelCurrentCommand(); 0470 d->talker->closeAlbum(); 0471 d->uploadQueue.clear(); 0472 } 0473 0474 void RajceWidget::slotSelectedAlbumChanged(const QString& newName) 0475 { 0476 d->currentAlbumName = newName; 0477 } 0478 0479 void RajceWidget::setEnabledWidgets(bool enabled) 0480 { 0481 d->changeUserBtn->setEnabled(enabled); 0482 d->newAlbumBtn->setEnabled(enabled); 0483 d->albumsCoB->setEnabled(enabled); 0484 d->reloadAlbumsBtn->setEnabled(enabled); 0485 d->dimensionSpB->setEnabled(enabled); 0486 d->imageQualitySpB->setEnabled(enabled); 0487 0488 Q_EMIT signalLoginStatusChanged(enabled); 0489 } 0490 0491 void RajceWidget::readSettings() 0492 { 0493 KSharedConfigPtr config = KSharedConfig::openConfig(); 0494 KConfigGroup grp = config->group(QLatin1String("RajceExport Settings")); 0495 0496 RajceSession session; 0497 0498 session.sessionToken() = grp.readEntry("token"); 0499 session.username() = grp.readEntry("username"); 0500 session.nickname() = grp.readEntry("nickname"); 0501 d->currentAlbumName = grp.readEntry("album"); 0502 session.maxHeight() = grp.readEntry("maxHeight", 1200); 0503 session.maxWidth() = grp.readEntry("maxWidth", 1200); 0504 session.imageQuality() = grp.readEntry("imageQuality", 85); 0505 0506 d->talker->init(session); 0507 0508 if (!d->talker->session().sessionToken().isEmpty()) 0509 { 0510 d->talker->loadAlbums(); 0511 } 0512 } 0513 0514 void RajceWidget::writeSettings() 0515 { 0516 KSharedConfigPtr config = KSharedConfig::openConfig(); 0517 KConfigGroup grp = config->group(QLatin1String("RajceExport Settings")); 0518 const RajceSession& session = d->talker->session(); 0519 0520 grp.writeEntry("token", session.sessionToken()); 0521 grp.writeEntry("username", session.username()); 0522 grp.writeEntry("nickname", session.nickname()); 0523 grp.writeEntry("album", d->currentAlbumName); 0524 grp.writeEntry("maxWidth", session.maxWidth()); 0525 grp.writeEntry("maxHeight", session.maxHeight()); 0526 grp.writeEntry("imageQuality", session.imageQuality()); 0527 } 0528 0529 } // namespace DigikamGenericRajcePlugin 0530 0531 #include "moc_rajcewidget.cpp"