KNewStuff

uploaddialog.cpp
1 /*
2  knewstuff3/ui/uploaddialog.cpp.
3  SPDX-FileCopyrightText: 2002 Cornelius Schumacher <[email protected]>
4  SPDX-FileCopyrightText: 2009 Jeremy Whiting <[email protected]>
5  SPDX-FileCopyrightText: 2009-2010 Frederik Gladhorn <[email protected]>
6 
7  SPDX-License-Identifier: LGPL-2.1-or-later
8 */
9 
10 #include "uploaddialog.h"
11 #include "uploaddialog_p.h"
12 #include "ui/widgetquestionlistener.h"
13 
14 #include <QDialogButtonBox>
15 #include <QFileDialog>
16 #include <QImageReader>
17 #include <QLayout>
18 #include <QPointer>
19 #include <QString>
20 #include <QCoreApplication>
21 
22 #include <KIconLoader>
23 #include <KMessageBox>
24 #include <KLocalizedString>
25 
26 #include <KPixmapSequence>
27 #include <KPixmapSequenceWidget>
28 #include <KIO/OpenUrlJob>
29 #include <KIO/JobUiDelegate>
30 
31 #include <knewstuff_debug.h>
32 #include <QLoggingCategory>
33 #include <KConfig>
34 #include <KConfigGroup>
35 #include <qstandardpaths.h>
36 
37 using namespace KNS3;
38 
39 bool UploadDialogPrivate::init(const QString &configfile)
40 {
41  QVBoxLayout *layout = new QVBoxLayout;
42  q->setLayout(layout);
43 
44  QWidget *_mainWidget = new QWidget(q);
45  ui.setupUi(_mainWidget);
46 
47  layout->addWidget(_mainWidget);
48 
49  backButton = new QPushButton;
50  KGuiItem::assign(backButton, KStandardGuiItem::back(KStandardGuiItem::UseRTL));
51 
52  nextButton = new QPushButton;
53  nextButton->setText(i18nc("Opposite to Back", "Next"));
54  nextButton->setIcon(KStandardGuiItem::forward(KStandardGuiItem::UseRTL).icon());
55  nextButton->setDefault(true);
56 
57  finishButton = new QPushButton;
58  finishButton->setText(i18n("Finish"));
59  finishButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-ok-apply")));
60 
61  buttonBox = new QDialogButtonBox(q);
62  buttonBox->addButton(backButton, QDialogButtonBox::ActionRole);
63  buttonBox->addButton(nextButton, QDialogButtonBox::ActionRole);
64  buttonBox->addButton(finishButton, QDialogButtonBox::AcceptRole);
65  buttonBox->setStandardButtons(QDialogButtonBox::Cancel);
66  layout->addWidget(buttonBox);
67 
68  atticaHelper = new KNSCore::AtticaHelper(q);
69 
70  bool success = true;
71  QFileInfo fi(configfile);
72  if (!fi.exists()) {
73  if (!fi.isAbsolute())
75  if (!fi.exists()) {
76  qCCritical(KNEWSTUFF) << "No knsrc file named '" << fi.absoluteFilePath() << "' was found.";
77  success = false;
78  }
79  }
80 
81  KConfig conf(fi.absoluteFilePath());
82  if (conf.accessMode() == KConfig::NoAccess) {
83  qCCritical(KNEWSTUFF) << "Knsrc file named '" << fi.absoluteFilePath() << "' could not be accessed.";
84  success = false;
85  }
86 
87  KConfigGroup group;
88  if (conf.hasGroup("KNewStuff3")) {
89  qCDebug(KNEWSTUFF) << "Loading KNewStuff3 config: " << fi.absoluteFilePath();
90  group = conf.group("KNewStuff3");
91  } else {
92  qCCritical(KNEWSTUFF) << "A knsrc file was found but it doesn't contain a KNewStuff3 section." << fi.absoluteFilePath();
93  success = false;
94  }
95 
96  if (success) {
97  const QString providersFileUrl = group.readEntry("ProvidersUrl");
98 
99  categoryNames = group.readEntry("UploadCategories", QStringList());
100  // fall back to download categories
101  if (categoryNames.isEmpty()) {
102  categoryNames = group.readEntry("Categories", QStringList());
103  }
104 
105  atticaHelper->addProviderFile(QUrl(providersFileUrl));
106  }
107 
108  ui.mCategoryCombo->addItems(categoryNames);
109 
110  if (categoryNames.size() == 1) {
111  ui.mCategoryLabel->setVisible(false);
112  ui.mCategoryCombo->setVisible(false);
113  }
114 
115  qCDebug(KNEWSTUFF) << "Categories: " << categoryNames;
116 
117  q->connect(atticaHelper, SIGNAL(providersLoaded(QStringList)), q, SLOT(_k_providersLoaded(QStringList)));
118  q->connect(atticaHelper, SIGNAL(loginChecked(bool)), q, SLOT(_k_checkCredentialsFinished(bool)));
119  q->connect(atticaHelper, SIGNAL(licensesLoaded(Attica::License::List)), q, SLOT(_k_licensesLoaded(Attica::License::List)));
120  q->connect(atticaHelper, SIGNAL(categoriesLoaded(Attica::Category::List)), q, SLOT(_k_categoriesLoaded(Attica::Category::List)));
121  q->connect(atticaHelper, SIGNAL(contentByCurrentUserLoaded(Attica::Content::List)), q, SLOT(_k_contentByCurrentUserLoaded(Attica::Content::List)));
122  q->connect(atticaHelper, SIGNAL(contentLoaded(Attica::Content)), q, SLOT(_k_updatedContentFetched(Attica::Content)));
123  q->connect(atticaHelper, SIGNAL(detailsLinkLoaded(QUrl)), q, SLOT(_k_detailsLinkLoaded(QUrl)));
124  q->connect(atticaHelper, SIGNAL(currencyLoaded(QString)), q, SLOT(_k_currencyLoaded(QString)));
125  q->connect(atticaHelper, SIGNAL(previewLoaded(int,QImage)), q, SLOT(_k_previewLoaded(int,QImage)));
126  atticaHelper->init();
127 
128  q->connect(ui.changePreview1Button, SIGNAL(clicked()), q, SLOT(_k_changePreview1()));
129  q->connect(ui.changePreview2Button, SIGNAL(clicked()), q, SLOT(_k_changePreview2()));
130  q->connect(ui.changePreview3Button, SIGNAL(clicked()), q, SLOT(_k_changePreview3()));
131 
132  q->connect(ui.providerComboBox, SIGNAL(currentIndexChanged(QString)), q, SLOT(_k_providerChanged(QString)));
133  q->connect(ui.radioUpdate, SIGNAL(toggled(bool)), q, SLOT(_k_updateContentsToggled(bool)));
134 
135  q->connect(ui.registerNewAccountLabel, SIGNAL(linkActivated(QString)), q, SLOT(_k_openRegisterAccountWebpage(QString)));
136 
137  //Busy widget
138  busyWidget = new KPixmapSequenceWidget();
139  busyWidget->setSequence(KIconLoader::global()->loadPixmapSequence(QStringLiteral("process-working"), 22));
140  busyWidget->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
141  ui.busyWidget->setLayout(new QHBoxLayout());
142  ui.busyWidget->layout()->addWidget(busyWidget);
143  busyWidget->setVisible(false);
144 
145  WidgetQuestionListener::instance();
146 
147  return success;
148 }
149 
150 void UploadDialogPrivate::setBusy(const QString &message)
151 {
152  ui.busyLabel->setText(message);
153  busyWidget->setVisible(true);
154 }
155 
156 void UploadDialogPrivate::setIdle(const QString &message)
157 {
158  ui.busyLabel->setText(message);
159  busyWidget->setVisible(false);
160 }
161 
162 void UploadDialogPrivate::_k_showPage(int page)
163 {
164  ui.stackedWidget->setCurrentIndex(page);
165  setIdle(QString());
166 
167  switch (ui.stackedWidget->currentIndex()) {
168  case UserPasswordPage:
169  ui.username->setFocus();
170  setBusy(i18n("Fetching provider information..."));
171  break;
172 
173  case FileNewUpdatePage:
174  atticaHelper->loadLicenses();
175  atticaHelper->loadCurrency();
176  ui.uploadButton->setFocus();
177  setBusy(i18n("Fetching license data from server..."));
178  break;
179 
180  case Details1Page:
181  if (ui.radioUpdate->isChecked()) {
182  // Fetch
183  atticaHelper->loadContent(ui.userContentList->currentItem()->data(Qt::UserRole).toString());
184  setBusy(i18n("Fetching content data from server..."));
185  }
186 
187  ui.mNameEdit->setFocus();
188  break;
189 
190  case UploadFinalPage:
191  if (previewFile1.isEmpty()) {
192  ui.uploadPreview1ImageLabel->setVisible(false);
193  ui.uploadPreview1Label->setVisible(false);
194  }
195  if (previewFile2.isEmpty()) {
196  ui.uploadPreview2ImageLabel->setVisible(false);
197  ui.uploadPreview2Label->setVisible(false);
198  }
199  if (previewFile3.isEmpty()) {
200  ui.uploadPreview3ImageLabel->setVisible(false);
201  ui.uploadPreview3Label->setVisible(false);
202  }
203  break;
204  }
205 
206  _k_updatePage();
207 }
208 
209 void UploadDialogPrivate::_k_updatePage()
210 {
211  bool firstPage = ui.stackedWidget->currentIndex() == 0;
212  backButton->setEnabled(!firstPage && !finished);
213 
214  bool nextEnabled = false;
215  switch (ui.stackedWidget->currentIndex()) {
216  case UserPasswordPage:
217  if (ui.providerComboBox->count() > 0 && !ui.username->text().isEmpty() && !ui.password->text().isEmpty()) {
218  nextEnabled = true;
219  }
220  break;
221 
222  case FileNewUpdatePage:
223  // FIXME: check if the file requester contains a valid file
224  if (!uploadFile.isEmpty() || ui.uploadFileRequester->url().isLocalFile()) {
225  if (ui.radioNewUpload->isChecked() || ui.userContentList->currentRow() >= 0) {
226  nextEnabled = true;
227  }
228  }
229  break;
230 
231  case Details1Page:
232  if (!ui.mNameEdit->text().isEmpty()) {
233  nextEnabled = true;
234  }
235  break;
236 
237  case Details2Page:
238  nextEnabled = true;
239  break;
240 
241  case UploadFinalPage:
242  break;
243  }
244 
245  nextButton->setEnabled(nextEnabled);
246  finishButton->setEnabled(finished);
247 
248  nextButton->setDefault(nextEnabled);
249  finishButton->setDefault(!nextEnabled);
250 
251  if (nextEnabled && buttonBox->button(QDialogButtonBox::Cancel)->hasFocus()) {
252  nextButton->setFocus();
253  }
254 }
255 
256 void UploadDialogPrivate::_k_providersLoaded(const QStringList &providers)
257 {
258  if (providers.isEmpty()) {
259  setIdle(i18n("Could not fetch provider information."));
260  ui.stackedWidget->setEnabled(false);
261  qWarning() << "Could not load providers.";
262  return;
263  }
264  setIdle(QString());
265  ui.providerComboBox->addItems(providers);
266  ui.providerComboBox->setCurrentIndex(0);
267  atticaHelper->setCurrentProvider(providers.at(0));
268 
269  QString user;
270  QString pass;
271  if (atticaHelper->loadCredentials(user, pass)) {
272  ui.username->setText(user);
273  ui.password->setText(pass);
274  }
275  _k_updatePage();
276 }
277 
278 void UploadDialogPrivate::_k_providerChanged(const QString &providerName)
279 {
280  atticaHelper->setCurrentProvider(providerName);
281  QString registerUrl = atticaHelper->provider().getRegisterAccountUrl();
282  if (! registerUrl.isEmpty()) {
283  ui.registerNewAccountLabel->setText(QStringLiteral("<a href=\"register\">") + i18n("Register a new account") + QStringLiteral("</a>"));
284  } else {
285  ui.registerNewAccountLabel->setText(QString());
286  }
287  ui.username->clear();
288  ui.password->clear();
289  QString user;
290  QString pass;
291  if (atticaHelper->loadCredentials(user, pass)) {
292  ui.username->setText(user);
293  ui.password->setText(pass);
294  }
295  _k_updatePage();
296 }
297 
298 void UploadDialogPrivate::_k_backPage()
299 {
300  _k_showPage(ui.stackedWidget->currentIndex() - 1);
301 }
302 
303 void UploadDialogPrivate::_k_nextPage()
304 {
305  // TODO: validate credentials after user name/password have been entered
306  if (ui.stackedWidget->currentIndex() == UserPasswordPage) {
307  setBusy(i18n("Checking login..."));
308  nextButton->setEnabled(false);
309  ui.providerComboBox->setEnabled(false);
310  ui.username->setEnabled(false);
311  ui.password->setEnabled(false);
312  atticaHelper->checkLogin(ui.username->text(), ui.password->text());
313  } else {
314  _k_showPage(ui.stackedWidget->currentIndex() + 1);
315  }
316 }
317 
318 void UploadDialogPrivate::_k_checkCredentialsFinished(bool success)
319 {
320  ui.providerComboBox->setEnabled(true);
321  ui.username->setEnabled(true);
322  ui.password->setEnabled(true);
323 
324  if (success) {
325  atticaHelper->saveCredentials(ui.username->text(), ui.password->text());
326  _k_showPage(FileNewUpdatePage);
327 
328  atticaHelper->loadCategories(categoryNames);
329  setBusy(i18n("Fetching your previously updated content..."));
330  } else {
331  // TODO check what the actual error is
332  setIdle(i18n("Could not verify login, please try again."));
333  }
334 }
335 
336 void UploadDialogPrivate::_k_licensesLoaded(const Attica::License::List &licenses)
337 {
338  ui.mLicenseCombo->clear();
339  for (const Attica::License &license : licenses) {
340  ui.mLicenseCombo->addItem(license.name(), license.id());
341  }
342 }
343 
344 void UploadDialogPrivate::_k_currencyLoaded(const QString &currency)
345 {
346  ui.priceCurrency->setText(currency);
347 }
348 
349 void UploadDialogPrivate::_k_contentByCurrentUserLoaded(const Attica::Content::List &contentList)
350 {
351  setIdle(i18n("Fetching your previously updated content finished."));
352 
353  for (const Attica::Content &content : contentList) {
354  QListWidgetItem *contentItem = new QListWidgetItem(content.name());
355  contentItem->setData(Qt::UserRole, content.id());
356  ui.userContentList->addItem(contentItem);
357  }
358 
359  if (ui.userContentList->count() > 0) {
360  ui.userContentList->setCurrentRow(0);
361  ui.radioUpdate->setEnabled(true);
362  _k_updatePage();
363  }
364 
365 }
366 
367 void UploadDialogPrivate::_k_updatedContentFetched(const Attica::Content &content)
368 {
369  setIdle(i18n("Fetching content data from server finished."));
370 
371  contentId = content.id();
372  // fill in ui
373  ui.mNameEdit->setText(content.name());
374  ui.mSummaryEdit->setText(content.description());
375  ui.mVersionEdit->setText(content.version());
376  ui.changelog->setText(content.changelog());
377  ui.priceCheckBox->setChecked(content.attribute(QStringLiteral("downloadbuy1")) == QLatin1Char('1'));
378  ui.priceSpinBox->setValue(content.attribute(QStringLiteral("downloadbuyprice1")).toDouble());
379  ui.priceReasonLineEdit->setText(content.attribute(QStringLiteral("downloadbuyreason1")));
380 
381  bool conversionOk = false;
382  int licenseNumber = content.license().toInt(&conversionOk);
383  if (conversionOk) {
384  // check if that int is in list
385  int row = ui.mLicenseCombo->findData(licenseNumber, Qt::UserRole);
386  ui.mLicenseCombo->setCurrentIndex(row);
387  } else {
388  ui.mLicenseCombo->setEditText(content.license());
389  }
390 
391  ui.contentWebsiteLink->setText(QLatin1String("<a href=\"") + content.detailpage().toString() + QLatin1String("\">")
392  + i18nc("A link to the website where the get hot new stuff upload can be seen", "Visit website") + QLatin1String("</a>"));
393  ui.fetchContentLinkImageLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(16));
394 }
395 
396 void UploadDialogPrivate::_k_previewLoaded(int index, const QImage &image)
397 {
398  switch (index) {
399  case 1:
400  ui.previewImage1->setPixmap(QPixmap::fromImage(image));
401  break;
402  case 2:
403  ui.previewImage2->setPixmap(QPixmap::fromImage(image));
404  break;
405  case 3:
406  ui.previewImage3->setPixmap(QPixmap::fromImage(image));
407  break;
408  }
409 }
410 
411 void UploadDialogPrivate::_k_updateContentsToggled(bool update)
412 {
413  ui.userContentList->setEnabled(update);
414 }
415 
417  : QDialog(parent), d(new UploadDialogPrivate(this))
418 {
420  init(name + QStringLiteral(".knsrc"));
421 }
422 
424  : QDialog(parent), d(new UploadDialogPrivate(this))
425 {
426  init(configFile);
427 }
428 
430 {
431  delete d;
432 }
433 
434 bool UploadDialog::init(const QString &configfile)
435 {
436  bool success = d->init(configfile);
437 
438  setWindowTitle(i18n("Share Hot New Stuff"));
439 
440  d->_k_updatePage();
441 
442  connect(d->ui.username, SIGNAL(textChanged(QString)), this, SLOT(_k_updatePage()));
443 
444  connect(d->ui.password, SIGNAL(textChanged(QString)), this, SLOT(_k_updatePage()));
445  connect(d->ui.mNameEdit, SIGNAL(textChanged(QString)), this, SLOT(_k_updatePage()));
446  connect(d->ui.uploadFileRequester, SIGNAL(textChanged(QString)), this, SLOT(_k_updatePage()));
447  connect(d->ui.priceCheckBox, SIGNAL(toggled(bool)), this, SLOT(_k_priceToggled(bool)));
448 
449  connect(d->ui.uploadButton, SIGNAL(clicked()), this, SLOT(_k_startUpload()));
450 
451  connect(d->backButton, SIGNAL(clicked()), this, SLOT(_k_backPage()));
452  connect(d->nextButton, SIGNAL(clicked()), this, SLOT(_k_nextPage()));
453  connect(d->buttonBox, &QDialogButtonBox::accepted, this, &UploadDialog::accept);
454  connect(d->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
455 
457  if (displayName.isEmpty()) {
458  displayName = QCoreApplication::applicationName();
459  }
460  d->ui.mTitleWidget->setText(i18nc("Program name followed by 'Add On Uploader'",
461  "%1 Add-On Uploader",
462  displayName));
463 
464  if (success) {
465  d->_k_showPage(0);
466  }
467 
468  return success;
469 }
470 
471 void UploadDialog::setUploadFile(const QUrl &payloadFile)
472 {
473  d->uploadFile = payloadFile;
474 
475  d->ui.uploadFileLabel->setVisible(false);
476  d->ui.uploadFileRequester->setVisible(false);
477 
478  QFile file(d->uploadFile.toLocalFile());
479  if (!file.open(QIODevice::ReadOnly)) {
480  KMessageBox::error(this, i18n("File not found: %1", d->uploadFile.url()), i18n("Upload Failed"));
481  }
482 }
483 
485 {
486  d->ui.mNameEdit->setText(name);
487 }
488 
490 {
491  d->ui.mCategoryCombo->setCurrentIndex(d->ui.mCategoryCombo->findText(category, Qt::MatchFixedString));
492 }
493 
494 void UploadDialog::setChangelog(const QString &changelog)
495 {
496  d->ui.changelog->setText(changelog);
497 }
498 
499 void UploadDialog::setDescription(const QString &description)
500 {
501  d->ui.mSummaryEdit->setText(description);
502 }
503 
505 {
506  d->ui.priceCheckBox->setVisible(enabled);
507  d->ui.priceGroupBox->setVisible(enabled);
508 }
509 
510 void UploadDialog::setPrice(double price)
511 {
512  d->ui.priceCheckBox->setEnabled(true);
513  d->ui.priceSpinBox->setValue(price);
514 }
515 
517 {
518  d->ui.priceReasonLineEdit->setText(reason);
519 }
520 
521 void UploadDialog::setVersion(const QString &version)
522 {
523  d->ui.mVersionEdit->setText(version);
524 }
525 
526 void UploadDialog::setPreviewImageFile(uint number, const QUrl &file)
527 {
528  QPixmap preview(file.toLocalFile());
529  switch (number) {
530  case 0 :
531  d->previewFile1 = file;
532  d->ui.previewImage1->setPixmap(preview.scaled(d->ui.previewImage1->size()));
533  break;
534  case 1 :
535  d->previewFile2 = file;
536  d->ui.previewImage2->setPixmap(preview.scaled(d->ui.previewImage2->size()));
537  break;
538  case 2 :
539  d->previewFile3 = file;
540  d->ui.previewImage3->setPixmap(preview.scaled(d->ui.previewImage3->size()));
541  break;
542  default :
543  qCCritical(KNEWSTUFF) << "Wrong preview image file number";
544  break;
545  }
546 }
547 
548 void UploadDialogPrivate::_k_priceToggled(bool priceEnabled)
549 {
550  ui.priceGroupBox->setEnabled(priceEnabled);
551 }
552 
553 void UploadDialogPrivate::_k_categoriesLoaded(const Attica::Category::List &loadedCategories)
554 {
555  categories = loadedCategories;
556 
557  // at least one category is needed
558  if (categories.isEmpty()) {
560  i18np("The server does not recognize the category %2 to which you are trying to upload.",
561  "The server does not recognize any of the categories to which you are trying to upload: %2",
562  categoryNames.size(), categoryNames.join(QLatin1String(", "))),
563  i18n("Error"));
564  // close the dialog
565  q->reject();
566  return;
567  }
568  for (const Attica::Category &c : qAsConst(categories)) {
569  ui.mCategoryCombo->addItem(c.name(), c.id());
570  }
571  atticaHelper->loadContentByCurrentUser();
572 }
573 
574 void UploadDialog::accept()
575 {
576  QDialog::accept();
577 }
578 
579 void UploadDialogPrivate::_k_startUpload()
580 {
581  // FIXME: this only works if categories are set in the .knsrc file
582  // TODO: ask for confirmation when closing the dialog
583 
584  backButton->setEnabled(false);
585  buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
586 
587  ui.uploadButton->setEnabled(false);
588 
589  // idle back and forth, we need a fix in attica to get at real progress values
590  ui.uploadProgressBar->setMinimum(0);
591  ui.uploadProgressBar->setMaximum(0);
592  ui.uploadProgressBar->setValue(0);
593 
594  // check the category
595  QString categoryName = ui.mCategoryCombo->currentText();
596  QList<Attica::Category>::const_iterator iter = categories.constBegin();
597  Attica::Category category;
598  QList<Attica::Category>::const_iterator iterEnd = categories.constEnd();
599  while (iter != iterEnd) {
600  if (iter->name() == categoryName) {
601  category = *iter;
602  break;
603  }
604  ++iter;
605  }
606  if (!category.isValid()) {
607  KMessageBox::error(q, i18n("The selected category \"%1\" is invalid.", categoryName), i18n("Upload Failed"));
608  return;
609  }
610 
611  // fill in the content object
612  Attica::Content content;
613  content.setName(ui.mNameEdit->text());
614  QString summary = ui.mSummaryEdit->toPlainText();
615  content.addAttribute(QStringLiteral("description"), summary);
616  content.addAttribute(QStringLiteral("version"), ui.mVersionEdit->text());
617 
618  // for the license, if one of the licenses coming from the server was used, pass its id, otherwise the string
619  QString licenseId = ui.mLicenseCombo->itemData(ui.mLicenseCombo->currentIndex()).toString();
620  if (licenseId.isEmpty()) {
621  // use other as type and add the string as text
622  content.addAttribute(QStringLiteral("licensetype"), QStringLiteral("0"));
623  content.addAttribute(QStringLiteral("license"), ui.mLicenseCombo->currentText());
624  } else {
625  content.addAttribute(QStringLiteral("licensetype"), licenseId);
626  }
627 
628  content.addAttribute(QStringLiteral("changelog"), ui.changelog->toPlainText());
629 
630  // TODO: add additional attributes
631  //content.addAttribute("downloadlink1", ui.link1->text());
632  //content.addAttribute("downloadlink2", ui.link2->text());
633  //content.addAttribute("homepage1", ui.homepage->text());
634  //content.addAttribute("blog1", ui.blog->text());
635 
636  content.addAttribute(QStringLiteral("downloadbuy1"), ui.priceCheckBox->isChecked() ? QStringLiteral("1") : QStringLiteral("0"));
637  content.addAttribute(QStringLiteral("downloadbuyprice1"), QString::number(ui.priceSpinBox->value()));
638  content.addAttribute(QStringLiteral("downloadbuyreason1"), ui.priceReasonLineEdit->text());
639 
640  if (ui.radioNewUpload->isChecked()) {
641  // upload a new content
642  Attica::ItemPostJob<Attica::Content> *job = currentProvider().addNewContent(category, content);
643  q->connect(job, SIGNAL(finished(Attica::BaseJob*)), q, SLOT(_k_contentAdded(Attica::BaseJob*)));
644  job->start();
645  } else {
646  // update old content
647  Attica::ItemPostJob<Attica::Content> *job = currentProvider().editContent(category, ui.userContentList->currentItem()->data(Qt::UserRole).toString(), content);
648  q->connect(job, SIGNAL(finished(Attica::BaseJob*)), q, SLOT(_k_contentAdded(Attica::BaseJob*)));
649  job->start();
650  }
651 }
652 
653 void UploadDialogPrivate::_k_changePreview1()
654 {
655  const QStringList filters = _supportedMimeTypes();
656  QPointer<QFileDialog> dialog = new QFileDialog(q, i18n("Select preview image"));
657  dialog->setMimeTypeFilters(filters);
658  if (dialog->exec() == QDialog::Accepted) {
659  QUrl url = dialog->selectedUrls().first();
660  previewFile1 = url;
661  qCDebug(KNEWSTUFF) << "preview is: " << url.url();
662  QPixmap preview(url.toLocalFile());
663  ui.previewImage1->setPixmap(preview.scaled(ui.previewImage1->size()));
664  }
665  delete dialog;
666 }
667 
668 void UploadDialogPrivate::_k_changePreview2()
669 {
670  const QStringList filters = _supportedMimeTypes();
671  QPointer<QFileDialog> dialog = new QFileDialog(q, i18n("Select preview image"));
672  dialog->setMimeTypeFilters(filters);
673  if (dialog->exec() == QDialog::Accepted) {
674  QUrl url = dialog->selectedUrls().first();
675  previewFile2 = url;
676  QPixmap preview(url.toLocalFile());
677  ui.previewImage2->setPixmap(preview.scaled(ui.previewImage1->size()));
678  }
679  delete dialog;
680 }
681 
682 void UploadDialogPrivate::_k_changePreview3()
683 {
684  const QStringList filters = _supportedMimeTypes();
685  QPointer<QFileDialog> dialog = new QFileDialog(q, i18n("Select preview image"));
686  dialog->setMimeTypeFilters(filters);
687  if (dialog->exec() == QDialog::Accepted) {
688  QUrl url = dialog->selectedUrls().first();
689  previewFile3 = url;
690  QPixmap preview(url.toLocalFile());
691  ui.previewImage3->setPixmap(preview.scaled(ui.previewImage1->size()));
692  }
693  delete dialog;
694 }
695 
696 void UploadDialogPrivate::_k_contentAdded(Attica::BaseJob *baseJob)
697 {
698  if (baseJob->metadata().error()) {
699  if (baseJob->metadata().error() == Attica::Metadata::NetworkError) {
700  KMessageBox::error(q, i18n("There was a network error."), i18n("Uploading Failed"));
701  return;
702  }
703  if (baseJob->metadata().error() == Attica::Metadata::OcsError) {
704  if (baseJob->metadata().statusCode() == 102) {
705  KMessageBox::error(q, i18n("Authentication error."), i18n("Uploading Failed"));
706  }
707  }
708  return;
709  }
710 
711  ui.createContentImageLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(16));
712 
713  Attica::ItemPostJob<Attica::Content> *job = static_cast<Attica::ItemPostJob<Attica::Content> *>(baseJob);
714  if (job->metadata().error() != Attica::Metadata::NoError) {
715  KMessageBox::error(q, i18n("Upload failed: %1", job->metadata().message()));
716  return;
717  }
718 
719  // only when adding new content we get an id returned, otherwise stick with the old one
720  QString id = job->result().id();
721  if (!id.isEmpty()) {
722  contentId = id;
723  }
724 
725  if (!uploadFile.isEmpty()) {
726  doUpload(QString(), uploadFile);
727  } else {
728  doUpload(QString(), ui.uploadFileRequester->url());
729  }
730 
731  // FIXME: status labels need to accommodate 3 previews
732  if (!previewFile1.isEmpty()) {
733  doUpload(QStringLiteral("1"), previewFile1);
734  }
735  if (!previewFile2.isEmpty()) {
736  doUpload(QStringLiteral("2"), previewFile2);
737  }
738  if (!previewFile3.isEmpty()) {
739  doUpload(QStringLiteral("3"), previewFile3);
740  }
741 
742  if (ui.radioNewUpload->isChecked()) {
743  atticaHelper->loadDetailsLink(contentId);
744  }
745 }
746 
747 void UploadDialogPrivate::_k_openRegisterAccountWebpage(QString)
748 {
749  KIO::OpenUrlJob *job = new KIO::OpenUrlJob(QUrl::fromUserInput(atticaHelper->provider().getRegisterAccountUrl()), QStringLiteral("text/html"));
750  job->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, q));
751  job->start();
752 }
753 
754 void UploadDialogPrivate::doUpload(const QString &index, const QUrl &path)
755 {
756  QFile file(path.toLocalFile());
757  if (!file.open(QIODevice::ReadOnly)) {
758  KMessageBox::error(q, i18n("File not found: %1", uploadFile.url()), i18n("Upload Failed"));
759  q->reject();
760  return;
761  }
762 
763  QByteArray fileContents;
764  fileContents.append(file.readAll());
765  file.close();
766 
767  QString fileName = QFileInfo(path.toLocalFile()).fileName();
768 
769  Attica::PostJob *job = nullptr;
770  if (index.isEmpty()) {
771  job = currentProvider().setDownloadFile(contentId, fileName, fileContents);
772  q->connect(job, SIGNAL(finished(Attica::BaseJob*)), q, SLOT(_k_fileUploadFinished(Attica::BaseJob*)));
773  } else if (index == QLatin1Char('1')) {
774  job = currentProvider().setPreviewImage(contentId, index, fileName, fileContents);
775  q->connect(job, SIGNAL(finished(Attica::BaseJob*)), q, SLOT(_k_preview1UploadFinished(Attica::BaseJob*)));
776  } else if (index == QLatin1Char('2')) {
777  job = currentProvider().setPreviewImage(contentId, index, fileName, fileContents);
778  q->connect(job, SIGNAL(finished(Attica::BaseJob*)), q, SLOT(_k_preview2UploadFinished(Attica::BaseJob*)));
779  } else if (index == QLatin1Char('3')) {
780  job = currentProvider().setPreviewImage(contentId, index, fileName, fileContents);
781  q->connect(job, SIGNAL(finished(Attica::BaseJob*)), q, SLOT(_k_preview3UploadFinished(Attica::BaseJob*)));
782  }
783  if (job) {
784  job->start();
785  }
786 }
787 
788 void UploadDialogPrivate::_k_fileUploadFinished(Attica::BaseJob *)
789 {
790  ui.uploadContentImageLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(16));
791  finishedContents = true;
792  uploadFileFinished();
793 }
794 
795 void UploadDialogPrivate::_k_preview1UploadFinished(Attica::BaseJob *)
796 {
797  ui.uploadPreview1ImageLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(16));
798  finishedPreview1 = true;
799  uploadFileFinished();
800 }
801 
802 void UploadDialogPrivate::_k_preview2UploadFinished(Attica::BaseJob *)
803 {
804  ui.uploadPreview2ImageLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(16));
805  finishedPreview2 = true;
806  uploadFileFinished();
807 }
808 
809 void UploadDialogPrivate::_k_preview3UploadFinished(Attica::BaseJob *)
810 {
811  ui.uploadPreview3ImageLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(16));
812  finishedPreview3 = true;
813  uploadFileFinished();
814 }
815 
816 void UploadDialogPrivate::uploadFileFinished()
817 {
818  // FIXME multiple previews
819  if (finishedContents && (previewFile1.isEmpty() || finishedPreview1)
820  && (previewFile2.isEmpty() || finishedPreview2)
821  && (previewFile3.isEmpty() || finishedPreview3)) {
822  finished = true;
823  ui.uploadProgressBar->setMinimum(0);
824  ui.uploadProgressBar->setMaximum(100);
825  ui.uploadProgressBar->setValue(100);
826  _k_updatePage();
827  }
828 }
829 
830 void UploadDialogPrivate::_k_detailsLinkLoaded(const QUrl &url)
831 {
832  ui.contentWebsiteLink->setText(QLatin1String("<a href=\"") + url.toString() + QLatin1String("\">")
833  + i18nc("A link to the website where the get hot new stuff upload can be seen", "Visit website") + QLatin1String("</a>"));
834  ui.fetchContentLinkImageLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(16));
835 }
836 
837 QStringList UploadDialogPrivate::_supportedMimeTypes() const
838 {
839  QStringList mimeTypes;
841  mimeTypes.reserve(supported.count());
842  for (const QByteArray &mimeType : supported) {
843  mimeTypes.append(QString::fromLatin1(mimeType));
844  }
845  return mimeTypes;
846 }
847 
848 #include "moc_uploaddialog.cpp"
QString url(QUrl::FormattingOptions options) const const
QList< QByteArray > supportedMimeTypes()
virtual void reject()
MatchFixedString
void setDescription(const QString &description)
Set the suggested description displayed in the upload dialog.
void start() override
void reserve(int alloc)
KGuiItem forward(BidiMode useBidi=IgnoreRTL)
void setUploadFile(const QUrl &payloadFile)
Set the file to be uploaded.
const T & at(int i) const const
QString attribute(const QString &key) const
void setPrice(double price)
Set the suggested price displayed in the upload dialog.
QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags)
QString i18np(const char *singular, const char *plural, const TYPE &arg...)
void setUploadName(const QString &name)
Set the suggested title for the upload.
double toDouble(bool *ok) const const
QUrl fromUserInput(const QString &userInput)
QString toString(QUrl::FormattingOptions options) const const
void clear()
void finished(int result)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
QString number(int n, int base)
int count(const T &value) const const
void append(const T &value)
KGuiItem back(BidiMode useBidi=IgnoreRTL)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
bool isEmpty() const const
UserRole
bool isEmpty() const const
static void assign(QPushButton *button, const KGuiItem &item)
void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
void addAttribute(const QString &key, const QString &value)
void setPriceEnabled(bool enabled)
Enable the UI to let the user to set a price for the uploaded item.
QString id() const
void setVersion(const QString &version)
Set the suggested version displayed in the upload dialog.
static KIconLoader * global()
virtual void accept()
QString toLocalFile() const const
QByteArray & append(char ch)
virtual void setData(int role, const QVariant &value)
QString description() const
void setPriceReason(const QString &reason)
Set the suggested rationale why this item costs something to download.
QString i18n(const char *text, const TYPE &arg...)
KConfigGroup group(const QString &group)
bool isValid() const
QString name() const
void setWindowTitle(const QString &)
QUrl detailpage() const
void setName(const QString &name)
void selectCategory(const QString &category)
Set the suggested category for the upload.
void setText(const QString &text)
QString fromLatin1(const char *str, int size)
UploadDialog(QWidget *parent=nullptr)
Create a new upload dialog.
QIcon fromTheme(const QString &name)
~UploadDialog() override
Destructor.
The namespace for the KNewStuff classes.
Definition: button.cpp:19
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
T readEntry(const QString &key, const T &aDefault) const
QString applicationDisplayName()
void setEnabled(bool)
void setChangelog(const QString &changelog)
Set the suggested changelog displayed in the upload dialog.
QAction * firstPage(const QObject *recvr, const char *slot, QObject *parent)
QString applicationName()
QString locate(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options)
void setPreviewImageFile(uint number, const QUrl &file)
Set one of the three preview images displayed in the upload dialog.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Jan 19 2021 22:44:09 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.