1 /*
2 * Copyright (C) 2015 by Stephen Allewell
3 * steve.allewell@gmail.com
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 */
10
11
12 /** @file
13 * This file defines an extension to a QLabel that scales the associated QPixmap
14 * to maintain the aspect ratio when scaling to fill the extents of the QLabel
15 * area.
16 */
17
18
19 // Class include
20 #include "ScaledPixmapLabel.h"
21
22 // Qt includes
23 #include <QMouseEvent>
24 #include <QPainter>
25 #include <QStyleOptionRubberBand>
26
27
ScaledPixmapLabel(QWidget * parent)28 ScaledPixmapLabel::ScaledPixmapLabel(QWidget *parent)
29 : QLabel(parent),
30 m_cropping(false)
31 {
32 setMinimumSize(1,1);
33 setAlignment(Qt::AlignCenter);
34 setMouseTracking(true);
35 }
36
37
setPixmap(const QPixmap & pixmap)38 void ScaledPixmapLabel::setPixmap(const QPixmap &pixmap)
39 {
40 m_pixmap = pixmap;
41 m_crop = QRect();
42 QLabel::setPixmap(m_pixmap.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
43 }
44
45
setCropping(bool checked)46 void ScaledPixmapLabel::setCropping(bool checked)
47 {
48 m_cropping = checked;
49 m_crop = QRect();
50 update();
51 }
52
53
heightForWidth(int width) const54 int ScaledPixmapLabel::heightForWidth(int width) const
55 {
56 return ((qreal)m_pixmap.height() * width) / m_pixmap.width();
57 }
58
59
sizeHint() const60 QSize ScaledPixmapLabel::sizeHint() const
61 {
62 int w = width();
63 return QSize(w, heightForWidth(w));
64 }
65
66
pixmapRect() const67 QRect ScaledPixmapLabel::pixmapRect() const
68 {
69 QSize previewSize = size();
70 QSize pixmapSize = pixmap()->size();
71
72 int dx = (previewSize.width() - pixmapSize.width()) / 2;
73 int dy = (previewSize.height() - pixmapSize.height()) / 2;
74
75 return QRect(dx, dy, pixmapSize.width(), pixmapSize.height());
76 }
77
78
resizeEvent(QResizeEvent * event)79 void ScaledPixmapLabel::resizeEvent(QResizeEvent *event)
80 {
81 Q_UNUSED(event);
82
83 QLabel::setPixmap(m_pixmap.scaled(this->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
84 }
85
86
paintEvent(QPaintEvent * event)87 void ScaledPixmapLabel::paintEvent(QPaintEvent *event)
88 {
89 QLabel::paintEvent(event);
90
91 QPainter painter(this);
92 painter.setRenderHint(QPainter::Qt4CompatiblePainting, true);
93
94 if (m_crop.isValid()) {
95
96 QStyleOptionRubberBand opt;
97 opt.initFrom(this);
98 opt.shape = QRubberBand::Rectangle;
99 opt.opaque = false;
100 opt.rect = m_crop.adjusted(0, 0, 1, 1);
101
102 style()->drawControl(QStyle::CE_RubberBand, &opt, &painter);
103 } else {
104 if (m_cropping && underMouse() && (children().count() == 0)) {
105 // draw guides
106 QPoint cursor = mapFromGlobal(QCursor::pos());
107 painter.drawLine(cursor.x(),0,cursor.x(),size().height());
108 painter.drawLine(0,cursor.y(),size().width(),cursor.y());
109 }
110 }
111 }
112
113
mousePressEvent(QMouseEvent * event)114 void ScaledPixmapLabel::mousePressEvent(QMouseEvent *event)
115 {
116 if (m_cropping) {
117 m_start = event->pos();
118 m_crop = QRect();
119 update();
120 }
121 }
122
123
mouseMoveEvent(QMouseEvent * event)124 void ScaledPixmapLabel::mouseMoveEvent(QMouseEvent *event)
125 {
126 if (m_cropping && (event->buttons() & Qt::LeftButton)) {
127 m_end = event->pos();
128 m_crop = pixmapRect().intersected(QRect(m_start, m_end).normalized());
129 }
130
131 update();
132 }
133
134
mouseReleaseEvent(QMouseEvent * event)135 void ScaledPixmapLabel::mouseReleaseEvent(QMouseEvent *event)
136 {
137 if (m_cropping) {
138 m_end = event->pos();
139 m_crop = pixmapRect().intersected(QRect(m_start, m_end).normalized());
140 update();
141
142 double scale = (double)m_pixmap.size().width()/(double)pixmap()->size().width();
143 m_crop.translate(-pixmapRect().topLeft());
144 QRectF cropF(scale*m_crop.x(), scale*m_crop.y(), scale*m_crop.width(), scale*m_crop.height());
145
146 emit imageCropped(cropF);
147
148 m_crop = QRect();
149 }
150 }
151
leaveEvent(QEvent * event)152 void ScaledPixmapLabel::leaveEvent(QEvent *event)
153 {
154 update();
155 QLabel::leaveEvent(event);
156 }
157