File indexing completed on 2024-04-28 04:32:07

0001 /*
0002  * Copyright (C) 2015 by Stephen Allewell
0003  * steve.allewell@gmail.com
0004  *
0005  * This program is free software; you can redistribute it and/or modify
0006  * it under the terms of the GNU General Public License as published by
0007  * the Free Software Foundation; either version 2 of the License, or
0008  * (at your option) any later version.
0009  */
0010 
0011 /** @file
0012  * This file defines an extension to a QLabel that scales the associated QPixmap
0013  * to maintain the aspect ratio when scaling to fill the extents of the QLabel
0014  * area.
0015  */
0016 
0017 // Class include
0018 #include "ScaledPixmapLabel.h"
0019 
0020 // Qt includes
0021 #include <QMouseEvent>
0022 #include <QPainter>
0023 #include <QStyleOptionRubberBand>
0024 
0025 ScaledPixmapLabel::ScaledPixmapLabel(QWidget *parent)
0026     : QLabel(parent)
0027     , m_cropping(false)
0028 {
0029     setMinimumSize(1, 1);
0030     setAlignment(Qt::AlignCenter);
0031     setMouseTracking(true);
0032 }
0033 
0034 void ScaledPixmapLabel::setPixmap(const QPixmap &pixmap)
0035 {
0036     m_pixmap = pixmap;
0037     m_crop = QRect();
0038     QLabel::setPixmap(m_pixmap.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
0039 }
0040 
0041 void ScaledPixmapLabel::setCropping(bool checked)
0042 {
0043     m_cropping = checked;
0044     m_crop = QRect();
0045     update();
0046 }
0047 
0048 int ScaledPixmapLabel::heightForWidth(int width) const
0049 {
0050     return ((qreal)m_pixmap.height() * width) / m_pixmap.width();
0051 }
0052 
0053 QSize ScaledPixmapLabel::sizeHint() const
0054 {
0055     int w = width();
0056     return QSize(w, heightForWidth(w));
0057 }
0058 
0059 QRect ScaledPixmapLabel::pixmapRect() const
0060 {
0061     QSize previewSize = size();
0062     QSize pixmapSize = pixmap()->size();
0063 
0064     int dx = (previewSize.width() - pixmapSize.width()) / 2;
0065     int dy = (previewSize.height() - pixmapSize.height()) / 2;
0066 
0067     return QRect(dx, dy, pixmapSize.width(), pixmapSize.height());
0068 }
0069 
0070 void ScaledPixmapLabel::resizeEvent(QResizeEvent *event)
0071 {
0072     Q_UNUSED(event);
0073 
0074     QLabel::setPixmap(m_pixmap.scaled(this->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
0075 }
0076 
0077 void ScaledPixmapLabel::paintEvent(QPaintEvent *event)
0078 {
0079     QLabel::paintEvent(event);
0080 
0081     QPainter painter(this);
0082     painter.setRenderHint(QPainter::Qt4CompatiblePainting, true);
0083 
0084     if (m_crop.isValid()) {
0085         QStyleOptionRubberBand opt;
0086         opt.initFrom(this);
0087         opt.shape = QRubberBand::Rectangle;
0088         opt.opaque = false;
0089         opt.rect = m_crop.adjusted(0, 0, 1, 1);
0090 
0091         style()->drawControl(QStyle::CE_RubberBand, &opt, &painter);
0092     } else {
0093         if (m_cropping && underMouse() && (children().count() == 0)) {
0094             // draw guides
0095             QPoint cursor = mapFromGlobal(QCursor::pos());
0096             painter.drawLine(cursor.x(), 0, cursor.x(), size().height());
0097             painter.drawLine(0, cursor.y(), size().width(), cursor.y());
0098         }
0099     }
0100 }
0101 
0102 void ScaledPixmapLabel::mousePressEvent(QMouseEvent *event)
0103 {
0104     if (m_cropping) {
0105         m_start = event->pos();
0106         m_crop = QRect();
0107         update();
0108     }
0109 }
0110 
0111 void ScaledPixmapLabel::mouseMoveEvent(QMouseEvent *event)
0112 {
0113     if (m_cropping && (event->buttons() & Qt::LeftButton)) {
0114         m_end = event->pos();
0115         m_crop = pixmapRect().intersected(QRect(m_start, m_end).normalized());
0116     }
0117 
0118     update();
0119 }
0120 
0121 void ScaledPixmapLabel::mouseReleaseEvent(QMouseEvent *event)
0122 {
0123     if (m_cropping) {
0124         m_end = event->pos();
0125         m_crop = pixmapRect().intersected(QRect(m_start, m_end).normalized());
0126         update();
0127 
0128         double scale = (double)m_pixmap.size().width() / (double)pixmap()->size().width();
0129         m_crop.translate(-pixmapRect().topLeft());
0130         QRectF cropF(scale * m_crop.x(), scale * m_crop.y(), scale * m_crop.width(), scale * m_crop.height());
0131 
0132         emit imageCropped(cropF);
0133 
0134         m_crop = QRect();
0135     }
0136 }
0137 
0138 void ScaledPixmapLabel::leaveEvent(QEvent *event)
0139 {
0140     update();
0141     QLabel::leaveEvent(event);
0142 }
0143 
0144 #include "moc_ScaledPixmapLabel.cpp"