1
# This file is part of the Frescobaldi project, http://www.frescobaldi.org/
3
# Copyright (c) 2008 - 2011 by Wilbert Berendsen
5
# This program is free software; you can redistribute it and/or
6
# modify it under the terms of the GNU General Public License
7
# as published by the Free Software Foundation; either version 2
8
# of the License, or (at your option) any later version.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
# See http://www.gnu.org/licenses/ for more information.
21
A simple scrollarea that can display an image.
24
from __future__ import unicode_literals
26
from PyQt4.QtCore import pyqtSignal, QMimeData, QSize, QRect, Qt
27
from PyQt4.QtGui import (
28
QApplication, QDrag, QImage, QPainter, QPalette, QPixmap, QScrollArea,
32
__all__ = ['ImageViewer']
40
class ImageViewer(QScrollArea):
42
actualSizeChanged = pyqtSignal(bool)
44
def __init__(self, parent=None):
45
super(ImageViewer, self).__init__(parent, alignment=Qt.AlignCenter)
46
self._actualsize = True
47
self._image = QImage()
48
self.setBackgroundRole(QPalette.Dark)
49
self.setWidget(ImageWidget(self))
51
def setActualSize(self, enabled=True):
52
if enabled == self._actualsize:
54
self.setWidgetResizable(not enabled)
55
if enabled and not self._image.isNull():
56
self.widget().resize(self._image.size())
57
self._actualsize = enabled
58
self.actualSizeChanged.emit(enabled)
61
return self._actualsize
63
def setImage(self, image):
66
self._pixmapsize = None
68
self.widget().resize(image.size())
69
self.widget().update()
74
def pixmap(self, size):
75
"""Returns (and caches) a scaled pixmap for the image."""
76
if self._pixmapsize == size:
78
self._pixmap = QPixmap.fromImage(
79
self._image.scaled(size, Qt.KeepAspectRatio, Qt.SmoothTransformation))
80
self._pixmapsize = size
86
data.setImageData(image)
88
drag.setMimeData(data)
89
if max(image.width(), image.height()) > 256:
90
image = image.scaled(QSize(256, 256), Qt.KeepAspectRatio, Qt.SmoothTransformation)
91
pixmap = QPixmap.fromImage(image)
92
drag.setPixmap(pixmap)
93
drag.setHotSpot(pixmap.rect().center())
94
drag.exec_(Qt.CopyAction)
97
class ImageWidget(QWidget):
98
def __init__(self, viewer):
99
super(ImageWidget, self).__init__()
101
self.setBackgroundRole(QPalette.Dark)
102
self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
104
self._startpos = None
106
def paintEvent(self, ev):
107
image = self.viewer.image()
108
painter = QPainter(self)
109
if self.size() == image.size():
110
painter.drawImage(ev.rect(), image, ev.rect())
113
s.scale(self.size(), Qt.KeepAspectRatio)
116
r.moveCenter(self.rect().center())
117
painter.drawPixmap(r, self.viewer.pixmap(s))
119
def mousePressEvent(self, ev):
120
if ev.button() == Qt.LeftButton:
121
if ev.modifiers() & Qt.ControlModifier:
125
self._startpos = ev.globalPos()
127
def mouseMoveEvent(self, ev):
128
diff = self._startpos - ev.globalPos()
129
if self._mode == MOVE:
130
self._startpos = ev.globalPos()
131
h = self.viewer.horizontalScrollBar()
132
v = self.viewer.verticalScrollBar()
133
h.setValue(h.value() + diff.x())
134
v.setValue(v.value() + diff.y())
135
elif self._mode == DRAG and diff.manhattanLength() >= QApplication.startDragDistance():
136
self.viewer.startDrag()
138
def mouseReleaseEvent(self, ev):
139
mode, self._mode = self._mode, None
140
if (ev.button() == Qt.LeftButton and
141
mode == DRAG and ev.globalPos() == self._startpos):
142
self.viewer.setActualSize(not self.viewer.actualSize())