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 kCollaborate = 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 return list;
00091 }
00092
00093 void ItemsViewDelegate::updateItemWidgets(const QList<QWidget*> widgets,
00094 const QStyleOptionViewItem &option,
00095 const QPersistentModelIndex &index) const
00096 {
00097 const QSortFilterProxyModel * model = qobject_cast<const QSortFilterProxyModel*>(index.model());
00098 if (model == NULL) {
00099 return;
00100 }
00101
00102 const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(model->sourceModel());
00103 if (realmodel == NULL || !index.isValid()) {
00104 return;
00105 }
00106
00107
00108 int margin = option.fontMetrics.height() / 2;
00109
00110 int right = option.rect.width();
00111
00112
00113 QSize size(option.fontMetrics.height() * 7, widgets.at(kInstall)->sizeHint().height());
00114
00115 QLabel * infoLabel = qobject_cast<QLabel*>(widgets.at(kLabel));
00116 if (infoLabel != NULL) {
00117 if (realmodel->hasPreviewImages()) {
00118
00119 infoLabel->move(64 + margin * 2, 0);
00120 infoLabel->resize(QSize(option.rect.width() - 64 - (margin * 4) - size.width(), option.fontMetrics.height() * 5));
00121 } else {
00122 infoLabel->move(margin, 0);
00123 infoLabel->resize(QSize(option.rect.width() - margin - size.width(), option.fontMetrics.height() * 5));
00124 }
00125
00126 QString text = "<b>" + index.data(ItemsModel::kNameRole).toString() + "</b><br />";
00127
00128 QString summary = option.fontMetrics.elidedText(index.data(ItemsModel::kSummary).toString(),
00129 Qt::ElideRight, infoLabel->width());
00130 QStringList summarylines = summary.split('\n');
00131 summary = summarylines[0];
00132 text += summary + "<br />";
00133
00134 QString authorName = index.data(ItemsModel::kAuthorName).toString();
00135 QString email = index.data(ItemsModel::kAuthorEmail).toString();
00136 if (!authorName.isEmpty()) {
00137 if (email.isEmpty()) {
00138 text += "<i>" + authorName + "</i>";
00139 } else {
00140 text += "<i>" + authorName + "</i> <a href=\"mailto:" + email + "\">" + email + "</a>";
00141 }
00142 text += "<br />";
00143 }
00144
00145 unsigned int downloads = index.data(ItemsModel::kDownloads).toUInt();
00146 text += downloads == 0 ? i18n("No Downloads") : i18n("Downloads: %1", downloads);
00147
00148 infoLabel->setText(text);
00149 }
00150
00151 QToolButton * button = qobject_cast<QToolButton*>(widgets.at(kInstall));
00152 if (button != NULL) {
00153 Entry::Status status = Entry::Status(model->data(index, ItemsModel::kStatus).toUInt());
00154
00155
00156
00157 button->resize(size);
00158
00159 button->move(right - button->width() - margin, option.rect.height() / 2 - button->height() / 2);
00160 button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 switch (status) {
00171 case Entry::Installed:
00172 button->setText(i18n("Uninstall"));
00173
00174
00175 button->setIcon(QIcon(m_statusicons[Entry::Deleted]));
00176 break;
00177 case Entry::Updateable:
00178 button->setText(i18n("Update"));
00179
00180
00181
00182
00183 button->setIcon(QIcon(m_statusicons[Entry::Updateable]));
00184 break;
00185 case Entry::Deleted:
00187 button->setText(i18n("Install"));
00188
00189
00190
00191
00192 button->setIcon(QIcon(m_statusicons[Entry::Installed]));
00193 break;
00194 default:
00195 button->setText(i18n("Install"));
00196
00197
00198
00199 button->setIcon(QIcon(m_statusicons[Entry::Installed]));
00200 }
00201 }
00202 }
00203
00204
00205
00206 void ItemsViewDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
00207 {
00208 int margin = option.fontMetrics.height() / 2;
00209
00210 painter->save();
00211
00212 if (option.state & QStyle::State_Selected) {
00213 painter->fillRect(option.rect, option.palette.highlight());
00214 } else {
00215 painter->fillRect(option.rect, (index.row() % 2 == 0 ? option.palette.base() : option.palette.alternateBase()));
00216 painter->setPen(QPen(option.palette.window().color()));
00217 painter->drawRect(option.rect);
00218 }
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 QSortFilterProxyModel * model = qobject_cast<const QSortFilterProxyModel*>(index.model());
00227 const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(model->sourceModel());
00228
00229 if (realmodel->hasPreviewImages()) {
00230
00231 int height = option.rect.height();
00232 QPoint point(option.rect.left() + margin, option.rect.top() + ((height - 64) / 2));
00233
00234 if (index.data(ItemsModel::kPreview).toString().isEmpty()) {
00235 QRect rect(point, QSize(64, 64));
00236 painter->drawText(rect, Qt::AlignCenter | Qt::TextWordWrap, i18n("No Preview"));
00237 } else {
00238 QImage image = index.data(ItemsModel::kPreviewPixmap).value<QImage>();
00239 if (!image.isNull()) {
00240 point.setY(option.rect.top() + ((height - image.height()) / 2));
00241 painter->drawImage(point, image);
00242 QPoint framePoint(point.x() - 5, point.y() - 5);
00243 painter->drawImage(framePoint, m_frameImage.scaled(image.width() + 10, image.height() + 10));
00244 } else {
00245 QRect rect(point, QSize(64, 64));
00246 painter->drawText(rect, Qt::AlignCenter | Qt::TextWordWrap, i18n("Loading Preview"));
00247 }
00248 }
00249 }
00250
00251 painter->restore();
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 QSize ItemsViewDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
00264 {
00265 Q_UNUSED(option);
00266 Q_UNUSED(index);
00267
00268 QSize size;
00269
00270 size.setWidth(option.fontMetrics.height() * 4);
00271 size.setHeight(option.fontMetrics.height() * 5);
00272
00273 return size;
00274 }
00275
00276 void ItemsViewDelegate::slotLinkClicked(const QString & url)
00277 {
00278 Q_UNUSED(url)
00279 QModelIndex index = focusedIndex();
00280 Q_ASSERT(index.isValid());
00281
00282 const QSortFilterProxyModel * model = qobject_cast<const QSortFilterProxyModel*>(index.model());
00283 const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(model->sourceModel());
00284 KNS::Entry * entry = realmodel->entryForIndex(model->mapToSource(index));
00285 emit performAction(DownloadDialog::kContactEmail, entry);
00286 }
00287
00288 void ItemsViewDelegate::slotActionTriggered(QAction *action)
00289 {
00290 QModelIndex index = focusedIndex();
00291 Q_ASSERT(index.isValid());
00292
00293 const QSortFilterProxyModel * model = qobject_cast<const QSortFilterProxyModel*>(index.model());
00294 const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(model->sourceModel());
00295 KNS::Entry * entry = realmodel->entryForIndex(model->mapToSource(index));
00296 emit performAction(DownloadDialog::EntryAction(action->data().toInt()), entry);
00297 }
00298
00299 void ItemsViewDelegate::slotInstallClicked()
00300 {
00301 QModelIndex index = focusedIndex();
00302
00303 if (index.isValid()) {
00304 const QSortFilterProxyModel * model = qobject_cast<const QSortFilterProxyModel*>(index.model());
00305 const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(model->sourceModel());
00306 KNS::Entry * entry = realmodel->entryForIndex(model->mapToSource(index));
00307 if ( !entry )
00308 return;
00309
00310 if (entry->status() == Entry::Installed) {
00311 emit performAction(DownloadDialog::kUninstall, entry);
00312 } else {
00313 emit performAction(DownloadDialog::kInstall, entry);
00314 }
00315 }
00316 }
00317 }