• Skip to content
  • Skip to link menu
KDE 4.2 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/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 // local includes
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     // 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     _layout->setSpacing(10);
00153 
00154     if (m_currentFeed != NULL) {
00155         Entry::List entries = m_currentFeed->entries();
00156         //switch (m_sorting)
00157         //{
00158         //    case 0:
00159         //        qSort(entries.begin(), entries.end(), NameSorter);
00160         //        break;
00161         //    case 1:
00162         //        qSort(entries.begin(), entries.end(), RatingSorter);
00163         //        break;
00164         //    case 2:
00165         //        qSort(entries.begin(), entries.end(), RecentSorter);
00166         //        break;
00167         //    case 3:
00168         //        qSort(entries.begin(), entries.end(), DownloadsSorter);
00169         //        break;
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                     //connect(pix, SIGNAL(signalLoaded(const QPixmap&)),
00199                     //        f, SLOT(setPixmap(const QPixmap&)));
00200                     previewLayout->addWidget(f);
00201                 }
00202                 //previewLayout->addWidget(dxsbutton);
00203 
00204                 part->setEntry(entry);
00205                 m_views.insert(entry, part);
00206                 ++row;
00207             }
00208         }
00209     }
00210 
00211     //setWidget(m_root);
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     // get item id string and iformations
00229     QString idString = QString::number((unsigned long)entry);
00230     //            AvailableItem::State state = item->state();
00231     //            bool showProgress = state != AvailableItem::Normal;
00232     //            int pixelProgress = showProgress ? (int)(item->progress() * 80.0) : 0;
00233 
00234     // perform internal scripting operations over the element
00235     //            executeScript( "document.getElementById('" + idString + "').style.color='red'" );
00236     //            executeScript( "document.getElementById('bar" + idString + "').style.width='" +
00237     //                           QString::number( pixelProgress ) + "px'" );
00238     //            executeScript( "document.getElementById('bc" + idString + "').style.backgroundColor='" +
00239     //                           (showProgress ? "gray" : "transparent") + "'" );
00240     //            executeScript( "document.getElementById('btn" + idString + "').value='" +
00241     //                           (item->installed() ? i18n( "Uninstall" ) : i18n( "Install" )) + "'" );
00242 }
00243 
00244 void EntryView::buildContents()
00245 {
00246     // write the html header and contents manipulation scripts
00247     QString t;
00248 
00249     t += "<html><body>";
00250 
00251     //t += setTheAaronnesqueStyle();
00252     // precalc the status icon
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         // find a good icon to represent downloadable data
00263         //statusIcon = "<img src='" + loader->iconPath("network-server", -KIconLoader::SizeSmall) + "' />";
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     // precalc the title string
00277     QString titleString = m_entry->name().representation();
00278     if (!m_entry->version().isEmpty()) titleString += " v." + Qt::escape(m_entry->version());
00279 
00280     // precalc the string for displaying stars (normal+grayed)
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;'>&nbsp;</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 + "&nbsp;</div>";
00288 
00289     // precalc the string for displaying author (parsing email)
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     // write the HTML code for the current item
00300     t += //QLatin1String("<table class='contentsHeader' cellspacing='2' cellpadding='0'>")
00301         statusIcon + Qt::escape(titleString) + "<br />"
00302         //+   "<span align='right'>" + starsString +  "</span><br />"
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"; //QApplication::palette().active().highlightedText().name();
00328     QString hoverBackground = "#f8f8f8"; //QApplication::palette().active().highlight().name();
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     // default elements style
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     // the main item container (custom element)
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     // s of the item elements (4 cells with multiple containers)
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     //kDebug() << "Clicked on URL " << link;
00360 
00361     KUrl url(link);
00362     QString urlProtocol = url.protocol();
00363     QString urlPath = url.path();
00364 
00365     if (urlProtocol == "mailto") {
00366         // clicked over a mail address
00367         // FIXME: if clicked with MRB, show context menu with IM etc.
00368         // FIXME: but RMB never reaches this method?!
00369         KToolInvocation::invokeMailer(url);
00370     } else if (urlProtocol == "item") {
00371         // clicked over an item
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         // I love to cast pointers
00380         Entry *entry = (Entry*)itemPointer;
00381         if (entry != m_entry) {
00382             kWarning() << "ItemsView: error retrieving item pointer.";
00383             return;
00384         }
00385 
00386         // XXX ???
00387         // install/uninstall the item
00388         //                if ( item->installed() )
00389         //                    m_newStuffDialog->removeItem( item );   // synchronous
00390         //                else
00391         //                    m_newStuffDialog->installItem( item );  // asynchronous
00392     }
00393 }
00394 
00395 #include "itemsview.moc"
00396 

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
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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