KNewStuff
itemsgridviewdelegate.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (C) 2008 Jeremy Whiting <jpwhiting@kde.org> 00003 Copyright (C) 2010 Reza Fatahilah Shah <rshah0385@kireihana.com> 00004 Copyright (C) 2010 Frederik Gladhorn <gladhorn@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Lesser General Public 00008 License as published by the Free Software Foundation; either 00009 version 2.1 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Lesser General Public License for more details. 00015 00016 You should have received a copy of the GNU Lesser General Public 00017 License along with this library. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 #include "itemsgridviewdelegate.h" 00021 00022 #include <QtGui/QPainter> 00023 #include <QtGui/QSortFilterProxyModel> 00024 #include <QtGui/QApplication> 00025 #include <QLabel> 00026 #include <QToolButton> 00027 #include <QMenu> 00028 #include <QHBoxLayout> 00029 #include <QAbstractItemView> 00030 00031 #include <kdebug.h> 00032 #include <klocale.h> 00033 #include <kmenu.h> 00034 #include <kratingwidget.h> 00035 #include <ksqueezedtextlabel.h> 00036 00037 #include "itemsmodel.h" 00038 00039 namespace KNS3 00040 { 00041 enum { DelegateTitleLabel, DelegateAuthorLabel, DelegateDownloadCounterLabel, 00042 DelegateGridRatingWidget }; 00043 00044 ItemsGridViewDelegate::ItemsGridViewDelegate(QAbstractItemView *itemView, Engine* engine, QObject * parent) 00045 : ItemsViewBaseDelegate(itemView, engine, parent) 00046 ,m_elementYPos(0) 00047 { 00048 createOperationBar(); 00049 } 00050 00051 ItemsGridViewDelegate::~ItemsGridViewDelegate() 00052 { 00053 } 00054 00055 QList<QWidget*> ItemsGridViewDelegate::createItemWidgets() const 00056 { 00057 QList<QWidget*> m_widgetList; 00058 KSqueezedTextLabel * titleLabel = new KSqueezedTextLabel(); 00059 titleLabel->setOpenExternalLinks(true); 00060 titleLabel->setTextElideMode(Qt::ElideRight); 00061 // not so nice - work around constness to install the event filter 00062 ItemsGridViewDelegate* delegate = const_cast<ItemsGridViewDelegate*>(this); 00063 titleLabel->installEventFilter(delegate); 00064 m_widgetList << titleLabel; 00065 00066 KSqueezedTextLabel * authorLabel = new KSqueezedTextLabel(); 00067 authorLabel->setTextElideMode(Qt::ElideRight); 00068 m_widgetList << authorLabel; 00069 00070 KSqueezedTextLabel * downloadCounterLabel = new KSqueezedTextLabel(); 00071 downloadCounterLabel->setTextElideMode(Qt::ElideRight); 00072 m_widgetList << downloadCounterLabel; 00073 00074 KRatingWidget* rating = new KRatingWidget(); 00075 rating->setMaxRating(10); 00076 rating->setHalfStepsEnabled(true); 00077 m_widgetList << rating; 00078 00079 return m_widgetList; 00080 } 00081 00082 void ItemsGridViewDelegate::updateItemWidgets(const QList<QWidget*> widgets, 00083 const QStyleOptionViewItem &option, 00084 const QPersistentModelIndex &index) const 00085 { 00086 const ItemsModel * model = qobject_cast<const ItemsModel*>(index.model()); 00087 if (!model) { 00088 kDebug() << "WARNING - INVALID MODEL!"; 00089 return; 00090 } 00091 00092 EntryInternal entry = index.data(Qt::UserRole).value<KNS3::EntryInternal>(); 00093 int elementXPos = ItemMargin; 00094 int elementYPos = PreviewHeight + ItemMargin + FrameThickness*2; 00095 00096 //setup rating widget 00097 KRatingWidget * rating = qobject_cast<KRatingWidget*>(widgets.at(DelegateGridRatingWidget)); 00098 if (rating) { 00099 if (entry.rating() > 0) { 00100 rating->setToolTip(i18n("Rating: %1%", entry.rating())); 00101 // 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 00102 rating->setRating((entry.rating()-20)*10/60); 00103 //make the rating widget smaller than the one at list view 00104 int newWidth = 68; 00105 QSize size(newWidth, 15); 00106 rating->resize(size); 00107 //put rating widget under image rectangle 00108 rating->move((ItemGridWidth-newWidth)/2, elementYPos); 00109 elementYPos += rating->height(); 00110 } else { 00111 //is it better to stay visible? 00112 rating->setVisible(false); 00113 } 00114 } 00115 elementYPos += ItemMargin; 00116 00117 //setup title label 00118 QLabel * titleLabel = qobject_cast<QLabel*>(widgets.at(DelegateTitleLabel)); 00119 if (titleLabel != NULL) { 00120 titleLabel->setWordWrap(true); 00121 titleLabel->setAlignment(Qt::AlignHCenter); 00122 //titleLabel->setFrameStyle(QFrame::Panel); 00123 titleLabel->resize(QSize(option.rect.width() - (ItemMargin * 2), option.fontMetrics.height() * 2)); 00124 titleLabel->move((ItemGridWidth-titleLabel->width())/2, elementYPos); 00125 00126 QString title; 00127 KUrl link = qvariant_cast<KUrl>(entry.homepage()); 00128 if (!link.isEmpty()) { 00129 title += "<b><a href=\"" + link.url() + "\">" + entry.name() + "</a></b>\n"; 00130 } else { 00131 title += "<b>" + entry.name() + "</b>"; 00132 } 00133 titleLabel->setText(title); 00134 elementYPos += titleLabel->height(); 00135 } 00136 //setup author label 00137 QLabel * authorLabel = qobject_cast<QLabel*>(widgets.at(DelegateAuthorLabel)); 00138 if (authorLabel != NULL) { 00139 authorLabel->setWordWrap(true); 00140 authorLabel->setAlignment(Qt::AlignHCenter); 00141 authorLabel->resize(QSize(option.rect.width() - (ItemMargin * 2), option.fontMetrics.height())); 00142 authorLabel->move((ItemGridWidth-authorLabel->width())/2,elementYPos); 00143 00144 QString text; 00145 QString authorName = entry.author().name(); 00146 QString email = entry.author().email(); 00147 QString authorPage = entry.author().homepage(); 00148 00149 if (!authorName.isEmpty()) { 00150 if (!authorPage.isEmpty()) { 00151 text += "<p>" + i18nc("Show the author of this item in a list", "By <i>%1</i>", " <a href=\"" + authorPage + "\">" + authorName + "</a>") + "</p>\n"; 00152 } else if (!email.isEmpty()) { 00153 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"; 00154 } else { 00155 text += "<p>" + i18nc("Show the author of this item in a list", "By <i>%1</i>", authorName) + "</p>\n"; 00156 } 00157 } 00158 authorLabel->setText(text); 00159 elementYPos += authorLabel->height(); 00160 } 00161 elementYPos += ItemMargin; 00162 00163 //setup download label 00164 QLabel * downloadLabel = qobject_cast<QLabel*>(widgets.at(DelegateDownloadCounterLabel)); 00165 if (downloadLabel != NULL) { 00166 downloadLabel->setWordWrap(true); 00167 downloadLabel->setAlignment(Qt::AlignHCenter); 00168 downloadLabel->resize(QSize(option.rect.width() - (ItemMargin * 2), option.fontMetrics.height())); 00169 downloadLabel->move((ItemGridWidth-downloadLabel->width())/2,elementYPos); 00170 00171 unsigned int fans = entry.numberFans(); 00172 unsigned int downloads = entry.downloadCount(); 00173 00174 QString text; 00175 QString fanString; 00176 QString downloadString; 00177 if (fans > 0) { 00178 fanString = i18ncp("fan as in supporter", "1 fan", "%1 fans", fans); 00179 } 00180 if (downloads > 0) { 00181 downloadString = i18np("1 download", "%1 downloads", downloads); 00182 } 00183 if (downloads > 0 || fans > 0) { 00184 text += "<p>" + downloadString; 00185 if (downloads > 0 && fans > 0) { 00186 text += ", "; 00187 } 00188 text += fanString + QLatin1String("</p>"); 00189 } 00190 downloadLabel->setText(text); 00191 elementYPos += downloadLabel->height(); 00192 } 00193 elementYPos += ItemMargin; 00194 m_elementYPos = elementYPos; 00195 } 00196 00197 void ItemsGridViewDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const 00198 { 00199 if (option.state & QStyle::State_MouseOver) { 00200 QModelIndex focIndex = focusedIndex(); 00201 if (m_oldIndex != focIndex || !m_operationBar->isVisible()) { 00202 ItemsGridViewDelegate* delegate = const_cast<ItemsGridViewDelegate*>(this); 00203 00204 delegate->displayOperationBar(option.rect,index); 00205 delegate->m_oldIndex = focIndex; 00206 } 00207 } else { 00208 QModelIndex focindex = focusedIndex(); 00209 if(!focindex.isValid()){ 00210 //kDebug() << "INVALID hide selection"; 00211 m_operationBar->hide(); 00212 } 00213 } 00214 00215 QStyle *style = QApplication::style(); 00216 style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, 0); 00217 00218 painter->save(); 00219 00220 if (option.state & QStyle::State_Selected) { 00221 painter->setPen(QPen(option.palette.highlightedText().color())); 00222 } else { 00223 painter->setPen(QPen(option.palette.text().color())); 00224 } 00225 00226 const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(index.model()); 00227 00228 if (realmodel->hasPreviewImages()) { 00229 int height = option.rect.height(); 00230 int width = option.rect.width(); 00231 00232 KNS3::EntryInternal entry = index.data(Qt::UserRole).value<KNS3::EntryInternal>(); 00233 if (entry.previewUrl(EntryInternal::PreviewSmall1).isEmpty()) { 00234 ; 00235 } else { 00236 QPoint centralPoint(option.rect.left() + width/2,option.rect.top() + ItemMargin + FrameThickness + PreviewHeight/2); 00237 QImage image = entry.previewImage(EntryInternal::PreviewSmall1); 00238 if (!image.isNull()) { 00239 QPoint previewPoint(centralPoint.x() - image.width()/2, centralPoint.y() - image.height()/2); 00240 painter->drawImage(previewPoint, image); 00241 00242 QPixmap frameImageScaled = m_frameImage.scaled(image.width() + FrameThickness*2, image.height() + FrameThickness*2); 00243 QPoint framePoint(centralPoint.x() - frameImageScaled.width()/2, centralPoint.y() - frameImageScaled.height()/2); 00244 painter->drawPixmap(framePoint, frameImageScaled); 00245 } else { 00246 QPoint thumbnailPoint(option.rect.left() + ((width - PreviewWidth - FrameThickness*2) / 2), option.rect.top() + ItemMargin); 00247 QRect rect(thumbnailPoint, QSize(PreviewWidth + FrameThickness*2, PreviewHeight + FrameThickness*2)); 00248 painter->drawText(rect, Qt::AlignCenter | Qt::TextWordWrap, i18n("Loading Preview")); 00249 } 00250 } 00251 } 00252 00253 painter->restore(); 00254 } 00255 00256 QSize ItemsGridViewDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const 00257 { 00258 Q_UNUSED(option); 00259 Q_UNUSED(index); 00260 00261 QSize size; 00262 00263 size.setWidth(ItemGridWidth); 00264 size.setHeight(qMax(option.fontMetrics.height() * 13, ItemGridHeight)); // up to 6 lines of text, and two margins 00265 return size; 00266 } 00267 00268 void ItemsGridViewDelegate::createOperationBar() 00269 { 00270 m_operationBar = new QWidget(this->itemView()->viewport()); 00271 00272 m_detailsButton = new QToolButton(); 00273 m_detailsButton->setToolButtonStyle(Qt::ToolButtonFollowStyle); 00274 m_detailsButton->setPopupMode(QToolButton::InstantPopup); 00275 m_detailsButton->setToolTip(i18n("Details")); 00276 m_detailsButton->setIcon(KIcon("documentinfo")); 00277 setBlockedEventTypes(m_detailsButton, QList<QEvent::Type>() << QEvent::MouseButtonPress 00278 << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick); 00279 connect(m_detailsButton, SIGNAL(clicked()), this, SLOT(slotDetailsClicked())); 00280 00281 m_installButton = new QToolButton(); 00282 m_installButton->setToolButtonStyle(Qt::ToolButtonFollowStyle); 00283 m_installButton->setPopupMode(QToolButton::InstantPopup); 00284 00285 setBlockedEventTypes(m_installButton, QList<QEvent::Type>() << QEvent::MouseButtonPress 00286 << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick); 00287 connect(m_installButton, SIGNAL(clicked()), this, SLOT(slotInstallClicked())); 00288 connect(m_installButton, SIGNAL(triggered(QAction *)), this, SLOT(slotInstallActionTriggered(QAction *))); 00289 00290 00291 if (m_installButton->menu()) { 00292 QMenu* buttonMenu = m_installButton->menu(); 00293 buttonMenu->clear(); 00294 m_installButton->setMenu(0); 00295 buttonMenu->deleteLater(); 00296 } 00297 00298 QHBoxLayout* layout = new QHBoxLayout(m_operationBar); 00299 00300 layout->setSpacing(1); 00301 layout->addWidget(m_installButton); 00302 layout->addWidget(m_detailsButton); 00303 00304 m_operationBar->adjustSize(); 00305 m_operationBar->hide(); 00306 } 00307 00308 void ItemsGridViewDelegate::displayOperationBar(const QRect &rect,const QModelIndex & index) 00309 { 00310 KNS3::EntryInternal entry = index.data(Qt::UserRole).value<KNS3::EntryInternal>(); 00311 if (m_installButton != 0) { 00312 if (m_installButton->menu() != 0) { 00313 QMenu* buttonMenu = m_installButton->menu(); 00314 buttonMenu->clear(); 00315 m_installButton->setMenu(0); 00316 buttonMenu->deleteLater(); 00317 } 00318 00319 bool installable = false; 00320 bool enabled = true; 00321 QString text; 00322 KIcon icon; 00323 00324 switch (entry.status()) { 00325 case Entry::Installed: 00326 text = i18n("Uninstall"); 00327 icon = m_iconDelete; 00328 break; 00329 case Entry::Updateable: 00330 text = i18n("Update"); 00331 icon = m_iconUpdate; 00332 installable = true; 00333 break; 00334 case Entry::Installing: 00335 text = i18n("Installing"); 00336 enabled = false; 00337 icon = m_iconUpdate; 00338 break; 00339 case Entry::Updating: 00340 text = i18n("Updating"); 00341 enabled = false; 00342 icon = m_iconUpdate; 00343 break; 00344 case Entry::Downloadable: 00345 text = i18n("Install"); 00346 icon = m_iconInstall; 00347 installable = true; 00348 break; 00349 case Entry::Deleted: 00350 text = i18n("Install Again"); 00351 icon = m_iconInstall; 00352 installable = true; 00353 break; 00354 default: 00355 text = i18n("Install"); 00356 } 00357 m_installButton->setToolTip(text); 00358 m_installButton->setIcon(icon); 00359 m_installButton->setEnabled(enabled); 00360 if (installable && entry.downloadLinkCount() > 1) { 00361 KMenu * installMenu = new KMenu(m_installButton); 00362 foreach (EntryInternal::DownloadLinkInformation info, entry.downloadLinkInformationList()) { 00363 QString text = info.name; 00364 if (!info.distributionType.trimmed().isEmpty()) { 00365 text + " (" + info.distributionType.trimmed() + ")"; 00366 } 00367 QAction* installAction = installMenu->addAction(m_iconInstall, text); 00368 installAction->setData(QPoint(index.row(), info.id)); 00369 } 00370 m_installButton->setMenu(installMenu); 00371 } 00372 00373 m_operationBar->move(rect.left()+(ItemGridWidth-m_operationBar->width())/2,rect.top() + m_elementYPos); 00374 m_operationBar->show(); 00375 } 00376 } 00377 } 00378 00379 #include "itemsgridviewdelegate.moc"
KDE 4.6 API Reference