File indexing completed on 2025-01-19 03:57:56

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2010-09-17
0007  * Description : Managing of face tag region items on a GraphicsDImgView
0008  *
0009  * SPDX-FileCopyrightText: 2010      by Aditya Bhatt <adityabhatt1991 at gmail dot com>
0010  * SPDX-FileCopyrightText: 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0011  * SPDX-FileCopyrightText: 2012-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #include "facegroup_p.h"
0018 
0019 namespace Digikam
0020 {
0021 
0022 FaceGroup::Private::Private(FaceGroup* const q)
0023     : view                  (nullptr),
0024       exifRotate            (true),
0025       autoSuggest           (false),
0026       showOnHover           (false),
0027       manuallyAddWrapItem   (nullptr),
0028       manuallyAddedItem     (nullptr),
0029       state                 (NoFaces),
0030       visibilityController  (nullptr),
0031       tagModel              (nullptr),
0032       filterModel           (nullptr),
0033       filteredModel         (nullptr),
0034       q                     (q)
0035 {
0036 }
0037 
0038 QList<QGraphicsItem*> FaceGroup::Private::hotItems(const QPointF& scenePos)
0039 {
0040     if (!q->hasVisibleItems())
0041     {
0042         return QList<QGraphicsItem*>();
0043     }
0044 
0045     const int distance               = 15;
0046     QRectF hotSceneRect              = QRectF(scenePos, QSize(0, 0)).adjusted(-distance, -distance, distance, distance);
0047     QList<QGraphicsItem*> closeItems = view->scene()->items(hotSceneRect, Qt::IntersectsItemBoundingRect);
0048 
0049     closeItems.removeOne(view->previewItem());
0050 
0051     return closeItems;
0052 
0053 /*
0054     qreal distance;
0055     d->faceGroup->closestItem(mapToScene(e->pos()), &distance);
0056 
0057     if (distance < 15)
0058     {
0059         return false;
0060     }
0061 */
0062 }
0063 
0064 void FaceGroup::Private::applyVisible()
0065 {
0066     if      (state == NoFaces)
0067     {
0068         // If not yet loaded, load. load() will transitionToVisible after loading.
0069 
0070         q->load();
0071     }
0072     else if (state == FacesLoaded)
0073     {
0074         // show existing faces, if we have an image
0075 
0076         if (view->previewItem()->isLoaded())
0077         {
0078             visibilityController->show();
0079         }
0080     }
0081 }
0082 
0083 FaceItem* FaceGroup::Private::createItem(const FaceTagsIface& face)
0084 {
0085     FaceItem* const item = new FaceItem(view->previewItem());
0086     item->setFace(face);
0087 
0088     QRect faceRect       = face.region().toRect();
0089 
0090     if (!exifRotate)
0091     {
0092         TagRegion::reverseToOrientation(faceRect,
0093                                         info.orientation(),
0094                                         info.dimensions());
0095     }
0096 
0097     item->setOriginalRect(faceRect);
0098     item->setVisible(false);
0099 
0100     return item;
0101 }
0102 
0103 FaceItem* FaceGroup::Private::addItem(const FaceTagsIface& face)
0104 {
0105     FaceItem* const item                 = createItem(face);
0106 
0107     // for identification, use index in our list
0108 
0109     QList<QVariant> identifier(face.toVariant().toList());
0110     identifier << items.size();
0111 
0112     AssignNameWidget* const assignWidget = createAssignNameWidget(face, identifier);
0113     item->setHudWidget(assignWidget);
0114 /*
0115     new StyleSheetDebugger(assignWidget);
0116 */
0117     visibilityController->addItem(item);
0118 
0119     items << item;
0120 
0121     return item;
0122 }
0123 
0124 void FaceGroup::Private::checkModels()
0125 {
0126     if (!tagModel)
0127     {
0128         tagModel = new TagModel(AbstractAlbumModel::IgnoreRootAlbum, q);
0129     }
0130 
0131     if (!filterModel)
0132     {
0133         filterModel = new CheckableAlbumFilterModel(q);
0134     }
0135 
0136     if (!filteredModel)
0137     {
0138         filteredModel = new TagPropertiesFilterModel(q);
0139     }
0140 }
0141 
0142 AssignNameWidget::Mode FaceGroup::Private::assignWidgetMode(FaceTagsIface::Type type)
0143 {
0144     switch (type)
0145     {
0146         case FaceTagsIface::UnknownName:
0147         case FaceTagsIface::UnconfirmedName:
0148         {
0149             return AssignNameWidget::UnconfirmedEditMode;
0150         }
0151 
0152         case FaceTagsIface::Type::IgnoredName:
0153         {
0154             return AssignNameWidget::IgnoredMode;
0155         }
0156 
0157         case FaceTagsIface::ConfirmedName:
0158         {
0159             return AssignNameWidget::ConfirmedMode;
0160         }
0161 
0162         default:
0163         {
0164             return AssignNameWidget::InvalidMode;
0165         }
0166     }
0167 }
0168 
0169 AssignNameWidget* FaceGroup::Private::createAssignNameWidget(const FaceTagsIface& face, const QVariant& identifier)
0170 {
0171     AssignNameWidget* const assignWidget = new AssignNameWidget(view);
0172     assignWidget->setMode(assignWidgetMode(face.type()));
0173     assignWidget->setTagEntryWidgetMode(AssignNameWidget::AddTagsComboBoxMode);
0174     assignWidget->setVisualStyle(AssignNameWidget::TranslucentDarkRound);
0175     assignWidget->setLayoutMode(AssignNameWidget::TwoLines);
0176     assignWidget->setUserData(info, identifier);
0177     checkModels();
0178     assignWidget->setAlbumModels(tagModel, filteredModel, filterModel);
0179     assignWidget->setParentTag(AlbumManager::instance()->findTAlbum(FaceTags::personParentTag()));
0180 
0181     q->connect(assignWidget, SIGNAL(assigned(TaggingAction,ItemInfo,QVariant)),
0182                q, SLOT(slotAssigned(TaggingAction,ItemInfo,QVariant)));
0183 
0184     q->connect(assignWidget, SIGNAL(rejected(ItemInfo,QVariant)),
0185                q, SLOT(slotRejected(ItemInfo,QVariant)));
0186 
0187     q->connect(assignWidget, SIGNAL(ignored(ItemInfo,QVariant)),
0188                q, SLOT(slotIgnored(ItemInfo,QVariant)));
0189 
0190     q->connect(assignWidget, SIGNAL(ignoredClicked(ItemInfo,QVariant)),
0191                q, SLOT(slotIgnoredClicked(ItemInfo,QVariant)));
0192 
0193     q->connect(assignWidget, SIGNAL(labelClicked(ItemInfo,QVariant)),
0194                q, SLOT(slotLabelClicked(ItemInfo,QVariant)));
0195 
0196     return assignWidget;
0197 }
0198 
0199 } // namespace Digikam