File indexing completed on 2025-01-05 03:58:06
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2010-06-21 0007 * Description : Demo test program for FacesEngine 0008 * 0009 * SPDX-FileCopyrightText: 2009-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2010 by Alex Jironkin <alexjironkin at gmail dot com> 0011 * SPDX-FileCopyrightText: 2010 by Aditya Bhatt <adityabhatt1991 at gmail dot com> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #include "demofaceitem.h" 0018 0019 // Qt includes 0020 0021 #include <QWidget> 0022 #include <QPainter> 0023 #include <QGraphicsOpacityEffect> 0024 #include <QTextDocument> 0025 #include <QGraphicsScene> 0026 #include <QColor> 0027 #include <QIcon> 0028 #include <qmath.h> 0029 0030 // Local includes 0031 0032 #include "digikam_debug.h" 0033 #include "demomarquee.h" 0034 #include "demofancyrect.h" 0035 0036 namespace FaceEngineDemo 0037 { 0038 0039 class Q_DECL_HIDDEN FaceItem::Private 0040 { 0041 public: 0042 0043 explicit Private() 0044 : suggestionMode(false), 0045 sceneWidth(0), 0046 sceneHeight(0), 0047 x1(0), 0048 x2(0), 0049 y1(0), 0050 y2(0), 0051 name(), 0052 faceMarquee(nullptr), 0053 faceName(nullptr), 0054 nameRect(nullptr), 0055 origRect(), 0056 origScale(0.0), 0057 scale(0.0), 0058 rejectButton(nullptr), 0059 acceptButton(nullptr), 0060 suggestionRejectButton(nullptr), 0061 suggestionAcceptButton(nullptr) 0062 { 0063 } 0064 0065 bool suggestionMode; 0066 0067 int sceneWidth, sceneHeight; 0068 int x1, x2, y1, y2; 0069 0070 QString name; 0071 Marquee* faceMarquee; 0072 0073 QGraphicsTextItem* faceName; 0074 QGraphicsRectItem* nameRect; 0075 0076 QRect origRect; 0077 double origScale; 0078 double scale; 0079 0080 Button* rejectButton; 0081 Button* acceptButton; 0082 0083 Button* suggestionRejectButton; 0084 Button* suggestionAcceptButton; 0085 }; 0086 0087 FaceItem::FaceItem(QGraphicsItem* const parent, 0088 QGraphicsScene* const scene, 0089 const QRect& rect, 0090 double scale, 0091 const QString& name, 0092 double originalscale) 0093 : QGraphicsObject(parent), 0094 d(new Private) 0095 { 0096 setAcceptHoverEvents(true); 0097 0098 d->origScale = originalscale; 0099 d->scale = scale; 0100 d->origRect = rect; 0101 d->sceneWidth = scene->width(); 0102 d->sceneHeight = scene->height(); 0103 0104 // Scale all coordinates to fit the initial size of the scene 0105 0106 d->x1 = rect.topLeft().x() * scale; 0107 d->y1 = rect.topLeft().y() * scale; 0108 d->x2 = rect.bottomRight().x() * scale; 0109 d->y2 = rect.bottomRight().y() * scale; 0110 0111 // A QRect containing coordinates for the face rectangle 0112 0113 QRect scaledRect; 0114 scaledRect.setTopLeft(QPoint(d->x1, d->y1)); 0115 scaledRect.setBottomRight(QPoint(d->x2, d->y2)); 0116 0117 // marquee 0118 0119 FancyRect* const fancy = new FancyRect(scaledRect); 0120 d->faceMarquee = new Marquee(fancy); 0121 scene->addItem(d->faceMarquee); 0122 0123 // Make a new QGraphicsTextItem for writing the name text, and a new QGraphicsRectItem to draw a good-looking, semi-transparent bounding box. 0124 0125 d->nameRect = new QGraphicsRectItem(nullptr); 0126 scene->addItem(d->nameRect); 0127 0128 d->faceName = new QGraphicsTextItem(name, nullptr); 0129 scene->addItem(d->faceName); 0130 0131 // Make the bounding box for the name update itself to cover all the text whenever contents are changed 0132 0133 QTextDocument* const doc = d->faceName->document(); 0134 QTextOption o; 0135 o.setAlignment(Qt::AlignCenter); 0136 doc->setDefaultTextOption(o); 0137 0138 // Get coordinates of the name relative to the scene 0139 0140 QRectF r = d->faceName->mapRectToScene(d->faceName->boundingRect()); 0141 0142 // Draw the bounding name rectangle with the scene coordinates 0143 0144 d->nameRect->setRect(r); 0145 QPen p(QColor(QLatin1String("white"))); 0146 p.setWidth(3); 0147 d->nameRect->setPen(p); 0148 d->nameRect->setBrush(QBrush(QColor(QLatin1String("black")))); 0149 d->nameRect->setOpacity(0.6); 0150 d->nameRect->show(); 0151 0152 // Draw the name input item 0153 0154 d->faceName->setDefaultTextColor(QColor(QLatin1String("white"))); 0155 d->faceName->setFont(QFont(QLatin1String("Helvetica"), 9)); 0156 d->faceName->setTextInteractionFlags(Qt::TextEditorInteraction); 0157 d->faceName->setOpacity(1); 0158 0159 //--------------------- 0160 0161 QPixmap rejectPix = QIcon::fromTheme(QLatin1String("window-close")).pixmap(16, 16); 0162 d->rejectButton = new Button( rejectPix, rejectPix); 0163 scene->addItem(d->rejectButton); 0164 d->rejectButton->show(); 0165 0166 QPixmap acceptPix = QIcon::fromTheme(QLatin1String("dialog-ok-apply")).pixmap(16, 16); 0167 d->acceptButton = new Button( acceptPix, acceptPix); 0168 scene->addItem(d->acceptButton); 0169 /* 0170 d->acceptButton->show(); 0171 */ 0172 d->suggestionRejectButton = new Button(rejectPix, rejectPix); 0173 scene->addItem(d->suggestionRejectButton); 0174 //d->suggestionAcceptButton->hide(); 0175 0176 d->suggestionAcceptButton = new Button(acceptPix, acceptPix); 0177 scene->addItem(d->suggestionAcceptButton); 0178 /* 0179 d->suggestionRejectButton->hide(); 0180 */ 0181 update(); 0182 0183 switchToEditMode(); 0184 0185 d->acceptButton->hide(); 0186 0187 connect(d->rejectButton, &Button::clicked, 0188 this, &FaceItem::reject); 0189 0190 connect(d->acceptButton, &Button::clicked, 0191 this, &FaceItem::accepted); 0192 0193 connect(d->suggestionAcceptButton, &Button::clicked, 0194 this, &FaceItem::slotSuggestionAccepted); 0195 0196 connect(d->suggestionRejectButton, &Button::clicked, this, 0197 &FaceItem::slotSuggestionRejected); 0198 0199 connect(doc, SIGNAL(contentsChanged()), 0200 this, SLOT(update())); 0201 0202 connect(d->faceMarquee, &Marquee::changed, 0203 this, &FaceItem::update); 0204 } 0205 0206 FaceItem::~FaceItem() 0207 { 0208 delete d; 0209 } 0210 0211 QRectF FaceItem::boundingRect() const 0212 { 0213 qreal adjust = 0.5; 0214 0215 return QRectF(-18 - adjust, 0216 -22 - adjust, 0217 36 + adjust, 0218 60 + adjust); 0219 } 0220 0221 void FaceItem::setText(const QString& newName) 0222 { 0223 d->faceName->setHtml(newName); 0224 } 0225 0226 QString FaceItem::text() const 0227 { 0228 return d->faceName->toPlainText().remove(QLatin1String("?")); 0229 } 0230 0231 void FaceItem::update() 0232 { 0233 if (text().isEmpty()) 0234 { 0235 d->faceName->setDefaultTextColor(QColor("white")); 0236 d->nameRect->setPen(QPen(QColor("white"))); 0237 d->acceptButton->hide(); 0238 d->name.clear(); 0239 } 0240 else 0241 { 0242 d->nameRect->setPen(QPen(QColor("yellow"))); 0243 d->faceName->setDefaultTextColor(QColor("yellow")); 0244 0245 if (!d->suggestionMode) 0246 { 0247 d->acceptButton->show(); 0248 d->name = text(); 0249 } 0250 } 0251 0252 QPointF bl = d->faceMarquee->mapRectToScene(d->faceMarquee->boundingRect()).bottomLeft(); 0253 QPointF br = d->nameRect->mapRectToScene(d->nameRect->boundingRect()).bottomRight(); 0254 d->faceName->setPos(bl.x() + 5, bl.y() + 5); 0255 0256 d->rejectButton->setPos(bl.x() - 16, bl.y() + 9); 0257 d->acceptButton->setPos(br.x() + 4, bl.y() + 11); 0258 0259 d->suggestionAcceptButton->setPos(br.x() + 4, bl.y() + 11); 0260 d->suggestionRejectButton->setPos(br.x() + 20, bl.y() + 11); 0261 0262 QRectF r = d->faceName->mapRectToScene(d->faceName->boundingRect()); 0263 d->nameRect->setRect(r); 0264 QRect newRect = this->d->faceMarquee->mapRectToScene(d->faceMarquee->boundingRect()).toRect(); 0265 qCDebug(DIGIKAM_TESTS_LOG) << "Origscale is : " << d->origScale << " and scale is " << d->scale; 0266 0267 QSize s(newRect.size()); 0268 s.scale(newRect.width() * qSqrt(d->origScale), newRect.height() * qSqrt(d->origScale), Qt::KeepAspectRatio); 0269 newRect.setSize(s); 0270 /* 0271 newRect.setRect(x,y,w,h); 0272 */ 0273 qCDebug(DIGIKAM_TESTS_LOG) << "Orig before" << d->origRect; 0274 /* 0275 d->origRect = newRect; 0276 */ 0277 qCDebug(DIGIKAM_TESTS_LOG) << "Orig after" << d->origRect; 0278 } 0279 0280 void FaceItem::setVisible(bool visible) 0281 { 0282 d->faceMarquee->setVisible(visible); 0283 setControlsVisible(visible); 0284 } 0285 0286 void FaceItem::setControlsVisible(bool visible) 0287 { 0288 d->nameRect->setVisible(visible); 0289 d->faceName->setVisible(visible); 0290 0291 if (d->suggestionMode) 0292 { 0293 d->suggestionAcceptButton->setVisible(visible); 0294 d->suggestionRejectButton->setVisible(visible); 0295 } 0296 else 0297 { 0298 d->rejectButton->setVisible(visible); 0299 d->acceptButton->setVisible(visible); 0300 } 0301 } 0302 0303 void FaceItem::clearText() 0304 { 0305 d->faceName->setPlainText(QString()); 0306 } 0307 0308 void FaceItem::clearAndHide() 0309 { 0310 clearText(); 0311 setVisible(false); 0312 } 0313 0314 void FaceItem::accepted() 0315 { 0316 d->acceptButton->hide(); 0317 d->faceName->setDefaultTextColor(QColor("white")); 0318 d->nameRect->setPen(QPen(QColor("white"))); 0319 Q_EMIT acceptButtonClicked(this->text(), this->originalRect()); 0320 } 0321 0322 QRect FaceItem::originalRect() const 0323 { 0324 return d->origRect; 0325 } 0326 0327 double FaceItem::originalScale() const 0328 { 0329 return d->origScale; 0330 } 0331 0332 void FaceItem::reject() 0333 { 0334 Q_EMIT rejectButtonClicked(this->text(), this->originalRect()); 0335 clearAndHide(); 0336 } 0337 0338 void FaceItem::suggest(const QString& name) 0339 { 0340 qCDebug(DIGIKAM_TESTS_LOG) << "suggested name is " << name; 0341 d->name = name; 0342 this->switchToSuggestionMode(); 0343 } 0344 0345 void FaceItem::switchToEditMode() 0346 { 0347 d->suggestionMode = false; 0348 d->faceName->setEnabled(true); 0349 d->faceName->setHtml(QLatin1String("<b>") + d->name + QLatin1String("</b>")); 0350 d->acceptButton->show(); 0351 d->suggestionAcceptButton->hide(); 0352 d->suggestionRejectButton->hide(); 0353 } 0354 0355 void FaceItem::switchToSuggestionMode() 0356 { 0357 d->suggestionMode = true; 0358 d->faceName->setEnabled(false); 0359 d->faceName->setHtml(QLatin1String("Is this <b>") + d->name + QLatin1String("</b> ?")); 0360 d->acceptButton->hide(); 0361 d->suggestionAcceptButton->show(); 0362 d->suggestionRejectButton->show(); 0363 } 0364 0365 void FaceItem::slotSuggestionAccepted() 0366 { 0367 switchToEditMode(); 0368 d->faceName->setHtml(QLatin1String("<b>") + d->name + QLatin1String("</b>")); 0369 accepted(); 0370 Q_EMIT suggestionAcceptButtonClicked(this->text(), this->originalRect()); 0371 } 0372 0373 void FaceItem::slotSuggestionRejected() 0374 { 0375 switchToEditMode(); 0376 d->faceName->setHtml(QLatin1String("<b>") + QString() + QLatin1String("</b>")); 0377 Q_EMIT suggestionRejectButtonClicked(this->text(), this->originalRect()); 0378 } 0379 0380 void FaceItem::paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) 0381 { 0382 } 0383 0384 } // namespace FaceEngineDemo 0385 0386 #include "moc_demofaceitem.cpp"