MauiKit Image Tools

picinfomodel.cpp
1// Copyright 2018-2020 Camilo Higuita <milo.h@aol.com>
2// Copyright 2018-2020 Nitrux Latinoamericana S.C.
3//
4// SPDX-License-Identifier: GPL-3.0-or-later
5
6#include "picinfomodel.h"
7#include "exiv2extractor.h"
8
9#include <QDateTime>
10#include <QDebug>
11#include <QLocale>
12#include <QUrl>
13#include <QImage>
14
15PicInfoModel::PicInfoModel(QObject *parent) : MauiList(parent)
16 , m_extractor(new Exiv2Extractor(this))
17
18{
19}
20
21void PicInfoModel::componentComplete()
22{
23 connect(this, &PicInfoModel::urlChanged, [this](QUrl)
24 {
25 if (!FMH::fileExists(m_url) || m_url.isEmpty() || !m_url.isValid()) {
26 return;
27 }
28
29 QFileInfo file(m_url.toLocalFile());
30 m_fileName = file.fileName();
31 Q_EMIT fileNameChanged();
32 m_extractor->setUrl(m_url);
33 this->parse();
34 });
35
36 if (FMH::fileExists(m_url) && !m_url.isEmpty() && m_url.isValid()) {
37 m_extractor->setUrl(m_url);
38 this->parse();
39 }
40}
41
42void PicInfoModel::setUrl(QUrl url)
43{
44 if (m_url == url)
45 {
46 return;
47 }
48
49 m_url = url;
50 Q_EMIT urlChanged(m_url);
51}
52
53bool PicInfoModel::removeTag(const QString& tag)
54{
55 if(!m_extractor)
56 return false;
57
58 if(m_extractor->removeTag(tag.toStdString().c_str()))
59 {
60 if(m_extractor->applyChanges())
61 {
62 this->parse();
63 return true;
64 }
65 }
66
67 return false;
68}
69
70bool PicInfoModel::editTag(const QString& tag, const QString& value)
71{
72 qDebug() << "trying to write tag1";
73
74 if(m_extractor->writeTag(tag.toStdString().c_str(), QVariant::fromValue(value)))
75 {
76 qDebug() << "trying to write tag3";
77 if(m_extractor->applyChanges())
78 {
79 if(m_extractor->applyChanges())
80 {
81 this->parse();
82 return true;
83 }
84 }else
85 {
86 qWarning() << "failed to apply tag changes";
87 }
88 }else
89 {
90 qWarning() << "failed to write the metadata value tag" << tag << value;
91 }
92
93 return false;
94}
95
96bool PicInfoModel::setGpsData( const QString &latitude, const QString &longitude, const QString &altitude)
97{
98 bool ok = false;
99 if( m_extractor->setGpsData(latitude.toDouble(&ok), longitude.toDouble(&ok), altitude.toDouble(&ok)))
100 {
101 qDebug() << "gps data has been set" << ok;
102 if(m_extractor->applyChanges())
103 {
104 this->parse();
105 return true;
106 }else
107 {
108 qWarning() << "failed to apply tag changes";
109 }
110 }else
111 {
112 qWarning() << "failed to set gps data to image";
113 }
114 return false;
115
116}
117
118bool PicInfoModel::setComment(const QString &comment)
119{
120 if(m_extractor->setComment(comment))
121 {
122 if(m_extractor->applyChanges())
123 {
124 this->parse();
125 return true;
126 }
127 }
128
129 return false;
130}
131
132QString PicInfoModel::exifComment() const
133{
134 return m_exifComment;
135}
136
137bool PicInfoModel::removeComment()
138{
139 if(m_extractor->removeComment())
140 {
141 if(m_extractor->applyChanges())
142 {
143 this->parse();
144 return true;
145 }
146 }
147
148 return false;
149}
150
151double PicInfoModel::latitude() const
152{
153 return m_latitude;
154}
155
156double PicInfoModel::longitude() const
157{
158 return m_longitude;
159}
160
161double PicInfoModel::altitude() const
162{
163 return m_altitude;
164}
165
166QString PicInfoModel::cityName() const
167{
168 return m_cityName;
169}
170
171QSize PicInfoModel::pixelSize() const
172{
173 return m_size;
174}
175
176QUrl PicInfoModel::url() const
177{
178 return m_url;
179}
180
181static FMH::MODEL_LIST basicInfo(const QUrl &url)
182{
183 FMH::MODEL_LIST res;
184 QFileInfo file(url.toLocalFile());
185 QLocale locale;
186 res << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Name"}, {FMH::MODEL_KEY::VALUE, file.fileName()}, {FMH::MODEL_KEY::ICON, "edit-rename"}};
187 res << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Path"}, {FMH::MODEL_KEY::VALUE, url.toLocalFile()}, {FMH::MODEL_KEY::ICON, "folder"}};
188 res << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Size"}, {FMH::MODEL_KEY::VALUE, locale.formattedDataSize(file.size())}, {FMH::MODEL_KEY::ICON, "folder"}};
189 res << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Last Modified"}, {FMH::MODEL_KEY::VALUE, file.lastModified().toString()}, {FMH::MODEL_KEY::ICON, "view-media-recent"}};
190 res << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Date"}, {FMH::MODEL_KEY::VALUE, file.birthTime().toString()}, {FMH::MODEL_KEY::ICON, "view-calendar-birthday"}};
191
192
193 return res;
194}
195
196void PicInfoModel::parse()
197{
198 qDebug() << "Setting image medatata model info";
200 m_data.clear();
201 m_data << basicInfo(m_url);
202
203 if (!m_extractor->error())
204 {
205 auto gps = m_extractor->extractGPS();
206 m_latitude = gps.latitude;
207 m_longitude = gps.longitude;
208 m_altitude = gps.altitude;
209 m_exifComment = m_extractor->getExifComment();
210 m_cityName= m_extractor->GPSString ();
211 m_size = m_extractor->getPixelSize();
212 qDebug() << "Pixel size of image" << m_size;
213
214 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Max Aperture"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Photo.MaxApertureValue")}, {FMH::MODEL_KEY::ICON, "documentinfo"}, {FMH::MODEL_KEY::KEY, "Exif.Photo.MaxApertureValue"}};
215
216 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Aperture"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Image.ApertureValue")}, {FMH::MODEL_KEY::ICON, "documentinfo"}, {FMH::MODEL_KEY::KEY, "Exif.Image.ApertureValue"}};
217
218 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "BrightnessValue"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Image.BrightnessValue")}, {FMH::MODEL_KEY::ICON, "documentinfo"}, {FMH::MODEL_KEY::KEY, "Exif.Image.BrightnessValue"}};
219
220 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Camera"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Image.Make")}, {FMH::MODEL_KEY::ICON, "camera-video"}, {FMH::MODEL_KEY::KEY, "Exif.Image.Make"}};
221
222 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Camera Model"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Image.Model")}, {FMH::MODEL_KEY::ICON, "documentinfo"}, {FMH::MODEL_KEY::KEY, "Exif.Image.Model"}};
223
224 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Focal Length"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Photo.FocalLength")}, {FMH::MODEL_KEY::ICON, "documentinfo"}, {FMH::MODEL_KEY::KEY, "Exif.Photo.FocalLength"}};
225
226 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Exposure Time"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Photo.ExposureTime")}, {FMH::MODEL_KEY::ICON, "documentinfo"}, {FMH::MODEL_KEY::KEY, "Exif.Photo.ExposureTime"}};
227
228 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Exposure Mode"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Photo.ExposureMode")}, {FMH::MODEL_KEY::ICON, "documentinfo"}, {FMH::MODEL_KEY::KEY, "Exif.Photo.ExposureMode"}};
229
230 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Flash"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Photo.Flash")}, {FMH::MODEL_KEY::ICON, "documentinfo"}, {FMH::MODEL_KEY::KEY, "Exif.Photo.Flash"}};
231
232 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "ISO Speed"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Photo.ISOSpeedRatings")}, {FMH::MODEL_KEY::ICON, "documentinfo"}, {FMH::MODEL_KEY::KEY, "Exif.Photo.ISOSpeedRatings"}};
233
234 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Shutter Speed"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Photo.ShutterSpeedValue")}, {FMH::MODEL_KEY::ICON, "documentinfo"}, {FMH::MODEL_KEY::KEY, "Exif.Photo.ShutterSpeedValue"}};
235
236 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Compression"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Thumbnail.Compression")}, {FMH::MODEL_KEY::ICON, "documentinfo"}, {FMH::MODEL_KEY::KEY, "Exif.Thumbnail.Compression"}};
237
238 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Color Space"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Photo.ColorSpace")}, {FMH::MODEL_KEY::ICON, "documentinfo"}, {FMH::MODEL_KEY::KEY, "Exif.Photo.ColorSpace"}};
239
240 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "White Balance"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Photo.WhiteBalance")}, {FMH::MODEL_KEY::ICON, "documentinfo"}, {FMH::MODEL_KEY::KEY, "Exif.Photo.WhiteBalance"}};
241
242 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Author"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Image.Artist")}, {FMH::MODEL_KEY::ICON, "user"}, {FMH::MODEL_KEY::KEY, "Exif.Image.Artist"}};
243
244 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Processing Software"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Image.ProcessingSoftware")}, {FMH::MODEL_KEY::KEY, "Exif.Image.ProcessingSoftware"}};
245
246 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "DocumentName"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Image.DocumentName")}, {FMH::MODEL_KEY::KEY, "Exif.Image.DocumentName"}};
247
248 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Software"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Image.Software")}, {FMH::MODEL_KEY::KEY, "Exif.Image.Software"}};
249
250 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "HostComputer"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Image.HostComputer")}, {FMH::MODEL_KEY::KEY, "Exif.Image.HostComputer"}};
251
252 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Rating"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Image.Rating")}, {FMH::MODEL_KEY::KEY, "Exif.Image.Rating"}};
253
254 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "Copyright"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Image.Copyright")}, {FMH::MODEL_KEY::KEY, "Exif.Image.Copyright"}};
255
256 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "SelfTimerMode"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Image.SelfTimerMode")}, {FMH::MODEL_KEY::KEY, "Exif.Image.SelfTimerMode"}};
257
258 m_data << FMH::MODEL{{FMH::MODEL_KEY::NAME, "ImageHistory"}, {FMH::MODEL_KEY::VALUE, m_extractor->getExifTagString("Exif.Image.ImageHistory")}, {FMH::MODEL_KEY::KEY, "Exif.Image.ImageHistory"}};
259
260
261 }else
262 {
263 qDebug() << "error extracting image metadata";
264 }
265
267 Q_EMIT dataReady();
268}
269
270bool PicInfoModel::removeGpsData()
271{
272 if(m_extractor->removeGpsData())
273 {
274 if(m_extractor->applyChanges())
275 {
276 this->parse();
277 return true;
278 }
279 }
280
281 return false;
282}
283
284const FMH::MODEL_LIST &PicInfoModel::items() const
285{
286 return m_data;
287}
288
289
Image metadata extractor.
void preListChanged()
void postListChanged()
QVector< MODEL > MODEL_LIST
bool fileExists(const QUrl &path)
QHash< MODEL_KEY, QString > MODEL
QString formattedDataSize(qint64 bytes, int precision, DataSizeFormats format) const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
std::string toStdString() const const
QString toLocalFile() const const
QVariant fromValue(T &&value)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Apr 11 2025 11:57:09 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.