185 lines
4.2 KiB
C++
185 lines
4.2 KiB
C++
#include "image_view.h"
|
|
|
|
#include <QBuffer>
|
|
#include <QDebug>
|
|
#include <QEvent>
|
|
#include <QGraphicsPixmapItem>
|
|
#include <QGraphicsScene>
|
|
#include <QMouseEvent>
|
|
#include <QScrollBar>
|
|
#include <QWheelEvent>
|
|
#include <qmath.h>
|
|
|
|
|
|
ImageView::ImageView(QWidget * parent): QGraphicsView(parent), item(new QGraphicsPixmapItem) {
|
|
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
setDragMode(QGraphicsView::NoDrag);
|
|
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
|
|
setScene(new QGraphicsScene());
|
|
setRenderHint(QPainter::Antialiasing, true);
|
|
setRenderHint(QPainter::SmoothPixmapTransform, true);
|
|
item->setTransformationMode(Qt::SmoothTransformation);
|
|
item->setFlags(QGraphicsItem::GraphicsItemFlags());
|
|
scene()->addItem(item);
|
|
viewport()->setAutoFillBackground(false);
|
|
viewport()->installEventFilter(this);
|
|
autofit_ = smooth_big = true;
|
|
interactive_ = false;
|
|
}
|
|
|
|
|
|
ImageView::~ImageView() {
|
|
delete item;
|
|
}
|
|
|
|
|
|
QPixmap ImageView::pixmap() const {
|
|
return map;
|
|
}
|
|
|
|
|
|
void ImageView::setPixmap(QPixmap pixmap) {
|
|
map = pixmap;
|
|
adjustView();
|
|
}
|
|
|
|
|
|
void ImageView::setViewInteractive(bool yes) {
|
|
interactive_ = yes;
|
|
}
|
|
|
|
|
|
void ImageView::setImage(const QImage & i, bool save) {
|
|
im_data.clear();
|
|
if (i.isNull()) {
|
|
item->setPixmap(QPixmap());
|
|
map = QPixmap();
|
|
return;
|
|
}
|
|
if (save) {
|
|
QBuffer b(&im_data);
|
|
b.open(QIODevice::ReadWrite);
|
|
i.save(&b, "png");
|
|
b.close();
|
|
}
|
|
map = QPixmap::fromImage(i);
|
|
adjustView();
|
|
}
|
|
|
|
|
|
void ImageView::setImage(const QByteArray & i) {
|
|
im_data = i;
|
|
if (i.isEmpty()) {
|
|
item->setPixmap(QPixmap());
|
|
map = QPixmap();
|
|
return;
|
|
}
|
|
map = QPixmap::fromImage(QImage::fromData(i));
|
|
adjustView();
|
|
}
|
|
|
|
|
|
void ImageView::clear() {
|
|
im_data.clear();
|
|
item->setPixmap(QPixmap());
|
|
map = QPixmap();
|
|
}
|
|
|
|
|
|
void ImageView::setSmoothBigImages(bool yes) {
|
|
smooth_big = yes;
|
|
adjustView();
|
|
}
|
|
|
|
|
|
void ImageView::mouseDoubleClickEvent(QMouseEvent *) {
|
|
autofit();
|
|
}
|
|
|
|
|
|
void ImageView::mousePressEvent(QMouseEvent * e) {
|
|
QGraphicsView::mousePressEvent(e);
|
|
emit clicked(mapToScene(e->pos()), e->buttons());
|
|
}
|
|
|
|
|
|
void ImageView::mouseMoveEvent(QMouseEvent * e) {
|
|
QGraphicsView::mouseMoveEvent(e);
|
|
emit hovered(mapToScene(e->pos()), e->buttons());
|
|
}
|
|
|
|
|
|
void ImageView::mouseReleaseEvent(QMouseEvent * e) {
|
|
QGraphicsView::mouseReleaseEvent(e);
|
|
emit released(mapToScene(e->pos()), e->buttons());
|
|
}
|
|
|
|
|
|
void ImageView::wheelEvent(QWheelEvent * e) {
|
|
if (!e->modifiers().testFlag(Qt::ControlModifier) || !viewInteractive()) return;
|
|
double scl = 1. + e->angleDelta().y() / 500.;
|
|
autofit_ = false;
|
|
scale(scl, scl);
|
|
}
|
|
|
|
|
|
bool ImageView::eventFilter(QObject * o, QEvent * e) {
|
|
QMouseEvent * me = reinterpret_cast<QMouseEvent *>(e);
|
|
switch (e->type()) {
|
|
case QEvent::Resize: adjustView(); break;
|
|
case QEvent::MouseButtonPress:
|
|
prev_pos = me->pos();
|
|
if (me->buttons().testFlag(Qt::RightButton) && !autofit_ && viewInteractive()) viewport()->setCursor(Qt::ClosedHandCursor);
|
|
break;
|
|
case QEvent::MouseButtonRelease:
|
|
viewport()->unsetCursor();
|
|
prev_pos = me->pos();
|
|
break;
|
|
case QEvent::MouseMove:
|
|
if (me->buttons().testFlag(Qt::RightButton) && !autofit_ && viewInteractive()) {
|
|
QPoint dp = QPoint(me->pos() - prev_pos);
|
|
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - dp.x());
|
|
verticalScrollBar()->setValue(verticalScrollBar()->value() - dp.y());
|
|
prev_pos = me->pos();
|
|
}
|
|
break;
|
|
default: break;
|
|
}
|
|
return QGraphicsView::eventFilter(o, e);
|
|
}
|
|
|
|
|
|
void ImageView::adjustView() {
|
|
item->setScale(1.);
|
|
if (smooth_big) {
|
|
QSize ws = size();
|
|
#if QT_VERSION_MAJOR >= 5
|
|
ws *= devicePixelRatio();
|
|
#endif
|
|
int nw = map.size().boundedTo(ws).width();
|
|
if (nw > 0) {
|
|
qreal mp = map.width() / nw;
|
|
if (mp > 1.) {
|
|
QSize ss = map.size();
|
|
item->setPixmap(map.scaled(map.size() / mp, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
|
item->setScale(double(ss.width()) / item->pixmap().width());
|
|
} else
|
|
item->setPixmap(map);
|
|
} else
|
|
item->setPixmap(map);
|
|
} else
|
|
item->setPixmap(map);
|
|
if (!autofit_) return;
|
|
QRectF r = item->mapRectToScene(item->boundingRect());
|
|
setSceneRect(r);
|
|
fitInView(r, Qt::KeepAspectRatio);
|
|
centerOn(r.center());
|
|
}
|
|
|
|
|
|
void ImageView::autofit() {
|
|
autofit_ = true;
|
|
adjustView();
|
|
}
|