1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2010-09-17
7  * Description : Managing of face tag region items on a GraphicsDImgView
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  * Copyright (C) 2012-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
12  *
13  * This program is free software; you can redistribute it
14  * and/or modify it under the terms of the GNU General
15  * Public License as published by the Free Software Foundation;
16  * either version 2, or (at your option)
17  * any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * ============================================================ */
25 
26 #include "facegroup_p.h"
27 
28 namespace Digikam
29 {
30 
Private(FaceGroup * const q)31 FaceGroup::Private::Private(FaceGroup* const q)
32     : view                  (nullptr),
33       exifRotate            (true),
34       autoSuggest           (false),
35       showOnHover           (false),
36       manuallyAddWrapItem   (nullptr),
37       manuallyAddedItem     (nullptr),
38       state                 (NoFaces),
39       visibilityController  (nullptr),
40       tagModel              (nullptr),
41       filterModel           (nullptr),
42       filteredModel         (nullptr),
43       q                     (q)
44 {
45 }
46 
hotItems(const QPointF & scenePos)47 QList<QGraphicsItem*> FaceGroup::Private::hotItems(const QPointF& scenePos)
48 {
49     if (!q->hasVisibleItems())
50     {
51         return QList<QGraphicsItem*>();
52     }
53 
54     const int distance               = 15;
55     QRectF hotSceneRect              = QRectF(scenePos, QSize(0, 0)).adjusted(-distance, -distance, distance, distance);
56     QList<QGraphicsItem*> closeItems = view->scene()->items(hotSceneRect, Qt::IntersectsItemBoundingRect);
57 
58     closeItems.removeOne(view->previewItem());
59 
60     return closeItems;
61 
62 /*
63     qreal distance;
64     d->faceGroup->closestItem(mapToScene(e->pos()), &distance);
65 
66     if (distance < 15)
67     {
68         return false;
69     }
70 */
71 }
72 
applyVisible()73 void FaceGroup::Private::applyVisible()
74 {
75     if      (state == NoFaces)
76     {
77         // If not yet loaded, load. load() will transitionToVisible after loading.
78 
79         q->load();
80     }
81     else if (state == FacesLoaded)
82     {
83         // show existing faces, if we have an image
84 
85         if (view->previewItem()->isLoaded())
86         {
87             visibilityController->show();
88         }
89     }
90 }
91 
createItem(const FaceTagsIface & face)92 FaceItem* FaceGroup::Private::createItem(const FaceTagsIface& face)
93 {
94     FaceItem* const item = new FaceItem(view->previewItem());
95     item->setFace(face);
96 
97     QRect faceRect       = face.region().toRect();
98 
99     if (!exifRotate)
100     {
101         TagRegion::reverseToOrientation(faceRect,
102                                         info.orientation(),
103                                         info.dimensions());
104     }
105 
106     item->setOriginalRect(faceRect);
107     item->setVisible(false);
108 
109     return item;
110 }
111 
addItem(const FaceTagsIface & face)112 FaceItem* FaceGroup::Private::addItem(const FaceTagsIface& face)
113 {
114     FaceItem* const item                 = createItem(face);
115 
116     // for identification, use index in our list
117 
118     QList<QVariant> identifier(face.toVariant().toList());
119     identifier << items.size();
120 
121     AssignNameWidget* const assignWidget = createAssignNameWidget(face, identifier);
122     item->setHudWidget(assignWidget);
123 /*
124     new StyleSheetDebugger(assignWidget);
125 */
126     visibilityController->addItem(item);
127 
128     items << item;
129 
130     return item;
131 }
132 
checkModels()133 void FaceGroup::Private::checkModels()
134 {
135     if (!tagModel)
136     {
137         tagModel = new TagModel(AbstractAlbumModel::IgnoreRootAlbum, q);
138     }
139 
140     if (!filterModel)
141     {
142         filterModel = new CheckableAlbumFilterModel(q);
143     }
144 
145     if (!filteredModel)
146     {
147         filteredModel = new TagPropertiesFilterModel(q);
148     }
149 }
150 
assignWidgetMode(FaceTagsIface::Type type)151 AssignNameWidget::Mode FaceGroup::Private::assignWidgetMode(FaceTagsIface::Type type)
152 {
153     switch (type)
154     {
155         case FaceTagsIface::UnknownName:
156         case FaceTagsIface::UnconfirmedName:
157         {
158             return AssignNameWidget::UnconfirmedEditMode;
159         }
160 
161         case FaceTagsIface::Type::IgnoredName:
162         {
163             return AssignNameWidget::IgnoredMode;
164         }
165 
166         case FaceTagsIface::ConfirmedName:
167         {
168             return AssignNameWidget::ConfirmedMode;
169         }
170 
171         default:
172         {
173             return AssignNameWidget::InvalidMode;
174         }
175     }
176 }
177 
createAssignNameWidget(const FaceTagsIface & face,const QVariant & identifier)178 AssignNameWidget* FaceGroup::Private::createAssignNameWidget(const FaceTagsIface& face, const QVariant& identifier)
179 {
180     AssignNameWidget* const assignWidget = new AssignNameWidget(view);
181     assignWidget->setMode(assignWidgetMode(face.type()));
182     assignWidget->setTagEntryWidgetMode(AssignNameWidget::AddTagsComboBoxMode);
183     assignWidget->setVisualStyle(AssignNameWidget::TranslucentDarkRound);
184     assignWidget->setLayoutMode(AssignNameWidget::TwoLines);
185     assignWidget->setUserData(info, identifier);
186     checkModels();
187     assignWidget->setModel(tagModel, filteredModel, filterModel);
188     assignWidget->setParentTag(AlbumManager::instance()->findTAlbum(FaceTags::personParentTag()));
189 
190     q->connect(assignWidget, SIGNAL(assigned(TaggingAction,ItemInfo,QVariant)),
191                q, SLOT(slotAssigned(TaggingAction,ItemInfo,QVariant)));
192 
193     q->connect(assignWidget, SIGNAL(rejected(ItemInfo,QVariant)),
194                q, SLOT(slotRejected(ItemInfo,QVariant)));
195 
196     q->connect(assignWidget, SIGNAL(ignoredClicked(ItemInfo,QVariant)),
197                q, SLOT(slotIgnoredClicked(ItemInfo,QVariant)));
198 
199     q->connect(assignWidget, SIGNAL(labelClicked(ItemInfo,QVariant)),
200                q, SLOT(slotLabelClicked(ItemInfo,QVariant)));
201 
202     return assignWidget;
203 }
204 
205 } // namespace Digikam
206