File indexing completed on 2026-07-12 13:18:38

0001 #include "overlay.h"
0002 
0003 #include <QDebug>
0004 #include <QMouseEvent>
0005 #include <QPainter>
0006 #include <QPainterPath>
0007 #include <QPen>
0008 
0009 constexpr int k_distance_selection= 10;
0010 constexpr int k_grey_color_level= 40;
0011 constexpr int k_pen_width= 4;
0012 constexpr int k_opacity= 200;
0013 
0014 #include "worker/utilshelper.h"
0015 
0016 int computeDistance(QPoint p, QPoint r)
0017 {
0018     auto result= p - r;
0019     return result.manhattanLength();
0020 }
0021 
0022 qreal ratioFromEnum(Overlay::Ratio ratio)
0023 {
0024     static QHash<Overlay::Ratio, qreal> hash(
0025         {{Overlay::Ratio::Ratio_Square, 1}, {Overlay::Ratio::Ratio_Tv, 4. / 3.}, {Overlay::Ratio::Ratio_Tv, 16. / 9.}});
0026     return hash.value(ratio);
0027 }
0028 
0029 inline uint qHash(const Overlay::Ratio& key, uint seed)
0030 {
0031     return qHash(static_cast<int>(key), seed) ^ static_cast<int>(key);
0032 }
0033 
0034 QRect computeRectGivenRatio(const QRect& rect, Overlay::Ratio ratio)
0035 {
0036     if(ratio == Overlay::Ratio::Ratio_Unconstrained)
0037         return rect;
0038 
0039     return helper::utils::computerBiggerRectInside(rect, ratioFromEnum(ratio)).toRect();
0040 }
0041 
0042 Overlay::Overlay(QWidget* parent) // QRect rect, Ratio ratio,, m_rect(rect), m_fullRect(rect), m_ratio(ratio)
0043     : QWidget(parent), m_currentCorner(None), m_lastPosition()
0044 {
0045 
0046     setAttribute(Qt::WA_NoSystemBackground);
0047 }
0048 
0049 Overlay::Ratio Overlay::ratio() const
0050 {
0051     return m_ratio;
0052 }
0053 
0054 void Overlay::initRect()
0055 {
0056     auto y= m_selectedRect.y();
0057     m_selectedRect.setY(0);
0058     m_selectedRect.setHeight(m_selectedRect.height() - y);
0059 
0060     setSelectedRect(computeRectGivenRatio(m_selectedRect, m_ratio));
0061 }
0062 
0063 void Overlay::setRatio(Ratio ratio)
0064 {
0065     if(ratio == m_ratio)
0066         return;
0067     m_ratio= ratio;
0068     emit ratioChanged();
0069 }
0070 
0071 void Overlay::paintEvent(QPaintEvent*)
0072 {
0073     QPainter painter(this);
0074 
0075     QPainterPath toShow;
0076     toShow.addRect(rect());
0077 
0078     QPainterPath toHide;
0079     toHide.addRect(m_selectedRect);
0080     toShow= toShow.subtracted(toHide);
0081 
0082     // qDebug() << "paint event" << toShow << toHide << rect() << m_selectedRect;
0083 
0084     painter.fillPath(toShow, QColor(k_grey_color_level, k_grey_color_level, k_grey_color_level, k_opacity));
0085     painter.save();
0086     auto pen= painter.pen();
0087     pen.setWidth(k_pen_width);
0088     pen.setStyle(Qt::DashDotLine);
0089     pen.setColor(Qt::red);
0090     painter.setPen(pen);
0091     painter.drawRect(m_selectedRect);
0092     painter.restore();
0093 
0094     auto offset= k_distance_selection / 2;
0095     painter.fillRect(m_selectedRect.topLeft().x() - offset, m_selectedRect.topLeft().y() - offset, k_distance_selection,
0096                      k_distance_selection, Qt::red);
0097     painter.fillRect(m_selectedRect.topRight().x() - offset, m_selectedRect.topRight().y() - offset,
0098                      k_distance_selection, k_distance_selection, Qt::red);
0099     painter.fillRect(m_selectedRect.bottomLeft().x() - offset, m_selectedRect.bottomLeft().y() - offset,
0100                      k_distance_selection, k_distance_selection, Qt::red);
0101     painter.fillRect(m_selectedRect.bottomRight().x() - offset, m_selectedRect.bottomRight().y() - offset,
0102                      k_distance_selection, k_distance_selection, Qt::red);
0103     painter.fillRect(m_selectedRect.center().x() - offset, m_selectedRect.center().y() - offset, k_distance_selection,
0104                      k_distance_selection, Qt::red);
0105 }
0106 
0107 QRect Overlay::selectedRect() const
0108 {
0109     return m_selectedRect;
0110 }
0111 
0112 void Overlay::setSelectedRect(const QRect& rect)
0113 {
0114     if(rect == m_selectedRect)
0115         return;
0116     m_selectedRect= computeRectGivenRatio(rect, m_ratio);
0117     m_selectedRect.translate((rect.width() - m_selectedRect.width()) / 2,
0118                              (rect.height() - m_selectedRect.height()) / 2);
0119     emit selectedRectChanged(m_selectedRect);
0120     update();
0121 }
0122 
0123 void Overlay::mousePressEvent(QMouseEvent* event)
0124 {
0125     auto pos= event->pos();
0126     if(computeDistance(pos, m_selectedRect.topLeft()) < k_distance_selection)
0127     {
0128         m_currentCorner= First;
0129     }
0130     else if(computeDistance(pos, m_selectedRect.topRight()) < k_distance_selection)
0131     {
0132         m_currentCorner= Second;
0133     }
0134     else if(computeDistance(pos, m_selectedRect.bottomRight()) < k_distance_selection)
0135     {
0136         m_currentCorner= Third;
0137     }
0138     else if(computeDistance(pos, m_selectedRect.bottomLeft()) < k_distance_selection)
0139     {
0140         m_currentCorner= Fourth;
0141     }
0142     else if(computeDistance(pos, m_selectedRect.center()) < k_distance_selection)
0143     {
0144         m_currentCorner= Center;
0145     }
0146     else
0147     {
0148         m_currentCorner= None;
0149     }
0150 
0151     if(m_currentCorner == None)
0152         QWidget::mousePressEvent(event);
0153     else
0154         m_lastPosition= pos;
0155 }
0156 
0157 void Overlay::mouseMoveEvent(QMouseEvent* event)
0158 {
0159     auto pos= event->pos();
0160     auto deplace= pos - m_lastPosition;
0161     auto oldRect= m_selectedRect;
0162 
0163     switch(m_currentCorner)
0164     {
0165     case First:
0166         m_selectedRect.setTopLeft(pos);
0167         break;
0168     case Second:
0169         m_selectedRect.setTopRight(pos);
0170         break;
0171     case Third:
0172         m_selectedRect.setBottomRight(pos);
0173         break;
0174     case Fourth:
0175         m_selectedRect.setBottomLeft(pos);
0176         break;
0177     case Center:
0178         m_selectedRect.translate(deplace);
0179         break;
0180     default:
0181         break;
0182     }
0183     if(oldRect == m_selectedRect)
0184         return;
0185 
0186     m_selectedRect= computeRectGivenRatio(m_selectedRect, m_ratio);
0187 
0188     if(!rect().contains(m_selectedRect))
0189     {
0190         m_selectedRect= oldRect;
0191     }
0192 
0193     m_lastPosition= event->pos();
0194     update();
0195     emit selectedRectChanged(m_selectedRect);
0196 }