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 KMenu * installMenu = new KMenu(NULL);
00064 QAction * action_install = installMenu->addAction(m_statusicons[Entry::Installed], i18n("Install"));
00065 QAction * action_uninstall = installMenu->addAction(m_statusicons[Entry::Deleted], i18n("Uninstall"));
00066 action_install->setData(DownloadDialog::kInstall);
00067 action_uninstall->setData(DownloadDialog::kUninstall);
00068
00069 action_install->setVisible(status != Entry::Installed);
00070 action_uninstall->setVisible(status == Entry::Installed);
00071 return installMenu;
00072 }
00073
00074 QList<QWidget*> ItemsViewDelegate::createItemWidgets() const
00075 {
00076 QList<QWidget*> list;
00077
00078 QLabel * infoLabel = new QLabel();
00079 infoLabel->setOpenExternalLinks(true);
00080 list << infoLabel;
00081
00082 QToolButton * installButton = new QToolButton();
00083 list << installButton;
00084 setBlockedEventTypes(installButton, QList<QEvent::Type>() << QEvent::MouseButtonPress
00085 << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick);
00086 connect(installButton, SIGNAL(triggered(QAction *)), this, SLOT(slotActionTriggered(QAction *)));
00087 connect(installButton, SIGNAL(clicked()), this, SLOT(slotInstallClicked()));
00088
00089 return list;
00090 }
00091
00092 void ItemsViewDelegate::updateItemWidgets(const QList<QWidget*> widgets,
00093 const QStyleOptionViewItem &option,
00094 const QPersistentModelIndex &index) const
00095 {
00096 const QSortFilterProxyModel * model = qobject_cast<const QSortFilterProxyModel*>(index.model());
00097 if (model == NULL) {
00098 return;
00099 }
00100
00101 const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(model->sourceModel());
00102 if (realmodel == NULL || !index.isValid()) {
00103 return;
00104 }
00105
00106
00107 int margin = option.fontMetrics.height() / 2;
00108
00109 int right = option.rect.width();
00110
00111
00112 QSize size(option.fontMetrics.height() * 7, widgets.at(kInstall)->sizeHint().height());
00113
00114 QLabel * infoLabel = qobject_cast<QLabel*>(widgets.at(kLabel));
00115 if (infoLabel != NULL) {
00116 if (realmodel->hasPreviewImages()) {
00117
00118 infoLabel->move(64 + margin * 2, 0);
00119 infoLabel->resize(QSize(option.rect.width() - 64 - (margin * 4) - size.width(), option.fontMetrics.height() * 5));
00120 } else {
00121 infoLabel->move(margin, 0);
00122 infoLabel->resize(QSize(option.rect.width() - margin - size.width(), option.fontMetrics.height() * 5));
00123 }
00124
00125 QString text = "<b>" + index.data(ItemsModel::kNameRole).toString() + "</b><br />";
00126
00127 QString summary = option.fontMetrics.elidedText(index.data(ItemsModel::kSummary).toString(),
00128 Qt::ElideRight, infoLabel->width());
00129 QStringList summarylines = summary.split('\n');
00130 summary = summarylines[0];
00131 text += summary + "<br />";
00132
00133 QString authorName = index.data(ItemsModel::kAuthorName).toString();
00134 QString email = index.data(ItemsModel::kAuthorEmail).toString();
00135 if (!authorName.isEmpty()) {
00136 if (email.isEmpty()) {
00137 text += "<i>" + authorName + "</i>";
00138 } else {
00139 text += "<i>" + authorName + "</i> <a href=\"mailto:" + email + "\">" + email + "</a>";
00140 }
00141 text += "<br />";
00142 }
00143
00144 unsigned int downloads = index.data(ItemsModel::kDownloads).toUInt();
00145 text += downloads == 0 ? i18n("No Downloads") : i18n("Downloads: %1", downloads);
00146
00147 infoLabel->setText(text);
00148 }
00149
00150 QToolButton * button = qobject_cast<QToolButton*>(widgets.at(kInstall));
00151 if (button != NULL) {
00152 Entry::Status status = Entry::Status(model->data(index, ItemsModel::kStatus).toUInt());
00153 if (!button->menu()) {
00154 button->setMenu(InstallMenu(button, status));
00155 button->setIconSize(QSize(16, 16));
00156 button->resize(size);
00157 }
00158 button->move(right - button->width() - margin, option.rect.height() / 2 - button->height() / 2);
00159 button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
00160 button->setPopupMode(QToolButton::MenuButtonPopup);
00161
00162
00163 Q_ASSERT(button->menu());
00164 Q_ASSERT(button->menu()->actions().count() == 2);
00165
00166
00167 QAction * action_install = button->menu()->actions()[0];
00168 QAction * action_uninstall = button->menu()->actions()[1];
00169 switch (status) {
00170 case Entry::Installed:
00171 button->setText(i18n("Uninstall"));
00172 action_install->setVisible(false);
00173 action_uninstall->setVisible(true);
00174 button->setIcon(QIcon(m_statusicons[Entry::Deleted]));
00175 break;
00176 case Entry::Updateable:
00177 button->setText(i18n("Update"));
00178 action_uninstall->setVisible(false);
00179 action_install->setText(i18n("Update"));
00180 action_install->setVisible(true);
00181 action_install->setIcon(QIcon(m_statusicons[Entry::Updateable]));
00182 button->setIcon(QIcon(m_statusicons[Entry::Updateable]));
00183 break;
00184 case Entry::Deleted:
00186 button->setText(i18n("Install"));
00187 action_uninstall->setVisible(false);
00188 action_install->setText(i18n("Install"));
00189 action_install->setVisible(true);
00190 action_install->setIcon(QIcon(m_statusicons[Entry::Installed]));
00191 button->setIcon(QIcon(m_statusicons[Entry::Installed]));
00192 break;
00193 default:
00194 button->setText(i18n("Install"));
00195 action_uninstall->setVisible(false);
00196 action_install->setVisible(true);
00197 action_install->setIcon(QIcon(m_statusicons[Entry::Installed]));
00198 button->setIcon(QIcon(m_statusicons[Entry::Installed]));
00199 }
00200 }
00201 }
00202
00203
00204
00205 void ItemsViewDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
00206 {
00207 int margin = option.fontMetrics.height() / 2;
00208
00209 painter->save();
00210
00211 if (option.state & QStyle::State_Selected) {
00212 painter->fillRect(option.rect, option.palette.highlight());
00213 } else {
00214 painter->fillRect(option.rect, (index.row() % 2 == 0 ? option.palette.base() : option.palette.alternateBase()));
00215 painter->setPen(QPen(option.palette.window().color()));
00216 painter->drawRect(option.rect);
00217 }
00218
00219 if (option.state & QStyle::State_Selected) {
00220 painter->setPen(QPen(option.palette.highlightedText().color()));
00221 } else {
00222 painter->setPen(QPen(option.palette.text().color()));
00223 }
00224
00225 const QSortFilterProxyModel * model = qobject_cast<const QSortFilterProxyModel*>(index.model());
00226 const ItemsModel * realmodel = qobject_cast<const ItemsModel*>(model->sourceModel());
00227
00228 if (realmodel->hasPreviewImages()) {
00229
00230 int height = option.rect.height();
00231 QPoint point(option.rect.left() + margin, option.rect.top() + ((height - 64) / 2));
00232
00233 if (index.data(ItemsModel::kPreview).toString().isEmpty()) {
00234 QRect rect(point, QSize(64, 64));
00235 painter->drawText(rect, Qt::AlignCenter | Qt::TextWordWrap, i18n("No Preview"));
00236 } else {
00237 QImage image = index.data(ItemsModel::kPreviewPixmap).value<QImage>();
00238 if (!image.isNull()) {
00239 point.setY(option.rect.top() + ((height - image.height()) / 2));
00240 painter->drawImage(point, image);
00241 QPoint framePoint(point.x() - 5, point.y() - 5);
00242 painter->drawImage(framePoint, m_frameImage.scaled(image.width() + 10, image.height() + 10));
00243 } else {
00244 QRect rect(point, QSize(64, 64));
00245 painter->drawText(rect, Qt::AlignCenter | Qt::TextWordWrap, i18n("Loading Preview"));
00246 }
00247 }
00248 }
00249
00250 painter->restore();
00251
00252 KWidgetItemDelegate::paintWidgets(painter, option, index);
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 QSize ItemsViewDelegate::sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const
00265 {
00266 Q_UNUSED(option);
00267 Q_UNUSED(index);
00268
00269 QSize size;
00270
00271 size.setWidth(option.fontMetrics.height() * 4);
00272 size.setHeight(option.fontMetrics.height() * 5);
00273
00274 return size;
00275 }
00276
00277 void ItemsViewDelegate::slotLinkClicked(const QString & url)
00278 {
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 }