1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2010-09-27
7  * Description : Interface for info stored about a face tag in the database
8  *
9  * Copyright (C) 2010      by Aditya Bhatt <adityabhatt1991 at gmail dot com>
10  * Copyright (C) 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
11  *
12  * This program is free software; you can redistribute it
13  * and/or modify it under the terms of the GNU General
14  * Public License as published by the Free Software Foundation;
15  * either version 2, or (at your option)
16  * any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * ============================================================ */
24 
25 #include "facetagsiface.h"
26 
27 // Qt includes
28 
29 #include <QStringList>
30 
31 // Local includes
32 
33 #include "digikam_debug.h"
34 #include "coredbconstants.h"
35 #include "tagscache.h"
36 #include "facetags.h"
37 
38 namespace Digikam
39 {
40 
FaceTagsIface()41 FaceTagsIface::FaceTagsIface()
42     : m_type(InvalidFace),
43       m_imageId(0),
44       m_tagId(0)
45 {
46 }
47 
FaceTagsIface(Type type,qlonglong imageId,int tagId,const TagRegion & region)48 FaceTagsIface::FaceTagsIface(Type type, qlonglong imageId, int tagId, const TagRegion& region)
49     : m_type(type),
50       m_imageId(imageId),
51       m_tagId(tagId),
52       m_region(region)
53 {
54 }
55 
FaceTagsIface(const QString & attribute,qlonglong imageId,int tagId,const TagRegion & region)56 FaceTagsIface::FaceTagsIface(const QString& attribute, qlonglong imageId, int tagId, const TagRegion& region)
57     : m_imageId(imageId),
58       m_tagId(tagId),
59       m_region(region)
60 {
61     m_type = typeForAttribute(attribute, tagId);
62 }
63 
isNull() const64 bool FaceTagsIface::isNull() const
65 {
66     return (m_type == InvalidFace);
67 }
68 
type() const69 FaceTagsIface::Type FaceTagsIface::type() const
70 {
71     return m_type;
72 }
73 
imageId() const74 qlonglong FaceTagsIface::imageId() const
75 {
76     return m_imageId;
77 }
78 
tagId() const79 int FaceTagsIface::tagId() const
80 {
81     return m_tagId;
82 }
83 
region() const84 TagRegion FaceTagsIface::region() const
85 {
86     return m_region;
87 }
88 
setType(Type type)89 void FaceTagsIface::setType(Type type)
90 {
91     m_type = type;
92 }
93 
setTagId(int tagId)94 void FaceTagsIface::setTagId(int tagId)
95 {
96     m_tagId = tagId;
97 }
98 
setRegion(const TagRegion & region)99 void FaceTagsIface::setRegion(const TagRegion& region)
100 {
101     m_region = region;
102 }
103 
operator ==(const FaceTagsIface & other) const104 bool FaceTagsIface::operator==(const FaceTagsIface& other) const
105 {
106     return (
107             (m_tagId   == other.m_tagId)   &&
108             (m_imageId == other.m_imageId) &&
109             (m_type    == other.m_type)    &&
110             (m_region  == other.m_region)
111            );
112 }
113 
attributesForFlags(TypeFlags flags)114 QStringList FaceTagsIface::attributesForFlags(TypeFlags flags)
115 {
116     QStringList attributes;
117 
118     for (int i = FaceTagsIface::TypeFirst ; i <= FaceTagsIface::TypeLast ; i <<= 1)
119     {
120         if (flags & FaceTagsIface::Type(i))
121         {
122             QString attribute = attributeForType(FaceTagsIface::Type(i));
123 
124             if (!attributes.contains(attribute))
125             {
126                 attributes << attribute;
127             }
128         }
129     }
130 
131     return attributes;
132 }
133 
attributeForType(Type type)134 QString FaceTagsIface::attributeForType(Type type)
135 {
136     if ((type == FaceTagsIface::UnknownName) || (type == FaceTagsIface::UnconfirmedName))
137     {
138         return ImageTagPropertyName::autodetectedFace();
139     }
140 
141     if (type == FaceTagsIface::ConfirmedName)
142     {
143         return ImageTagPropertyName::tagRegion();
144     }
145 
146     if (type == FaceTagsIface::IgnoredName)
147     {
148         return ImageTagPropertyName::ignoredFace();
149     }
150 
151     if (type == FaceTagsIface::FaceForTraining)
152     {
153         return ImageTagPropertyName::faceToTrain();
154     }
155 
156     return QString();
157 }
158 
typeForId(int tagId)159 FaceTagsIface::Type FaceTagsIface::typeForId(int tagId)
160 {
161         if (!FaceTags::isPerson(tagId))
162         {
163             return InvalidFace;
164         }
165 
166         if      (FaceTags::isTheUnknownPerson(tagId))
167         {
168             return UnknownName;
169         }
170         else if (FaceTags::isTheUnconfirmedPerson(tagId))
171         {
172             return UnconfirmedName;
173         }
174         else if (FaceTags::isTheIgnoredPerson(tagId))
175         {
176             return IgnoredName;
177         }
178 
179         return ConfirmedName;
180 }
181 
typeForAttribute(const QString & attribute,int tagId)182 FaceTagsIface::Type FaceTagsIface::typeForAttribute(const QString& attribute, int tagId)
183 {
184     if      (attribute == ImageTagPropertyName::autodetectedFace())
185     {
186         if (tagId && TagsCache::instance()->hasProperty(tagId, TagPropertyName::unknownPerson()))
187         {
188             return FaceTagsIface::UnknownName;
189         }
190         else
191         {
192             return FaceTagsIface::UnconfirmedName;
193         }
194     }
195     else if (attribute == ImageTagPropertyName::ignoredFace())
196     {
197         return FaceTagsIface::IgnoredName;
198     }
199     else if (attribute == ImageTagPropertyName::tagRegion())
200     {
201         return FaceTagsIface::ConfirmedName;
202     }
203     else if (attribute == ImageTagPropertyName::faceToTrain())
204     {
205         return FaceTagsIface::FaceForTraining;
206     }
207 
208     return FaceTagsIface::InvalidFace;
209 }
210 
fromVariant(const QVariant & var)211 FaceTagsIface FaceTagsIface::fromVariant(const QVariant& var)
212 {
213     if (var.type() == QVariant::List)
214     {
215         QList<QVariant> list(var.toList());
216 
217         if ((list.size() == 4) || (list.size() == 5))
218         {
219             return FaceTagsIface((Type)list.at(0).toInt(),
220                                  list.at(1).toLongLong(),
221                                  list.at(2).toInt(),
222                                  TagRegion::fromVariant(list.at(3)));
223         }
224     }
225 
226     return FaceTagsIface();
227 }
228 
toVariant() const229 QVariant FaceTagsIface::toVariant() const
230 {
231     // this is still not perfect, with QList<QVariant> being inefficient
232     // we must keep to native types, to make operator== work.
233 
234     QList<QVariant> list;
235     list << (int)m_type;
236     list << m_imageId;
237     list << m_tagId;
238     list << m_region.toVariant();
239 
240     return list;
241 }
242 
fromListing(qlonglong imageId,const QList<QVariant> & extraValues)243 FaceTagsIface FaceTagsIface::fromListing(qlonglong imageId, const QList<QVariant>& extraValues)
244 {
245     if (extraValues.size() < 3)
246     {
247         return FaceTagsIface();
248     }
249 
250     // See imagelister.cpp: value - property - tagId
251 
252     int tagId         = extraValues.at(2).toInt();
253     QString attribute = extraValues.at(1).toString();
254     QString value     = extraValues.at(0).toString();
255 /*
256     qCDebug(DIGIKAM_DATABASE_LOG) << tagId << attribute << value;
257 */
258     return FaceTagsIface(attribute,
259                         imageId, tagId,
260                         TagRegion(value));
261 }
262 
getAutodetectedPersonString() const263 QString FaceTagsIface::getAutodetectedPersonString() const
264 {
265     if (isUnconfirmedType())
266     {
267         return (QString::number(tagId())                 +
268                 QLatin1Char(',')                         +
269                 ImageTagPropertyName::autodetectedFace() +
270                 QLatin1Char(',')                         +
271                 (TagRegion(region().toRect())).toXml());
272     }
273     else
274     {
275         return QString();
276     }
277 }
278 
operator <<(QDebug dbg,const FaceTagsIface & f)279 QDebug operator<<(QDebug dbg, const FaceTagsIface& f)
280 {
281     dbg.nospace() << "FaceTagsIface(" << f.type()
282                   << ", image "       << f.imageId()
283                   << ", tag "         << f.tagId()
284                   << ", region"       << f.region();
285     return dbg;
286 }
287 
288 } // namespace Digikam
289