• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KNewStuff

itemsview.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of KNewStuff2.
00003     Copyright (C) 2005 by Enrico Ros <eros.kde@email.it>
00004     Copyright (C) 2005 - 2007 Josef Spillner <spillner@kde.org>
00005     Copyright (C) 2007 Dirk Mueller <mueller@kde.org>
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2.1 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library.  If not, see <http://www.gnu.org/licenses/>.
00019 */
00020 
00021 // own include
00022 #include "itemsview.h"
00023 
00024 // qt/kde includes
00025 #include <QtCore/QFile>
00026 #include <QtGui/QWidget>
00027 #include <QtCore/QTimer>
00028 #include <QtGui/QLayout>
00029 #include <QtGui/QImage>
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 // local includes
00066 #include "ui_DownloadDialog.h"
00067 #include "kdxsbutton.h"
00068 #include "qasyncimage_p.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     // return > instead of < to sort in reverse order
00085     return e1->releaseDate() > e2->releaseDate();
00086 }
00087 
00088 static bool DownloadsSorter(const Entry* e1, const Entry* e2)
00089 {
00090     // return > instead of < to sort most downloads at the top
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     //setWidgetResizable(true);
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     // FIXME: change this to call updateEntry once it is complete
00141 //   if (m_views.contains(entry)) {
00142 //        m_views[entry]->setEntry(entry);
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 
00153     if (m_currentFeed != NULL) {
00154         Entry::List entries = m_currentFeed->entries();
00155         //switch (m_sorting)
00156         //{
00157         //    case 0:
00158         //        qSort(entries.begin(), entries.end(), NameSorter);
00159         //        break;
00160         //    case 1:
00161         //        qSort(entries.begin(), entries.end(), RatingSorter);
00162         //        break;
00163         //    case 2:
00164         //        qSort(entries.begin(), entries.end(), RecentSorter);
00165         //        break;
00166         //    case 3:
00167         //        qSort(entries.begin(), entries.end(), DownloadsSorter);
00168         //        break;
00169         //}
00170 
00171         Entry::List::iterator it = entries.begin(), iEnd = entries.end();
00172         for (unsigned row = 0; it != iEnd; ++it) {
00173             Entry* entry = (*it);
00174 
00175             if (entry->name().representation().toLower().contains(m_searchText.toLower())) {
00176                 QHBoxLayout * itemLayout = new QHBoxLayout;
00177                 _layout->addLayout(itemLayout);
00178 
00179                 EntryView *part = new EntryView(m_root);
00180                 part->setBackgroundRole(row & 1 ? QPalette::AlternateBase : QPalette::Base);
00181                 itemLayout->addWidget(part);
00182 
00183                 QVBoxLayout * previewLayout = new QVBoxLayout;
00184                 itemLayout->insertLayout(0, previewLayout);
00185 
00186                 KDXSButton *dxsbutton = new KDXSButton(m_root);
00187                 dxsbutton->setEntry(entry);
00188                 dxsbutton->setProvider(m_currentProvider);
00189                 dxsbutton->setEngine(m_engine);
00190 
00191                 QString imageurl = entry->preview().representation();
00192                 if (!imageurl.isEmpty()) {
00193                     QLabel *f = new QLabel(m_root);
00194                     f->setFrameStyle(QFrame::Panel | QFrame::Sunken);
00195                     QAsyncImage *pix = new QAsyncImage(imageurl, m_root);
00196                     f->setFixedSize(64, 64);
00197                     //connect(pix, SIGNAL(signalLoaded(const QImage&)),
00198                     //        f, SLOT(setImage(const QImage&)));
00199                     previewLayout->addWidget(f);
00200                 }
00201                 //previewLayout->addWidget(dxsbutton);
00202 
00203                 part->setEntry(entry);
00204                 m_views.insert(entry, part);
00205                 ++row;
00206             }
00207         }
00208     }
00209 
00210     //setWidget(m_root);
00211 }
00212 
00213 EntryView::EntryView(QWidget * _parent)
00214         : QLabel(_parent)
00215 {
00216     connect(this, SIGNAL(linkActivated(const QString&)), SLOT(urlSelected(const QString&)));
00217 }
00218 
00219 void EntryView::setEntry(Entry *entry)
00220 {
00221     m_entry = entry;
00222     buildContents();
00223 }
00224 
00225 void EntryView::updateEntry(Entry *entry)
00226 {
00227     // get item id string and iformations
00228     QString idString = QString::number((unsigned long)entry);
00229     //            AvailableItem::State state = item->state();
00230     //            bool showProgress = state != AvailableItem::Normal;
00231     //            int pixelProgress = showProgress ? (int)(item->progress() * 80.0) : 0;
00232 
00233     // perform internal scripting operations over the element
00234     //            executeScript( "document.getElementById('" + idString + "').style.color='red'" );
00235     //            executeScript( "document.getElementById('bar" + idString + "').style.width='" +
00236     //                           QString::number( pixelProgress ) + "px'" );
00237     //            executeScript( "document.getElementById('bc" + idString + "').style.backgroundColor='" +
00238     //                           (showProgress ? "gray" : "transparent") + "'" );
00239     //            executeScript( "document.getElementById('btn" + idString + "').value='" +
00240     //                           (item->installed() ? i18n( "Uninstall" ) : i18n( "Install" )) + "'" );
00241 }
00242 
00243 void EntryView::buildContents()
00244 {
00245     // write the html header and contents manipulation scripts
00246     QString t;
00247 
00248     t += "<html><body>";
00249 
00250     //t += setTheAaronnesqueStyle();
00251     // precalc the status icon
00252     Entry::Status status = m_entry->status();
00253     QString statusIcon;
00254     KIconLoader *loader = KIconLoader::global();
00255 
00256     switch (status) {
00257     case Entry::Invalid:
00258         statusIcon = "<img src='" + loader->iconPath("dialog-error", -KIconLoader::SizeSmall) + "' />";
00259         break;
00260     case Entry::Downloadable:
00261         // find a good icon to represent downloadable data
00262         //statusIcon = "<img src='" + loader->iconPath("network-server", -KIconLoader::SizeSmall) + "' />";
00263         break;
00264     case Entry::Installed:
00265         statusIcon = "<img src='" + loader->iconPath("dialog-ok", -KIconLoader::SizeSmall) + "' />";
00266         break;
00267     case Entry::Updateable:
00268         statusIcon = "<img src='" + loader->iconPath("software-update-available", -KIconLoader::SizeSmall) + "' />";
00269         break;
00270     case Entry::Deleted:
00271         statusIcon = "<img src='" + loader->iconPath("user-trash", -KIconLoader::SizeSmall) + "' />";
00272         break;
00273     }
00274 
00275     // precalc the title string
00276     QString titleString = m_entry->name().representation();
00277     if (!m_entry->version().isEmpty()) titleString += " v." + Qt::escape(m_entry->version());
00278 
00279     // precalc the string for displaying stars (normal+grayed)
00280     QString starIconPath = KStandardDirs::locate("data", "knewstuff/pics/ghns_star.png");
00281     QString starBgIconPath = KStandardDirs::locate("data", "knewstuff/pics/ghns_star_gray.png");
00282 
00283     int starPixels = 11 + 11 * (m_entry->rating() / 10);
00284     QString starsString = "<div style='width: " + QString::number(starPixels) + "px; background-image: url(" + starIconPath + "); background-repeat: repeat-x;'>&nbsp;</div>";
00285     int grayPixels = 22 + 22 * (m_entry->rating() / 20);
00286     starsString = "<div style='width: " + QString::number(grayPixels) + "px;background-image: url(" + starBgIconPath + "); background-repeat: repeat-x;'>" + starsString + "&nbsp;</div>";
00287 
00288     // precalc the string for displaying author (parsing email)
00289     KNS::Author author = m_entry->author();
00290     QString authorString = author.name();
00291 
00292     QString emailString = author.email();
00293     if (!emailString.isEmpty()) {
00294         authorString = "<a href='mailto:" + Qt::escape(emailString) + "'>"
00295                        + Qt::escape(authorString) + "</a>";
00296     }
00297 
00298     // write the HTML code for the current item
00299     t += //QLatin1String("<table class='contentsHeader' cellspacing='2' cellpadding='0'>")
00300         statusIcon + Qt::escape(titleString) + "<br />"
00301         //+   "<span align='right'>" + starsString +  "</span><br />"
00302         +      Qt::escape(m_entry->summary().representation())
00303         +   "<br />";
00304 
00305     if (m_entry->rating() > 0) {
00306         t += i18n("Rating: ") + QString::number(m_entry->rating())
00307              +   "<br />";
00308     }
00309 
00310     if (m_entry->downloads() > 0) {
00311         t += i18n("Downloads: ") + QString::number(m_entry->downloads())
00312              +   "<br />";
00313     }
00314 
00315     if (!authorString.isEmpty()) {
00316         t += "<em>" + authorString + "</em>, ";
00317     }
00318     t += KGlobal::locale()->formatDate(m_entry->releaseDate(), KLocale::ShortDate)
00319          + "<br />" + "</body></html>";
00320 
00321     setText(t);
00322 }
00323 
00324 void EntryView::setTheAaronnesqueStyle()
00325 {
00326     QString hoverColor = "#000000"; //QApplication::palette().active().highlightedText().name();
00327     QString hoverBackground = "#f8f8f8"; //QApplication::palette().active().highlight().name();
00328     QString starIconPath = KStandardDirs::locate("data", "knewstuff/pics/ghns_star.png");
00329     QString starBgIconPath = KStandardDirs::locate("data", "knewstuff/pics/ghns_star_gray.png");
00330 
00331     // default elements style
00332     QString s;
00333     s += "body { background-color: white; color: black; padding: 0; margin: 0; }";
00334     s += "table, td, th { padding: 0; margin: 0; text-align: left; }";
00335     s += "input { color: #000080; font-size:120%; }";
00336 
00337     // the main item container (custom element)
00338     s += ".itemBox { background-color: white; color: black; width: 100%;  border-bottom: 1px solid gray; margin: 0px 0px; }";
00339     s += ".itemBox:hover { background-color: " + hoverBackground + "; color: " + hoverColor + "; }";
00340 
00341     // s of the item elements (4 cells with multiple containers)
00342     s += ".leftColumn { width: 100px; height:100%; text-align: center; }";
00343     s += ".leftImage {}";
00344     s += ".leftButton {}";
00345     s += ".leftProgressContainer { width: 82px; height: 10px; background-color: transparent; }";
00346     s += ".leftProgressBar { left: 1px; width: 0px; top: 1px; height: 8px; background-color: red; }";
00347     s += ".contentsColumn { vertical-align: top; }";
00348     s += ".contentsHeader { width: 100%; font-size: 120%; font-weight: bold; border-bottom: 1px solid #c8c8c8; }";
00349     s += ".contentsBody {}";
00350     s += ".contentsFooter {}";
00351     s += ".star { width: 0px; height: 24px; background-image: url(" + starIconPath + "); background-repeat: repeat-x; }";
00352     s += ".starbg { width: 110px; height: 24px; background-image: url(" + starBgIconPath + "); background-repeat: repeat-x; }";
00353     setStyleSheet(s);
00354 }
00355 
00356 void EntryView::urlSelected(const QString &link)
00357 {
00358     //kDebug() << "Clicked on URL " << link;
00359 
00360     KUrl url(link);
00361     QString urlProtocol = url.protocol();
00362     QString urlPath = url.path();
00363 
00364     if (urlProtocol == "mailto") {
00365         // clicked over a mail address
00366         // FIXME: if clicked with MRB, show context menu with IM etc.
00367         // FIXME: but RMB never reaches this method?!
00368         KToolInvocation::invokeMailer(url);
00369     } else if (urlProtocol == "item") {
00370         // clicked over an item
00371         bool ok;
00372         unsigned long itemPointer = urlPath.toULong(&ok);
00373         if (!ok) {
00374             kWarning() << "ItemsView: error converting item pointer.";
00375             return;
00376         }
00377 
00378         // I love to cast pointers
00379         Entry *entry = (Entry*)itemPointer;
00380         if (entry != m_entry) {
00381             kWarning() << "ItemsView: error retrieving item pointer.";
00382             return;
00383         }
00384 
00385         // XXX ???
00386         // install/uninstall the item
00387         //                if ( item->installed() )
00388         //                    m_newStuffDialog->removeItem( item );   // synchronous
00389         //                else
00390         //                    m_newStuffDialog->installItem( item );  // asynchronous
00391     }
00392 }
00393 
00394 #include "itemsview.moc"
00395 

KNewStuff

Skip menu "KNewStuff"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal