File indexing completed on 2025-01-19 03:57:01
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2021-07-24 0007 * Description : frame on screen display. 0008 * 0009 * SPDX-FileCopyrightText: 2021-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2021 by Quoc Hưng Tran <quochungtran1999 at gmail dot com> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "frameosd.h" 0017 0018 // Qt includes 0019 0020 #include <QString> 0021 #include <QBuffer> 0022 #include <QApplication> 0023 #include <QFontMetrics> 0024 #include <QPainter> 0025 0026 // KDE includes 0027 0028 #include <klocalizedstring.h> 0029 0030 // Local includes 0031 0032 #include "digikam_debug.h" 0033 #include "itempropertiestab.h" 0034 0035 namespace Digikam 0036 { 0037 0038 FrameOsd::FrameOsd() 0039 : m_desc (QLatin1String("")), 0040 m_descPos (QPoint(10, 10)), 0041 m_descFnt (QFont(QLatin1String("Monospace"))), 0042 m_descAlign(Qt::AlignLeft), 0043 m_descBg (Qt::darkGray) 0044 { 0045 m_descFnt.setStyleHint(QFont::Monospace); 0046 m_descFnt.setPixelSize(8); 0047 m_descFnt.setBold(true); 0048 } 0049 0050 FrameOsd::~FrameOsd() 0051 { 0052 } 0053 0054 void FrameOsd::populateOSD(const QUrl& url, 0055 const FrameOsdSettings& settings, 0056 DInfoInterface* const iface) 0057 { 0058 // First stage is to get the information map from host application. 0059 0060 DItemInfo item(iface->itemInfo(url)); 0061 0062 QString comment = item.comment(); 0063 QString title = item.title(); 0064 QStringList tags = item.keywords(); 0065 int rating = item.rating(); 0066 m_descFnt = settings.osdFont; 0067 0068 QString str; 0069 0070 // Display image File Name. 0071 0072 if (settings.printName) 0073 { 0074 str.clear(); 0075 QString name = url.fileName(); 0076 0077 if (!name.isEmpty()) 0078 { 0079 str += name; 0080 m_desc.append(QString::fromLatin1("\n%1").arg(str)); 0081 } 0082 } 0083 0084 // Display Creation Date. 0085 0086 if (settings.printDate) 0087 { 0088 str.clear(); 0089 QDateTime dateTime = item.dateTime(); 0090 0091 if (dateTime.isValid()) 0092 { 0093 str = QLocale().toString(dateTime, QLocale::ShortFormat); 0094 m_desc.append(QString::fromLatin1("\n%1").arg(str)); 0095 } 0096 } 0097 0098 // Display tag names. 0099 0100 if (settings.printTags) 0101 { 0102 printTags(tags); 0103 } 0104 0105 // Display descs. 0106 0107 if (settings.printTitle) 0108 { 0109 str.clear(); 0110 0111 if (!title.isEmpty()) 0112 { 0113 str += title; 0114 m_desc.append(QString::fromLatin1("\n%1").arg(str)); 0115 } 0116 } 0117 0118 // Display Captions if no Titles. 0119 0120 if (settings.printCapIfNoTitle) 0121 { 0122 str.clear(); 0123 0124 if (title.isEmpty()) 0125 { 0126 str += comment; 0127 printComments(str); 0128 } 0129 } 0130 0131 // Display Comments. 0132 0133 if (settings.printComment) 0134 { 0135 str.clear(); 0136 0137 if (title.isEmpty()) 0138 { 0139 str += comment; 0140 printComments(str); 0141 } 0142 } 0143 0144 // Display Make and Model. 0145 0146 if (settings.printMakeModel) 0147 { 0148 str.clear(); 0149 0150 QString make = item.make(); 0151 QString model = item.model(); 0152 0153 if (!make.isEmpty()) 0154 { 0155 ItemPropertiesTab::shortenedMakeInfo(make); 0156 str = make; 0157 } 0158 0159 if (!model.isEmpty()) 0160 { 0161 if (!make.isEmpty()) 0162 { 0163 str += QLatin1String(" / "); 0164 } 0165 0166 ItemPropertiesTab::shortenedModelInfo(model); 0167 str += model; 0168 } 0169 0170 if (!str.isEmpty()) 0171 { 0172 m_desc.append(QString::fromLatin1("\n%1").arg(str)); 0173 } 0174 } 0175 0176 // Display Lens model. 0177 0178 if (settings.printLensModel) 0179 { 0180 str.clear(); 0181 0182 QString lens = item.lens(); 0183 0184 if (!lens.isEmpty()) 0185 { 0186 str += lens; 0187 m_desc.append(QString::fromLatin1("\n%1").arg(str)); 0188 } 0189 } 0190 0191 // Display Exposure and Sensitivity. 0192 0193 if (settings.printExpoSensitivity) 0194 { 0195 str.clear(); 0196 0197 QString exposureTime = item.exposureTime(); 0198 QString sensitivity = item.sensitivity(); 0199 0200 if (!exposureTime.isEmpty()) 0201 { 0202 str = exposureTime; 0203 } 0204 0205 if (!sensitivity.isEmpty()) 0206 { 0207 if (!exposureTime.isEmpty()) 0208 { 0209 str += QLatin1String(" / "); 0210 } 0211 0212 str += i18n("%1 ISO", sensitivity); 0213 } 0214 0215 if (!str.isEmpty()) 0216 { 0217 m_desc.append(QString::fromLatin1("\n%1").arg(str)); 0218 } 0219 } 0220 0221 // Display Aperture and Focal. 0222 0223 if (settings.printApertureFocal) 0224 { 0225 str.clear(); 0226 0227 QString aperture = item.aperture(); 0228 QString focalLength = item.focalLength(); 0229 QString focalLength35mm = item.focalLength35mm(); 0230 0231 if (!aperture.isEmpty()) 0232 { 0233 str = aperture; 0234 } 0235 0236 if (focalLength35mm.isEmpty()) 0237 { 0238 if (!focalLength.isEmpty()) 0239 { 0240 if (!aperture.isEmpty()) 0241 { 0242 str += QLatin1String(" / "); 0243 } 0244 0245 str += focalLength; 0246 } 0247 } 0248 else 0249 { 0250 if (!aperture.isEmpty()) 0251 { 0252 str += QLatin1String(" / "); 0253 } 0254 0255 if (!focalLength.isEmpty()) 0256 { 0257 str += QString::fromUtf8("%1 (%2)").arg(focalLength).arg(focalLength35mm); 0258 } 0259 else 0260 { 0261 str += QString::fromUtf8("%1").arg(focalLength35mm); 0262 } 0263 } 0264 0265 if (!str.isEmpty()) 0266 { 0267 m_desc.append(QString::fromLatin1("\n%1").arg(str)); 0268 } 0269 } 0270 0271 0272 // Display rating 0273 0274 if (settings.printRating) 0275 { 0276 if (rating != -1) 0277 { 0278 m_desc.append(QString::fromLatin1("\n%1/5").arg(rating)); 0279 } 0280 } 0281 0282 m_desc.append(QString::fromLatin1("\n")); 0283 } 0284 0285 void FrameOsd::printTags(QStringList& tags) 0286 { 0287 tags.removeDuplicates(); 0288 tags.sort(); 0289 0290 QString str = tags.join(QLatin1String(", ")); 0291 0292 if (!str.isEmpty()) 0293 { 0294 m_desc.append(QString::fromLatin1("%1").arg(str)); 0295 } 0296 } 0297 0298 void FrameOsd::printComments(const QString& comments) 0299 { 0300 QStringList commentsByLines; 0301 0302 uint commentsIndex = 0; // Comments QString index 0303 0304 while (commentsIndex < (uint)comments.length()) 0305 { 0306 QString newLine; 0307 bool breakLine = false; // End Of Line found 0308 uint currIndex; // Comments QString current index 0309 0310 // Check minimal lines dimension 0311 0312 uint maxStringLen = 80; 0313 0314 uint commentsLinesLengthLocal = maxStringLen; 0315 0316 for (currIndex = commentsIndex ; 0317 (currIndex < (uint)comments.length()) && !breakLine ; ++currIndex) 0318 { 0319 if ((comments.at(currIndex) == QLatin1Char('\n')) || comments.at(currIndex).isSpace()) 0320 { 0321 breakLine = true; 0322 } 0323 } 0324 0325 if (commentsLinesLengthLocal <= (currIndex - commentsIndex)) 0326 { 0327 commentsLinesLengthLocal = (currIndex - commentsIndex); 0328 } 0329 0330 breakLine = false; 0331 0332 for (currIndex = commentsIndex ; 0333 (currIndex <= (commentsIndex + commentsLinesLengthLocal)) && 0334 (currIndex < (uint)comments.length()) && !breakLine ; 0335 ++currIndex) 0336 { 0337 breakLine = (comments.at(currIndex) == QLatin1Char('\n')) ? true : false; 0338 0339 if (breakLine) 0340 { 0341 newLine.append(QLatin1Char(' ')); 0342 } 0343 else 0344 { 0345 newLine.append(comments.at(currIndex)); 0346 } 0347 } 0348 0349 commentsIndex = currIndex; // The line is ended 0350 0351 if (commentsIndex != (uint)comments.length()) 0352 { 0353 while (!newLine.endsWith(QLatin1Char(' '))) 0354 { 0355 newLine.truncate(newLine.length() - 1); 0356 --commentsIndex; 0357 } 0358 } 0359 0360 commentsByLines.prepend(newLine.trimmed()); 0361 } 0362 0363 for (int i = 0 ; i < (int)commentsByLines.count() ; ++i) 0364 { 0365 m_desc.append(QString::fromLatin1("\n%1").arg(commentsByLines.at(i))); 0366 } 0367 } 0368 0369 void FrameOsd::insertOsdToFrame(QImage& frm, 0370 const QUrl& url, 0371 const FrameOsdSettings& settings, 0372 DInfoInterface* const iface) 0373 { 0374 // Populate items properties based on url, 0375 // eg. album name, rating, tags, labels, date, etc. 0376 0377 populateOSD(url, settings, iface); 0378 0379 QPainter p(&frm); 0380 0381 QFontMetrics descMt(m_descFnt); 0382 p.setFont(m_descFnt); 0383 0384 QRect descRect = descMt.boundingRect(0, 0, frm.width(), frm.height(), 0, m_desc); 0385 QRect bgdescRect(m_descPos.x(), 0386 m_descPos.y(), 0387 descRect.width(), 0388 descRect.height() + 3); 0389 0390 p.fillRect(bgdescRect, m_descBg); 0391 0392 p.setPen(QPen(Qt::white)); 0393 p.drawText(bgdescRect, m_descAlign, m_desc); 0394 0395 m_desc.clear(); 0396 } 0397 0398 void FrameOsd::insertMessageOsdToFrame(QImage& frm, 0399 const QSize& JPEGsize, 0400 const QString& mess) 0401 { 0402 QPoint messPos = QPoint(10, 10); 0403 Qt::Alignment messAlign = Qt::AlignLeft; 0404 QColor messBg = Qt::darkGray; 0405 QFont messFnt = QFont(QLatin1String("Monospace")); 0406 0407 messFnt.setStyleHint(QFont::Monospace); 0408 messFnt.setBold(true); 0409 0410 if ((JPEGsize.width() <= 480) && (JPEGsize.height() <= 480)) 0411 { 0412 messFnt.setPixelSize(18); 0413 } 0414 else 0415 { 0416 messFnt.setPixelSize(60); 0417 } 0418 0419 //--- 0420 0421 QPainter p(&frm); 0422 p.setFont(messFnt); 0423 0424 QFontMetrics messMt(messFnt); 0425 0426 QRect messRect = messMt.boundingRect(0, 0, frm.width(), frm.height(), 0, mess); 0427 0428 // print message in the middle of frame 0429 0430 QRect bgErreurRect(messPos.x(), 0431 messPos.y(), 0432 messRect.width(), 0433 messRect.height() + 3); 0434 0435 p.fillRect(bgErreurRect, messBg); 0436 0437 p.setPen(QPen(Qt::white)); 0438 p.drawText(bgErreurRect, messAlign, mess); 0439 } 0440 0441 } // namespace Digikam