KNewStuff
itemsview.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "itemsview.h"
00023
00024
00025 #include <QtCore/QFile>
00026 #include <QtGui/QWidget>
00027 #include <QtCore/QTimer>
00028 #include <QtGui/QLayout>
00029 #include <QtGui/QPixmap>
00030 #include <QtGui/QFont>
00031 #include <QtGui/QComboBox>
00032 #include <QtGui/QPushButton>
00033 #include <QtCore/QMutableVectorIterator>
00034 #include <QtCore/QRect>
00035 #include <QtGui/QPainter>
00036 #include <QtGui/QScrollArea>
00037 #include <QtGui/QApplication>
00038 #include <QtGui/QTextDocument>
00039 #include <kaboutdata.h>
00040 #include <kapplication.h>
00041 #include <kcomponentdata.h>
00042 #include <kglobalsettings.h>
00043 #include <klocale.h>
00044 #include <klineedit.h>
00045 #include <kconfig.h>
00046 #include <kstandarddirs.h>
00047 #include <kmessagebox.h>
00048 #include <kdebug.h>
00049 #include <kiconloader.h>
00050 #include <kio/job.h>
00051 #include <kio/netaccess.h>
00052 #include <ktitlewidget.h>
00053 #include <ktoolinvocation.h>
00054
00055 #include "knewstuff2/core/provider.h"
00056 #include "knewstuff2/core/providerhandler.h"
00057 #include "knewstuff2/core/entry.h"
00058 #include "knewstuff2/core/entryhandler.h"
00059 #include "knewstuff2/core/category.h"
00060
00061 #include "knewstuff2/dxs/dxs.h"
00062
00063 #include "knewstuff2/ui/qprogressindicator.h"
00064
00065
00066 #include "ui_DownloadDialog.h"
00067 #include "kdxsbutton.h"
00068 #include "qasyncpixmap.h"
00069
00070 using namespace KNS;
00071
00072 static bool NameSorter(const Entry* e1, const Entry* e2)
00073 {
00074 return e1->name().representation() < e2->name().representation();
00075 }
00076
00077 static bool RatingSorter(const Entry* e1, const Entry* e2)
00078 {
00079 return e1->rating() < e2->rating();
00080 }
00081
00082 static bool RecentSorter(const Entry* e1, const Entry* e2)
00083 {
00084
00085 return e1->releaseDate() > e2->releaseDate();
00086 }
00087
00088 static bool DownloadsSorter(const Entry* e1, const Entry* e2)
00089 {
00090
00091 return e1->downloads() > e2->downloads();
00092 }
00093
00094 ItemsView::ItemsView(QWidget* _parent)
00095 : QListView(_parent),
00096 m_currentProvider(0), m_currentFeed(0), m_root(0), m_sorting(0), m_engine(0)
00097 {
00098 m_root = new QWidget(this);
00099 setFrameStyle(QFrame::Plain | QFrame::StyledPanel);
00100 setVerticalScrollMode(ScrollPerPixel);
00101
00102 }
00103
00104 ItemsView::~ItemsView()
00105 {
00106 }
00107
00108 void ItemsView::setEngine(DxsEngine *engine)
00109 {
00110 m_engine = engine;
00111 }
00112
00113 void ItemsView::setProvider(const Provider * provider, const Feed * feed)
00114 {
00115 m_currentProvider = provider;
00116 m_currentFeed = feed;
00117 buildContents();
00118 }
00119
00120 void ItemsView::setSorting(int sortType)
00121 {
00122 m_sorting = sortType;
00123 buildContents();
00124 }
00125
00126 void ItemsView::setFeed(const Feed * feed)
00127 {
00128 m_currentFeed = feed;
00129 buildContents();
00130 }
00131
00132 void ItemsView::setSearchText(const QString & text)
00133 {
00134 m_searchText = text;
00135 buildContents();
00136 }
00137
00138 void ItemsView::updateItem(Entry *entry)
00139 {
00140
00141
00142
00143
00144 }
00145
00146 void ItemsView::buildContents()
00147 {
00148 m_views.clear();
00149
00150 m_root->setBackgroundRole(QPalette::Base);
00151 QVBoxLayout* _layout = new QVBoxLayout(m_root);
00152 _layout->setSpacing(10);
00153
00154 if (m_currentFeed != NULL) {
00155 Entry::List entries = m_currentFeed->entries();
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 Entry::List::iterator it = entries.begin(), iEnd = entries.end();
00173 for (unsigned row = 0; it != iEnd; ++it) {
00174 Entry* entry = (*it);
00175
00176 if (entry->name().representation().toLower().contains(m_searchText.toLower())) {
00177 QHBoxLayout * itemLayout = new QHBoxLayout;
00178 _layout->addLayout(itemLayout);
00179
00180 EntryView *part = new EntryView(m_root);
00181 part->setBackgroundRole(row & 1 ? QPalette::AlternateBase : QPalette::Base);
00182 itemLayout->addWidget(part);
00183
00184 QVBoxLayout * previewLayout = new QVBoxLayout;
00185 itemLayout->insertLayout(0, previewLayout);
00186
00187 KDXSButton *dxsbutton = new KDXSButton(m_root);
00188 dxsbutton->setEntry(entry);
00189 dxsbutton->setProvider(m_currentProvider);
00190 dxsbutton->setEngine(m_engine);
00191
00192 QString imageurl = entry->preview().representation();
00193 if (!imageurl.isEmpty()) {
00194 QLabel *f = new QLabel(m_root);
00195 f->setFrameStyle(QFrame::Panel | QFrame::Sunken);
00196 QAsyncPixmap *pix = new QAsyncPixmap(imageurl, m_root);
00197 f->setFixedSize(64, 64);
00198
00199
00200 previewLayout->addWidget(f);
00201 }
00202
00203
00204 part->setEntry(entry);
00205 m_views.insert(entry, part);
00206 ++row;
00207 }
00208 }
00209 }
00210
00211
00212 }
00213
00214 EntryView::EntryView(QWidget * _parent)
00215 : QLabel(_parent)
00216 {
00217 connect(this, SIGNAL(linkActivated(const QString&)), SLOT(urlSelected(const QString&)));
00218 }
00219
00220 void EntryView::setEntry(Entry *entry)
00221 {
00222 m_entry = entry;
00223 buildContents();
00224 }
00225
00226 void EntryView::updateEntry(Entry *entry)
00227 {
00228
00229 QString idString = QString::number((unsigned long)entry);
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 }
00243
00244 void EntryView::buildContents()
00245 {
00246
00247 QString t;
00248
00249 t += "<html><body>";
00250
00251
00252
00253 Entry::Status status = m_entry->status();
00254 QString statusIcon;
00255 KIconLoader *loader = KIconLoader::global();
00256
00257 switch (status) {
00258 case Entry::Invalid:
00259 statusIcon = "<img src='" + loader->iconPath("dialog-error", -KIconLoader::SizeSmall) + "' />";
00260 break;
00261 case Entry::Downloadable:
00262
00263
00264 break;
00265 case Entry::Installed:
00266 statusIcon = "<img src='" + loader->iconPath("dialog-ok", -KIconLoader::SizeSmall) + "' />";
00267 break;
00268 case Entry::Updateable:
00269 statusIcon = "<img src='" + loader->iconPath("software-update-available", -KIconLoader::SizeSmall) + "' />";
00270 break;
00271 case Entry::Deleted:
00272 statusIcon = "<img src='" + loader->iconPath("user-trash", -KIconLoader::SizeSmall) + "' />";
00273 break;
00274 }
00275
00276
00277 QString titleString = m_entry->name().representation();
00278 if (!m_entry->version().isEmpty()) titleString += " v." + Qt::escape(m_entry->version());
00279
00280
00281 QString starIconPath = KStandardDirs::locate("data", "knewstuff/pics/ghns_star.png");
00282 QString starBgIconPath = KStandardDirs::locate("data", "knewstuff/pics/ghns_star_gray.png");
00283
00284 int starPixels = 11 + 11 * (m_entry->rating() / 10);
00285 QString starsString = "<div style='width: " + QString::number(starPixels) + "px; background-image: url(" + starIconPath + "); background-repeat: repeat-x;'> </div>";
00286 int grayPixels = 22 + 22 * (m_entry->rating() / 20);
00287 starsString = "<div style='width: " + QString::number(grayPixels) + "px;background-image: url(" + starBgIconPath + "); background-repeat: repeat-x;'>" + starsString + " </div>";
00288
00289
00290 KNS::Author author = m_entry->author();
00291 QString authorString = author.name();
00292
00293 QString emailString = author.email();
00294 if (!emailString.isEmpty()) {
00295 authorString = "<a href='mailto:" + Qt::escape(emailString) + "'>"
00296 + Qt::escape(authorString) + "</a>";
00297 }
00298
00299
00300 t +=
00301 statusIcon + Qt::escape(titleString) + "<br />"
00302
00303 + Qt::escape(m_entry->summary().representation())
00304 + "<br />";
00305
00306 if (m_entry->rating() > 0) {
00307 t += i18n("Rating: ") + QString::number(m_entry->rating())
00308 + "<br />";
00309 }
00310
00311 if (m_entry->downloads() > 0) {
00312 t += i18n("Downloads: ") + QString::number(m_entry->downloads())
00313 + "<br />";
00314 }
00315
00316 if (!authorString.isEmpty()) {
00317 t += "<em>" + authorString + "</em>, ";
00318 }
00319 t += KGlobal::locale()->formatDate(m_entry->releaseDate(), KLocale::ShortDate)
00320 + "<br />" + "</body></html>";
00321
00322 setText(t);
00323 }
00324
00325 void EntryView::setTheAaronnesqueStyle()
00326 {
00327 QString hoverColor = "#000000";
00328 QString hoverBackground = "#f8f8f8";
00329 QString starIconPath = KStandardDirs::locate("data", "knewstuff/pics/ghns_star.png");
00330 QString starBgIconPath = KStandardDirs::locate("data", "knewstuff/pics/ghns_star_gray.png");
00331
00332
00333 QString s;
00334 s += "body { background-color: white; color: black; padding: 0; margin: 0; }";
00335 s += "table, td, th { padding: 0; margin: 0; text-align: left; }";
00336 s += "input { color: #000080; font-size:120%; }";
00337
00338
00339 s += ".itemBox { background-color: white; color: black; width: 100%; border-bottom: 1px solid gray; margin: 0px 0px; }";
00340 s += ".itemBox:hover { background-color: " + hoverBackground + "; color: " + hoverColor + "; }";
00341
00342
00343 s += ".leftColumn { width: 100px; height:100%; text-align: center; }";
00344 s += ".leftImage {}";
00345 s += ".leftButton {}";
00346 s += ".leftProgressContainer { width: 82px; height: 10px; background-color: transparent; }";
00347 s += ".leftProgressBar { left: 1px; width: 0px; top: 1px; height: 8px; background-color: red; }";
00348 s += ".contentsColumn { vertical-align: top; }";
00349 s += ".contentsHeader { width: 100%; font-size: 120%; font-weight: bold; border-bottom: 1px solid #c8c8c8; }";
00350 s += ".contentsBody {}";
00351 s += ".contentsFooter {}";
00352 s += ".star { width: 0px; height: 24px; background-image: url(" + starIconPath + "); background-repeat: repeat-x; }";
00353 s += ".starbg { width: 110px; height: 24px; background-image: url(" + starBgIconPath + "); background-repeat: repeat-x; }";
00354 setStyleSheet(s);
00355 }
00356
00357 void EntryView::urlSelected(const QString &link)
00358 {
00359
00360
00361 KUrl url(link);
00362 QString urlProtocol = url.protocol();
00363 QString urlPath = url.path();
00364
00365 if (urlProtocol == "mailto") {
00366
00367
00368
00369 KToolInvocation::invokeMailer(url);
00370 } else if (urlProtocol == "item") {
00371
00372 bool ok;
00373 unsigned long itemPointer = urlPath.toULong(&ok);
00374 if (!ok) {
00375 kWarning() << "ItemsView: error converting item pointer.";
00376 return;
00377 }
00378
00379
00380 Entry *entry = (Entry*)itemPointer;
00381 if (entry != m_entry) {
00382 kWarning() << "ItemsView: error retrieving item pointer.";
00383 return;
00384 }
00385
00386
00387
00388
00389
00390
00391
00392 }
00393 }
00394
00395 #include "itemsview.moc"
00396