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-07-23
0007  * Description : face marquer widget for FacesEngine Demo
0008  *
0009  * SPDX-FileCopyrightText: 2009-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText:      2010 by Adrien Bustany <madcat at mymadcat 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 "demomarquee.h"
0018 
0019 // Qt includes
0020 
0021 #include <QPointF>
0022 #include <QPen>
0023 #include <QString>
0024 #include <QGraphicsSimpleTextItem>
0025 #include <QGraphicsScene>
0026 #include <QTimer>
0027 
0028 // Local includes
0029 
0030 #include "digikam_debug.h"
0031 #include "demofancyrect.h"
0032 
0033 namespace FaceEngineDemo
0034 {
0035 
0036 class Q_DECL_HIDDEN Marquee::Private
0037 {
0038 public:
0039 
0040     enum ResizeType
0041     {
0042         TopLeft = 0,
0043         TopRight,
0044         BottomLeft,
0045         BottomRight
0046     };
0047 
0048 public:
0049 
0050     explicit Private()
0051       : handleSize  (10),
0052         htl         (nullptr),
0053         htr         (nullptr),
0054         hbr         (nullptr),
0055         hbl         (nullptr),
0056         rect        (nullptr),
0057         label       (nullptr),
0058         moving      (false),
0059         resizing    (false),
0060         resizeType  (0)
0061     {
0062     }
0063 
0064 public:
0065 
0066     const int                handleSize;
0067     QPen                     rectPen;    ///< The pen used to draw the frames
0068     QPen                     outlinePen; ///< Text outline pen
0069 
0070     /// Handles
0071     FancyRect*               htl;
0072     FancyRect*               htr;
0073     FancyRect*               hbr;
0074     FancyRect*               hbl;
0075 
0076     FancyRect*               rect;       ///< Main frame
0077     QGraphicsSimpleTextItem* label;
0078 
0079     bool                     moving;     ///< Tells if we are moving the marquee
0080     QPointF                  moveOffset; ///< where the mouse was when the user began to drag the marquee
0081     bool                     resizing;   ///< Tells if we are resizing the marquee
0082     int                      resizeType; ///< See ResizeType values.
0083 };
0084 
0085 Marquee::Marquee(FancyRect* const rect, QGraphicsItem* const parent)
0086     : QObject           (nullptr),
0087       QGraphicsItemGroup(parent),
0088       d                 (new Private)
0089 {
0090     d->rect    = rect;
0091     d->rectPen.setColor(Qt::red);
0092     d->rectPen.setWidth(2);
0093     d->outlinePen.setColor(Qt::red);
0094     addToGroup(d->rect);
0095     d->rect->setPen(d->rectPen);
0096     setPos(d->rect->scenePos());
0097     d->rect->setPos(0, 0);
0098     createHandles();
0099 
0100     d->label   = new QGraphicsSimpleTextItem(QString::fromLatin1(""), this);
0101     d->label->setBrush(QBrush(d->rectPen.color()));
0102     d->label->setPen(d->outlinePen);
0103     d->label->setZValue(2);
0104 
0105     QFont font = d->label->font();
0106     font.setBold(true);
0107     font.setPointSize(12);
0108     d->label->setFont(font);
0109     setFlag(QGraphicsItem::ItemIsSelectable);
0110     setSelected(true);
0111 
0112     QTimer::singleShot(1000, this, SIGNAL(selected(this)));
0113 }
0114 
0115 Marquee::~Marquee()
0116 {
0117     delete d;
0118 }
0119 
0120 QRectF Marquee::boundingRect() const
0121 {
0122     return d->rect->rect();
0123 }
0124 
0125 QRectF Marquee::toRectF() const
0126 {
0127     return QRectF(x(), y(), d->rect->rect().width(), d->rect->rect().height());
0128 }
0129 
0130 void Marquee::createHandles()
0131 {
0132     d->htl = new FancyRect(0, 0, d->handleSize, d->handleSize);
0133     d->htl->setZValue(1);
0134     d->htr = new FancyRect(0, 0, d->handleSize, d->handleSize);
0135     d->htr->setZValue(1);
0136     d->hbl = new FancyRect(0, 0, d->handleSize, d->handleSize);
0137     d->hbl->setZValue(1);
0138     d->hbr = new FancyRect(0, 0, d->handleSize, d->handleSize);
0139     d->hbr->setZValue(1);
0140 
0141     d->htl->setPen(d->rectPen);
0142     d->htr->setPen(d->rectPen);
0143     d->hbl->setPen(d->rectPen);
0144     d->hbr->setPen(d->rectPen);
0145 
0146     addToGroup(d->htl);
0147     addToGroup(d->htr);
0148     addToGroup(d->hbl);
0149     addToGroup(d->hbr);
0150     placeHandles();
0151 }
0152 
0153 void Marquee::placeHandles()
0154 {
0155     qreal rw = d->rect->rect().width();
0156     qreal rh = d->rect->rect().height();
0157     qreal ox = d->rect->rect().x();
0158     qreal oy = d->rect->rect().y();
0159     qreal hs = d->hbr->boundingRect().width();
0160 
0161     d->htl->setPos(ox,         oy);
0162     d->htr->setPos(ox+rw-hs+2, oy);
0163     d->hbl->setPos(ox,         oy+rh-hs+2);
0164     d->hbr->setPos(ox+rw-hs+2, oy+rh-hs+2);
0165 }
0166 
0167 void Marquee::mousePressEvent(QGraphicsSceneMouseEvent* e)
0168 {
0169     Q_EMIT selected(this);
0170 
0171     // Check for some resize handles under the mouse
0172 
0173     if (d->htl->isUnderMouse())
0174     {
0175         d->resizing   = true;
0176         d->resizeType = Private::TopLeft;
0177         return;
0178     }
0179 
0180     if (d->htr->isUnderMouse())
0181     {
0182         d->resizing   = true;
0183         d->resizeType = Private::TopRight;
0184         return;
0185     }
0186 
0187     if (d->hbl->isUnderMouse())
0188     {
0189         d->resizing   = true;
0190         d->resizeType = Private::BottomLeft;
0191         return;
0192     }
0193 
0194     if (d->hbr->isUnderMouse())
0195     {
0196         d->resizing   = true;
0197         d->resizeType = Private::BottomRight;
0198         return;
0199     }
0200 
0201     // If no handle is under the mouse, then we move the frame
0202 
0203     d->resizing   = false;
0204     d->moving     = true;
0205     d->moveOffset = e->pos();
0206 
0207     Q_EMIT changed();
0208 }
0209 
0210 void Marquee::mouseMoveEvent(QGraphicsSceneMouseEvent* e)
0211 {
0212     if (d->resizing)
0213     {
0214         QRectF r = d->rect->rect();
0215 
0216         switch (d->resizeType)
0217         {
0218             case Private::TopLeft:
0219             {
0220                 r.setTopLeft(e->pos());
0221                 break;
0222             }
0223 
0224             case Private::TopRight:
0225             {
0226                 r.setTopRight(e->pos());
0227                 break;
0228             }
0229 
0230             case Private::BottomLeft:
0231             {
0232                 r.setBottomLeft(e->pos());
0233                 break;
0234             }
0235 
0236             case Private::BottomRight:
0237             {
0238                 r.setBottomRight(e->pos());
0239                 break;
0240             }
0241 
0242             default:
0243             {
0244                 break;
0245             }
0246         }
0247 
0248         if ((r.width() < 2*d->handleSize) || (r.height() < 2*d->handleSize))
0249         {
0250             return;
0251         }
0252 
0253         setPos(pos() + r.topLeft());
0254         r.moveTopLeft(QPointF(0, 0));
0255         d->rect->setRect(r);
0256         placeHandles();
0257     }
0258 
0259     if (d->moving)
0260     {
0261         setPos(e->scenePos() - d->moveOffset);
0262     }
0263 
0264     Q_EMIT changed();
0265 }
0266 
0267 void Marquee::mouseReleaseEvent(QGraphicsSceneMouseEvent* e)
0268 {
0269     Q_UNUSED(e);
0270     d->resizing = false;
0271     d->moving   = false;
0272 
0273     Q_EMIT changed();
0274 }
0275 
0276 } // namespace FaceEngineDemo
0277 
0278 #include "moc_demomarquee.cpp"