88
89
/** How many pixels around the thumbnail are shadowed */
89
90
const int SHADOW_SIZE = 4;
92
static KFileItem fileItemForIndex(const QModelIndex& index) {
93
Q_ASSERT(index.isValid());
94
QVariant data = index.data(KDirModel::FileItemRole);
95
return qvariant_cast<KFileItem>(data);
99
static KUrl urlForIndex(const QModelIndex& index) {
100
KFileItem item = fileItemForIndex(index);
92
static KFileItem fileItemForIndex(const QModelIndex& index)
94
Q_ASSERT(index.isValid());
95
QVariant data = index.data(KDirModel::FileItemRole);
96
return qvariant_cast<KFileItem>(data);
99
static KUrl urlForIndex(const QModelIndex& index)
101
KFileItem item = fileItemForIndex(index);
105
105
struct PreviewItemDelegatePrivate {
107
* Maps full text to elided text.
109
mutable QHash<QString, QString> mElidedTextCache;
111
// Key is height * 1000 + width
112
typedef QHash<int, QPixmap> ShadowCache;
113
mutable ShadowCache mShadowCache;
115
PreviewItemDelegate* that;
116
ThumbnailView* mView;
117
QWidget* mContextBar;
118
QToolButton* mSaveButton;
119
QPixmap mSaveButtonPixmap;
121
QToolButton* mToggleSelectionButton;
122
QToolButton* mFullScreenButton;
123
QToolButton* mRotateLeftButton;
124
QToolButton* mRotateRightButton;
125
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
126
KRatingPainter mRatingPainter;
129
QModelIndex mIndexUnderCursor;
131
PreviewItemDelegate::ThumbnailDetails mDetails;
132
PreviewItemDelegate::ContextBarMode mContextBarMode;
133
Qt::TextElideMode mTextElideMode;
135
QPointer<ToolTipWidget> mToolTip;
136
QScopedPointer<QAbstractAnimation> mToolTipAnimation;
139
void initSaveButtonPixmap() {
140
if (!mSaveButtonPixmap.isNull()) {
143
// Necessary otherwise we won't see the save button itself
144
mSaveButton->adjustSize();
146
mSaveButtonPixmap = QPixmap(mSaveButton->sizeHint());
147
mSaveButtonPixmap.fill(Qt::transparent);
148
mSaveButton->render(&mSaveButtonPixmap, QPoint(), QRegion(), QWidget::DrawChildren);
152
void showContextBar(const QRect& rect, const QPixmap& thumbnailPix) {
153
if (mContextBarMode == PreviewItemDelegate::NoContextBar) {
156
mContextBar->adjustSize();
157
// Center bar in FullContextBar mode, left align in
158
// SelectionOnlyContextBar mode
159
const int posX = mContextBarMode == PreviewItemDelegate::FullContextBar
160
? (rect.width() - mContextBar->width()) / 2
162
const int posY = qMax(CONTEXTBAR_MARGIN, mThumbnailSize - thumbnailPix.height() - mContextBar->height());
163
mContextBar->move(rect.topLeft() + QPoint(posX, posY));
169
mToolTip = new ToolTipWidget(mView->viewport());
170
mToolTip->setOpacity(0);
175
bool hoverEventFilter(QHoverEvent* event) {
176
QModelIndex index = mView->indexAt(event->pos());
177
if (index != mIndexUnderCursor) {
178
updateHoverUi(index);
180
// Same index, nothing to do, but repaint anyway in case we are
181
// over the rating row
182
mView->update(mIndexUnderCursor);
188
void updateHoverUi(const QModelIndex& index) {
189
QModelIndex oldIndex = mIndexUnderCursor;
190
mIndexUnderCursor = index;
191
mView->update(oldIndex);
193
if (KGlobalSettings::singleClick() && KGlobalSettings::changeCursorOverIcon()) {
194
mView->setCursor(mIndexUnderCursor.isValid() ? Qt::PointingHandCursor : Qt::ArrowCursor);
197
if (mIndexUnderCursor.isValid()) {
198
updateToggleSelectionButton();
199
updateImageButtons();
201
const QRect rect = mView->visualRect(mIndexUnderCursor);
202
const QPixmap thumbnailPix = mView->thumbnailForIndex(index);
203
showContextBar(rect, thumbnailPix);
204
if (mView->isModified(mIndexUnderCursor)) {
205
showSaveButton(rect);
211
mView->update(mIndexUnderCursor);
220
QRect ratingRectFromIndexRect(const QRect& rect) const {
223
rect.bottom() - ratingRowHeight() - ITEM_MARGIN,
228
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
229
int ratingFromCursorPosition(const QRect& ratingRect) const {
230
const QPoint pos = mView->viewport()->mapFromGlobal(QCursor::pos());
231
return mRatingPainter.ratingFromPosition(ratingRect, pos);
235
bool mouseButtonEventFilter(QEvent::Type type) {
236
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
237
const QRect rect = ratingRectFromIndexRect(mView->visualRect(mIndexUnderCursor));
238
const int rating = ratingFromCursorPosition(rect);
242
if (type == QEvent::MouseButtonRelease) {
243
that->setDocumentRatingRequested(urlForIndex(mIndexUnderCursor) , rating);
252
QPoint saveButtonPosition(const QRect& itemRect) const {
253
QSize buttonSize = mSaveButton->sizeHint();
254
int posX = itemRect.right() - buttonSize.width();
255
int posY = itemRect.top() + mThumbnailSize + 2 * ITEM_MARGIN - buttonSize.height();
257
return QPoint(posX, posY);
261
void showSaveButton(const QRect& itemRect) const {
262
mSaveButton->move(saveButtonPosition(itemRect));
267
void drawBackground(QPainter* painter, const QRect& rect, const QColor& bgColor, const QColor& borderColor) const {
269
int borderH, borderS, borderV, borderMargin;
270
#ifdef FINETUNE_SELECTION_BACKGROUND
271
QSettings settings(QDir::homePath() + "/colors.ini", QSettings::IniFormat);
272
bgH = settings.value("bg/h").toInt();
273
bgS = settings.value("bg/s").toInt();
274
bgV = settings.value("bg/v").toInt();
275
borderH = settings.value("border/h").toInt();
276
borderS = settings.value("border/s").toInt();
277
borderV = settings.value("border/v").toInt();
278
borderMargin = settings.value("border/margin").toInt();
288
painter->setRenderHint(QPainter::Antialiasing);
290
QRectF rectF = QRectF(rect).adjusted(0.5, 0.5, -0.5, -0.5);
292
QPainterPath path = PaintUtils::roundedRectangle(rectF, SELECTION_RADIUS);
294
QLinearGradient gradient(rectF.topLeft(), rectF.bottomLeft());
295
gradient.setColorAt(0, PaintUtils::adjustedHsv(bgColor, bgH, bgS, bgV));
296
gradient.setColorAt(1, bgColor);
297
painter->fillPath(path, gradient);
299
painter->setPen(borderColor);
300
painter->drawPath(path);
302
painter->setPen(PaintUtils::adjustedHsv(borderColor, borderH, borderS, borderV));
303
rectF = rectF.adjusted(borderMargin, borderMargin, -borderMargin, -borderMargin);
304
path = PaintUtils::roundedRectangle(rectF, SELECTION_RADIUS);
305
painter->drawPath(path);
309
void drawShadow(QPainter* painter, const QRect& rect) const {
310
const QPoint shadowOffset(-SHADOW_SIZE, -SHADOW_SIZE + 1);
312
int key = rect.height() * 1000 + rect.width();
314
ShadowCache::Iterator it = mShadowCache.find(key);
315
if (it == mShadowCache.end()) {
316
QSize size = QSize(rect.width() + 2*SHADOW_SIZE, rect.height() + 2*SHADOW_SIZE);
317
QColor color(0, 0, 0, SHADOW_STRENGTH);
318
QPixmap shadow = PaintUtils::generateFuzzyRect(size, color, SHADOW_SIZE);
319
it = mShadowCache.insert(key, shadow);
321
painter->drawPixmap(rect.topLeft() + shadowOffset, it.value());
325
void drawText(QPainter* painter, const QRect& rect, const QColor& fgColor, const QString& fullText) const {
326
QFontMetrics fm = mView->fontMetrics();
330
QHash<QString, QString>::const_iterator it = mElidedTextCache.constFind(fullText);
331
if (it == mElidedTextCache.constEnd()) {
332
text = fm.elidedText(fullText, mTextElideMode, rect.width());
333
mElidedTextCache[fullText] = text;
340
if (text.length() == fullText.length()) {
341
// Not elided, center text
342
posX = (rect.width() - fm.width(text)) / 2;
344
// Elided, left align
349
painter->setPen(fgColor);
350
painter->drawText(rect.left() + posX, rect.top() + fm.ascent(), text);
354
void drawRating(QPainter* painter, const QRect& rect, const QVariant& value) {
355
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
356
const int rating = value.toInt();
357
const QRect ratingRect = ratingRectFromIndexRect(rect);
358
const int hoverRating = ratingFromCursorPosition(ratingRect);
359
mRatingPainter.paint(painter, ratingRect, rating, hoverRating);
364
bool isTextElided(const QString& text) const {
365
QHash<QString, QString>::const_iterator it = mElidedTextCache.constFind(text);
366
if (it == mElidedTextCache.constEnd()) {
369
return it.value().length() < text.length();
374
* Show a tooltip only if the item has been elided.
375
* This function places the tooltip over the item text.
377
void showToolTip(const QModelIndex& index) {
378
if (mDetails == 0 || mDetails == PreviewItemDelegate::RatingDetail) {
379
// No text to display
384
QStringList textList;
386
if (mDetails & PreviewItemDelegate::FileNameDetail) {
387
const QString text = index.data().toString();
388
elided |= isTextElided(text);
392
// FIXME: Duplicated from drawText
393
const KFileItem fileItem = fileItemForIndex(index);
394
const bool isDirOrArchive = ArchiveUtils::fileItemIsDirOrArchive(fileItem);
395
if (mDetails & PreviewItemDelegate::DateDetail) {
396
if (!ArchiveUtils::fileItemIsDirOrArchive(fileItem)) {
397
const KDateTime dt = TimeUtils::dateTimeForFileItem(fileItem);
398
const QString text = KGlobal::locale()->formatDateTime(dt);
399
elided |= isTextElided(text);
404
if (!isDirOrArchive && (mDetails & PreviewItemDelegate::ImageSizeDetail)) {
406
QPixmap thumbnailPix = mView->thumbnailForIndex(index, &fullSize);
407
if (fullSize.isValid()) {
408
const QString text = QString("%1x%2").arg(fullSize.width()).arg(fullSize.height());
409
elided |= isTextElided(text);
414
if (!isDirOrArchive && (mDetails & PreviewItemDelegate::FileSizeDetail)) {
415
const KIO::filesize_t size = fileItem.size();
417
const QString text = KIO::convertSize(size);
418
elided |= isTextElided(text);
428
bool newTipLabel = !mToolTip;
432
mToolTip->setText(textList.join("\n"));
433
QSize tipSize = mToolTip->sizeHint();
435
// Compute tip position
436
QRect rect = mView->visualRect(index);
437
const int textY = ITEM_MARGIN + mThumbnailSize + ITEM_MARGIN;
438
const int spacing = 1;
440
QPoint(rect.topLeft() + QPoint((rect.width() - tipSize.width()) / 2, textY + spacing)),
443
if (geometry.left() < 0) {
444
geometry.moveLeft(0);
445
} else if (geometry.right() > mView->viewport()->width()) {
446
geometry.moveRight(mView->viewport()->width());
450
QParallelAnimationGroup* anim = new QParallelAnimationGroup();
451
QPropertyAnimation* fadeIn = new QPropertyAnimation(mToolTip, "opacity");
452
fadeIn->setStartValue(mToolTip->opacity());
453
fadeIn->setEndValue(1.);
454
anim->addAnimation(fadeIn);
457
mToolTip->setGeometry(geometry);
459
QPropertyAnimation* move = new QPropertyAnimation(mToolTip, "geometry");
460
move->setStartValue(mToolTip->geometry());
461
move->setEndValue(geometry);
462
anim->addAnimation(move);
465
mToolTipAnimation.reset(anim);
466
mToolTipAnimation->start();
473
QSequentialAnimationGroup* anim = new QSequentialAnimationGroup();
475
QPropertyAnimation* fadeOut = new QPropertyAnimation(mToolTip, "opacity");
476
fadeOut->setStartValue(mToolTip->opacity());
477
fadeOut->setEndValue(0.);
478
anim->addAnimation(fadeOut);
479
mToolTipAnimation.reset(anim);
480
mToolTipAnimation->start();
481
QObject::connect(anim, SIGNAL(finished()), mToolTip, SLOT(deleteLater()));
484
int itemWidth() const {
485
return mThumbnailSize + 2 * ITEM_MARGIN;
488
int ratingRowHeight() const {
489
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
490
return mView->fontMetrics().ascent();
495
int itemHeight() const {
496
const int lineHeight = mView->fontMetrics().height();
498
if (mDetails & PreviewItemDelegate::FileNameDetail) {
499
textHeight += lineHeight;
501
if (mDetails & PreviewItemDelegate::DateDetail) {
502
textHeight += lineHeight;
504
if (mDetails & PreviewItemDelegate::ImageSizeDetail) {
505
textHeight += lineHeight;
507
if (mDetails & PreviewItemDelegate::FileSizeDetail) {
508
textHeight += lineHeight;
510
if (mDetails & PreviewItemDelegate::RatingDetail) {
511
textHeight += ratingRowHeight();
513
if (textHeight == 0) {
514
// Keep at least one row of text, so that we can show folder names
515
textHeight = lineHeight;
517
return mThumbnailSize + textHeight + 3*ITEM_MARGIN;
520
void selectIndexUnderCursorIfNoMultiSelection() {
521
if (mView->selectionModel()->selectedIndexes().size() <= 1) {
522
mView->setCurrentIndex(mIndexUnderCursor);
526
void updateToggleSelectionButton() {
527
mToggleSelectionButton->setIcon(SmallIcon(
528
mView->selectionModel()->isSelected(mIndexUnderCursor) ? "list-remove" : "list-add"
532
void updateImageButtons() {
533
const KFileItem item = fileItemForIndex(mIndexUnderCursor);
534
const bool isImage = !ArchiveUtils::fileItemIsDirOrArchive(item);
535
mFullScreenButton->setEnabled(isImage);
536
mRotateLeftButton->setEnabled(isImage);
537
mRotateRightButton->setEnabled(isImage);
540
void updateContextBar() {
541
if (mContextBarMode == PreviewItemDelegate::NoContextBar) {
545
const int width = itemWidth();
546
const int buttonWidth = mRotateRightButton->sizeHint().width();
547
bool full = mContextBarMode == PreviewItemDelegate::FullContextBar;
548
mFullScreenButton->setVisible(full);
549
mRotateLeftButton->setVisible(full && width >= 3 * buttonWidth);
550
mRotateRightButton->setVisible(full && width >= 4 * buttonWidth);
551
mContextBar->adjustSize();
554
void updateViewGridSize() {
555
mView->setGridSize(QSize(itemWidth(), itemHeight()));
107
* Maps full text to elided text.
109
mutable QHash<QString, QString> mElidedTextCache;
111
// Key is height * 1000 + width
112
typedef QHash<int, QPixmap> ShadowCache;
113
mutable ShadowCache mShadowCache;
115
PreviewItemDelegate* q;
116
ThumbnailView* mView;
117
QWidget* mContextBar;
118
QToolButton* mSaveButton;
119
QPixmap mSaveButtonPixmap;
121
QToolButton* mToggleSelectionButton;
122
QToolButton* mFullScreenButton;
123
QToolButton* mRotateLeftButton;
124
QToolButton* mRotateRightButton;
125
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
126
KRatingPainter mRatingPainter;
129
QModelIndex mIndexUnderCursor;
131
PreviewItemDelegate::ThumbnailDetails mDetails;
132
PreviewItemDelegate::ContextBarMode mContextBarMode;
133
Qt::TextElideMode mTextElideMode;
135
QPointer<ToolTipWidget> mToolTip;
136
QScopedPointer<QAbstractAnimation> mToolTipAnimation;
138
void initSaveButtonPixmap()
140
if (!mSaveButtonPixmap.isNull()) {
143
// Necessary otherwise we won't see the save button itself
144
mSaveButton->adjustSize();
146
mSaveButtonPixmap = QPixmap(mSaveButton->sizeHint());
147
mSaveButtonPixmap.fill(Qt::transparent);
148
mSaveButton->render(&mSaveButtonPixmap, QPoint(), QRegion(), QWidget::DrawChildren);
151
void showContextBar(const QRect& rect, const QPixmap& thumbnailPix)
153
if (mContextBarMode == PreviewItemDelegate::NoContextBar) {
156
mContextBar->adjustSize();
157
// Center bar in FullContextBar mode, left align in
158
// SelectionOnlyContextBar mode
159
const int posX = mContextBarMode == PreviewItemDelegate::FullContextBar
160
? (rect.width() - mContextBar->width()) / 2
162
const int posY = qMax(CONTEXTBAR_MARGIN, mThumbnailSize - thumbnailPix.height() - mContextBar->height());
163
mContextBar->move(rect.topLeft() + QPoint(posX, posY));
169
mToolTip = new ToolTipWidget(mView->viewport());
170
mToolTip->setOpacity(0);
174
bool hoverEventFilter(QHoverEvent* event)
176
QModelIndex index = mView->indexAt(event->pos());
177
if (index != mIndexUnderCursor) {
178
updateHoverUi(index);
180
// Same index, nothing to do, but repaint anyway in case we are
181
// over the rating row
182
mView->update(mIndexUnderCursor);
187
void updateHoverUi(const QModelIndex& index)
189
QModelIndex oldIndex = mIndexUnderCursor;
190
mIndexUnderCursor = index;
191
mView->update(oldIndex);
193
if (KGlobalSettings::singleClick() && KGlobalSettings::changeCursorOverIcon()) {
194
mView->setCursor(mIndexUnderCursor.isValid() ? Qt::PointingHandCursor : Qt::ArrowCursor);
197
if (mIndexUnderCursor.isValid()) {
198
updateToggleSelectionButton();
199
updateImageButtons();
201
const QRect rect = mView->visualRect(mIndexUnderCursor);
202
const QPixmap thumbnailPix = mView->thumbnailForIndex(index);
203
showContextBar(rect, thumbnailPix);
204
if (mView->isModified(mIndexUnderCursor)) {
205
showSaveButton(rect);
211
mView->update(mIndexUnderCursor);
220
QRect ratingRectFromIndexRect(const QRect& rect) const {
223
rect.bottom() - ratingRowHeight() - ITEM_MARGIN,
228
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
229
int ratingFromCursorPosition(const QRect& ratingRect) const {
230
const QPoint pos = mView->viewport()->mapFromGlobal(QCursor::pos());
231
return mRatingPainter.ratingFromPosition(ratingRect, pos);
235
bool mouseButtonEventFilter(QEvent::Type type)
237
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
238
const QRect rect = ratingRectFromIndexRect(mView->visualRect(mIndexUnderCursor));
239
const int rating = ratingFromCursorPosition(rect);
243
if (type == QEvent::MouseButtonRelease) {
244
q->setDocumentRatingRequested(urlForIndex(mIndexUnderCursor) , rating);
252
QPoint saveButtonPosition(const QRect& itemRect) const {
253
QSize buttonSize = mSaveButton->sizeHint();
254
int posX = itemRect.right() - buttonSize.width();
255
int posY = itemRect.top() + mThumbnailSize + 2 * ITEM_MARGIN - buttonSize.height();
257
return QPoint(posX, posY);
260
void showSaveButton(const QRect& itemRect) const
262
mSaveButton->move(saveButtonPosition(itemRect));
266
void drawBackground(QPainter* painter, const QRect& rect, const QColor& bgColor, const QColor& borderColor) const
269
int borderH, borderS, borderV, borderMargin;
270
#ifdef FINETUNE_SELECTION_BACKGROUND
271
QSettings settings(QDir::homePath() + "/colors.ini", QSettings::IniFormat);
272
bgH = settings.value("bg/h").toInt();
273
bgS = settings.value("bg/s").toInt();
274
bgV = settings.value("bg/v").toInt();
275
borderH = settings.value("border/h").toInt();
276
borderS = settings.value("border/s").toInt();
277
borderV = settings.value("border/v").toInt();
278
borderMargin = settings.value("border/margin").toInt();
288
painter->setRenderHint(QPainter::Antialiasing);
290
QRectF rectF = QRectF(rect).adjusted(0.5, 0.5, -0.5, -0.5);
292
QPainterPath path = PaintUtils::roundedRectangle(rectF, SELECTION_RADIUS);
294
QLinearGradient gradient(rectF.topLeft(), rectF.bottomLeft());
295
gradient.setColorAt(0, PaintUtils::adjustedHsv(bgColor, bgH, bgS, bgV));
296
gradient.setColorAt(1, bgColor);
297
painter->fillPath(path, gradient);
299
painter->setPen(borderColor);
300
painter->drawPath(path);
302
painter->setPen(PaintUtils::adjustedHsv(borderColor, borderH, borderS, borderV));
303
rectF = rectF.adjusted(borderMargin, borderMargin, -borderMargin, -borderMargin);
304
path = PaintUtils::roundedRectangle(rectF, SELECTION_RADIUS);
305
painter->drawPath(path);
308
void drawShadow(QPainter* painter, const QRect& rect) const
310
const QPoint shadowOffset(-SHADOW_SIZE, -SHADOW_SIZE + 1);
312
int key = rect.height() * 1000 + rect.width();
314
ShadowCache::Iterator it = mShadowCache.find(key);
315
if (it == mShadowCache.end()) {
316
QSize size = QSize(rect.width() + 2 * SHADOW_SIZE, rect.height() + 2 * SHADOW_SIZE);
317
QColor color(0, 0, 0, SHADOW_STRENGTH);
318
QPixmap shadow = PaintUtils::generateFuzzyRect(size, color, SHADOW_SIZE);
319
it = mShadowCache.insert(key, shadow);
321
painter->drawPixmap(rect.topLeft() + shadowOffset, it.value());
324
void drawText(QPainter* painter, const QRect& rect, const QColor& fgColor, const QString& fullText) const
326
QFontMetrics fm = mView->fontMetrics();
330
QHash<QString, QString>::const_iterator it = mElidedTextCache.constFind(fullText);
331
if (it == mElidedTextCache.constEnd()) {
332
text = fm.elidedText(fullText, mTextElideMode, rect.width());
333
mElidedTextCache[fullText] = text;
340
if (text.length() == fullText.length()) {
341
// Not elided, center text
342
posX = (rect.width() - fm.width(text)) / 2;
344
// Elided, left align
349
painter->setPen(fgColor);
350
painter->drawText(rect.left() + posX, rect.top() + fm.ascent(), text);
353
void drawRating(QPainter* painter, const QRect& rect, const QVariant& value)
355
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
356
const int rating = value.toInt();
357
const QRect ratingRect = ratingRectFromIndexRect(rect);
358
const int hoverRating = ratingFromCursorPosition(ratingRect);
359
mRatingPainter.paint(painter, ratingRect, rating, hoverRating);
363
bool isTextElided(const QString& text) const {
364
QHash<QString, QString>::const_iterator it = mElidedTextCache.constFind(text);
365
if (it == mElidedTextCache.constEnd()) {
368
return it.value().length() < text.length();
372
* Show a tooltip only if the item has been elided.
373
* This function places the tooltip over the item text.
375
void showToolTip(const QModelIndex& index)
377
if (mDetails == 0 || mDetails == PreviewItemDelegate::RatingDetail) {
378
// No text to display
383
QStringList textList;
385
if (mDetails & PreviewItemDelegate::FileNameDetail) {
386
const QString text = index.data().toString();
387
elided |= isTextElided(text);
391
// FIXME: Duplicated from drawText
392
const KFileItem fileItem = fileItemForIndex(index);
393
const bool isDirOrArchive = ArchiveUtils::fileItemIsDirOrArchive(fileItem);
394
if (mDetails & PreviewItemDelegate::DateDetail) {
395
if (!ArchiveUtils::fileItemIsDirOrArchive(fileItem)) {
396
const KDateTime dt = TimeUtils::dateTimeForFileItem(fileItem);
397
const QString text = KGlobal::locale()->formatDateTime(dt);
398
elided |= isTextElided(text);
403
if (!isDirOrArchive && (mDetails & PreviewItemDelegate::ImageSizeDetail)) {
405
QPixmap thumbnailPix = mView->thumbnailForIndex(index, &fullSize);
406
if (fullSize.isValid()) {
407
const QString text = QString("%1x%2").arg(fullSize.width()).arg(fullSize.height());
408
elided |= isTextElided(text);
413
if (!isDirOrArchive && (mDetails & PreviewItemDelegate::FileSizeDetail)) {
414
const KIO::filesize_t size = fileItem.size();
416
const QString text = KIO::convertSize(size);
417
elided |= isTextElided(text);
427
bool newTipLabel = !mToolTip;
431
mToolTip->setText(textList.join("\n"));
432
QSize tipSize = mToolTip->sizeHint();
434
// Compute tip position
435
QRect rect = mView->visualRect(index);
436
const int textY = ITEM_MARGIN + mThumbnailSize + ITEM_MARGIN;
437
const int spacing = 1;
439
QPoint(rect.topLeft() + QPoint((rect.width() - tipSize.width()) / 2, textY + spacing)),
442
if (geometry.left() < 0) {
443
geometry.moveLeft(0);
444
} else if (geometry.right() > mView->viewport()->width()) {
445
geometry.moveRight(mView->viewport()->width());
449
QParallelAnimationGroup* anim = new QParallelAnimationGroup();
450
QPropertyAnimation* fadeIn = new QPropertyAnimation(mToolTip, "opacity");
451
fadeIn->setStartValue(mToolTip->opacity());
452
fadeIn->setEndValue(1.);
453
anim->addAnimation(fadeIn);
456
mToolTip->setGeometry(geometry);
458
QPropertyAnimation* move = new QPropertyAnimation(mToolTip, "geometry");
459
move->setStartValue(mToolTip->geometry());
460
move->setEndValue(geometry);
461
anim->addAnimation(move);
464
mToolTipAnimation.reset(anim);
465
mToolTipAnimation->start();
473
QSequentialAnimationGroup* anim = new QSequentialAnimationGroup();
475
QPropertyAnimation* fadeOut = new QPropertyAnimation(mToolTip, "opacity");
476
fadeOut->setStartValue(mToolTip->opacity());
477
fadeOut->setEndValue(0.);
478
anim->addAnimation(fadeOut);
479
mToolTipAnimation.reset(anim);
480
mToolTipAnimation->start();
481
QObject::connect(anim, SIGNAL(finished()), mToolTip, SLOT(deleteLater()));
484
int itemWidth() const {
485
return mThumbnailSize + 2 * ITEM_MARGIN;
488
int ratingRowHeight() const {
489
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
490
return mView->fontMetrics().ascent();
495
int itemHeight() const {
496
const int lineHeight = mView->fontMetrics().height();
498
if (mDetails & PreviewItemDelegate::FileNameDetail) {
499
textHeight += lineHeight;
501
if (mDetails & PreviewItemDelegate::DateDetail) {
502
textHeight += lineHeight;
504
if (mDetails & PreviewItemDelegate::ImageSizeDetail) {
505
textHeight += lineHeight;
507
if (mDetails & PreviewItemDelegate::FileSizeDetail) {
508
textHeight += lineHeight;
510
if (mDetails & PreviewItemDelegate::RatingDetail) {
511
textHeight += ratingRowHeight();
513
if (textHeight == 0) {
514
// Keep at least one row of text, so that we can show folder names
515
textHeight = lineHeight;
517
return mThumbnailSize + textHeight + 3 * ITEM_MARGIN;
520
void selectIndexUnderCursorIfNoMultiSelection()
522
if (mView->selectionModel()->selectedIndexes().size() <= 1) {
523
mView->setCurrentIndex(mIndexUnderCursor);
527
void updateToggleSelectionButton()
529
mToggleSelectionButton->setIcon(SmallIcon(
530
mView->selectionModel()->isSelected(mIndexUnderCursor) ? "list-remove" : "list-add"
534
void updateImageButtons()
536
const KFileItem item = fileItemForIndex(mIndexUnderCursor);
537
const bool isImage = !ArchiveUtils::fileItemIsDirOrArchive(item);
538
mFullScreenButton->setEnabled(isImage);
539
mRotateLeftButton->setEnabled(isImage);
540
mRotateRightButton->setEnabled(isImage);
543
void updateContextBar()
545
if (mContextBarMode == PreviewItemDelegate::NoContextBar) {
549
const int width = itemWidth();
550
const int buttonWidth = mRotateRightButton->sizeHint().width();
551
bool full = mContextBarMode == PreviewItemDelegate::FullContextBar;
552
mFullScreenButton->setVisible(full);
553
mRotateLeftButton->setVisible(full && width >= 3 * buttonWidth);
554
mRotateRightButton->setVisible(full && width >= 4 * buttonWidth);
555
mContextBar->adjustSize();
558
void updateViewGridSize()
560
mView->setGridSize(QSize(itemWidth(), itemHeight()));
560
564
PreviewItemDelegate::PreviewItemDelegate(ThumbnailView* view)
561
565
: QItemDelegate(view)
562
, d(new PreviewItemDelegatePrivate) {
565
view->viewport()->installEventFilter(this);
566
d->mThumbnailSize = view->thumbnailSize();
567
d->mDetails = FileNameDetail;
568
d->mContextBarMode = FullContextBar;
569
d->mTextElideMode = Qt::ElideRight;
566
, d(new PreviewItemDelegatePrivate)
570
view->viewport()->installEventFilter(this);
571
d->mThumbnailSize = view->thumbnailSize();
572
d->mDetails = FileNameDetail;
573
d->mContextBarMode = FullContextBar;
574
d->mTextElideMode = Qt::ElideRight;
571
connect(view, SIGNAL(rowsRemovedSignal(const QModelIndex&, int, int)),
572
SLOT(slotRowsChanged()));
573
connect(view, SIGNAL(rowsInsertedSignal(const QModelIndex&, int, int)),
574
SLOT(slotRowsChanged()));
576
connect(view, SIGNAL(rowsRemovedSignal(QModelIndex, int, int)),
577
SLOT(slotRowsChanged()));
578
connect(view, SIGNAL(rowsInsertedSignal(QModelIndex, int, int)),
579
SLOT(slotRowsChanged()));
576
581
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
577
d->mRatingPainter.setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
578
d->mRatingPainter.setLayoutDirection(view->layoutDirection());
579
d->mRatingPainter.setMaxRating(10);
582
d->mRatingPainter.setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
583
d->mRatingPainter.setLayoutDirection(view->layoutDirection());
584
d->mRatingPainter.setMaxRating(10);
582
connect(view, SIGNAL(thumbnailSizeChanged(int)),
583
SLOT(setThumbnailSize(int)) );
586
d->mContextBar = new QWidget(d->mView->viewport());
587
d->mContextBar->hide();
589
d->mToggleSelectionButton = new ContextBarButton("list-add");
590
connect(d->mToggleSelectionButton, SIGNAL(clicked()),
591
SLOT(slotToggleSelectionClicked()));
593
d->mFullScreenButton = new ContextBarButton("view-fullscreen");
594
connect(d->mFullScreenButton, SIGNAL(clicked()),
595
SLOT(slotFullScreenClicked()) );
597
d->mRotateLeftButton = new ContextBarButton("object-rotate-left");
598
connect(d->mRotateLeftButton, SIGNAL(clicked()),
599
SLOT(slotRotateLeftClicked()) );
601
d->mRotateRightButton = new ContextBarButton("object-rotate-right");
602
connect(d->mRotateRightButton, SIGNAL(clicked()),
603
SLOT(slotRotateRightClicked()) );
605
QHBoxLayout* layout = new QHBoxLayout(d->mContextBar);
606
layout->setMargin(2);
607
layout->setSpacing(2);
608
layout->addWidget(d->mToggleSelectionButton);
609
layout->addWidget(d->mFullScreenButton);
610
layout->addWidget(d->mRotateLeftButton);
611
layout->addWidget(d->mRotateRightButton);
614
d->mSaveButton = new ContextBarButton("document-save", d->mView->viewport());
615
d->mSaveButton->hide();
616
connect(d->mSaveButton, SIGNAL(clicked()),
617
SLOT(slotSaveClicked()) );
621
PreviewItemDelegate::~PreviewItemDelegate() {
626
QSize PreviewItemDelegate::sizeHint( const QStyleOptionViewItem & /*option*/, const QModelIndex & /*index*/ ) const {
627
return d->mView->gridSize();
631
bool PreviewItemDelegate::eventFilter(QObject* object, QEvent* event) {
632
if (object == d->mView->viewport()) {
633
switch (event->type()) {
634
case QEvent::ToolTip:
637
case QEvent::HoverMove:
638
case QEvent::HoverLeave:
639
return d->hoverEventFilter(static_cast<QHoverEvent*>(event));
641
case QEvent::MouseButtonPress:
642
case QEvent::MouseButtonRelease:
643
return d->mouseButtonEventFilter(event->type());
649
// Necessary for the item editor to work correctly (especially closing
650
// the editor with the Escape key)
651
return QItemDelegate::eventFilter(object, event);
656
void PreviewItemDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const {
657
int thumbnailSize = d->mThumbnailSize;
659
QPixmap thumbnailPix = d->mView->thumbnailForIndex(index, &fullSize);
660
const KFileItem fileItem = fileItemForIndex(index);
661
const bool opaque = !thumbnailPix.hasAlphaChannel();
662
const bool isDirOrArchive = ArchiveUtils::fileItemIsDirOrArchive(fileItem);
663
QRect rect = option.rect;
664
const bool selected = option.state & QStyle::State_Selected;
665
const bool underMouse = option.state & QStyle::State_MouseOver;
666
const QWidget* viewport = d->mView->viewport();
587
connect(view, SIGNAL(thumbnailSizeChanged(int)),
588
SLOT(setThumbnailSize(int)));
591
d->mContextBar = new QWidget(d->mView->viewport());
592
d->mContextBar->hide();
594
d->mToggleSelectionButton = new ContextBarButton("list-add");
595
connect(d->mToggleSelectionButton, SIGNAL(clicked()),
596
SLOT(slotToggleSelectionClicked()));
598
d->mFullScreenButton = new ContextBarButton("view-fullscreen");
599
connect(d->mFullScreenButton, SIGNAL(clicked()),
600
SLOT(slotFullScreenClicked()));
602
d->mRotateLeftButton = new ContextBarButton("object-rotate-left");
603
connect(d->mRotateLeftButton, SIGNAL(clicked()),
604
SLOT(slotRotateLeftClicked()));
606
d->mRotateRightButton = new ContextBarButton("object-rotate-right");
607
connect(d->mRotateRightButton, SIGNAL(clicked()),
608
SLOT(slotRotateRightClicked()));
610
QHBoxLayout* layout = new QHBoxLayout(d->mContextBar);
611
layout->setMargin(2);
612
layout->setSpacing(2);
613
layout->addWidget(d->mToggleSelectionButton);
614
layout->addWidget(d->mFullScreenButton);
615
layout->addWidget(d->mRotateLeftButton);
616
layout->addWidget(d->mRotateRightButton);
619
d->mSaveButton = new ContextBarButton("document-save", d->mView->viewport());
620
d->mSaveButton->hide();
621
connect(d->mSaveButton, SIGNAL(clicked()),
622
SLOT(slotSaveClicked()));
625
PreviewItemDelegate::~PreviewItemDelegate()
630
QSize PreviewItemDelegate::sizeHint(const QStyleOptionViewItem & /*option*/, const QModelIndex & /*index*/) const
632
return d->mView->gridSize();
635
bool PreviewItemDelegate::eventFilter(QObject* object, QEvent* event)
637
if (object == d->mView->viewport()) {
638
switch (event->type()) {
639
case QEvent::ToolTip:
642
case QEvent::HoverMove:
643
case QEvent::HoverLeave:
644
return d->hoverEventFilter(static_cast<QHoverEvent*>(event));
646
case QEvent::MouseButtonPress:
647
case QEvent::MouseButtonRelease:
648
return d->mouseButtonEventFilter(event->type());
654
// Necessary for the item editor to work correctly (especially closing
655
// the editor with the Escape key)
656
return QItemDelegate::eventFilter(object, event);
660
void PreviewItemDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
662
int thumbnailSize = d->mThumbnailSize;
664
QPixmap thumbnailPix = d->mView->thumbnailForIndex(index, &fullSize);
665
const KFileItem fileItem = fileItemForIndex(index);
666
const bool opaque = !thumbnailPix.hasAlphaChannel();
667
const bool isDirOrArchive = ArchiveUtils::fileItemIsDirOrArchive(fileItem);
668
QRect rect = option.rect;
669
const bool selected = option.state & QStyle::State_Selected;
670
const bool underMouse = option.state & QStyle::State_MouseOver;
671
const QWidget* viewport = d->mView->viewport();
668
673
#ifdef DEBUG_RECT
669
painter->setPen(Qt::red);
670
painter->setBrush(Qt::NoBrush);
671
painter->drawRect(rect);
674
painter->setPen(Qt::red);
675
painter->setBrush(Qt::NoBrush);
676
painter->drawRect(rect);
674
// Select color group
675
QPalette::ColorGroup cg;
677
if ( (option.state & QStyle::State_Enabled) && (option.state & QStyle::State_Active) ) {
678
cg = QPalette::Normal;
679
} else if ( (option.state & QStyle::State_Enabled)) {
680
cg = QPalette::Inactive;
682
cg = QPalette::Disabled;
686
QColor bgColor, borderColor, fgColor;
687
if (selected || underMouse) {
688
bgColor = option.palette.color(cg, QPalette::Highlight);
689
borderColor = bgColor.dark(SELECTION_BORDER_DARKNESS);
691
bgColor = viewport->palette().color(viewport->backgroundRole());
692
borderColor = bgColor.light(200);
694
fgColor = viewport->palette().color(viewport->foregroundRole());
696
// Compute thumbnailRect
697
QRect thumbnailRect = QRect(
698
rect.left() + (rect.width() - thumbnailPix.width())/2,
699
rect.top() + (thumbnailSize - thumbnailPix.height()) + ITEM_MARGIN,
700
thumbnailPix.width(),
701
thumbnailPix.height());
704
const QRect backgroundRect = thumbnailRect.adjusted(-ITEM_MARGIN, -ITEM_MARGIN, ITEM_MARGIN, ITEM_MARGIN);
706
d->drawBackground(painter, backgroundRect, bgColor, borderColor);
707
} else if (underMouse) {
708
painter->setOpacity(0.2);
709
d->drawBackground(painter, backgroundRect, bgColor, borderColor);
710
painter->setOpacity(1.);
712
d->drawShadow(painter, thumbnailRect);
717
painter->setPen(borderColor);
718
painter->setRenderHint(QPainter::Antialiasing, false);
719
QRect borderRect = thumbnailRect.adjusted(-1, -1, 0, 0);
720
painter->drawRect(borderRect);
722
painter->drawPixmap(thumbnailRect.left(), thumbnailRect.top(), thumbnailPix);
724
// Draw modified indicator
725
bool isModified = d->mView->isModified(index);
727
// Draws a pixmap of the save button frame, as an indicator that
728
// the image has been modified
729
QPoint framePosition = d->saveButtonPosition(rect);
730
d->initSaveButtonPixmap();
731
painter->drawPixmap(framePosition, d->mSaveButtonPixmap);
734
// Draw busy indicator
735
if (d->mView->isBusy(index)) {
736
QPixmap pix = d->mView->busySequenceCurrentPixmap();
738
thumbnailRect.left() + (thumbnailRect.width() - pix.width()) / 2,
739
thumbnailRect.top() + (thumbnailRect.height() - pix.height()) / 2,
743
if (index == d->mIndexUnderCursor) {
744
// Show bar again: if the thumbnail has changed, we may need to update
745
// its position. Don't do it if we are over rotate buttons, though: it
746
// would not be nice to move the button now, the user may want to
747
// rotate the image one more time.
748
// The button will get moved when the mouse leaves.
749
if (!d->mRotateLeftButton->underMouse() && !d->mRotateRightButton->underMouse()) {
750
d->showContextBar(rect, thumbnailPix);
753
// If we just rotated the image with the buttons from the
754
// button frame, we need to show the save button frame right now.
755
d->showSaveButton(rect);
757
d->mSaveButton->hide();
762
rect.left() + ITEM_MARGIN,
763
rect.top() + 2 * ITEM_MARGIN + thumbnailSize,
764
rect.width() - 2 * ITEM_MARGIN,
765
d->mView->fontMetrics().height());
766
if (isDirOrArchive || (d->mDetails & PreviewItemDelegate::FileNameDetail)) {
767
d->drawText(painter, textRect, fgColor, index.data().toString());
768
textRect.moveTop(textRect.bottom());
771
if (!isDirOrArchive && (d->mDetails & PreviewItemDelegate::DateDetail)) {
772
const KDateTime dt = TimeUtils::dateTimeForFileItem(fileItem);
773
d->drawText(painter, textRect, fgColor, KGlobal::locale()->formatDateTime(dt));
774
textRect.moveTop(textRect.bottom());
777
if (!isDirOrArchive && (d->mDetails & PreviewItemDelegate::ImageSizeDetail)) {
778
if (fullSize.isValid()) {
779
const QString text = QString("%1x%2").arg(fullSize.width()).arg(fullSize.height());
780
d->drawText(painter, textRect, fgColor, text);
781
textRect.moveTop(textRect.bottom());
785
if (!isDirOrArchive && (d->mDetails & PreviewItemDelegate::FileSizeDetail)) {
786
const KIO::filesize_t size = fileItem.size();
788
const QString st = KIO::convertSize(size);
789
d->drawText(painter, textRect, fgColor, st);
790
textRect.moveTop(textRect.bottom());
794
if (!isDirOrArchive && (d->mDetails & PreviewItemDelegate::RatingDetail)) {
679
// Select color group
680
QPalette::ColorGroup cg;
682
if ((option.state & QStyle::State_Enabled) && (option.state & QStyle::State_Active)) {
683
cg = QPalette::Normal;
684
} else if ((option.state & QStyle::State_Enabled)) {
685
cg = QPalette::Inactive;
687
cg = QPalette::Disabled;
691
QColor bgColor, borderColor, fgColor;
692
if (selected || underMouse) {
693
bgColor = option.palette.color(cg, QPalette::Highlight);
694
borderColor = bgColor.dark(SELECTION_BORDER_DARKNESS);
696
bgColor = viewport->palette().color(viewport->backgroundRole());
697
borderColor = bgColor.light(200);
699
fgColor = viewport->palette().color(viewport->foregroundRole());
701
// Compute thumbnailRect
702
QRect thumbnailRect = QRect(
703
rect.left() + (rect.width() - thumbnailPix.width()) / 2,
704
rect.top() + (thumbnailSize - thumbnailPix.height()) + ITEM_MARGIN,
705
thumbnailPix.width(),
706
thumbnailPix.height());
709
const QRect backgroundRect = thumbnailRect.adjusted(-ITEM_MARGIN, -ITEM_MARGIN, ITEM_MARGIN, ITEM_MARGIN);
711
d->drawBackground(painter, backgroundRect, bgColor, borderColor);
712
} else if (underMouse) {
713
painter->setOpacity(0.2);
714
d->drawBackground(painter, backgroundRect, bgColor, borderColor);
715
painter->setOpacity(1.);
717
d->drawShadow(painter, thumbnailRect);
722
painter->setPen(borderColor);
723
painter->setRenderHint(QPainter::Antialiasing, false);
724
QRect borderRect = thumbnailRect.adjusted(-1, -1, 0, 0);
725
painter->drawRect(borderRect);
727
painter->drawPixmap(thumbnailRect.left(), thumbnailRect.top(), thumbnailPix);
729
// Draw modified indicator
730
bool isModified = d->mView->isModified(index);
732
// Draws a pixmap of the save button frame, as an indicator that
733
// the image has been modified
734
QPoint framePosition = d->saveButtonPosition(rect);
735
d->initSaveButtonPixmap();
736
painter->drawPixmap(framePosition, d->mSaveButtonPixmap);
739
// Draw busy indicator
740
if (d->mView->isBusy(index)) {
741
QPixmap pix = d->mView->busySequenceCurrentPixmap();
743
thumbnailRect.left() + (thumbnailRect.width() - pix.width()) / 2,
744
thumbnailRect.top() + (thumbnailRect.height() - pix.height()) / 2,
748
if (index == d->mIndexUnderCursor) {
749
// Show bar again: if the thumbnail has changed, we may need to update
750
// its position. Don't do it if we are over rotate buttons, though: it
751
// would not be nice to move the button now, the user may want to
752
// rotate the image one more time.
753
// The button will get moved when the mouse leaves.
754
if (!d->mRotateLeftButton->underMouse() && !d->mRotateRightButton->underMouse()) {
755
d->showContextBar(rect, thumbnailPix);
758
// If we just rotated the image with the buttons from the
759
// button frame, we need to show the save button frame right now.
760
d->showSaveButton(rect);
762
d->mSaveButton->hide();
767
rect.left() + ITEM_MARGIN,
768
rect.top() + 2 * ITEM_MARGIN + thumbnailSize,
769
rect.width() - 2 * ITEM_MARGIN,
770
d->mView->fontMetrics().height());
771
if (isDirOrArchive || (d->mDetails & PreviewItemDelegate::FileNameDetail)) {
772
d->drawText(painter, textRect, fgColor, index.data().toString());
773
textRect.moveTop(textRect.bottom());
776
if (!isDirOrArchive && (d->mDetails & PreviewItemDelegate::DateDetail)) {
777
const KDateTime dt = TimeUtils::dateTimeForFileItem(fileItem);
778
d->drawText(painter, textRect, fgColor, KGlobal::locale()->formatDateTime(dt));
779
textRect.moveTop(textRect.bottom());
782
if (!isDirOrArchive && (d->mDetails & PreviewItemDelegate::ImageSizeDetail)) {
783
if (fullSize.isValid()) {
784
const QString text = QString("%1x%2").arg(fullSize.width()).arg(fullSize.height());
785
d->drawText(painter, textRect, fgColor, text);
786
textRect.moveTop(textRect.bottom());
790
if (!isDirOrArchive && (d->mDetails & PreviewItemDelegate::FileSizeDetail)) {
791
const KIO::filesize_t size = fileItem.size();
793
const QString st = KIO::convertSize(size);
794
d->drawText(painter, textRect, fgColor, st);
795
textRect.moveTop(textRect.bottom());
799
if (!isDirOrArchive && (d->mDetails & PreviewItemDelegate::RatingDetail)) {
795
800
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
796
d->drawRating(painter, rect, index.data(SemanticInfoDirModel::RatingRole));
801
d->drawRating(painter, rect, index.data(SemanticInfoDirModel::RatingRole));
802
void PreviewItemDelegate::setThumbnailSize(int value) {
803
d->mThumbnailSize = value;
804
d->updateViewGridSize();
805
d->updateContextBar();
806
d->mElidedTextCache.clear();
810
void PreviewItemDelegate::slotSaveClicked() {
811
saveDocumentRequested(urlForIndex(d->mIndexUnderCursor));
815
void PreviewItemDelegate::slotRotateLeftClicked() {
816
d->selectIndexUnderCursorIfNoMultiSelection();
817
rotateDocumentLeftRequested(urlForIndex(d->mIndexUnderCursor));
821
void PreviewItemDelegate::slotRotateRightClicked() {
822
d->selectIndexUnderCursorIfNoMultiSelection();
823
rotateDocumentRightRequested(urlForIndex(d->mIndexUnderCursor));
827
void PreviewItemDelegate::slotFullScreenClicked() {
828
showDocumentInFullScreenRequested(urlForIndex(d->mIndexUnderCursor));
832
void PreviewItemDelegate::slotToggleSelectionClicked() {
833
d->mView->selectionModel()->select(d->mIndexUnderCursor, QItemSelectionModel::Toggle);
834
d->updateToggleSelectionButton();
838
PreviewItemDelegate::ThumbnailDetails PreviewItemDelegate::thumbnailDetails() const {
843
void PreviewItemDelegate::setThumbnailDetails(PreviewItemDelegate::ThumbnailDetails details) {
844
d->mDetails = details;
845
d->updateViewGridSize();
846
d->mView->scheduleDelayedItemsLayout();
850
PreviewItemDelegate::ContextBarMode PreviewItemDelegate::contextBarMode() const {
851
return d->mContextBarMode;
855
void PreviewItemDelegate::setContextBarMode(PreviewItemDelegate::ContextBarMode mode) {
856
d->mContextBarMode = mode;
857
d->updateContextBar();
861
Qt::TextElideMode PreviewItemDelegate::textElideMode() const {
862
return d->mTextElideMode;
866
void PreviewItemDelegate::setTextElideMode(Qt::TextElideMode mode) {
867
if (d->mTextElideMode == mode) {
870
d->mTextElideMode = mode;
871
d->mElidedTextCache.clear();
872
d->mView->viewport()->update();
876
void PreviewItemDelegate::slotRowsChanged() {
877
// We need to update hover ui because the current index may have
878
// disappeared: for example if the current image is removed with "del".
879
QPoint pos = d->mView->viewport()->mapFromGlobal(QCursor::pos());
880
QModelIndex index = d->mView->indexAt(pos);
881
d->updateHoverUi(index);
885
QWidget * PreviewItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const {
886
return new ItemEditor(parent);
890
void PreviewItemDelegate::setEditorData(QWidget* widget, const QModelIndex& index) const {
891
ItemEditor* edit = qobject_cast<ItemEditor*>(widget);
895
edit->setText(index.data().toString());
899
void PreviewItemDelegate::updateEditorGeometry(QWidget* widget, const QStyleOptionViewItem& option, const QModelIndex& index) const {
900
ItemEditor* edit = qobject_cast<ItemEditor*>(widget);
904
QString text = index.data().toString();
905
int textWidth = edit->fontMetrics().width(" " + text + " ");
907
option.rect.left() + (option.rect.width() - textWidth) / 2,
908
option.rect.top() + 2 * ITEM_MARGIN + d->mThumbnailSize,
910
edit->sizeHint().height());
912
edit->setGeometry(textRect);
916
void PreviewItemDelegate::setModelData(QWidget* widget, QAbstractItemModel* model, const QModelIndex& index) const {
917
ItemEditor* edit = qobject_cast<ItemEditor*>(widget);
921
if (index.data().toString() != edit->text()) {
922
model->setData(index, edit->text(), Qt::EditRole);
806
void PreviewItemDelegate::setThumbnailSize(int value)
808
d->mThumbnailSize = value;
809
d->updateViewGridSize();
810
d->updateContextBar();
811
d->mElidedTextCache.clear();
814
void PreviewItemDelegate::slotSaveClicked()
816
saveDocumentRequested(urlForIndex(d->mIndexUnderCursor));
819
void PreviewItemDelegate::slotRotateLeftClicked()
821
d->selectIndexUnderCursorIfNoMultiSelection();
822
rotateDocumentLeftRequested(urlForIndex(d->mIndexUnderCursor));
825
void PreviewItemDelegate::slotRotateRightClicked()
827
d->selectIndexUnderCursorIfNoMultiSelection();
828
rotateDocumentRightRequested(urlForIndex(d->mIndexUnderCursor));
831
void PreviewItemDelegate::slotFullScreenClicked()
833
showDocumentInFullScreenRequested(urlForIndex(d->mIndexUnderCursor));
836
void PreviewItemDelegate::slotToggleSelectionClicked()
838
d->mView->selectionModel()->select(d->mIndexUnderCursor, QItemSelectionModel::Toggle);
839
d->updateToggleSelectionButton();
842
PreviewItemDelegate::ThumbnailDetails PreviewItemDelegate::thumbnailDetails() const
847
void PreviewItemDelegate::setThumbnailDetails(PreviewItemDelegate::ThumbnailDetails details)
849
d->mDetails = details;
850
d->updateViewGridSize();
851
d->mView->scheduleDelayedItemsLayout();
854
PreviewItemDelegate::ContextBarMode PreviewItemDelegate::contextBarMode() const
856
return d->mContextBarMode;
859
void PreviewItemDelegate::setContextBarMode(PreviewItemDelegate::ContextBarMode mode)
861
d->mContextBarMode = mode;
862
d->updateContextBar();
865
Qt::TextElideMode PreviewItemDelegate::textElideMode() const
867
return d->mTextElideMode;
870
void PreviewItemDelegate::setTextElideMode(Qt::TextElideMode mode)
872
if (d->mTextElideMode == mode) {
875
d->mTextElideMode = mode;
876
d->mElidedTextCache.clear();
877
d->mView->viewport()->update();
880
void PreviewItemDelegate::slotRowsChanged()
882
// We need to update hover ui because the current index may have
883
// disappeared: for example if the current image is removed with "del".
884
QPoint pos = d->mView->viewport()->mapFromGlobal(QCursor::pos());
885
QModelIndex index = d->mView->indexAt(pos);
886
d->updateHoverUi(index);
889
QWidget * PreviewItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const
891
return new ItemEditor(parent);
894
void PreviewItemDelegate::setEditorData(QWidget* widget, const QModelIndex& index) const
896
ItemEditor* edit = qobject_cast<ItemEditor*>(widget);
900
edit->setText(index.data().toString());
903
void PreviewItemDelegate::updateEditorGeometry(QWidget* widget, const QStyleOptionViewItem& option, const QModelIndex& index) const
905
ItemEditor* edit = qobject_cast<ItemEditor*>(widget);
909
QString text = index.data().toString();
910
int textWidth = edit->fontMetrics().width(" " + text + " ");
912
option.rect.left() + (option.rect.width() - textWidth) / 2,
913
option.rect.top() + 2 * ITEM_MARGIN + d->mThumbnailSize,
915
edit->sizeHint().height());
917
edit->setGeometry(textRect);
920
void PreviewItemDelegate::setModelData(QWidget* widget, QAbstractItemModel* model, const QModelIndex& index) const
922
ItemEditor* edit = qobject_cast<ItemEditor*>(widget);
926
if (index.data().toString() != edit->text()) {
927
model->setData(index, edit->text(), Qt::EditRole);