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