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 }