00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "itemsviewdelegate.h"
00020 #include "itemsmodel.h"
00021
00022 #include <QtGui/QPainter>
00023 #include <QtGui/QSortFilterProxyModel>
00024
00025 #include <kdebug.h>
00026 #include <kstandarddirs.h>
00027 #include <kicon.h>
00028 #include <klocale.h>
00029 #include <kmenu.h>
00030 #include <krun.h>
00031
00032 static const int kLabel = 0;
00033 static const int kInstall = 1;
00034 static const int kRating = 2;
00035
00036 namespace KNS
00037 {
00038 ItemsViewDelegate::ItemsViewDelegate(QAbstractItemView *itemView, QObject * parent)
00039 : KWidgetItemDelegate(itemView, parent)
00040 {
00041 QString framefile = KStandardDirs::locate("data", "knewstuff/pics/thumb_frame.png");
00042
00043 m_frameImage = QPixmap(framefile).toImage();
00044
00045
00046 m_statusicons << KIcon("dialog-error");
00047
00048 m_statusicons << KIcon();
00049
00050 m_statusicons << KIcon("dialog-ok");
00051
00052 m_statusicons << KIcon("system-software-update");
00053
00054 m_statusicons << KIcon("edit-delete");
00055 }
00056
00057 ItemsViewDelegate::~ItemsViewDelegate()
00058 {
00059 }
00060
00061 KMenu * ItemsViewDelegate::InstallMenu(const QToolButton* button, Entry::Status status) const
00062 {
00063 Q_UNUSED(button)
00064 KMenu * installMenu = new KMenu(NULL);
00065 QAction * action_install = installMenu->addAction(m_statusicons[Entry::Installed], i18n("Install"));
00066 QAction * action_uninstall = installMenu->addAction(m_statusicons[Entry::Deleted], i18n("Uninstall"));
00067 action_install->setData(DownloadDialog::kInstall);
00068 action_uninstall->setData(DownloadDialog::kUninstall);
00069
00070 action_install->setVisible(status != Entry::Installed);
00071 action_uninstall->setVisible(status == Entry::Installed);
00072 return installMenu;
00073 }
00074
00075 QList<QWidget*> ItemsViewDelegate::createItemWidgets() const
00076 {
00077 QList<QWidget*> list;
00078
00079 QLabel * infoLabel = new QLabel();
00080 infoLabel->setOpenExternalLinks(true);
00081 list << infoLabel;
00082
00083 QToolButton * installButton = new QToolButton();
00084 list << installButton;
00085 setBlockedEventTypes(installButton, QList<QEvent::Type>() << QEvent::MouseButtonPress
00086 << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick);
00087 connect(installButton, SIGNAL(triggered(QAction *)), this, SLOT(slotActionTriggered(QAction *)));
00088 connect(installButton, SIGNAL(clicked()), this, SLOT(slotInstallClicked()));
00089
00090 QLabel * ratingLabel = new QLabel();
00091 list << ratingLabel;
00092
00093 return list;
00094 }
00095
00096 void ItemsViewDelegate::updateItemWidgets(const QList<QWidget*> widgets,
00097 const QStyleOptionViewItem &option,
00098 const QPersistentModelIndex &index) const
00099 {
00100 const QSortFilterProxyModel * model = qobject_cast<const QSortFilterProxyModel*>(index.model());
00101 if (model == NULL) {
00102 return;
00103 }
00104
00105 const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(model->sourceModel());
00106 if (realmodel == NULL || !index.isValid()) {
00107 return;
00108 }
00109
00110
00111 int margin = option.fontMetrics.height() / 2;
00112
00113 int right = option.rect.width();
00114
00115
00116 QSize size(option.fontMetrics.height() * 7, widgets.at(kInstall)->sizeHint().height());
00117
00118 QLabel * infoLabel = qobject_cast<QLabel*>(widgets.at(kLabel));
00119 infoLabel->setWordWrap(true);
00120 if (infoLabel != NULL) {
00121 if (realmodel->hasPreviewImages()) {
00122
00123 infoLabel->move(kPreviewWidth + margin * 2, 0);
00124 infoLabel->resize(QSize(option.rect.width() - kPreviewWidth - (margin * 6) - size.width(), option.fontMetrics.height() * 7));
00125 } else {
00126 infoLabel->move(margin, 0);
00127 infoLabel->resize(QSize(option.rect.width() - (margin * 4) - size.width(), option.fontMetrics.height() * 7));
00128 }
00129
00130 QString text = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
00131 "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">p, li { white-space: pre-wrap; margin:0 0 0 0;}\n"
00132 "</style></head><body><p><b>" +
00133 index.data(ItemsModel::kNameRole).toString() + "</b></p>\n";
00134
00135 QString summary = "<p>" + option.fontMetrics.elidedText(index.data(ItemsModel::kSummary).toString(),
00136 Qt::ElideRight, infoLabel->width() * 3) + "</p>\n";
00137 text += summary;
00138
00139 QString authorName = index.data(ItemsModel::kAuthorName).toString();
00140 QString email = index.data(ItemsModel::kAuthorEmail).toString();
00141 if (!authorName.isEmpty()) {
00142 if (email.isEmpty()) {
00143 text += "<p><i>" + authorName + "</i></p>\n";
00144 } else {
00145 text += "<p><i>" + authorName + "</i> <a href=\"mailto:" + email + "\">" + email + "</a></p>\n";
00146 }
00147 }
00148
00149 unsigned int downloads = index.data(ItemsModel::kDownloads).toUInt();
00150 text += downloads == 0 ? i18n("<p>No Downloads</p>") : i18n("<p>Downloads: %1</p>\n", downloads);
00151
00152 text += "</body></html>";
00153 text.replace("[b]", "<b>");
00154 text.replace("[/b]", "</b>");
00155 text.replace("[i]", "<i>");
00156 text.replace("[/i]", "</i>");
00157 text.replace("[u]", "<i>");
00158 text.replace("[/u]", "</i>");
00159 text.remove("[url]");
00160 text.remove("[/url]");
00161 text.replace("\\\'", "\'");
00162 infoLabel->setText(text.simplified());
00163 }
00164
00165 QToolButton * button = qobject_cast<QToolButton*>(widgets.at(kInstall));
00166 if (button != NULL) {
00167 Entry::Status status = Entry::Status(model->data(index, ItemsModel::kStatus).toUInt());
00168
00169
00170
00171 button->resize(size);
00172
00173 button->move(right - button->width() - margin, option.rect.height() / 2 - button->height());
00174 button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 switch (status) {
00185 case Entry::Installed:
00186 button->setText(i18n("Uninstall"));
00187
00188
00189 button->setIcon(QIcon(m_statusicons[Entry::Deleted]));
00190 break;
00191 case Entry::Updateable:
00192 button->setText(i18n("Update"));
00193
00194
00195
00196
00197 button->setIcon(QIcon(m_statusicons[Entry::Updateable]));
00198 break;
00199 case Entry::Deleted:
00201 button->setText(i18n("Install"));
00202
00203
00204
00205
00206 button->setIcon(QIcon(m_statusicons[Entry::Installed]));
00207 break;
00208 default:
00209 button->setText(i18n("Install"));
00210
00211
00212
00213 button->setIcon(QIcon(m_statusicons[Entry::Installed]));
00214 }
00215 }
00216
00217 QLabel * ratingLabel = qobject_cast<QLabel*>(widgets.at(kRating));
00218 if (ratingLabel != NULL) {
00219 ratingLabel->setText(i18n("Rating: %1", model->data(index, ItemsModel::kRating).toString()));
00220
00221
00222 ratingLabel->move(right - button->width() - margin, option.rect.height() / 2 + button->height()/2);
00223 ratingLabel->resize(size);
00224 }
00225 }
00226
00227
00228
00229 void ItemsViewDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
00230 {
00231 int margin = option.fontMetrics.height() / 2;
00232
00233 QStyle *style = QApplication::style();
00234 style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, 0);
00235
00236 painter->save();
00237
00238 if (option.state & QStyle::State_Selected) {
00239 painter->setPen(QPen(option.palette.highlightedText().color()));
00240 } else {
00241 painter->setPen(QPen(option.palette.text().color()));
00242 }
00243
00244 const QSortFilterProxyModel * model = qobject_cast<const QSortFilterProxyModel*>(index.model());
00245 const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(model->sourceModel());
00246
00247 if (realmodel->hasPreviewImages()) {
00248
00249 int height = option.rect.height();
00250 QPoint point(option.rect.left() + margin, option.rect.top() + ((height - kPreviewHeight) / 2));
00251
00252 if (index.data(ItemsModel::kPreview).toString().isEmpty()) {
00253 QRect rect(point, QSize(kPreviewWidth, kPreviewHeight));
00254 painter->drawText(rect, Qt::AlignCenter | Qt::TextWordWrap, i18n("No Preview"));
00255 } else {
00256 QImage image = index.data(ItemsModel::kPreviewPixmap).value<QImage>();
00257 if (!image.isNull()) {
00258 point.setY(option.rect.top() + ((height - image.height()) / 2));
00259 painter->drawImage(point, image);
00260 QPoint framePoint(point.x() - 5, point.y() - 5);
00261 painter->drawImage(framePoint, m_frameImage.scaled(image.width() + 10, image.height() + 10));
00262 } else {
00263 QRect rect(point, QSize(kPreviewWidth, kPreviewHeight));
00264 painter->drawText(rect, Qt::AlignCenter | Qt::TextWordWrap, i18n("Loading Preview"));
00265 }
00266 }
00267 }
00268
00269 painter->restore();
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 QSize ItemsViewDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
00282 {
00283 Q_UNUSED(option);
00284 Q_UNUSED(index);
00285
00286 QSize size;
00287
00288 size.setWidth(option.fontMetrics.height() * 4);
00289 size.setHeight(qMax(option.fontMetrics.height() * 7, kPreviewHeight));
00290
00291 return size;
00292 }
00293
00294 void ItemsViewDelegate::slotLinkClicked(const QString & url)
00295 {
00296 Q_UNUSED(url)
00297 QModelIndex index = focusedIndex();
00298 Q_ASSERT(index.isValid());
00299
00300 const QSortFilterProxyModel * model = qobject_cast<const QSortFilterProxyModel*>(index.model());
00301 const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(model->sourceModel());
00302 KNS::Entry * entry = realmodel->entryForIndex(model->mapToSource(index));
00303 emit performAction(DownloadDialog::kContactEmail, entry);
00304 }
00305
00306 void ItemsViewDelegate::slotActionTriggered(QAction *action)
00307 {
00308 QModelIndex index = focusedIndex();
00309 Q_ASSERT(index.isValid());
00310
00311 const QSortFilterProxyModel * model = qobject_cast<const QSortFilterProxyModel*>(index.model());
00312 const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(model->sourceModel());
00313 KNS::Entry * entry = realmodel->entryForIndex(model->mapToSource(index));
00314 emit performAction(DownloadDialog::EntryAction(action->data().toInt()), entry);
00315 }
00316
00317 void ItemsViewDelegate::slotInstallClicked()
00318 {
00319 QModelIndex index = focusedIndex();
00320
00321 if (index.isValid()) {
00322 const QSortFilterProxyModel * model = qobject_cast<const QSortFilterProxyModel*>(index.model());
00323 const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(model->sourceModel());
00324 KNS::Entry * entry = realmodel->entryForIndex(model->mapToSource(index));
00325 if ( !entry )
00326 return;
00327
00328 if (entry->status() == Entry::Installed) {
00329 emit performAction(DownloadDialog::kUninstall, entry);
00330 } else {
00331 emit performAction(DownloadDialog::kInstall, entry);
00332 }
00333 }
00334 }
00335 }