File indexing completed on 2025-03-09 03:50:50
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2009-12-13 0007 * Description : a tool to blend bracketed images. 0008 * 0009 * SPDX-FileCopyrightText: 2009-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2015 by Benjamin Girault <benjamin dot girault at gmail dot com> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "bracketstack.h" 0017 0018 // Qt includes 0019 0020 #include <QHeaderView> 0021 #include <QPainter> 0022 #include <QIcon> 0023 0024 // KDE includes 0025 0026 #include <klocalizedstring.h> 0027 0028 // Local includes 0029 0030 #include "digikam_debug.h" 0031 #include "thumbnailloadthread.h" 0032 0033 namespace DigikamGenericExpoBlendingPlugin 0034 { 0035 0036 BracketStackItem::BracketStackItem(QTreeWidget* const parent) 0037 : QTreeWidgetItem(parent) 0038 { 0039 setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); 0040 setCheckState(0, Qt::Unchecked); 0041 setThumbnail(QIcon::fromTheme(QLatin1String("view-preview")).pixmap(treeWidget()->iconSize().width(), QIcon::Disabled)); 0042 } 0043 0044 void BracketStackItem::setUrl(const QUrl& url) 0045 { 0046 m_url = url; 0047 setText(1, m_url.fileName()); 0048 } 0049 0050 const QUrl& BracketStackItem::url() const 0051 { 0052 return m_url; 0053 } 0054 0055 void BracketStackItem::setThumbnail(const QPixmap& pix) 0056 { 0057 int iconSize = qMax<int>(treeWidget()->iconSize().width(), treeWidget()->iconSize().height()); 0058 QPixmap pixmap(iconSize+2, iconSize+2); 0059 pixmap.fill(Qt::transparent); 0060 QPainter p(&pixmap); 0061 p.drawPixmap((pixmap.width()/2) - (pix.width()/2), (pixmap.height()/2) - (pix.height()/2), pix); 0062 setIcon(0, QIcon(pixmap)); 0063 } 0064 0065 void BracketStackItem::setExposure(const QString& exp) 0066 { 0067 setText(2, exp); 0068 } 0069 0070 bool BracketStackItem::isOn() const 0071 { 0072 return ((checkState(0) == Qt::Checked) ? true : false); 0073 } 0074 0075 void BracketStackItem::setOn(bool b) 0076 { 0077 setCheckState(0, b ? Qt::Checked : Qt::Unchecked); 0078 } 0079 0080 bool BracketStackItem::operator< (const QTreeWidgetItem& other) const 0081 { 0082 int column = treeWidget()->sortColumn(); 0083 double thisEv = text(column).toDouble(); 0084 double otherEv = other.text(column).toDouble(); 0085 0086 return (thisEv < otherEv); 0087 } 0088 0089 // ------------------------------------------------------------------------- 0090 0091 BracketStackList::BracketStackList(QWidget* const parent) 0092 : QTreeWidget(parent) 0093 { 0094 setIconSize(QSize(64, 64)); 0095 setSelectionMode(QAbstractItemView::SingleSelection); 0096 setSortingEnabled(true); 0097 setRootIsDecorated(false); 0098 setUniformRowHeights(true); 0099 setAllColumnsShowFocus(true); 0100 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 0101 setColumnCount(3); 0102 setHeaderHidden(false); 0103 setDragEnabled(false); 0104 header()->setSectionResizeMode(QHeaderView::Stretch); 0105 0106 QStringList labels; 0107 labels.append( i18nc("@title:column Processing checkbox", "Include for Enfuse") ); 0108 labels.append( i18nc("@title:column Input file name", "File Name") ); 0109 labels.append( i18nc("@title:column Input image exposure", "Exposure (EV)") ); 0110 setHeaderLabels(labels); 0111 0112 connect(ThumbnailLoadThread::defaultThread(), SIGNAL(signalThumbnailLoaded(LoadingDescription,QPixmap)), 0113 this, SLOT(slotThumbnail(LoadingDescription,QPixmap))); 0114 0115 connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)), 0116 this, SLOT(slotItemClicked(QTreeWidgetItem*,int))); 0117 0118 sortItems(2, Qt::DescendingOrder); 0119 } 0120 0121 QList<QUrl> BracketStackList::urls() 0122 { 0123 QList<QUrl> list; 0124 QTreeWidgetItemIterator it(this); 0125 0126 while (*it) 0127 { 0128 BracketStackItem* const item = dynamic_cast<BracketStackItem*>(*it); 0129 0130 if (item && item->isOn()) 0131 { 0132 list.append(item->url()); 0133 } 0134 0135 ++it; 0136 } 0137 0138 return list; 0139 } 0140 0141 BracketStackItem* BracketStackList::findItem(const QUrl& url) 0142 { 0143 QTreeWidgetItemIterator it(this); 0144 0145 while (*it) 0146 { 0147 BracketStackItem* const lvItem = dynamic_cast<BracketStackItem*>(*it); 0148 0149 if (lvItem && (lvItem->url() == url)) 0150 { 0151 return lvItem; 0152 } 0153 0154 ++it; 0155 } 0156 0157 return nullptr; 0158 } 0159 0160 void BracketStackList::addItems(const QList<QUrl>& list) 0161 { 0162 if (list.count() == 0) 0163 { 0164 return; 0165 } 0166 0167 QList<QUrl> urls; 0168 0169 for (const QUrl& imageUrl: list) 0170 { 0171 // Check if the new item already exist in the list. 0172 0173 bool found = false; 0174 0175 QTreeWidgetItemIterator iter(this); 0176 0177 while (*iter) 0178 { 0179 BracketStackItem* const item = dynamic_cast<BracketStackItem*>(*iter); 0180 0181 if (item->url() == imageUrl) 0182 { 0183 found = true; 0184 } 0185 0186 ++iter; 0187 } 0188 0189 if (!found) 0190 { 0191 BracketStackItem* const item = new BracketStackItem(this); 0192 item->setUrl(imageUrl); 0193 item->setOn(true); 0194 urls.append(imageUrl); 0195 } 0196 } 0197 0198 Q_FOREACH (const QUrl& url, urls) 0199 { 0200 ThumbnailLoadThread::defaultThread()->find(ThumbnailIdentifier(url.toLocalFile())); 0201 } 0202 0203 Q_EMIT signalAddItems(urls); 0204 } 0205 0206 void BracketStackList::slotThumbnail(const LoadingDescription& desc, const QPixmap& pix) 0207 { 0208 QTreeWidgetItemIterator it(this); 0209 0210 while (*it) 0211 { 0212 BracketStackItem* const item = static_cast<BracketStackItem*>(*it); 0213 0214 if (item->url() == QUrl::fromLocalFile(desc.filePath)) 0215 { 0216 if (pix.isNull()) 0217 { 0218 item->setThumbnail(QIcon::fromTheme(QLatin1String("view-preview")).pixmap(iconSize().width(), QIcon::Disabled)); 0219 } 0220 else 0221 { 0222 item->setThumbnail(pix.scaled(iconSize().width(), iconSize().height(), Qt::KeepAspectRatio)); 0223 } 0224 0225 return; 0226 } 0227 0228 ++it; 0229 } 0230 } 0231 0232 void BracketStackList::slotItemClicked(QTreeWidgetItem* item, int column) 0233 { 0234 BracketStackItem* const cItem = dynamic_cast<BracketStackItem*>(item); 0235 0236 if (cItem && (column == 1)) 0237 { 0238 Q_EMIT signalItemClicked(cItem->url()); 0239 } 0240 } 0241 0242 } // namespace DigikamGenericExpoBlendingPlugin 0243 0244 #include "moc_bracketstack.cpp"