• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KNewStuff

itemsviewdelegate.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of KNewStuff2.
00003     Copyright (C) 2008 Jeremy Whiting <jpwhiting@kde.org>
00004     Copyright (C) 2010 Reza Fatahilah Shah <rshah0385@kireihana.com>
00005     Copyright (C) 2010 Frederik Gladhorn <gladhorn@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 #include "itemsviewdelegate.h"
00022 
00023 #include <QtGui/QPainter>
00024 #include <QtGui/QSortFilterProxyModel>
00025 #include <QtGui/QApplication>
00026 #include <QtGui/QToolButton>
00027 #include <QMenu>
00028 #include <kdebug.h>
00029 #include <kstandarddirs.h>
00030 #include <kicon.h>
00031 #include <klocale.h>
00032 #include <kmenu.h>
00033 #include <kratingwidget.h>
00034 
00035 #include "itemsmodel.h"
00036 #include "entrydetailsdialog.h"
00037 
00038 namespace KNS3
00039 {
00040     enum { DelegateLabel, DelegateInstallButton, DelegateDetailsButton,  DelegateRatingWidget };
00041 
00042 ItemsViewDelegate::ItemsViewDelegate(QAbstractItemView *itemView, Engine* engine, QObject * parent)
00043         : ItemsViewBaseDelegate(itemView, engine, parent)
00044 {
00045 }
00046 
00047 ItemsViewDelegate::~ItemsViewDelegate()
00048 {
00049 }
00050 
00051 QList<QWidget*> ItemsViewDelegate::createItemWidgets() const
00052 {
00053     QList<QWidget*> list;
00054 
00055     QLabel * infoLabel = new QLabel();
00056     infoLabel->setOpenExternalLinks(true);
00057     // not so nice - work around constness to install the event filter
00058     ItemsViewDelegate* delegate = const_cast<ItemsViewDelegate*>(this);
00059     infoLabel->installEventFilter(delegate);
00060     list << infoLabel;
00061 
00062     QToolButton * installButton = new QToolButton();
00063     installButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
00064     installButton->setPopupMode(QToolButton::InstantPopup);
00065     list << installButton;
00066     setBlockedEventTypes(installButton, QList<QEvent::Type>() << QEvent::MouseButtonPress
00067                          << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick);
00068     connect(installButton, SIGNAL(clicked()), this, SLOT(slotInstallClicked()));
00069     connect(installButton, SIGNAL(triggered(QAction *)), this, SLOT(slotInstallActionTriggered(QAction *)));
00070 
00071     QToolButton* detailsButton = new QToolButton();
00072     detailsButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
00073     list << detailsButton;
00074     setBlockedEventTypes(detailsButton, QList<QEvent::Type>() << QEvent::MouseButtonPress
00075                          << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick);
00076     connect(detailsButton, SIGNAL(clicked()), this, SLOT(slotDetailsClicked()));
00077 
00078     KRatingWidget* rating = new KRatingWidget();
00079     rating->setMaxRating(10);
00080     rating->setHalfStepsEnabled(true);
00081     list << rating;
00082     //connect(rating, SIGNAL(ratingChanged(uint)), this, SLOT());
00083 
00084     return list;
00085 }
00086 
00087 void ItemsViewDelegate::updateItemWidgets(const QList<QWidget*> widgets,
00088         const QStyleOptionViewItem &option,
00089         const QPersistentModelIndex &index) const
00090 {
00091     const ItemsModel * model = qobject_cast<const ItemsModel*>(index.model());
00092     if (!model) {
00093         kDebug() << "WARNING - INVALID MODEL!";
00094         return;
00095     }
00096 
00097     EntryInternal entry = index.data(Qt::UserRole).value<KNS3::EntryInternal>();
00098 
00099     // setup the install button
00100     int margin = option.fontMetrics.height() / 2;
00101     int right = option.rect.width();
00102 
00103     QToolButton * installButton = qobject_cast<QToolButton*>(widgets.at(DelegateInstallButton));
00104     if (installButton != 0) {
00105 
00106         if (installButton->menu()) {
00107             QMenu* buttonMenu = installButton->menu();
00108             buttonMenu->clear();
00109             installButton->setMenu(0);
00110             buttonMenu->deleteLater();
00111         }
00112 
00113         bool installable = false;
00114         bool enabled = true;
00115         QString text;
00116         KIcon icon;
00117 
00118         switch (entry.status()) {
00119         case Entry::Installed:
00120             text = i18n("Uninstall");
00121             icon = m_iconDelete;
00122             break;
00123         case Entry::Updateable:
00124             text = i18n("Update");
00125             icon = m_iconUpdate;
00126             installable = true;
00127             break;
00128         case Entry::Installing:
00129             text = i18n("Installing");
00130             enabled = false;
00131             icon = m_iconUpdate;
00132             break;
00133         case Entry::Updating:
00134             text = i18n("Updating");
00135             enabled = false;
00136             icon = m_iconUpdate;
00137             break;
00138         case Entry::Downloadable:
00139             text = i18n("Install");
00140             icon = m_iconInstall;
00141             installable = true;
00142             break;
00143         case Entry::Deleted:
00144             text = i18n("Install Again");
00145             icon = m_iconInstall;
00146             installable = true;
00147             break;
00148         default:
00149             text = i18n("Install");
00150         }
00151         installButton->setText(text);
00152         installButton->setEnabled(enabled);
00153         installButton->setIcon(icon);
00154         if (installable && entry.downloadLinkCount() > 1) {
00155             KMenu * installMenu = new KMenu(installButton);
00156             foreach (EntryInternal::DownloadLinkInformation info, entry.downloadLinkInformationList()) {
00157                 QString text = info.name;
00158                 if (!info.distributionType.trimmed().isEmpty()) {
00159                     text + " (" + info.distributionType.trimmed() + ")";
00160                 }
00161                 QAction* installAction = installMenu->addAction(m_iconInstall, text);
00162                 installAction->setData(QPoint(index.row(), info.id));
00163             }
00164             installButton->setMenu(installMenu);
00165         }
00166     }
00167 
00168     QToolButton* detailsButton = qobject_cast<QToolButton*>(widgets.at(DelegateDetailsButton));
00169     if (detailsButton) {
00170         detailsButton->setText(i18n("Details"));
00171         detailsButton->setIcon(KIcon("documentinfo"));
00172     }
00173 
00174     if (installButton && detailsButton) {
00175         if (m_buttonSize.width() < installButton->sizeHint().width()) {
00176             const_cast<QSize&>(m_buttonSize) = QSize(
00177                     qMax(option.fontMetrics.height() * 7,
00178                          qMax(installButton->sizeHint().width(), detailsButton->sizeHint().width())),
00179                     installButton->sizeHint().height());
00180         }
00181         installButton->resize(m_buttonSize);
00182         installButton->move(right - installButton->width() - margin, option.rect.height()/2 - installButton->height()*1.5);
00183         detailsButton->resize(m_buttonSize);
00184         detailsButton->move(right - installButton->width() - margin, option.rect.height()/2 - installButton->height()/2);
00185     }
00186 
00187     QLabel * infoLabel = qobject_cast<QLabel*>(widgets.at(DelegateLabel));
00188     infoLabel->setWordWrap(true);
00189     if (infoLabel != NULL) {
00190         if (model->hasPreviewImages()) {
00191             // move the text right by kPreviewWidth + margin pixels to fit the preview
00192             infoLabel->move(PreviewWidth + margin * 2, 0);
00193             infoLabel->resize(QSize(option.rect.width() - PreviewWidth - (margin * 6) - m_buttonSize.width(), option.fontMetrics.height() * 7));
00194 
00195         } else {
00196             infoLabel->move(margin, 0);
00197             infoLabel->resize(QSize(option.rect.width() - (margin * 4) - m_buttonSize.width(), option.fontMetrics.height() * 7));
00198         }
00199 
00200         QString text = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
00201             "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">p, li { white-space: pre-wrap; margin:0 0 0 0;}\n"
00202             "</style></head><body><p><b>";
00203 
00204         KUrl link = qvariant_cast<KUrl>(entry.homepage());
00205         if (!link.isEmpty()) {
00206             text += "<p><a href=\"" + link.url() + "\">" + entry.name() + "</a></p>\n";
00207         } else {
00208             text += entry.name();
00209         }
00210 
00211         text += "</b></p>\n";
00212 
00213         QString authorName = entry.author().name();
00214         QString email = entry.author().email();
00215         QString authorPage = entry.author().homepage();
00216 
00217         if (!authorName.isEmpty()) {
00218             if (!authorPage.isEmpty()) {
00219                 text += "<p>" + i18nc("Show the author of this item in a list", "By <i>%1</i>", " <a href=\"" + authorPage + "\">" + authorName + "</a>") + "</p>\n";
00220             } else if (!email.isEmpty()) {
00221                 text += "<p>" + i18nc("Show the author of this item in a list", "By <i>%1</i>", authorName) + " <a href=\"mailto:" + email + "\">" + email + "</a></p>\n";
00222             } else {
00223                 text += "<p>" + i18nc("Show the author of this item in a list", "By <i>%1</i>", authorName) + "</p>\n";
00224             }
00225         }
00226 
00227         QString summary = "<p>" + option.fontMetrics.elidedText(entry.summary(),
00228             Qt::ElideRight, infoLabel->width() * 3) + "</p>\n";
00229         text += summary;
00230 
00231         unsigned int fans = entry.numberFans();
00232         unsigned int downloads = entry.downloadCount();
00233 
00234         QString fanString;
00235         QString downloadString;
00236         if (fans > 0) {
00237             fanString = i18ncp("fan as in supporter", "1 fan", "%1 fans", fans);
00238         }
00239         if (downloads > 0) {
00240             downloadString = i18np("1 download", "%1 downloads", downloads);
00241         }
00242         if (downloads > 0 || fans > 0) {
00243             text += "<p>" + downloadString;
00244             if (downloads > 0 && fans > 0) {
00245                 text += ", ";
00246             }
00247             text += fanString + QLatin1String("</p>\n");
00248         }
00249 
00250         text += "</body></html>";
00251         // use simplified to get rid of newlines etc
00252         text = replaceBBCode(text).simplified();
00253         infoLabel->setText(text);
00254     }
00255 
00256     KRatingWidget * rating = qobject_cast<KRatingWidget*>(widgets.at(DelegateRatingWidget));
00257     if (rating) {
00258         if (entry.rating() > 0) {
00259             rating->setToolTip(i18n("Rating: %1%", entry.rating()));
00260             // assume all entries come with rating 0..100 but most are in the range 20 - 80, so 20 is 0 stars, 80 is 5 stars
00261             rating->setRating((entry.rating()-20)*10/60);
00262             // put the rating label below the install button
00263             rating->move(right - installButton->width() - margin, option.rect.height()/2 + installButton->height()/2);
00264             rating->resize(m_buttonSize);
00265         } else {
00266             rating->setVisible(false);
00267         }
00268     }
00269 }
00270 
00271 // draws the preview
00272 void ItemsViewDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
00273 {
00274     int margin = option.fontMetrics.height() / 2;
00275 
00276     QStyle *style = QApplication::style();
00277     style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, 0);
00278 
00279     painter->save();
00280 
00281     if (option.state & QStyle::State_Selected) {
00282         painter->setPen(QPen(option.palette.highlightedText().color()));
00283     } else {
00284         painter->setPen(QPen(option.palette.text().color()));
00285     }
00286 
00287     const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(index.model());
00288 
00289     if (realmodel->hasPreviewImages()) {
00290         int height = option.rect.height();
00291         QPoint point(option.rect.left() + margin, option.rect.top() + ((height - PreviewHeight) / 2));
00292 
00293         KNS3::EntryInternal entry = index.data(Qt::UserRole).value<KNS3::EntryInternal>();
00294         if (entry.previewUrl(EntryInternal::PreviewSmall1).isEmpty()) {
00295             // paint the no preview icon
00296             //point.setX((PreviewWidth - m_noImage.width())/2 + 5);
00297             //point.setY(option.rect.top() + ((height - m_noImage.height()) / 2));
00298             //painter->drawPixmap(point, m_noImage);
00299         } else {
00300             QImage image = entry.previewImage(EntryInternal::PreviewSmall1);
00301             if (!image.isNull()) {
00302                 point.setX((PreviewWidth - image.width())/2 + 5);
00303                 point.setY(option.rect.top() + ((height - image.height()) / 2));
00304                 painter->drawImage(point, image);
00305 
00306                 QPoint framePoint(point.x() - 5, point.y() - 5);
00307                 painter->drawPixmap(framePoint, m_frameImage.scaled(image.width() + 10, image.height() + 10));
00308             } else {
00309                 QRect rect(point, QSize(PreviewWidth, PreviewHeight));
00310                 painter->drawText(rect, Qt::AlignCenter | Qt::TextWordWrap, i18n("Loading Preview"));
00311             }
00312         }
00313 
00314     }
00315     painter->restore();
00316 }
00317 
00318 QSize ItemsViewDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
00319 {
00320     Q_UNUSED(option);
00321     Q_UNUSED(index);
00322 
00323     QSize size;
00324 
00325     size.setWidth(option.fontMetrics.height() * 4);
00326     size.setHeight(qMax(option.fontMetrics.height() * 7, PreviewHeight)); // up to 6 lines of text, and two margins
00327     return size;
00328 }
00329 
00330 } // namespace
00331 
00332 #include "itemsviewdelegate.moc"

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
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
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