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", QString());
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  //d->ui.mTitleWidget->setPixmap(QIcon::fromTheme(KGlobal::activeComponent().aboutData()->programIconName()));
464 
465  if (success) {
466  d->_k_showPage(0);
467  }
468 
469  return success;
470 }
471 
472 void UploadDialog::setUploadFile(const QUrl &payloadFile)
473 {
474  d->uploadFile = payloadFile;
475 
476  d->ui.uploadFileLabel->setVisible(false);
477  d->ui.uploadFileRequester->setVisible(false);
478 
479  QFile file(d->uploadFile.toLocalFile());
480  if (!file.open(QIODevice::ReadOnly)) {
481  KMessageBox::error(this, i18n("File not found: %1", d->uploadFile.url()), i18n("Upload Failed"));
482  }
483 }
484 
486 {
487  d->ui.mNameEdit->setText(name);
488 }
489 
491 {
492  d->ui.mCategoryCombo->setCurrentIndex(d->ui.mCategoryCombo->findText(category, Qt::MatchFixedString));
493 }
494 
495 void UploadDialog::setChangelog(const QString &changelog)
496 {
497  d->ui.changelog->setText(changelog);
498 }
499 
500 void UploadDialog::setDescription(const QString &description)
501 {
502  d->ui.mSummaryEdit->setText(description);
503 }
504 
506 {
507  d->ui.priceCheckBox->setVisible(enabled);
508  d->ui.priceGroupBox->setVisible(enabled);
509 }
510 
511 void UploadDialog::setPrice(double price)
512 {
513  d->ui.priceCheckBox->setEnabled(true);
514  d->ui.priceSpinBox->setValue(price);
515 }
516 
518 {
519  d->ui.priceReasonLineEdit->setText(reason);
520 }
521 
522 void UploadDialog::setVersion(const QString &version)
523 {
524  d->ui.mVersionEdit->setText(version);
525 }
526 
527 void UploadDialog::setPreviewImageFile(uint number, const QUrl &file)
528 {
529  QPixmap preview(file.toLocalFile());
530  switch (number) {
531  case 0 :
532  d->previewFile1 = file;
533  d->ui.previewImage1->setPixmap(preview.scaled(d->ui.previewImage1->size()));
534  break;
535  case 1 :
536  d->previewFile2 = file;
537  d->ui.previewImage2->setPixmap(preview.scaled(d->ui.previewImage2->size()));
538  break;
539  case 2 :
540  d->previewFile3 = file;
541  d->ui.previewImage3->setPixmap(preview.scaled(d->ui.previewImage3->size()));
542  break;
543  default :
544  qCCritical(KNEWSTUFF) << "Wrong preview image file number";
545  break;
546  }
547 }
548 
549 void UploadDialogPrivate::_k_priceToggled(bool priceEnabled)
550 {
551  ui.priceGroupBox->setEnabled(priceEnabled);
552 }
553 
554 void UploadDialogPrivate::_k_categoriesLoaded(const Attica::Category::List &loadedCategories)
555 {
556  categories = loadedCategories;
557 
558  // at least one category is needed
559  if (categories.isEmpty()) {
561  i18np("The server does not recognize the category %2 to which you are trying to upload.",
562  "The server does not recognize any of the categories to which you are trying to upload: %2",
563  categoryNames.size(), categoryNames.join(QLatin1String(", "))),
564  i18n("Error"));
565  // close the dialog
566  q->reject();
567  return;
568  }
569  for (const Attica::Category &c : qAsConst(categories)) {
570  ui.mCategoryCombo->addItem(c.name(), c.id());
571  }
572  atticaHelper->loadContentByCurrentUser();
573 }
574 
575 void UploadDialog::accept()
576 {
577  QDialog::accept();
578 }
579 
580 void UploadDialogPrivate::_k_startUpload()
581 {
582  // FIXME: this only works if categories are set in the .knsrc file
583  // TODO: ask for confirmation when closing the dialog
584 
585  backButton->setEnabled(false);
586  buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
587 
588  ui.uploadButton->setEnabled(false);
589 
590  // idle back and forth, we need a fix in attica to get at real progress values
591  ui.uploadProgressBar->setMinimum(0);
592  ui.uploadProgressBar->setMaximum(0);
593  ui.uploadProgressBar->setValue(0);
594 
595  // check the category
596  QString categoryName = ui.mCategoryCombo->currentText();
597  QList<Attica::Category>::const_iterator iter = categories.constBegin();
598  Attica::Category category;
599  QList<Attica::Category>::const_iterator iterEnd = categories.constEnd();
600  while (iter != iterEnd) {
601  if (iter->name() == categoryName) {
602  category = *iter;
603  break;
604  }
605  ++iter;
606  }
607  if (!category.isValid()) {
608  KMessageBox::error(q, i18n("The selected category \"%1\" is invalid.", categoryName), i18n("Upload Failed"));
609  return;
610  }
611 
612  // fill in the content object
613  Attica::Content content;
614  content.setName(ui.mNameEdit->text());
615  QString summary = ui.mSummaryEdit->toPlainText();
616  content.addAttribute(QStringLiteral("description"), summary);
617  content.addAttribute(QStringLiteral("version"), ui.mVersionEdit->text());
618 
619  // for the license, if one of the licenses coming from the server was used, pass its id, otherwise the string
620  QString licenseId = ui.mLicenseCombo->itemData(ui.mLicenseCombo->currentIndex()).toString();
621  if (licenseId.isEmpty()) {
622  // use other as type and add the string as text
623  content.addAttribute(QStringLiteral("licensetype"), QStringLiteral("0"));
624  content.addAttribute(QStringLiteral("license"), ui.mLicenseCombo->currentText());
625  } else {
626  content.addAttribute(QStringLiteral("licensetype"), licenseId);
627  }
628 
629  content.addAttribute(QStringLiteral("changelog"), ui.changelog->toPlainText());
630 
631  // TODO: add additional attributes
632  //content.addAttribute("downloadlink1", ui.link1->text());
633  //content.addAttribute("downloadlink2", ui.link2->text());
634  //content.addAttribute("homepage1", ui.homepage->text());
635  //content.addAttribute("blog1", ui.blog->text());
636 
637  content.addAttribute(QStringLiteral("downloadbuy1"), ui.priceCheckBox->isChecked() ? QStringLiteral("1") : QStringLiteral("0"));
638  content.addAttribute(QStringLiteral("downloadbuyprice1"), QString::number(ui.priceSpinBox->value()));
639  content.addAttribute(QStringLiteral("downloadbuyreason1"), ui.priceReasonLineEdit->text());
640 
641  if (ui.radioNewUpload->isChecked()) {
642  // upload a new content
643  Attica::ItemPostJob<Attica::Content> *job = currentProvider().addNewContent(category, content);
644  q->connect(job, SIGNAL(finished(Attica::BaseJob*)), q, SLOT(_k_contentAdded(Attica::BaseJob*)));
645  job->start();
646  } else {
647  // update old content
648  Attica::ItemPostJob<Attica::Content> *job = currentProvider().editContent(category, ui.userContentList->currentItem()->data(Qt::UserRole).toString(), content);
649  q->connect(job, SIGNAL(finished(Attica::BaseJob*)), q, SLOT(_k_contentAdded(Attica::BaseJob*)));
650  job->start();
651  }
652 }
653 
654 void UploadDialogPrivate::_k_changePreview1()
655 {
656  const QStringList filters = _supportedMimeTypes();
657  QPointer<QFileDialog> dialog = new QFileDialog(q, i18n("Select preview image"));
658  dialog->setMimeTypeFilters(filters);
659  if (dialog->exec() == QDialog::Accepted) {
660  QUrl url = dialog->selectedUrls().first();
661  previewFile1 = url;
662  qCDebug(KNEWSTUFF) << "preview is: " << url.url();
663  QPixmap preview(url.toLocalFile());
664  ui.previewImage1->setPixmap(preview.scaled(ui.previewImage1->size()));
665  }
666  delete dialog;
667 }
668 
669 void UploadDialogPrivate::_k_changePreview2()
670 {
671  const QStringList filters = _supportedMimeTypes();
672  QPointer<QFileDialog> dialog = new QFileDialog(q, i18n("Select preview image"));
673  dialog->setMimeTypeFilters(filters);
674  if (dialog->exec() == QDialog::Accepted) {
675  QUrl url = dialog->selectedUrls().first();
676  previewFile2 = url;
677  QPixmap preview(url.toLocalFile());
678  ui.previewImage2->setPixmap(preview.scaled(ui.previewImage1->size()));
679  }
680  delete dialog;
681 }
682 
683 void UploadDialogPrivate::_k_changePreview3()
684 {
685  const QStringList filters = _supportedMimeTypes();
686  QPointer<QFileDialog> dialog = new QFileDialog(q, i18n("Select preview image"));
687  dialog->setMimeTypeFilters(filters);
688  if (dialog->exec() == QDialog::Accepted) {
689  QUrl url = dialog->selectedUrls().first();
690  previewFile3 = url;
691  QPixmap preview(url.toLocalFile());
692  ui.previewImage3->setPixmap(preview.scaled(ui.previewImage1->size()));
693  }
694  delete dialog;
695 }
696 
697 void UploadDialogPrivate::_k_contentAdded(Attica::BaseJob *baseJob)
698 {
699  if (baseJob->metadata().error()) {
700  if (baseJob->metadata().error() == Attica::Metadata::NetworkError) {
701  KMessageBox::error(q, i18n("There was a network error."), i18n("Uploading Failed"));
702  return;
703  }
704  if (baseJob->metadata().error() == Attica::Metadata::OcsError) {
705  if (baseJob->metadata().statusCode() == 102) {
706  KMessageBox::error(q, i18n("Authentication error."), i18n("Uploading Failed"));
707  }
708  }
709  return;
710  }
711 
712  ui.createContentImageLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(16));
713 
714  Attica::ItemPostJob<Attica::Content> *job = static_cast<Attica::ItemPostJob<Attica::Content> *>(baseJob);
715  if (job->metadata().error() != Attica::Metadata::NoError) {
716  KMessageBox::error(q, i18n("Upload failed: %1", job->metadata().message()));
717  return;
718  }
719 
720  // only when adding new content we get an id returned, otherwise stick with the old one
721  QString id = job->result().id();
722  if (!id.isEmpty()) {
723  contentId = id;
724  }
725 
726  if (!uploadFile.isEmpty()) {
727  doUpload(QString(), uploadFile);
728  } else {
729  doUpload(QString(), ui.uploadFileRequester->url());
730  }
731 
732  // FIXME: status labels need to accommodate 3 previews
733  if (!previewFile1.isEmpty()) {
734  doUpload(QStringLiteral("1"), previewFile1);
735  }
736  if (!previewFile2.isEmpty()) {
737  doUpload(QStringLiteral("2"), previewFile2);
738  }
739  if (!previewFile3.isEmpty()) {
740  doUpload(QStringLiteral("3"), previewFile3);
741  }
742 
743  if (ui.radioNewUpload->isChecked()) {
744  atticaHelper->loadDetailsLink(contentId);
745  }
746 }
747 
748 void UploadDialogPrivate::_k_openRegisterAccountWebpage(QString)
749 {
750  KIO::OpenUrlJob *job = new KIO::OpenUrlJob(QUrl::fromUserInput(atticaHelper->provider().getRegisterAccountUrl()), QStringLiteral("text/html"));
751  job->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, q));
752  job->start();
753 }
754 
755 void UploadDialogPrivate::doUpload(const QString &index, const QUrl &path)
756 {
757  QFile file(path.toLocalFile());
758  if (!file.open(QIODevice::ReadOnly)) {
759  KMessageBox::error(q, i18n("File not found: %1", uploadFile.url()), i18n("Upload Failed"));
760  q->reject();
761  return;
762  }
763 
764  QByteArray fileContents;
765  fileContents.append(file.readAll());
766  file.close();
767 
768  QString fileName = QFileInfo(path.toLocalFile()).fileName();
769 
770  Attica::PostJob *job = nullptr;
771  if (index.isEmpty()) {
772  job = currentProvider().setDownloadFile(contentId, fileName, fileContents);
773  q->connect(job, SIGNAL(finished(Attica::BaseJob*)), q, SLOT(_k_fileUploadFinished(Attica::BaseJob*)));
774  } else if (index == QLatin1Char('1')) {
775  job = currentProvider().setPreviewImage(contentId, index, fileName, fileContents);
776  q->connect(job, SIGNAL(finished(Attica::BaseJob*)), q, SLOT(_k_preview1UploadFinished(Attica::BaseJob*)));
777  } else if (index == QLatin1Char('2')) {
778  job = currentProvider().setPreviewImage(contentId, index, fileName, fileContents);
779  q->connect(job, SIGNAL(finished(Attica::BaseJob*)), q, SLOT(_k_preview2UploadFinished(Attica::BaseJob*)));
780  } else if (index == QLatin1Char('3')) {
781  job = currentProvider().setPreviewImage(contentId, index, fileName, fileContents);
782  q->connect(job, SIGNAL(finished(Attica::BaseJob*)), q, SLOT(_k_preview3UploadFinished(Attica::BaseJob*)));
783  }
784  if (job) {
785  job->start();
786  }
787 }
788 
789 void UploadDialogPrivate::_k_fileUploadFinished(Attica::BaseJob *)
790 {
791  ui.uploadContentImageLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(16));
792  finishedContents = true;
793  uploadFileFinished();
794 }
795 
796 void UploadDialogPrivate::_k_preview1UploadFinished(Attica::BaseJob *)
797 {
798  ui.uploadPreview1ImageLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(16));
799  finishedPreview1 = true;
800  uploadFileFinished();
801 }
802 
803 void UploadDialogPrivate::_k_preview2UploadFinished(Attica::BaseJob *)
804 {
805  ui.uploadPreview2ImageLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(16));
806  finishedPreview2 = true;
807  uploadFileFinished();
808 }
809 
810 void UploadDialogPrivate::_k_preview3UploadFinished(Attica::BaseJob *)
811 {
812  ui.uploadPreview3ImageLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(16));
813  finishedPreview3 = true;
814  uploadFileFinished();
815 }
816 
817 void UploadDialogPrivate::uploadFileFinished()
818 {
819  // FIXME multiple previews
820  if (finishedContents && (previewFile1.isEmpty() || finishedPreview1)
821  && (previewFile2.isEmpty() || finishedPreview2)
822  && (previewFile3.isEmpty() || finishedPreview3)) {
823  finished = true;
824  ui.uploadProgressBar->setMinimum(0);
825  ui.uploadProgressBar->setMaximum(100);
826  ui.uploadProgressBar->setValue(100);
827  _k_updatePage();
828  }
829 }
830 
831 void UploadDialogPrivate::_k_detailsLinkLoaded(const QUrl &url)
832 {
833  ui.contentWebsiteLink->setText(QLatin1String("<a href=\"") + url.toString() + QLatin1String("\">")
834  + i18nc("A link to the website where the get hot new stuff upload can be seen", "Visit website") + QLatin1String("</a>"));
835  ui.fetchContentLinkImageLabel->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-ok")).pixmap(16));
836 }
837 
838 QStringList UploadDialogPrivate::_supportedMimeTypes() const
839 {
840  QStringList mimeTypes;
842  mimeTypes.reserve(supported.count());
843  for (const QByteArray &mimeType : supported) {
844  mimeTypes.append(QString::fromLatin1(mimeType));
845  }
846  return mimeTypes;
847 }
848 
849 #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
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.
Definition: button.cpp:18
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-2020 The KDE developers.
Generated on Thu Aug 13 2020 22:41:57 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.