00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "downloaddialog.h"
00024
00025
00026 #include <QtCore/QTimer>
00027 #include <QtGui/QPixmap>
00028 #include <QtGui/QSortFilterProxyModel>
00029 #include <kaboutdata.h>
00030 #include <kcomponentdata.h>
00031 #include <kmessagebox.h>
00032 #include <ktoolinvocation.h>
00033
00034 #include <kdebug.h>
00035
00036 #include "knewstuff2/core/provider.h"
00037 #include "knewstuff2/core/providerhandler.h"
00038 #include "knewstuff2/core/entry.h"
00039 #include "knewstuff2/core/entryhandler.h"
00040 #include "knewstuff2/core/category.h"
00041
00042 #include "knewstuff2/dxs/dxs.h"
00043
00044
00045 #include "ui_DownloadDialog.h"
00046 #include "itemsmodel.h"
00047 #include "itemsviewdelegate.h"
00048 #include "kdxsrating.h"
00049 #include "kdxscomment.h"
00050 #include "kdxscomments.h"
00051
00052 const char * ConfigGroup = "DownloadDialog Settings";
00053
00054 using namespace KNS;
00055
00056 DownloadDialog::DownloadDialog(DxsEngine* _engine, QWidget * _parent)
00057 : KDialog(_parent)
00058 {
00059 setButtons(0);
00060
00061 m_engine = _engine;
00062 connect(m_engine, SIGNAL(signalProgress(QString, int)), SLOT(slotProgress(QString, int)));
00063 connect(m_engine, SIGNAL(signalEntryChanged(KNS::Entry*)), SLOT(slotEntryChanged(KNS::Entry*)));
00064 connect(m_engine, SIGNAL(signalPayloadFailed(KNS::Entry*)), SLOT(slotPayloadFailed(KNS::Entry*)));
00065 connect(m_engine, SIGNAL(signalPayloadLoaded(KUrl)), SLOT(slotPayloadLoaded(KUrl)));
00066 connect(m_engine, SIGNAL(signalProvidersFailed()), SLOT(slotProvidersFailed()));
00067 connect(m_engine, SIGNAL(signalEntriesFailed()), SLOT(slotEntriesFailed()));
00068
00069 connect(m_engine, SIGNAL(signalEntryLoaded(KNS::Entry*, const KNS::Feed*, const KNS::Provider*)),
00070 this, SLOT(slotEntryLoaded(KNS::Entry*, const KNS::Feed*, const KNS::Provider*)));
00071 connect(m_engine, SIGNAL(signalEntryRemoved(KNS::Entry*, const KNS::Feed*)),
00072 this, SLOT(slotEntryRemoved(KNS::Entry *, const KNS::Feed *)));
00073
00074
00075 messageTimer = new QTimer(this);
00076 messageTimer->setSingleShot(true);
00077 connect(messageTimer, SIGNAL(timeout()), SLOT(slotResetMessage()));
00078
00079 networkTimer = new QTimer(this);
00080 connect(networkTimer, SIGNAL(timeout()), SLOT(slotNetworkTimeout()));
00081
00082 m_searchTimer = new QTimer(this);
00083 m_searchTimer->setSingleShot(true);
00084 m_searchTimer->setInterval(1000);
00085 connect(m_searchTimer, SIGNAL(timeout()), SLOT(slotUpdateSearch()));
00086
00087
00088 QWidget* _mainWidget = new QWidget(this);
00089 setMainWidget(_mainWidget);
00090 setupUi(_mainWidget);
00091
00092
00093 mDelegate = new ItemsViewDelegate(m_listView, this);
00094 m_listView->setItemDelegate(mDelegate);
00095 connect(mDelegate, SIGNAL(performAction(DownloadDialog::EntryAction, KNS::Entry *)),
00096 SLOT(slotPerformAction(DownloadDialog::EntryAction, KNS::Entry *)));
00097
00098
00099 m_filteredModel = new QSortFilterProxyModel(this);
00100 m_filteredModel->setFilterRole(ItemsModel::kNameRole);
00101 m_filteredModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
00102 m_listView->setModel(m_filteredModel);
00103 connect(m_listView->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
00104 this, SLOT(slotListIndexChanged(const QModelIndex &, const QModelIndex &)));
00105
00106
00107
00108
00109
00110
00111
00112
00113 connect(m_sourceCombo, SIGNAL(currentIndexChanged(int)), SLOT(slotLoadProviderDXS()));
00114 connect(m_sortCombo, SIGNAL(currentIndexChanged(int)), SLOT(slotSortingSelected(int)));
00115 connect(m_searchEdit, SIGNAL(textChanged(const QString &)), SLOT(slotSearchTextChanged()));
00116 connect(m_searchEdit, SIGNAL(editingFinished()), SLOT(slotUpdateSearch()));
00117
00118
00119
00120
00121
00122
00123 KConfigGroup group(KGlobal::config(), ConfigGroup);
00124 restoreDialogSize(group);
00125 setMinimumSize(700, 400);
00126
00127 setCaption(i18n("Get Hot New Stuff"));
00128 m_titleWidget->setText(i18nc("Program name followed by 'Add On Installer'",
00129 "%1 Add-On Installer",
00130 KGlobal::activeComponent().aboutData()->programName()));
00131 m_titleWidget->setPixmap(KIcon(KGlobal::activeComponent().aboutData()->programIconName()));
00132
00133 connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(accept()));
00134
00135 KMenu * collabMenu = new KMenu(m_collaborationButton);
00136 QAction * action_collabrating = collabMenu->addAction(i18n("Add Rating"));
00137 action_collabrating->setData(DownloadDialog::kCollabRate);
00138
00139 QAction * action_collabcomment = collabMenu->addAction(i18n("Add Comment"));
00140 action_collabcomment->setData(DownloadDialog::kCollabComment);
00141
00142 QAction * action_comment = collabMenu->addAction(SmallIcon("help-about"), i18n("View Comments"));
00143 action_comment->setData(DownloadDialog::kComments);
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 m_collaborationButton->setMenu(collabMenu);
00157 connect(m_collaborationButton, SIGNAL(triggered(QAction*)), this, SLOT(slotCollabAction(QAction*)));
00158 }
00159
00160 DownloadDialog::~DownloadDialog()
00161 {
00162 KConfigGroup group(KGlobal::config(), ConfigGroup);
00163 saveDialogSize(group, KConfigBase::Persistent);
00164 }
00165
00166 void DownloadDialog::slotPerformAction(DownloadDialog::EntryAction action, KNS::Entry * entry)
00167 {
00168 kDebug(551) << "perform action: " << action;
00169 const Provider * provider = m_providers.contains(entry) ? m_providers[entry] : NULL;
00170 Dxs * dxs = m_engine->dxsObject(provider);
00171 switch (action) {
00172 case kViewInfo:
00173 if (provider && dxs) {
00174 if (provider->webService().isValid()) {
00175 dxs->call_info();
00176 } else {
00177 slotInfo(provider->name().representation(),
00178 provider->webAccess().pathOrUrl(),
00179 QString());
00180 }
00181 }
00182 break;
00183 case kComments:
00184
00185 if (provider && dxs) {
00186 connect(dxs, SIGNAL(signalComments(QStringList)), this, SLOT(slotComments(QStringList)));
00187 dxs->call_comments(entry->idNumber());
00188 }
00189 break;
00190 case kChanges:
00191
00192 break;
00193 case kContactEmail:
00194
00195 KToolInvocation::invokeMailer(entry->author().email(), i18n("Re: %1", entry->name().representation()));
00196 break;
00197 case kContactJabber:
00198
00199 break;
00200 case kCollabTranslate:
00201
00202 break;
00203 case kCollabRemoval:
00204
00205 break;
00206 case kCollabSubscribe:
00207
00208 break;
00209 case kUninstall:
00210
00211 setCursor(Qt::WaitCursor);
00212 m_engine->uninstall(entry);
00213 setCursor(Qt::ArrowCursor);
00214 break;
00215 case kInstall:
00216
00217 setCursor(Qt::WaitCursor);
00218 m_engine->downloadPayload(entry);
00219 break;
00220 case kCollabComment: {
00221
00222 QPointer<KDXSComment> commentDialog = new KDXSComment(this);
00223 int ret = commentDialog->exec();
00224 if (ret == QDialog::Accepted) {
00225 QString s = commentDialog->comment();
00226 if (dxs && !s.isEmpty()) {
00227 dxs->call_comment(entry->idNumber(), s);
00228 }
00229 }
00230 }
00231 break;
00232 case kCollabRate: {
00233
00234 QPointer<KDXSRating> ratingDialog = new KDXSRating(this);
00235 int ret = ratingDialog->exec();
00236 if (ret == QDialog::Accepted) {
00237 int rating = ratingDialog->rating();
00238 if (dxs) {
00239 dxs->call_rating(entry->idNumber(), rating);
00240 }
00241 }
00242 }
00243 break;
00244 }
00245 }
00246
00247 void DownloadDialog::slotCollabAction(QAction * action)
00248 {
00249 DownloadDialog::EntryAction entryAction = (DownloadDialog::EntryAction)action->data().toInt();
00250 QModelIndex currentIndex = m_listView->currentIndex();
00251 const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(m_filteredModel->sourceModel());
00252 QModelIndex index = m_filteredModel->mapToSource(currentIndex);
00253 KNS::Entry * entry = realmodel->entryForIndex(index);
00254 slotPerformAction(entryAction, entry);
00255 }
00256
00257 void DownloadDialog::slotListIndexChanged(const QModelIndex &index, const QModelIndex &)
00258 {
00259
00260
00261 m_collaborationButton->setEnabled(m_hasDxs && index.isValid());
00262 }
00263
00264 void DownloadDialog::hideEvent(QHideEvent * event)
00265 {
00266 KConfigGroup group(KGlobal::config(), ConfigGroup);
00267 saveDialogSize(group, KConfigBase::Persistent);
00268 KDialog::hideEvent(event);
00269 }
00270
00271 void DownloadDialog::displayMessage(const QString & msg, KTitleWidget::MessageType type, int timeOutMs)
00272 {
00273
00274 messageTimer->stop();
00275
00276
00277 m_titleWidget->setComment(msg, type);
00278
00279
00280 if (timeOutMs > 0) {
00281
00282 messageTimer->start(timeOutMs);
00283 }
00284 }
00285
00286 void DownloadDialog::installItem(Entry *entry)
00287 {
00288
00289
00290
00291
00292
00293
00294
00295
00296 slotEntryChanged(entry);
00297 }
00298
00299 void DownloadDialog::removeItem(Entry *entry)
00300 {
00301 Q_UNUSED(entry);
00302
00303 }
00304
00305 void DownloadDialog::slotResetMessage()
00306 {
00307 m_titleWidget->setComment(QString());
00308 }
00309
00310 void DownloadDialog::slotNetworkTimeout()
00311 {
00312 displayMessage(i18n("Timeout. Check Internet connection!"), KTitleWidget::ErrorMessage);
00313 }
00314
00315 void DownloadDialog::slotSortingSelected(int sortType)
00316 {
00317 if (sortType >= 0) {
00318
00319 QString feedName = m_sortCombo->currentText();
00320 QString feedType = m_sortCombo->itemData(sortType).toString();
00321
00322 const Provider * currentProvider = m_entriesByProvider.keys()[m_sourceCombo->currentIndex()];
00323 Feed * selectedFeed = currentProvider->downloadUrlFeed(feedType);
00324 m_filteredModel->setSourceModel(m_models.value(selectedFeed));
00325 m_collaborationButton->setEnabled(false);
00326 }
00327 }
00328
00329
00331
00332 void DownloadDialog::slotLoadProviderDXS()
00333 {
00334 kDebug(551) << "slotLoadProviderDXS called";
00335
00336
00337 QString providerName = m_sourceCombo->currentText();
00338
00339 QList<const Provider*> providers = m_entriesByProvider.keys();
00340 const Provider * provider = 0;
00341
00342 for (int i = 0; i < providers.size(); ++i) {
00343 if (providers[i]->name().representation() == providerName) {
00344 provider = providers[i];
00345
00346 populateSortCombo(providers[i]);
00347
00348 Feed * selectedFeed = providers[i]->downloadUrlFeed(m_sortCombo->itemData(m_sortCombo->currentIndex()).toString());
00349 m_filteredModel->setSourceModel(m_models.value(selectedFeed));
00350
00351
00352 break;
00353 }
00354 }
00355 m_hasDxs = (provider && m_engine->dxsObject(provider) != NULL);
00356 m_collaborationButton->setEnabled(m_hasDxs);
00357 }
00358
00359 void DownloadDialog::slotUpdateSearch()
00360 {
00361 m_searchTimer->stop();
00362 m_filteredModel->setFilterFixedString(m_searchEdit->text());
00363 m_filteredModel->invalidate();
00364 }
00365
00366 void DownloadDialog::slotLoadProvidersListDXS()
00367 {
00368 }
00369
00370 void DownloadDialog::slotSearchTextChanged()
00371 {
00372 m_searchTimer->start();
00373 }
00374
00375 void DownloadDialog::slotCategories(QList<KNS::Category*> categories)
00376 {
00377 categorymap.clear();
00378
00379 for (QList<KNS::Category*>::Iterator it = categories.begin(); it != categories.end(); ++it) {
00380 KNS::Category *category = (*it);
00381
00382 QPixmap icon = DesktopIcon(category->icon().url(), 16);
00383
00384 m_sourceCombo->addItem(icon, category->name().representation());
00385 categorymap[category->name().representation()] = category->id();
00386
00387
00388 }
00389
00390
00391
00392 slotLoadProviderDXS();
00393 }
00394
00395 void DownloadDialog::slotEntries(QList<KNS::Entry*> _entries)
00396 {
00397 Q_UNUSED(_entries);
00398
00399
00400
00401 }
00402
00403 void DownloadDialog::slotEntriesFailed()
00404 {
00405 displayMessage(i18n("Entries failed to load"));
00406 }
00407
00408
00409 void DownloadDialog::slotEntryLoaded(Entry *entry, const Feed *feed, const Provider *provider)
00410 {
00411 Entry::List e = entries[feed];
00412 e.append(entry);
00413 entries[feed] = e;
00414
00415 if (!m_entriesByProvider.contains(provider)) {
00416 kDebug(551) << "adding provider " << provider->name().representation() << " to combobox";
00417 m_sourceCombo->addItem(provider->name().representation());
00418 }
00419 m_entriesByProvider[provider].append(entry);
00420
00421
00422 m_providers[entry] = provider;
00423
00424 mMutex.lock();
00425
00426 if (!m_models.value(feed)) {
00427
00428 kDebug(551) << "making a new model for this feed" << feed;
00429 m_models[feed] = new KNS::ItemsModel(this, provider->webService().isValid());
00430 connect(m_engine, SIGNAL(signalEntryChanged(KNS::Entry*)),
00431 m_models[feed], SLOT(slotEntryChanged(KNS::Entry*)));
00432 if (provider->name().representation() == m_sourceCombo->currentText()) {
00433
00434 populateSortCombo(provider);
00435 }
00436 }
00437 mMutex.unlock();
00438
00439 KNS::ItemsModel* thisModel = m_models.value(feed);
00440
00441 Q_ASSERT(thisModel != NULL);
00442 thisModel->addEntry(entry);
00443 }
00444
00445 void DownloadDialog::slotEntryRemoved(KNS::Entry *entry, const KNS::Feed *feed)
00446 {
00447 Q_ASSERT(m_models[feed] != NULL);
00448
00449 m_models[feed]->removeEntry(entry);
00450 }
00451
00452 void DownloadDialog::refresh()
00453 {
00454 m_sourceCombo->clear();
00455
00456 Q_ASSERT(m_entriesByProvider.keys().size() > 0);
00457
00458 for (int i = 0; i < m_entriesByProvider.keys().count(); i++) {
00459 const Provider *provider = m_entriesByProvider.keys().at(i);
00460 if (!provider) {
00461
00462 continue;
00463 }
00464
00465
00466 m_sourceCombo->addItem(provider->name().representation());
00467
00468 }
00469
00470 slotLoadProviderDXS();
00471
00473
00474
00475
00476
00477
00478
00479
00480 }
00481
00482 void DownloadDialog::populateSortCombo(const Provider * provider)
00483 {
00484 QString url = provider->webAccess().pathOrUrl();
00485 if (url.isEmpty()) {
00486 m_providerLinkLabel->hide();
00487 } else {
00488 m_providerLinkLabel->setText(QString("<a href=\"%1\">?</a>").arg(url));
00489 }
00490
00491 QStringList feeds = provider->feeds();
00492 m_sortCombo->clear();
00493 for (int i = 0; i < feeds.size(); ++i) {
00494 QString feedName = provider->downloadUrlFeed(feeds[i])->name().representation();
00495 kDebug(551) << "adding feed " << feeds[i] << " to combobox";
00496 m_sortCombo->addItem(feedName, feeds[i]);
00497 }
00498 }
00499
00500 void DownloadDialog::slotInfo(QString provider, QString server, QString version)
00501 {
00502 QString link = QString("<a href=\"%1\">%1</a>").arg(server);
00503 QString infostring = i18n("Server: %1", link);
00504 infostring += i18n("<br />Provider: %1", provider);
00505 infostring += i18n("<br />Version: %1", version);
00506
00507 KMessageBox::information(this,
00508 infostring,
00509 i18n("Provider information"));
00510 }
00511
00512 void DownloadDialog::slotComments(QStringList comments)
00513 {
00514 QPointer<KDXSComments> commentsdlg = new KDXSComments(this);
00515
00516 for (QStringList::const_iterator it = comments.constBegin(); it != comments.constEnd(); ++it) {
00517
00518 commentsdlg->addComment("foo", (*it));
00519 }
00520
00521 commentsdlg->exec();
00522 }
00523
00525
00526 void DownloadDialog::slotEntryChanged(KNS::Entry * entry)
00527 {
00528 Q_UNUSED(entry)
00529 setCursor(Qt::ArrowCursor);
00530 }
00531
00532 void DownloadDialog::slotPayloadFailed(KNS::Entry * entry)
00533 {
00534 setCursor(Qt::ArrowCursor);
00535 KMessageBox::error(this, i18n("Could not install %1", entry->name().representation()),
00536 i18n("Get Hot New Stuff!"));
00537 }
00538
00539 void DownloadDialog::slotPayloadLoaded(KUrl url)
00540 {
00541 Q_UNUSED(url)
00542 setCursor(Qt::ArrowCursor);
00543 }
00544
00545 void DownloadDialog::slotProgress(const QString & text, int percentage)
00546 {
00547 m_progress->addProgress(text, percentage);
00548 }
00549
00550 void DownloadDialog::slotProvidersFailed()
00551 {
00552 kDebug(551) << "slotProvidersFailed";
00553 KMessageBox::error(this,
00554 i18n("There was an error loading data providers."),
00555 i18n("Get Hot New Stuff"));
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 void DownloadDialog::slotFault()
00583 {
00584 KMessageBox::error(this,
00585 i18n("A protocol fault has occurred. The request has failed."),
00586 i18n("Desktop Exchange Service"));
00587 }
00588
00589 void DownloadDialog::slotError()
00590 {
00591 KMessageBox::error(this,
00592 i18n("A network error has occurred. The request has failed."),
00593 i18n("Desktop Exchange Service"));
00594 }
00595
00596 #include "downloaddialog.moc"