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

KNewStuff

  • knewstuff
  • knewstuff3
  • ui
knewstuff3/ui/itemsviewdelegate.cpp
Go to the documentation of this file.
1 /*
2  This file is part of KNewStuff2.
3  Copyright (C) 2008 Jeremy Whiting <jpwhiting@kde.org>
4  Copyright (C) 2010 Reza Fatahilah Shah <rshah0385@kireihana.com>
5  Copyright (C) 2010 Frederik Gladhorn <gladhorn@kde.org>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public
9  License as published by the Free Software Foundation; either
10  version 2.1 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "itemsviewdelegate.h"
22 
23 #include <QtGui/QPainter>
24 #include <QtGui/QSortFilterProxyModel>
25 #include <QtGui/QApplication>
26 #include <QtGui/QToolButton>
27 #include <QMenu>
28 #include <kdebug.h>
29 #include <kstandarddirs.h>
30 #include <kicon.h>
31 #include <klocale.h>
32 #include <kmenu.h>
33 #include <kratingwidget.h>
34 
35 #include "itemsmodel.h"
36 #include "entrydetailsdialog.h"
37 
38 namespace KNS3
39 {
40  enum { DelegateLabel, DelegateInstallButton, DelegateDetailsButton, DelegateRatingWidget };
41 
42 ItemsViewDelegate::ItemsViewDelegate(QAbstractItemView *itemView, Engine* engine, QObject * parent)
43  : ItemsViewBaseDelegate(itemView, engine, parent)
44 {
45 }
46 
47 ItemsViewDelegate::~ItemsViewDelegate()
48 {
49 }
50 
51 QList<QWidget*> ItemsViewDelegate::createItemWidgets() const
52 {
53  QList<QWidget*> list;
54 
55  QLabel * infoLabel = new QLabel();
56  infoLabel->setOpenExternalLinks(true);
57  // not so nice - work around constness to install the event filter
58  ItemsViewDelegate* delegate = const_cast<ItemsViewDelegate*>(this);
59  infoLabel->installEventFilter(delegate);
60  list << infoLabel;
61 
62  QToolButton * installButton = new QToolButton();
63  installButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
64  installButton->setPopupMode(QToolButton::InstantPopup);
65  list << installButton;
66  setBlockedEventTypes(installButton, QList<QEvent::Type>() << QEvent::MouseButtonPress
67  << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick);
68  connect(installButton, SIGNAL(clicked()), this, SLOT(slotInstallClicked()));
69  connect(installButton, SIGNAL(triggered(QAction*)), this, SLOT(slotInstallActionTriggered(QAction*)));
70 
71  QToolButton* detailsButton = new QToolButton();
72  detailsButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
73  list << detailsButton;
74  setBlockedEventTypes(detailsButton, QList<QEvent::Type>() << QEvent::MouseButtonPress
75  << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick);
76  connect(detailsButton, SIGNAL(clicked()), this, SLOT(slotDetailsClicked()));
77 
78  KRatingWidget* rating = new KRatingWidget();
79  rating->setMaxRating(10);
80  rating->setHalfStepsEnabled(true);
81  list << rating;
82  //connect(rating, SIGNAL(ratingChanged(uint)), this, SLOT());
83 
84  return list;
85 }
86 
87 void ItemsViewDelegate::updateItemWidgets(const QList<QWidget*> widgets,
88  const QStyleOptionViewItem &option,
89  const QPersistentModelIndex &index) const
90 {
91  const ItemsModel * model = qobject_cast<const ItemsModel*>(index.model());
92  if (!model) {
93  kDebug() << "WARNING - INVALID MODEL!";
94  return;
95  }
96 
97  EntryInternal entry = index.data(Qt::UserRole).value<KNS3::EntryInternal>();
98 
99  // setup the install button
100  int margin = option.fontMetrics.height() / 2;
101  int right = option.rect.width();
102 
103  QToolButton * installButton = qobject_cast<QToolButton*>(widgets.at(DelegateInstallButton));
104  if (installButton != 0) {
105 
106  if (installButton->menu()) {
107  QMenu* buttonMenu = installButton->menu();
108  buttonMenu->clear();
109  installButton->setMenu(0);
110  buttonMenu->deleteLater();
111  }
112 
113  bool installable = false;
114  bool enabled = true;
115  QString text;
116  KIcon icon;
117 
118  switch (entry.status()) {
119  case Entry::Installed:
120  text = i18n("Uninstall");
121  icon = m_iconDelete;
122  break;
123  case Entry::Updateable:
124  text = i18n("Update");
125  icon = m_iconUpdate;
126  installable = true;
127  break;
128  case Entry::Installing:
129  text = i18n("Installing");
130  enabled = false;
131  icon = m_iconUpdate;
132  break;
133  case Entry::Updating:
134  text = i18n("Updating");
135  enabled = false;
136  icon = m_iconUpdate;
137  break;
138  case Entry::Downloadable:
139  text = i18n("Install");
140  icon = m_iconInstall;
141  installable = true;
142  break;
143  case Entry::Deleted:
144  text = i18n("Install Again");
145  icon = m_iconInstall;
146  installable = true;
147  break;
148  default:
149  text = i18n("Install");
150  }
151  installButton->setText(text);
152  installButton->setEnabled(enabled);
153  installButton->setIcon(icon);
154  if (installable && entry.downloadLinkCount() > 1) {
155  KMenu * installMenu = new KMenu(installButton);
156  foreach (EntryInternal::DownloadLinkInformation info, entry.downloadLinkInformationList()) {
157  QString text = info.name;
158  if (!info.distributionType.trimmed().isEmpty()) {
159  text + " (" + info.distributionType.trimmed() + ")";
160  }
161  QAction* installAction = installMenu->addAction(m_iconInstall, text);
162  installAction->setData(QPoint(index.row(), info.id));
163  }
164  installButton->setMenu(installMenu);
165  }
166  }
167 
168  QToolButton* detailsButton = qobject_cast<QToolButton*>(widgets.at(DelegateDetailsButton));
169  if (detailsButton) {
170  detailsButton->setText(i18n("Details"));
171  detailsButton->setIcon(KIcon("documentinfo"));
172  }
173 
174  if (installButton && detailsButton) {
175  if (m_buttonSize.width() < installButton->sizeHint().width()) {
176  const_cast<QSize&>(m_buttonSize) = QSize(
177  qMax(option.fontMetrics.height() * 7,
178  qMax(installButton->sizeHint().width(), detailsButton->sizeHint().width())),
179  installButton->sizeHint().height());
180  }
181  installButton->resize(m_buttonSize);
182  installButton->move(right - installButton->width() - margin, option.rect.height()/2 - installButton->height()*1.5);
183  detailsButton->resize(m_buttonSize);
184  detailsButton->move(right - installButton->width() - margin, option.rect.height()/2 - installButton->height()/2);
185  }
186 
187  QLabel * infoLabel = qobject_cast<QLabel*>(widgets.at(DelegateLabel));
188  infoLabel->setWordWrap(true);
189  if (infoLabel != NULL) {
190  if (model->hasPreviewImages()) {
191  // move the text right by kPreviewWidth + margin pixels to fit the preview
192  infoLabel->move(PreviewWidth + margin * 2, 0);
193  infoLabel->resize(QSize(option.rect.width() - PreviewWidth - (margin * 6) - m_buttonSize.width(), option.fontMetrics.height() * 7));
194 
195  } else {
196  infoLabel->move(margin, 0);
197  infoLabel->resize(QSize(option.rect.width() - (margin * 4) - m_buttonSize.width(), option.fontMetrics.height() * 7));
198  }
199 
200  QString text = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
201  "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">p, li { white-space: pre-wrap; margin:0 0 0 0;}\n"
202  "</style></head><body><p><b>";
203 
204  KUrl link = qvariant_cast<KUrl>(entry.homepage());
205  if (!link.isEmpty()) {
206  text += "<p><a href=\"" + link.url() + "\">" + entry.name() + "</a></p>\n";
207  } else {
208  text += entry.name();
209  }
210 
211  text += "</b></p>\n";
212 
213  QString authorName = entry.author().name();
214  QString email = entry.author().email();
215  QString authorPage = entry.author().homepage();
216 
217  if (!authorName.isEmpty()) {
218  if (!authorPage.isEmpty()) {
219  text += "<p>" + i18nc("Show the author of this item in a list", "By <i>%1</i>", " <a href=\"" + authorPage + "\">" + authorName + "</a>") + "</p>\n";
220  } else if (!email.isEmpty()) {
221  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";
222  } else {
223  text += "<p>" + i18nc("Show the author of this item in a list", "By <i>%1</i>", authorName) + "</p>\n";
224  }
225  }
226 
227  QString summary = "<p>" + option.fontMetrics.elidedText(entry.summary(),
228  Qt::ElideRight, infoLabel->width() * 3) + "</p>\n";
229  text += summary;
230 
231  unsigned int fans = entry.numberFans();
232  unsigned int downloads = entry.downloadCount();
233 
234  QString fanString;
235  QString downloadString;
236  if (fans > 0) {
237  fanString = i18ncp("fan as in supporter", "1 fan", "%1 fans", fans);
238  }
239  if (downloads > 0) {
240  downloadString = i18np("1 download", "%1 downloads", downloads);
241  }
242  if (downloads > 0 || fans > 0) {
243  text += "<p>" + downloadString;
244  if (downloads > 0 && fans > 0) {
245  text += ", ";
246  }
247  text += fanString + QLatin1String("</p>\n");
248  }
249 
250  text += "</body></html>";
251  // use simplified to get rid of newlines etc
252  text = replaceBBCode(text).simplified();
253  infoLabel->setText(text);
254  }
255 
256  KRatingWidget * rating = qobject_cast<KRatingWidget*>(widgets.at(DelegateRatingWidget));
257  if (rating) {
258  if (entry.rating() > 0) {
259  rating->setToolTip(i18n("Rating: %1%", entry.rating()));
260  // 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
261  rating->setRating((entry.rating()-20)*10/60);
262  // put the rating label below the install button
263  rating->move(right - installButton->width() - margin, option.rect.height()/2 + installButton->height()/2);
264  rating->resize(m_buttonSize);
265  } else {
266  rating->setVisible(false);
267  }
268  }
269 }
270 
271 // draws the preview
272 void ItemsViewDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
273 {
274  int margin = option.fontMetrics.height() / 2;
275 
276  QStyle *style = QApplication::style();
277  style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, 0);
278 
279  painter->save();
280 
281  if (option.state & QStyle::State_Selected) {
282  painter->setPen(QPen(option.palette.highlightedText().color()));
283  } else {
284  painter->setPen(QPen(option.palette.text().color()));
285  }
286 
287  const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(index.model());
288 
289  if (realmodel->hasPreviewImages()) {
290  int height = option.rect.height();
291  QPoint point(option.rect.left() + margin, option.rect.top() + ((height - PreviewHeight) / 2));
292 
293  KNS3::EntryInternal entry = index.data(Qt::UserRole).value<KNS3::EntryInternal>();
294  if (entry.previewUrl(EntryInternal::PreviewSmall1).isEmpty()) {
295  // paint the no preview icon
296  //point.setX((PreviewWidth - m_noImage.width())/2 + 5);
297  //point.setY(option.rect.top() + ((height - m_noImage.height()) / 2));
298  //painter->drawPixmap(point, m_noImage);
299  } else {
300  QImage image = entry.previewImage(EntryInternal::PreviewSmall1);
301  if (!image.isNull()) {
302  point.setX((PreviewWidth - image.width())/2 + 5);
303  point.setY(option.rect.top() + ((height - image.height()) / 2));
304  painter->drawImage(point, image);
305 
306  QPoint framePoint(point.x() - 5, point.y() - 5);
307  painter->drawPixmap(framePoint, m_frameImage.scaled(image.width() + 10, image.height() + 10));
308  } else {
309  QRect rect(point, QSize(PreviewWidth, PreviewHeight));
310  painter->drawText(rect, Qt::AlignCenter | Qt::TextWordWrap, i18n("Loading Preview"));
311  }
312  }
313 
314  }
315  painter->restore();
316 }
317 
318 QSize ItemsViewDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
319 {
320  Q_UNUSED(option);
321  Q_UNUSED(index);
322 
323  QSize size;
324 
325  size.setWidth(option.fontMetrics.height() * 4);
326  size.setHeight(qMax(option.fontMetrics.height() * 7, PreviewHeight)); // up to 6 lines of text, and two margins
327  return size;
328 }
329 
330 } // namespace
331 
332 #include "itemsviewdelegate.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Tue Apr 16 2013 21:07:56 by doxygen 1.8.3.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KNewStuff

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

kdelibs-4.10.2 API Reference

Skip menu "kdelibs-4.10.2 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • 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
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal