1 /* ============================================================
2 *
3 * This file is a part of KDE project
4 *
5 *
6 * Date : 2011-02-11
7 * Description : A kipi plugin to export images to a MediaWiki wiki
8 *
9 * Copyright (C) 2011 by Alexandre Mendes <alex dot mendes1988 at gmail dot com>
10 * Copyright (C) 2011-2018 by Gilles Caulier <caulier dot gilles at gmail dot com>
11 * Copyright (C) 2012 by Parthasarathy Gopavarapu <gparthasarathy93 at gmail dot com>
12 * Copyright (C) 2012-2016 by Peter Potrowl <peter dot potrowl at gmail dot com>
13 *
14 * This program is free software; you can redistribute it
15 * and/or modify it under the terms of the GNU General
16 * Public License as published by the Free Software Foundation;
17 * either version 2, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * ============================================================ */
25
26 #include "wmwindow.h"
27
28 // Qt includes
29
30 #include <QWindow>
31 #include <QPointer>
32 #include <QLayout>
33 #include <QCloseEvent>
34 #include <QFileInfo>
35 #include <QFile>
36 #include <QMenu>
37 #include <QUrl>
38 #include <QComboBox>
39 #include <QPushButton>
40 #include <QMessageBox>
41 #include <QDir>
42
43 // KDE includes
44
45 #include <kconfig.h>
46 #include <klocalizedstring.h>
47 #include <kwindowconfig.h>
48
49 // MediaWiki includes
50
51 #include <MediaWiki/Login>
52 #include <MediaWiki/MediaWiki>
53 #include <mediawiki_version.h>
54
55 // KIPI includes
56
57 #include <KIPI/Interface>
58 #include <KIPI/ImageCollection>
59
60 // Local includes
61
62 #include "kipiplugins_debug.h"
63 #include "kpaboutdata.h"
64 #include "kpimageinfo.h"
65 #include "kpimageslist.h"
66 #include "kpprogresswidget.h"
67 #include "wmwidget.h"
68 #include "wmtalker.h"
69
70 using namespace KIPI;
71 using namespace mediawiki;
72
73 namespace KIPIWikiMediaPlugin
74 {
75
76 class WMWindow::Private
77 {
78 public:
79
Private()80 Private()
81 {
82 widget = nullptr;
83 mediawiki = nullptr;
84 uploadTalker = nullptr;
85 }
86
87 QString tmpDir;
88 QString tmpPath;
89 QString login;
90 QString pass;
91 QString wikiName;
92 QUrl wikiUrl;
93
94 WmWidget* widget;
95 MediaWiki* mediawiki;
96
97 WMTalker* uploadTalker;
98 };
99
WMWindow(const QString & tmpFolder,QWidget * const)100 WMWindow::WMWindow(const QString& tmpFolder, QWidget* const /*parent*/)
101 : KPToolDialog(nullptr),
102 d(new Private)
103 {
104 d->tmpPath.clear();
105 d->tmpDir = tmpFolder;
106 d->widget = new WmWidget(this);
107 d->uploadTalker = nullptr;
108 d->login = QString();
109 d->pass = QString();
110
111 setMainWidget(d->widget);
112 setWindowIcon(QIcon::fromTheme(QLatin1String("kipi-wikimedia")));
113 setModal(false);
114 setWindowTitle(i18n("Export to MediaWiki"));
115
116 startButton()->setText(i18n("Start Upload"));
117 startButton()->setToolTip(i18n("Start upload to MediaWiki"));
118
119 startButton()->setEnabled(false);
120
121 d->widget->setMinimumSize(700, 500);
122 d->widget->installEventFilter(this);
123
124 KPAboutData* const about = new KPAboutData(ki18n("MediaWiki export"),
125 ki18n("A tool to export image collection "
126 "to a MediaWiki installation.\n"
127 "Using libmediawiki version %1").subs(QLatin1String(MEDIAWIKI_VERSION_STRING)),
128 ki18n("(c) 2011, Alexandre Mendes"));
129
130 about->addAuthor(ki18n("Alexandre Mendes").toString(),
131 ki18n("Author").toString(),
132 QLatin1String("alex dot mendes1988 at gmail dot com"));
133
134 about->addAuthor(ki18n("Guillaume Hormiere").toString(),
135 ki18n("Developer").toString(),
136 QLatin1String("hormiere dot guillaume at gmail dot com"));
137
138 about->addAuthor(ki18n("Gilles Caulier").toString(),
139 ki18n("Developer").toString(),
140 QLatin1String("caulier dot gilles at gmail dot com"));
141
142 about->addAuthor(ki18n("Peter Potrowl").toString(),
143 ki18n("Developer").toString(),
144 QLatin1String("peter dot potrowl at gmail dot com"));
145
146 about->setHandbookEntry(QLatin1String("tool-wikimediaexport"));
147 setAboutData(about);
148
149 connect(startButton(), SIGNAL(clicked()),
150 this, SLOT(slotStartTransfer()));
151
152 connect(this, SIGNAL(finished(int)),
153 this, SLOT(slotFinished()));
154
155 connect(d->widget, SIGNAL(signalChangeUserRequest()),
156 this, SLOT(slotChangeUserClicked()));
157
158 connect(d->widget, SIGNAL(signalLoginRequest(QString, QString, QString, QUrl)),
159 this, SLOT(slotDoLogin(QString, QString, QString, QUrl)));
160
161 connect(d->widget->progressBar(), SIGNAL(signalProgressCanceled()),
162 this, SLOT(slotProgressCanceled()));
163
164 readSettings();
165 reactivate();
166 }
167
~WMWindow()168 WMWindow::~WMWindow()
169 {
170 delete d;
171 }
172
closeEvent(QCloseEvent * e)173 void WMWindow::closeEvent(QCloseEvent* e)
174 {
175 if (!e)
176 {
177 return;
178 }
179
180 slotFinished();
181 e->accept();
182 }
183
reactivate()184 void WMWindow::reactivate()
185 {
186 d->widget->imagesList()->listView()->clear();
187 d->widget->imagesList()->loadImagesFromCurrentSelection();
188 d->widget->loadImageInfoFirstLoad();
189 d->widget->clearEditFields();
190 qCDebug(KIPIPLUGINS_LOG) << "imagesList items count:" << d->widget->imagesList()->listView()->topLevelItemCount();
191 qCDebug(KIPIPLUGINS_LOG) << "imagesList url length:" << d->widget->imagesList()->imageUrls(false).size();
192 qCDebug(KIPIPLUGINS_LOG) << "allImagesDesc length:" << d->widget->allImagesDesc().size();
193 show();
194 }
195
readSettings()196 void WMWindow::readSettings()
197 {
198 KConfig config(QLatin1String("kipirc"));
199 KConfigGroup group = config.group(QLatin1String("MediaWiki export settings"));
200
201 d->widget->readSettings(group);
202
203 winId();
204 KConfigGroup group2 = config.group(QLatin1String("MediaWiki export dialog"));
205 KWindowConfig::restoreWindowSize(windowHandle(), group2);
206 resize(windowHandle()->size());
207 }
208
saveSettings()209 void WMWindow::saveSettings()
210 {
211 KConfig config(QLatin1String("kipirc"));
212 KConfigGroup group = config.group(QLatin1String("MediaWiki export settings"));
213
214 d->widget->saveSettings(group);
215
216 KConfigGroup group2 = config.group(QLatin1String("MediaWiki export dialog"));
217 KWindowConfig::saveWindowSize(windowHandle(), group2);
218 config.sync();
219 }
220
slotFinished()221 void WMWindow::slotFinished()
222 {
223 d->widget->progressBar()->progressCompleted();
224 saveSettings();
225 }
226
slotProgressCanceled()227 void WMWindow::slotProgressCanceled()
228 {
229 slotFinished();
230 reject();
231 }
232
prepareImageForUpload(const QString & imgPath)233 bool WMWindow::prepareImageForUpload(const QString& imgPath)
234 {
235 // Create temporary directory if it does not exist
236
237 if (!QDir(d->tmpDir).exists())
238 {
239 QDir().mkdir(d->tmpDir);
240 }
241
242 // Get temporary file name
243
244 d->tmpPath = d->tmpDir + QFileInfo(imgPath).baseName().trimmed() + QLatin1String(".jpg");
245
246 QImage image;
247
248 // Rescale image if requested: metadata is lost
249
250 if (d->widget->resize())
251 {
252 if (iface())
253 {
254 image = iface()->preview(QUrl::fromLocalFile(imgPath));
255 }
256
257 if (image.isNull())
258 {
259 image.load(imgPath);
260 }
261
262 if (image.isNull())
263 {
264 return false;
265 }
266
267 int maxDim = d->widget->dimension();
268
269 if (d->widget->resize() && (image.width() > maxDim || image.height() > maxDim))
270 {
271 qCDebug(KIPIPLUGINS_LOG) << "Resizing to" << maxDim;
272 image = image.scaled(maxDim, maxDim, Qt::KeepAspectRatio, Qt::SmoothTransformation);
273 }
274
275 qCDebug(KIPIPLUGINS_LOG) << "Saving to temp file:" << d->tmpPath;
276 image.save(d->tmpPath, "JPEG", d->widget->quality());
277 }
278 else
279 {
280 // file is copied with its embedded metadata
281 if (!QFile::copy(imgPath, d->tmpPath))
282 {
283 qCDebug(KIPIPLUGINS_LOG) << "File copy error from:" << imgPath << "to" << d->tmpPath;
284 return false;
285 }
286 }
287
288 if (iface())
289 {
290 // NOTE : In case of metadata are saved to tmp file, we will override MetadataProcessor settings from KIPI host
291 // to write metadata to image file rather than sidecar file, to be effective with remote web service.
292
293 QPointer<MetadataProcessor> meta = iface()->createMetadataProcessor();
294
295 if (d->widget->removeMeta())
296 {
297 // save empty metadata to erase them
298 meta->save(QUrl::fromLocalFile(d->tmpPath), true);
299 }
300 else
301 {
302 // copy meta data from initial to temporary image
303
304 if (meta->load(QUrl::fromLocalFile(imgPath)))
305 {
306 if (d->widget->resize())
307 {
308 meta->setImageDimensions(image.size());
309 }
310
311 if (d->widget->removeGeo())
312 {
313 meta->removeGPSInfo();
314 }
315
316 meta->setImageOrientation(MetadataProcessor::NORMAL);
317 meta->save(QUrl::fromLocalFile(d->tmpPath), true);
318 }
319 }
320 }
321
322 return true;
323 }
324
slotStartTransfer()325 void WMWindow::slotStartTransfer()
326 {
327 saveSettings();
328 QList<QUrl> urls = d->widget->imagesList()->imageUrls(false);
329 QMap <QString, QMap <QString, QString> > imagesDesc = d->widget->allImagesDesc();
330
331 for (int i = 0; i < urls.size(); ++i)
332 {
333 QString url;
334
335 if (d->widget->resize() || d->widget->removeMeta() || d->widget->removeGeo())
336 {
337 prepareImageForUpload(urls.at(i).toLocalFile());
338 imagesDesc.insert(d->tmpPath, imagesDesc.take(urls.at(i).toLocalFile()));
339 }
340 }
341
342 d->uploadTalker->setImageMap(imagesDesc);
343
344 d->widget->progressBar()->setRange(0, 100);
345 d->widget->progressBar()->setValue(0);
346
347 connect(d->uploadTalker, SIGNAL(uploadProgress(int)),
348 d->widget->progressBar(), SLOT(setValue(int)));
349
350 connect(d->uploadTalker, SIGNAL(endUpload()),
351 this, SLOT(slotEndUpload()));
352
353 d->widget->progressBar()->show();
354 d->widget->progressBar()->progressScheduled(i18n("MediaWiki export"), true, true);
355 d->widget->progressBar()->progressThumbnailChanged(QIcon(QLatin1String(":/icons/kipi-icon.svg")).pixmap(22, 22));
356 d->uploadTalker->begin();
357 }
358
slotChangeUserClicked()359 void WMWindow::slotChangeUserClicked()
360 {
361 startButton()->setEnabled(false);
362 d->widget->invertAccountLoginBox();
363 }
364
slotDoLogin(const QString & login,const QString & pass,const QString & wikiName,const QUrl & wikiUrl)365 void WMWindow::slotDoLogin(const QString& login, const QString& pass, const QString& wikiName, const QUrl& wikiUrl)
366 {
367 d->login = login;
368 d->pass = pass;
369 d->wikiName = wikiName;
370 d->wikiUrl = wikiUrl;
371 d->mediawiki = new MediaWiki(wikiUrl);
372 Login* const loginJob = new Login(*d->mediawiki, login, pass);
373
374 connect(loginJob, SIGNAL(result(KJob*)),
375 this, SLOT(slotLoginHandle(KJob*)));
376
377 loginJob->start();
378 }
379
slotLoginHandle(KJob * loginJob)380 int WMWindow::slotLoginHandle(KJob* loginJob)
381 {
382 qCDebug(KIPIPLUGINS_LOG) << loginJob->error() << loginJob->errorString() << loginJob->errorText();
383
384 if (loginJob->error())
385 {
386 d->login.clear();
387 d->pass.clear();
388 d->uploadTalker = nullptr;
389 QMessageBox::critical(this, i18n("Login Error"), i18n("Please check your credentials and try again."));
390 }
391 else
392 {
393 d->uploadTalker = new WMTalker(iface(), d->mediawiki, this);
394 startButton()->setEnabled(true);
395 d->widget->invertAccountLoginBox();
396 d->widget->updateLabels(d->login, d->wikiName, d->wikiUrl.toString());
397 }
398
399 return loginJob->error();
400 }
401
slotEndUpload()402 void WMWindow::slotEndUpload()
403 {
404 disconnect(d->uploadTalker, SIGNAL(uploadProgress(int)),
405 d->widget->progressBar(),SLOT(setValue(int)));
406
407 disconnect(d->uploadTalker, SIGNAL(endUpload()),
408 this, SLOT(slotEndUpload()));
409
410 QMessageBox::information(this, QString(), i18n("Upload finished with no errors."));
411 d->widget->progressBar()->hide();
412 d->widget->progressBar()->progressCompleted();
413 }
414
eventFilter(QObject *,QEvent * event)415 bool WMWindow::eventFilter(QObject* /*obj*/, QEvent* event)
416 {
417 if (event->type() == QEvent::KeyRelease)
418 {
419 QKeyEvent* const c = dynamic_cast<QKeyEvent *>(event);
420
421 if (c && c->key() == Qt::Key_Return)
422 {
423 event->ignore();
424 qCDebug(KIPIPLUGINS_LOG) << "Key event pass";
425 return false;
426
427 }
428 }
429
430 return true;
431 }
432
433 } // namespace KIPIWikiMediaPlugin
434