File indexing completed on 2025-01-19 03:50:49
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2013-02-25 0007 * Description : Table view column helpers: Thumbnail column 0008 * 0009 * SPDX-FileCopyrightText: 2017-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2013 by Michael G. Hansen <mike at mghansen dot de> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "tableview_column_thumbnail.h" 0017 0018 // Qt includes 0019 0020 #include <QPainter> 0021 #include <QStyleOptionViewItem> 0022 0023 // KDE includes 0024 0025 #include <klocalizedstring.h> 0026 0027 // Local includes 0028 0029 #include "itemfiltermodel.h" 0030 #include "tableview.h" 0031 #include "thumbnailloadthread.h" 0032 #include "thumbnailsize.h" 0033 #include "metaengine.h" 0034 0035 namespace 0036 { 0037 const int ThumbnailBorder = 2; 0038 } 0039 0040 namespace Digikam 0041 { 0042 0043 namespace TableViewColumns 0044 { 0045 0046 ColumnThumbnail::ColumnThumbnail(TableViewShared* const tableViewShared, 0047 const TableViewColumnConfiguration& pConfiguration, 0048 QWidget* const parent) 0049 : TableViewColumn(tableViewShared, pConfiguration, parent), 0050 m_thumbnailSize(s->tableView->getThumbnailSize().size()), 0051 m_displayWidget(parent) 0052 { 0053 connect(s->thumbnailLoadThread, SIGNAL(signalThumbnailLoaded(LoadingDescription,QPixmap)), 0054 this, SLOT(slotThumbnailLoaded(LoadingDescription,QPixmap))); 0055 } 0056 0057 ColumnThumbnail::~ColumnThumbnail() 0058 { 0059 } 0060 0061 bool ColumnThumbnail::CreateFromConfiguration(TableViewShared* const tableViewShared, 0062 const TableViewColumnConfiguration& pConfiguration, 0063 TableViewColumn** const pNewColumn, 0064 QWidget* const parent) 0065 { 0066 if (pConfiguration.columnId != QLatin1String("thumbnail")) 0067 { 0068 return false; 0069 } 0070 0071 *pNewColumn = new ColumnThumbnail(tableViewShared, pConfiguration, parent); 0072 0073 return true; 0074 } 0075 0076 TableViewColumnDescription ColumnThumbnail::getDescription() 0077 { 0078 return TableViewColumnDescription(QLatin1String("thumbnail"), i18n("Thumbnail")); 0079 } 0080 0081 TableViewColumn::ColumnFlags ColumnThumbnail::getColumnFlags() const 0082 { 0083 return ColumnCustomPainting; 0084 } 0085 0086 QString ColumnThumbnail::getTitle() const 0087 { 0088 return i18n("Thumbnail"); 0089 } 0090 0091 QVariant ColumnThumbnail::data(TableViewModel::Item* const item, const int role) const 0092 { 0093 Q_UNUSED(item) 0094 Q_UNUSED(role) 0095 0096 // we do not return any data, but paint(...) something 0097 0098 return QVariant(); 0099 } 0100 0101 bool ColumnThumbnail::paint(QPainter* const painter, const QStyleOptionViewItem& option, TableViewModel::Item* const item) const 0102 { 0103 if (option.state & QStyle::State_Selected) 0104 { 0105 painter->fillRect(option.rect, option.palette.highlight()); 0106 } 0107 0108 const ItemInfo info = s->tableViewModel->infoFromItem(item); 0109 0110 if (!info.isNull()) 0111 { 0112 QSize availableSize = option.rect.size() - QSize(ThumbnailBorder, ThumbnailBorder); 0113 QSize imageSize = info.dimensions(); 0114 int maxSize = m_thumbnailSize; 0115 0116 // When the image is rotated, swap width and height. 0117 0118 if (info.orientation() > MetaEngine::ORIENTATION_VFLIP) 0119 { 0120 imageSize.transpose(); 0121 } 0122 0123 if (imageSize.isValid() && (imageSize.width() > imageSize.height())) 0124 { 0125 // for landscape pictures, try to use all available horizontal space 0126 0127 qreal scaleFactor = qreal(availableSize.height()) / qreal(imageSize.height()); 0128 maxSize = imageSize.width() * scaleFactor; 0129 } 0130 0131 // Calculate the maximum thumbnail size 0132 // The idea here is that for landscape images, we adjust the height to 0133 // to be as high as the row height as long as the width can stretch enough 0134 // because the column is wider than the thumbnail size. 0135 0136 maxSize = qMin(maxSize, availableSize.width()); 0137 0138 // However, digiKam limits the thumbnail size, so we also do that here 0139 0140 maxSize = qMin(maxSize, (int)ThumbnailSize::maxThumbsSize()); 0141 double dpr = m_displayWidget->devicePixelRatio(); 0142 maxSize = qRound((double)maxSize * dpr); 0143 0144 QPixmap thumbnail; 0145 0146 if (s->thumbnailLoadThread->find(info.thumbnailIdentifier(), thumbnail, maxSize)) 0147 { 0148 thumbnail.setDevicePixelRatio(dpr); 0149 0150 /// @todo Is slotThumbnailLoaded still called when the thumbnail is found right away? 0151 0152 QSize pixmapSize = (QSizeF(thumbnail.size()) / dpr).toSize(); 0153 pixmapSize = pixmapSize.boundedTo(availableSize); 0154 QSize alignSize = option.rect.size(); 0155 0156 QPoint startPoint((alignSize.width() - pixmapSize.width()) / 2, 0157 (alignSize.height() - pixmapSize.height()) / 2); 0158 startPoint += option.rect.topLeft(); 0159 0160 painter->drawPixmap(QRect(startPoint, pixmapSize), thumbnail, 0161 QRect(QPoint(0, 0), thumbnail.size())); 0162 0163 return true; 0164 } 0165 } 0166 0167 // we did not get to paint a thumbnail... 0168 0169 return false; 0170 } 0171 0172 QSize ColumnThumbnail::sizeHint(const QStyleOptionViewItem& option, TableViewModel::Item* const item) const 0173 { 0174 Q_UNUSED(option) 0175 Q_UNUSED(item) 0176 0177 /// @todo On portrait pictures, the borders are too close. There should be a gap. Is this setting okay? 0178 0179 const int thumbnailSizeWithBorder = m_thumbnailSize+ThumbnailBorder; 0180 0181 return QSize(thumbnailSizeWithBorder, thumbnailSizeWithBorder); 0182 } 0183 0184 void ColumnThumbnail::slotThumbnailLoaded(const LoadingDescription& loadingDescription, const QPixmap& thumb) 0185 { 0186 if (thumb.isNull()) 0187 { 0188 return; 0189 } 0190 0191 /// @todo Find a way to do this without the ItemFilterModel 0192 0193 const QModelIndex imageModelIndex = s->imageModel->indexForPath(loadingDescription.filePath); 0194 0195 if (!imageModelIndex.isValid()) 0196 { 0197 return; 0198 } 0199 0200 const qlonglong imageId = s->imageModel->imageId(imageModelIndex); 0201 0202 Q_EMIT signalDataChanged(imageId); 0203 } 0204 0205 void ColumnThumbnail::updateThumbnailSize() 0206 { 0207 /// @todo Set minimum column width to m_thumbnailSize 0208 0209 m_thumbnailSize = s->tableView->getThumbnailSize().size(); 0210 0211 Q_EMIT signalAllDataChanged(); 0212 } 0213 0214 } // namespace TableViewColumns 0215 0216 } // namespace Digikam 0217 0218 #include "moc_tableview_column_thumbnail.cpp"