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