00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "downloaddialog.h"
00022 #include "downloaddialog.moc"
00023
00024 #include <klocale.h>
00025 #include <ktabctl.h>
00026 #include <klistview.h>
00027 #include <kdebug.h>
00028 #include <kio/job.h>
00029 #include <kio/netaccess.h>
00030 #include <kmessagebox.h>
00031 #include <kurl.h>
00032 #include <kconfig.h>
00033 #include <kapplication.h>
00034 #include <kiconloader.h>
00035
00036 #include <knewstuff/entry.h>
00037 #include <knewstuff/knewstuffgeneric.h>
00038 #include <knewstuff/engine.h>
00039
00040 #include <qlayout.h>
00041 #include <qpushbutton.h>
00042 #include <qdom.h>
00043 #include <qlabel.h>
00044 #include <qtextbrowser.h>
00045 #include <qtimer.h>
00046
00047 using namespace KNS;
00048
00049 struct DownloadDialog::Private
00050 {
00051 QString m_providerlist;
00052 QWidget *m_page;
00053 };
00054
00055 class NumSortListViewItem : public KListViewItem
00056 {
00057 public:
00058 NumSortListViewItem( QListView * parent, QString label1, QString label2 = QString::null, QString label3 = QString::null, QString label4 = QString::null, QString label5 = QString::null, QString label6 = QString::null, QString label7 = QString::null, QString label8 = QString::null ) :
00059 KListViewItem( parent, label1, label2, label3, label4, label5, label6, label7, label8 )
00060 {
00061 }
00062
00063 QString key(int col, bool asc) const {
00064 if (col == 2)
00065 {
00066
00067 QString s;
00068 s.sprintf("%08d", text(col).toInt());
00069 return s;
00070 }
00071 return KListViewItem::key( col, asc );
00072 }
00073 };
00074
00075
00076 DownloadDialog::DownloadDialog(Engine *engine, QWidget *)
00077 : KDialogBase(KDialogBase::IconList, i18n("Get Hot New Stuff"),
00078 KDialogBase::Close, KDialogBase::Close)
00079 {
00080 init(engine);
00081 }
00082
00083 DownloadDialog::DownloadDialog(QWidget *)
00084 : KDialogBase(KDialogBase::IconList, i18n("Get Hot New Stuff"),
00085 KDialogBase::Close, KDialogBase::Close)
00086 {
00087 init(0);
00088 }
00089
00090 void DownloadDialog::open(QString type)
00091 {
00092 DownloadDialog d;
00093 d.setType(type);
00094 d.load();
00095 d.exec();
00096 }
00097
00098
00099 DownloadDialog::DownloadDialog(Engine *engine, QWidget *, const QString& caption)
00100 : KDialogBase(KDialogBase::IconList, (caption.isNull() ? i18n("Get Hot New Stuff") : caption),
00101 KDialogBase::Close, KDialogBase::Close)
00102 {
00103 init(engine);
00104 }
00105
00106 DownloadDialog::DownloadDialog(QWidget *, const QString& caption)
00107 : KDialogBase(KDialogBase::IconList, (caption.isNull() ? i18n("Get Hot New Stuff") : caption),
00108 KDialogBase::Close, KDialogBase::Close)
00109 {
00110 init(0);
00111 }
00112
00113 void DownloadDialog::init(Engine *engine)
00114 {
00115 resize(700, 400);
00116 d = new Private();
00117
00118 m_engine = engine;
00119 d->m_page = NULL;
00120
00121 connect(this, SIGNAL(aboutToShowPage(QWidget*)), SLOT(slotPage(QWidget*)));
00122
00123 if(!engine)
00124 {
00125 m_loader = new ProviderLoader(this);
00126 connect(m_loader, SIGNAL(providersLoaded(Provider::List*)), SLOT(slotProviders(Provider::List*)));
00127 }
00128 }
00129
00130 DownloadDialog::~DownloadDialog()
00131 {
00132 delete d;
00133 }
00134
00135 void DownloadDialog::load()
00136 {
00137 m_loader->load(m_filter, d->m_providerlist);
00138 }
00139
00140 void DownloadDialog::load(QString providerList)
00141 {
00142 m_loader->load(m_filter, providerList);
00143 }
00144
00145 void DownloadDialog::clear()
00146 {
00147 QMap<QWidget*, QValueList<KListView*>* >::Iterator it;
00148 for(it = m_map.begin(); it != m_map.end(); it++)
00149 {
00150 QValueList<KListView*> *v = it.data();
00151 kdDebug() << "clear listviews in " << v << endl;
00152 if(v)
00153 {
00154 (*(v->at(0)))->clear();
00155 (*(v->at(1)))->clear();
00156 (*(v->at(2)))->clear();
00157
00158
00159 }
00160
00161 delete it.key();
00162 }
00163 m_map.clear();
00164 }
00165
00166 void DownloadDialog::slotProviders(Provider::List *list)
00167 {
00168 Provider *p;
00169
00170
00171 for(p = list->first(); p; p = list->next())
00172 {
00173 kdDebug() << "++ provider ++ " << p->name() << endl;
00174
00175 if(!m_filter.isEmpty())
00176 loadProvider(p);
00177 else
00178 addProvider(p);
00179
00180
00181 }
00182 }
00183
00184 void DownloadDialog::addProvider(Provider *p)
00185 {
00186 QFrame *frame;
00187 KTabCtl *ctl;
00188 QWidget *w_d, *w_r, *w_l;
00189 QWidget *w2;
00190 KListView *lvtmp_r, *lvtmp_d, *lvtmp_l;
00191 QTextBrowser *rt;
00192 QString tmp;
00193 int ret;
00194 QPixmap pix;
00195
00196 if(m_map.count() == 0)
00197 {
00198 frame = addPage(i18n("Welcome"), i18n("Welcome"), QPixmap(""));
00199 delete frame;
00200 }
00201
00202 kdDebug() << "addProvider()/begin" << endl;
00203
00204 ret = true;
00205 if(!p->icon().isValid()) ret = false;
00206 else ret = KIO::NetAccess::download(p->icon(), tmp, this);
00207 if(ret) pix = QPixmap(tmp);
00208 else pix = KGlobal::iconLoader()->loadIcon("knewstuff", KIcon::Panel);
00209 frame = addPage(p->name(), p->name(), pix);
00210 m_frame = frame;
00211
00212 w2 = new QWidget(frame);
00213 w_d = new QWidget(frame);
00214 w_r = new QWidget(frame);
00215 w_l = new QWidget(frame);
00216
00217 ctl = new KTabCtl(frame);
00218 ctl->addTab(w_r, i18n("Highest Rated"));
00219 ctl->addTab(w_d, i18n("Most Downloads"));
00220 ctl->addTab(w_l, i18n("Latest"));
00221
00222 m_curtab = 0;
00223 connect(ctl, SIGNAL(tabSelected(int)), SLOT(slotTab(int)));
00224
00225 QHBoxLayout *box = new QHBoxLayout(frame);
00226 box->add(ctl);
00227
00228 lvtmp_r = new KListView(w_r);
00229 lvtmp_r->addColumn(i18n("Name"));
00230 lvtmp_r->addColumn(i18n("Version"));
00231 lvtmp_r->addColumn(i18n("Rating"));
00232 lvtmp_r->setSorting(2, false);
00233
00234 lvtmp_d = new KListView(w_d);
00235 lvtmp_d->addColumn(i18n("Name"));
00236 lvtmp_d->addColumn(i18n("Version"));
00237 lvtmp_d->addColumn(i18n("Downloads"));
00238 lvtmp_d->setSorting(2, false);
00239
00240 lvtmp_l = new KListView(w_l);
00241 lvtmp_l->addColumn(i18n("Name"));
00242 lvtmp_l->addColumn(i18n("Version"));
00243 lvtmp_l->addColumn(i18n("Release Date"));
00244 lvtmp_l->setSorting(2, false);
00245
00246 connect(lvtmp_r, SIGNAL(selectionChanged()), SLOT(slotSelected()));
00247 connect(lvtmp_d, SIGNAL(selectionChanged()), SLOT(slotSelected()));
00248 connect(lvtmp_l, SIGNAL(selectionChanged()), SLOT(slotSelected()));
00249
00250 rt = new QTextBrowser(frame);
00251 rt->setMinimumWidth(150);
00252
00253 QPushButton *in = new QPushButton(i18n("Install"), frame);
00254 QPushButton *de = new QPushButton(i18n("Details"), frame);
00255 in->setEnabled(false);
00256 de->setEnabled(false);
00257
00258 box->addSpacing(spacingHint());
00259 QVBoxLayout *vbox = new QVBoxLayout(box);
00260 vbox->add(rt);
00261 vbox->addSpacing(spacingHint());
00262 vbox->add(de);
00263 vbox->add(in);
00264
00265 connect(in, SIGNAL(clicked()), SLOT(slotInstall()));
00266 connect(de, SIGNAL(clicked()), SLOT(slotDetails()));
00267
00268 QVBoxLayout *box2 = new QVBoxLayout(w_r);
00269 box2->add(lvtmp_r);
00270 QVBoxLayout *box3 = new QVBoxLayout(w_d);
00271 box3->add(lvtmp_d);
00272 QVBoxLayout *box4 = new QVBoxLayout(w_l);
00273 box4->add(lvtmp_l);
00274
00275 QValueList<KListView*> *v = new QValueList<KListView*>;
00276 *v << lvtmp_r << lvtmp_d << lvtmp_l;
00277 m_map[frame] = v;
00278 m_rts[frame] = rt;
00279 QValueList<QPushButton*> *vb = new QValueList<QPushButton*>;
00280 *vb << in << de;
00281 m_buttons[frame] = vb;
00282 m_providers[frame] = p;
00283
00284 kdDebug() << "addProvider()/end; lvtmp_r = " << lvtmp_r << endl;
00285
00286 if(m_engine) slotPage(frame);
00287
00288 QTimer::singleShot(100, this, SLOT(slotFinish()));
00289 }
00290
00291 void DownloadDialog::slotResult(KIO::Job *job)
00292 {
00293 QDomDocument dom;
00294 QDomElement knewstuff;
00295
00296 kdDebug() << "got data: " << m_data[job] << endl;
00297
00298 kapp->config()->setGroup("KNewStuffStatus");
00299
00300 dom.setContent(m_data[job]);
00301 knewstuff = dom.documentElement();
00302
00303 for(QDomNode pn = knewstuff.firstChild(); !pn.isNull(); pn = pn.nextSibling())
00304 {
00305 QDomElement stuff = pn.toElement();
00306
00307 kdDebug() << "element: " << stuff.tagName() << endl;
00308
00309 if(stuff.tagName() == "stuff")
00310 {
00311 Entry *entry = new Entry(stuff);
00312 kdDebug() << "TYPE::" << entry->type() << " FILTER::" << m_filter << endl;
00313 if(!entry->type().isEmpty())
00314 {
00315 if((!m_filter.isEmpty()) && (entry->type() != m_filter)) continue;
00316 }
00317
00318 if((!m_filter.isEmpty()) && (m_jobs[job]))
00319 {
00320 Provider *p = m_jobs[job];
00321 addProvider(p);
00322 slotPage(m_frame);
00323 m_jobs[job] = 0;
00324 }
00325 addEntry(entry);
00326 }
00327 }
00328
00329 m_data[job] = "";
00330 }
00331
00332 int DownloadDialog::installStatus(Entry *entry)
00333 {
00334 QDate date;
00335 QString datestring;
00336 int installed;
00337
00338 kapp->config()->setGroup("KNewStuffStatus");
00339 datestring = kapp->config()->readEntry(entry->name());
00340 if(datestring.isNull()) installed = 0;
00341 else
00342 {
00343 date = QDate::fromString(datestring, Qt::ISODate);
00344 if(!date.isValid()) installed = 0;
00345 else if(date < entry->releaseDate()) installed = -1;
00346 else installed = 1;
00347 }
00348
00349 return installed;
00350 }
00351
00352 void DownloadDialog::addEntry(Entry *entry)
00353 {
00354 QPixmap pix;
00355 int installed;
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 installed = installStatus(entry);
00369
00370 if(installed > 0) pix = KGlobal::iconLoader()->loadIcon("ok", KIcon::Small);
00371 else if(installed < 0) pix = KGlobal::iconLoader()->loadIcon("history", KIcon::Small);
00372 else pix = QPixmap();
00373
00374 KListViewItem *tmp_r = new KListViewItem(lv_r,
00375 entry->name(), entry->version(), QString("%1").arg(entry->rating()));
00376 KListViewItem *tmp_d = new NumSortListViewItem(lv_d,
00377 entry->name(), entry->version(), QString("%1").arg(entry->downloads()));
00378 KListViewItem *tmp_l = new KListViewItem(lv_l,
00379 entry->name(), entry->version(), KGlobal::locale()->formatDate(entry->releaseDate()));
00380
00381 tmp_r->setPixmap(0, pix);
00382 tmp_d->setPixmap(0, pix);
00383 tmp_l->setPixmap(0, pix);
00384
00385 m_entries.append(entry);
00386
00387 kdDebug() << "added entry " << entry->name() << endl;
00388 }
00389
00390 void DownloadDialog::slotData(KIO::Job *job, const QByteArray &a)
00391 {
00392 QCString tmp(a, a.size() + 1);
00393 m_data[job].append(QString::fromUtf8(tmp));
00394 }
00395
00396 void DownloadDialog::slotDetails()
00397 {
00398 Entry *e = getEntry();
00399 if(!e) return;
00400
00401 QString lang = KGlobal::locale()->language();
00402
00403 QString info = i18n
00404 (
00405 "Name: %1\n"
00406 "Author: %2\n"
00407 "License: %3\n"
00408 "Version: %4\n"
00409 "Release: %5\n"
00410 "Rating: %6\n"
00411 "Downloads: %7\n"
00412 "Release date: %8\n"
00413 "Summary: %9\n"
00414 ).arg(e->name()
00415 ).arg(e->author()
00416 ).arg(e->license()
00417 ).arg(e->version()
00418 ).arg(e->release()
00419 ).arg(e->rating()
00420 ).arg(e->downloads()
00421 ).arg(KGlobal::locale()->formatDate(e->releaseDate())
00422 ).arg(e->summary(lang)
00423 );
00424
00425 info.append(i18n
00426 (
00427 "Preview: %1\n"
00428 "Payload: %2\n"
00429 ).arg(e->preview().url()
00430 ).arg(e->payload().url()
00431 ));
00432
00433 KMessageBox::information(this, info, i18n("Details"));
00434 }
00435
00436 void DownloadDialog::slotInstall()
00437 {
00438 Entry *e = getEntry();
00439 if(!e) return;
00440
00441 kdDebug() << "download entry now" << endl;
00442
00443 if(m_engine)
00444 {
00445 m_engine->download(e);
00446 install(e);
00447 }
00448 else
00449 {
00450 m_s = new KNewStuffGeneric(e->type(), this);
00451
00452 m_entry = e;
00453
00454 KURL source = e->payload();
00455 KURL dest = KURL(m_s->downloadDestination(e));
00456
00457 KIO::FileCopyJob *job = KIO::file_copy(source, dest, -1, true);
00458 connect(job, SIGNAL(result(KIO::Job*)), SLOT(slotInstalled(KIO::Job*)));
00459 }
00460 }
00461
00462 void DownloadDialog::install(Entry *e)
00463 {
00464 kapp->config()->setGroup("KNewStuffStatus");
00465 kapp->config()->writeEntry(m_entryname, e->releaseDate().toString(Qt::ISODate));
00466 kapp->config()->sync();
00467
00468 QPixmap pix = KGlobal::iconLoader()->loadIcon("ok", KIcon::Small);
00469 m_entryitem = lv_r->findItem(m_entryname, 0);
00470 if(m_entryitem) m_entryitem->setPixmap(0, pix);
00471 m_entryitem = lv_d->findItem(m_entryname, 0);
00472 if(m_entryitem) m_entryitem->setPixmap(0, pix);
00473 m_entryitem = lv_l->findItem(m_entryname, 0);
00474 if(m_entryitem) m_entryitem->setPixmap(0, pix);
00475
00476
00477 QPushButton *in;
00478 in = *(m_buttons[d->m_page]->at(0));
00479 if(in) in->setEnabled(false);
00480 }
00481
00482 void DownloadDialog::slotInstalled(KIO::Job *job)
00483 {
00484 bool ret = (job->error() == 0);
00485 KIO::FileCopyJob *cjob;
00486
00487 if(ret)
00488 {
00489 cjob = static_cast<KIO::FileCopyJob*>(job);
00490 if(cjob)
00491 {
00492 ret = m_s->install(cjob->destURL().path());
00493 }
00494 else ret = false;
00495 }
00496
00497 if(ret)
00498 {
00499 install(m_entry);
00500
00501 KMessageBox::information(this, i18n("Installation successful."), i18n("Installation"));
00502 }
00503 else KMessageBox::error(this, i18n("Installation failed."), i18n("Installation"));
00504
00505 delete m_s;
00506 }
00507
00508 void DownloadDialog::slotTab(int tab)
00509 {
00510 kdDebug() << "switch tab to: " << tab << endl;
00511 m_curtab = tab;
00512 }
00513
00514 void DownloadDialog::slotSelected()
00515 {
00516 QString tmp;
00517 bool enabled;
00518 Entry *e = getEntry();
00519 QString lang = KGlobal::locale()->language();
00520
00521 if(e)
00522 {
00523 if(!e->preview(lang).isValid())
00524 {
00525 m_rt->setText(QString("<b>%1</b><br>%2<br>%3<br><br><i>%4</i><br>(%5)").arg(
00526 e->name()).arg(e->author()).arg(KGlobal::locale()->formatDate(e->releaseDate())).arg(e->summary(lang)).arg(e->license()));
00527 }
00528 else
00529 {
00530 KIO::NetAccess::download(e->preview(lang), tmp, this);
00531 m_rt->setText(QString("<b>%1</b><br>%2<br>%3<br><br><img src='%4'><br><i>%5</i><br>(%6)").arg(
00532 e->name()).arg(e->author()).arg(KGlobal::locale()->formatDate(e->releaseDate())).arg(tmp).arg(e->summary(lang)).arg(e->license()));
00533 }
00534
00535 if(installStatus(e) == 1) enabled = false;
00536 else enabled = true;
00537
00538 QPushButton *de, *in;
00539 in = *(m_buttons[d->m_page]->at(0));
00540 de = *(m_buttons[d->m_page]->at(1));
00541 if(in) in->setEnabled(enabled);
00542 if(de) de->setEnabled(true);
00543 }
00544 }
00545
00546 Entry *DownloadDialog::getEntry()
00547 {
00548 if(m_curtab == 0) m_entryitem = lv_r->currentItem();
00549 else if(m_curtab == 1) m_entryitem = lv_d->currentItem();
00550 else if(m_curtab == 2) m_entryitem = lv_l->currentItem();
00551 else return 0;
00552
00553 m_entryname = m_entryitem->text(0);
00554
00555 for(Entry *e = m_entries.first(); e; e = m_entries.next())
00556 {
00557 if(e->name() == m_entryname) return e;
00558 }
00559
00560 return 0;
00561 }
00562
00563 void DownloadDialog::slotPage(QWidget *w)
00564 {
00565 Provider *p;
00566
00567 kdDebug() << "changed widget!!!" << endl;
00568
00569 if(m_map.find(w) == m_map.end()) return;
00570
00571 d->m_page = w;
00572
00573 lv_r = *(m_map[w]->at(0));
00574 lv_d = *(m_map[w]->at(1));
00575 lv_l = *(m_map[w]->at(2));
00576 p = m_providers[w];
00577 m_rt = m_rts[w];
00578
00579 kdDebug() << "valid change!!!; lv_r = " << lv_r << endl;
00580
00581 if(m_engine) return;
00582
00583 if(!m_filter.isEmpty()) return;
00584
00585 lv_r->clear();
00586 lv_d->clear();
00587 lv_l->clear();
00588
00589 kdDebug() << "-- fetch -- " << p->downloadUrl() << endl;
00590
00591 loadProvider(p);
00592 }
00593
00594 void DownloadDialog::loadProvider(Provider *p)
00595 {
00596 KIO::TransferJob *job = KIO::get(p->downloadUrl());
00597
00598 m_jobs[job] = p;
00599
00600 connect(job, SIGNAL(result(KIO::Job*)), SLOT(slotResult(KIO::Job*)));
00601 connect(job, SIGNAL(data(KIO::Job*, const QByteArray&)),
00602 SLOT(slotData(KIO::Job*, const QByteArray&)));
00603 }
00604
00605 void DownloadDialog::setType(QString type)
00606 {
00607 m_filter = type;
00608 }
00609
00610 void DownloadDialog::setProviderList(const QString& providerList)
00611 {
00612 d->m_providerlist = providerList;
00613 }
00614
00615 void DownloadDialog::slotOk()
00616 {
00617 }
00618
00619 void DownloadDialog::slotApply()
00620 {
00621 }
00622
00623 void DownloadDialog::open(const QString& type, const QString& caption)
00624 {
00625 DownloadDialog d(0, caption);
00626 d.setType(type);
00627 d.load();
00628 d.exec();
00629 }
00630
00631 void DownloadDialog::slotFinish()
00632 {
00633 showPage(1);
00634
00635 }
00636