File indexing completed on 2025-01-05 03:53:38
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2011-02-11 0007 * Description : a tool to export images to WikiMedia web service 0008 * 0009 * SPDX-FileCopyrightText: 2011 by Alexandre Mendes <alex dot mendes1988 at gmail dot com> 0010 * SPDX-FileCopyrightText: 2011-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * SPDX-FileCopyrightText: 2012 by Parthasarathy Gopavarapu <gparthasarathy93 at gmail dot com> 0012 * SPDX-FileCopyrightText: 2012-2016 by Peter Potrowl <peter dot potrowl at gmail dot com> 0013 * 0014 * SPDX-License-Identifier: GPL-2.0-or-later 0015 * 0016 * ============================================================ */ 0017 0018 #include "mediawikiwindow.h" 0019 0020 // Qt includes 0021 0022 #include <QWindow> 0023 #include <QPointer> 0024 #include <QLayout> 0025 #include <QCloseEvent> 0026 #include <QFileInfo> 0027 #include <QFile> 0028 #include <QMenu> 0029 #include <QUrl> 0030 #include <QComboBox> 0031 #include <QPushButton> 0032 #include <QMessageBox> 0033 #include <QDir> 0034 0035 // KDE includes 0036 0037 #include <klocalizedstring.h> 0038 #include <ksharedconfig.h> 0039 #include <kconfiggroup.h> 0040 0041 // MediaWiki includes 0042 0043 #include "mediawiki_login.h" 0044 #include "mediawiki_iface.h" 0045 0046 // Local includes 0047 0048 #include "digikam_debug.h" 0049 #include "dmetadata.h" 0050 #include "wstoolutils.h" 0051 #include "ditemslist.h" 0052 #include "previewloadthread.h" 0053 #include "mediawikiwidget.h" 0054 #include "mediawikitalker.h" 0055 #include "dfileoperations.h" 0056 0057 using namespace MediaWiki; 0058 0059 namespace DigikamGenericMediaWikiPlugin 0060 { 0061 0062 class Q_DECL_HIDDEN MediaWikiWindow::Private 0063 { 0064 public: 0065 0066 explicit Private() 0067 { 0068 widget = nullptr; 0069 MediaWiki = nullptr; 0070 iface = nullptr; 0071 uploadTalker = nullptr; 0072 } 0073 0074 QString tmpDir; 0075 QString tmpPath; 0076 QString login; 0077 QString pass; 0078 QString wikiName; 0079 QUrl wikiUrl; 0080 0081 MediaWikiWidget* widget; 0082 Iface* MediaWiki; 0083 DInfoInterface* iface; 0084 MediaWikiTalker* uploadTalker; 0085 }; 0086 0087 MediaWikiWindow::MediaWikiWindow(DInfoInterface* const iface, QWidget* const /*parent*/) 0088 : WSToolDialog(nullptr, QLatin1String("MediaWiki export dialog")), 0089 d (new Private) 0090 { 0091 d->tmpPath.clear(); 0092 d->tmpDir = WSToolUtils::makeTemporaryDir("MediaWiki").absolutePath() + QLatin1Char('/'); 0093 d->widget = new MediaWikiWidget(iface, this); 0094 d->uploadTalker = nullptr; 0095 d->login = QString(); 0096 d->pass = QString(); 0097 d->iface = iface; 0098 0099 setMainWidget(d->widget); 0100 setModal(false); 0101 setWindowTitle(i18nc("@title:window", "Export to MediaWiki")); 0102 0103 startButton()->setText(i18nc("@action:button", "Start Upload")); 0104 startButton()->setToolTip(i18nc("@info:tooltip, button", "Start upload to MediaWiki")); 0105 0106 startButton()->setEnabled(false); 0107 0108 d->widget->setMinimumSize(700, 500); 0109 d->widget->installEventFilter(this); 0110 0111 connect(startButton(), SIGNAL(clicked()), 0112 this, SLOT(slotStartTransfer())); 0113 0114 connect(this, SIGNAL(finished(int)), 0115 this, SLOT(slotFinished())); 0116 0117 connect(d->widget, SIGNAL(signalChangeUserRequest()), 0118 this, SLOT(slotChangeUserClicked())); 0119 0120 connect(d->widget, SIGNAL(signalLoginRequest(QString,QString,QString,QUrl)), 0121 this, SLOT(slotDoLogin(QString,QString,QString,QUrl))); 0122 0123 connect(d->widget->progressBar(), SIGNAL(signalProgressCanceled()), 0124 this, SLOT(slotProgressCanceled())); 0125 0126 readSettings(); 0127 reactivate(); 0128 } 0129 0130 MediaWikiWindow::~MediaWikiWindow() 0131 { 0132 delete d; 0133 } 0134 0135 void MediaWikiWindow::closeEvent(QCloseEvent* e) 0136 { 0137 if (!e) 0138 { 0139 return; 0140 } 0141 0142 slotFinished(); 0143 e->accept(); 0144 } 0145 0146 void MediaWikiWindow::reactivate() 0147 { 0148 d->widget->imagesList()->listView()->clear(); 0149 d->widget->imagesList()->loadImagesFromCurrentSelection(); 0150 d->widget->loadItemInfoFirstLoad(); 0151 d->widget->clearEditFields(); 0152 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "imagesList items count:" << d->widget->imagesList()->listView()->topLevelItemCount(); 0153 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "imagesList url length:" << d->widget->imagesList()->imageUrls(false).size(); 0154 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "allImagesDesc length:" << d->widget->allImagesDesc().size(); 0155 show(); 0156 } 0157 0158 void MediaWikiWindow::readSettings() 0159 { 0160 KSharedConfigPtr config = KSharedConfig::openConfig(); 0161 KConfigGroup group = config->group(QLatin1String("MediaWiki export settings")); 0162 0163 d->widget->readSettings(group); 0164 } 0165 0166 void MediaWikiWindow::saveSettings() 0167 { 0168 KSharedConfigPtr config = KSharedConfig::openConfig(); 0169 KConfigGroup group = config->group(QLatin1String("MediaWiki export settings")); 0170 0171 d->widget->saveSettings(group); 0172 } 0173 0174 void MediaWikiWindow::slotFinished() 0175 { 0176 d->widget->progressBar()->progressCompleted(); 0177 saveSettings(); 0178 } 0179 0180 void MediaWikiWindow::slotProgressCanceled() 0181 { 0182 slotFinished(); 0183 reject(); 0184 } 0185 0186 bool MediaWikiWindow::prepareImageForUpload(const QString& imgPath) 0187 { 0188 // Create temporary directory if it does not exist 0189 0190 if (!QDir(d->tmpDir).exists()) 0191 { 0192 QDir().mkpath(d->tmpDir); 0193 } 0194 0195 // Get temporary file name 0196 0197 d->tmpPath = d->tmpDir + QFileInfo(imgPath).baseName().trimmed() + QLatin1String(".jpg"); 0198 0199 QImage image; 0200 0201 // Rescale image if requested: metadata is lost 0202 0203 if (d->widget->resize()) 0204 { 0205 image = PreviewLoadThread::loadHighQualitySynchronously(imgPath).copyQImage(); 0206 0207 if (image.isNull()) 0208 { 0209 image.load(imgPath); 0210 } 0211 0212 if (image.isNull()) 0213 { 0214 return false; 0215 } 0216 0217 int maxDim = d->widget->dimension(); 0218 0219 if (d->widget->resize() && (image.width() > maxDim || image.height() > maxDim)) 0220 { 0221 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Resizing to" << maxDim; 0222 image = image.scaled(maxDim, maxDim, Qt::KeepAspectRatio, Qt::SmoothTransformation); 0223 } 0224 0225 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Saving to temp file:" << d->tmpPath; 0226 image.save(d->tmpPath, "JPEG", d->widget->quality()); 0227 } 0228 else 0229 { 0230 // file is copied with its embedded metadata 0231 if (!DFileOperations::copyFile(imgPath, d->tmpPath)) 0232 { 0233 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "File copy error from:" << imgPath << "to" << d->tmpPath; 0234 return false; 0235 } 0236 } 0237 0238 // NOTE : In case of metadata are saved to tmp file, we will override metadata processor settings from host 0239 // to write metadata to image file rather than sidecar file, to be effective with remote web service. 0240 0241 QScopedPointer<DMetadata> meta(new DMetadata); 0242 meta->setMetadataWritingMode((int)DMetadata::WRITE_TO_FILE_ONLY); 0243 0244 if (d->widget->removeMeta()) 0245 { 0246 // save empty metadata to erase them 0247 meta->save(d->tmpPath); 0248 } 0249 else 0250 { 0251 // copy meta data from initial to temporary image 0252 0253 if (meta->load(imgPath)) 0254 { 0255 if (d->widget->resize()) 0256 { 0257 meta->setItemDimensions(image.size()); 0258 } 0259 0260 if (d->widget->removeGeo()) 0261 { 0262 meta->removeGPSInfo(); 0263 } 0264 0265 meta->setItemOrientation(MetaEngine::ORIENTATION_NORMAL); 0266 meta->save(d->tmpPath, true); 0267 } 0268 } 0269 0270 return true; 0271 } 0272 0273 void MediaWikiWindow::slotStartTransfer() 0274 { 0275 saveSettings(); 0276 QList<QUrl> urls = d->widget->imagesList()->imageUrls(false); 0277 QMap <QString, QMap <QString, QString> > imagesDesc = d->widget->allImagesDesc(); 0278 0279 for (int i = 0 ; i < urls.size() ; ++i) 0280 { 0281 QString url; 0282 0283 if (d->widget->resize() || d->widget->removeMeta() || d->widget->removeGeo()) 0284 { 0285 prepareImageForUpload(urls.at(i).toLocalFile()); 0286 imagesDesc.insert(d->tmpPath, imagesDesc.take(urls.at(i).toLocalFile())); 0287 } 0288 } 0289 0290 d->uploadTalker->setImageMap(imagesDesc); 0291 0292 d->widget->progressBar()->setRange(0, 100); 0293 d->widget->progressBar()->setValue(0); 0294 0295 connect(d->uploadTalker, SIGNAL(signalUploadProgress(int)), 0296 d->widget->progressBar(), SLOT(setValue(int))); 0297 0298 connect(d->uploadTalker, SIGNAL(signalEndUpload()), 0299 this, SLOT(slotEndUpload())); 0300 0301 d->widget->progressBar()->show(); 0302 d->widget->progressBar()->progressScheduled(i18n("MediaWiki export"), true, true); 0303 d->widget->progressBar()->progressThumbnailChanged( 0304 QIcon::fromTheme(QLatin1String("dk-mediawiki")).pixmap(22, 22)); 0305 d->uploadTalker->slotBegin(); 0306 } 0307 0308 void MediaWikiWindow::slotChangeUserClicked() 0309 { 0310 startButton()->setEnabled(false); 0311 d->widget->invertAccountLoginBox(); 0312 } 0313 0314 void MediaWikiWindow::slotDoLogin(const QString& login, const QString& pass, const QString& wikiName, const QUrl& wikiUrl) 0315 { 0316 d->login = login; 0317 d->pass = pass; 0318 d->wikiName = wikiName; 0319 d->wikiUrl = wikiUrl; 0320 d->MediaWiki = new Iface(wikiUrl); 0321 Login* const loginJob = new Login(*d->MediaWiki, login, pass); 0322 0323 connect(loginJob, SIGNAL(result(KJob*)), 0324 this, SLOT(slotLoginHandle(KJob*))); 0325 0326 loginJob->start(); 0327 } 0328 0329 int MediaWikiWindow::slotLoginHandle(KJob* loginJob) 0330 { 0331 qCDebug(DIGIKAM_WEBSERVICES_LOG) << loginJob->error() << loginJob->errorString() << loginJob->errorText(); 0332 0333 if (loginJob->error()) 0334 { 0335 d->login.clear(); 0336 d->pass.clear(); 0337 d->uploadTalker = nullptr; 0338 QMessageBox::critical(this, i18nc("@title:window", "Login Error"), i18n("Please check your credentials and try again.")); 0339 } 0340 else 0341 { 0342 d->uploadTalker = new MediaWikiTalker(d->iface, d->MediaWiki, this); 0343 startButton()->setEnabled(true); 0344 d->widget->invertAccountLoginBox(); 0345 d->widget->updateLabels(d->login, d->wikiName, d->wikiUrl.toString()); 0346 } 0347 0348 return loginJob->error(); 0349 } 0350 0351 void MediaWikiWindow::slotEndUpload() 0352 { 0353 disconnect(d->uploadTalker, SIGNAL(signalUploadProgress(int)), 0354 d->widget->progressBar(),SLOT(setValue(int))); 0355 0356 disconnect(d->uploadTalker, SIGNAL(signalEndUpload()), 0357 this, SLOT(slotEndUpload())); 0358 0359 QMessageBox::information(this, QString(), i18n("Upload finished with no errors.")); 0360 d->widget->progressBar()->hide(); 0361 d->widget->progressBar()->progressCompleted(); 0362 } 0363 0364 bool MediaWikiWindow::eventFilter(QObject* /*obj*/, QEvent* event) 0365 { 0366 if (event->type() == QEvent::KeyRelease) 0367 { 0368 QKeyEvent* const c = dynamic_cast<QKeyEvent *>(event); 0369 0370 if (c && c->key() == Qt::Key_Return) 0371 { 0372 event->ignore(); 0373 qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Key event pass"; 0374 return false; 0375 0376 } 0377 } 0378 0379 return true; 0380 } 0381 0382 } // namespace DigikamGenericMediaWikiPlugin 0383 0384 #include "moc_mediawikiwindow.cpp"