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