#!/usr/bin/env python
##
## This file is part of pyFormex 1.0.7 (Mon Jun 17 12:20:39 CEST 2019)
## pyFormex is a tool for generating, manipulating and transforming 3D
## geometrical models by sequences of mathematical operations.
## Home page: http://pyformex.org
## Project page: http://savannah.nongnu.org/projects/pyformex/
## Copyright 2004-2019 (C) Benedict Verhegghe (benedict.verhegghe@ugent.be)
## Distributed under the GNU General Public License version 3 or later.
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see http://www.gnu.org/licenses/.
##
"""A general image viewer
Part of this code was borrowed from the TrollTech Qt examples.
"""
from __future__ import absolute_import, division, print_function
caption = "pyFormex Image Viewer"
from pyformex.gui import QtCore, QtGui, QtWidgets, QPixmap, QImage
def tr(s):
return QtCore.QCoreApplication.translate('ImageViewer', s)
[docs]class ImageViewer(QtWidgets.QMainWindow):
"""pyFormex image viewer
The pyFormex image viewer was shaped after the Image Viewer from the
TrollTech Qt documentation.
It can be use as stand alone application, as well as from inside
pyFormex. The viewer allows browsing through directories, selecting
an image to be displayed. The image can be resized to fit a window.
Parameters:
- `parent`: The parent Qt4 widget (the Qt4 app in the stand alone case).
- `path`: string: the full path to the image to be initially displayed.
"""
def __init__(self, parent=None, path=None):
QtGui.QMainWindow.__init__(self)
self.parent = parent
self.filename = path
self.image = QtGui.QLabel()
self.image.setBackgroundRole(QtGui.QPalette.Base)
self.image.setSizePolicy(QtGui.QSizePolicy.Ignored, QtGui.QSizePolicy.Ignored)
#self.image.setScaledContents(True)
self.scroll = QtGui.QScrollArea()
self.scroll.setBackgroundRole(QtGui.QPalette.Dark)
self.scroll.setWidget(self.image)
self.scroll.setWidgetResizable(True)
self.setCentralWidget(self.scroll)
self.createActions()
self.createMenus()
self.setWindowTitle(tr(caption))
self.resize(500, 400)
self.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum)
if path:
self.openfile(path)
def openfile(self, filename=None):
if filename is None:
filename = self.filename
if filename is None:
filename = QtCore.QDir.currentPath()
filename = QtGui.QFileDialog.getOpenFileName(self, tr("Open File"), filename)
if not filename:
return
image = QImage(filename)
if image.isNull():
QtGui.QMessageBox.information(self, tr(caption), tr("Cannot load %1.").arg(filename))
return
#print("Size %sx%s" % (image.width(),image.height()))
self.filename = str(filename)
self.image.setPixmap(QPixmap.fromImage(image))
self.scaleFactor = 1.0
self.printAct.setEnabled(True)
self.fitToWindowAct.setEnabled(True)
self.updateActions()
## if not self.fitToWindowAct.isChecked():
self.image.adjustSize()
self.normalSize()
def print_(self):
if not self.image.pixmap():
return
self.printer = QtGui.QPrinter()
dialog = QtGui.QPrintDialog(self.printer, self)
if dialog.exec_():
painter = QtGui.QPainter(self.printer)
rect = painter.viewport()
size = self.image.pixmap().size()
size.scale(rect.size(), QtCore.Qt.KeepAspectRatio)
painter.setViewport(rect.x(), rect.y(), size.width(), size.height())
painter.setWindow(self.image.pixmap().rect())
painter.drawPixmap(0, 0, self.image.pixmap())
def zoomIn(self):
self.scaleImage(1.25)
def zoomOut(self):
self.scaleImage(0.8)
def normalSize(self):
self.image.resize(self.image.pixmap().size())
#self.image.adjustSize()
self.scaleFactor = 1.0
def fitToWindow(self):
fitToWindow = self.fitToWindowAct.isChecked()
self.scroll.setWidgetResizable(fitToWindow)
if not fitToWindow:
self.normalSize()
self.updateActions()
def fitToImage(self):
self.normalSize()
self.scroll.resize(self.image.size())
def about(self):
QtGui.QMessageBox.about(self, tr("About pyFormex Image Viewer"), tr("""
<p>The <b>pyFormex Image Viewer</b> was shaped after the
<b>Image Viewer</b> from the TrollTech Qt documentation.</p>
<p>The example shows how to combine QLabel
and QScrollArea to display an image. QLabel is typically used
for displaying a text,but it can also display an image.
QScrollArea provides a scrolling view around another widget.
If the child widget exceeds the size of the frame,QScrollArea
automatically provides scroll bars. </p>
<p>The example
demonstrates how QLabel's ability to scale its contents
(QLabel.scaledContents),and QScrollArea's ability to
automatically resize its contents
(QScrollArea.widgetResizable),can be used to implement
zooming and scaling features. </p>
<p>In addition the example
shows how to use QPainter to print an image.</p>
"""))
def createActions(self):
self.openAct = QtGui.QAction(tr("&Open..."), self)
self.openAct.setShortcut(tr("Ctrl+O"))
self.openAct.triggered.connect(self.openfile)
self.printAct = QtGui.QAction(tr("&Print..."), self)
self.printAct.setShortcut(tr("Ctrl+P"))
self.printAct.setEnabled(False)
self.printAct.triggered.connect(self.print_)
self.zoomInAct = QtGui.QAction(tr("Zoom &In (25%)"), self)
self.zoomInAct.setShortcut(tr("Ctrl++"))
self.zoomInAct.setEnabled(False)
self.zoomInAct.triggered.connect(self.zoomIn)
self.zoomOutAct = QtGui.QAction(tr("Zoom &Out (25%)"), self)
self.zoomOutAct.setShortcut(tr("Ctrl+-"))
self.zoomOutAct.setEnabled(False)
self.zoomOutAct.triggered.connect(self.zoomOut)
self.normalSizeAct = QtGui.QAction(tr("&Normal Size"), self)
self.normalSizeAct.setShortcut(tr("Ctrl+S"))
self.normalSizeAct.setEnabled(False)
self.normalSizeAct.triggered.connect(self.normalSize)
self.fitToImageAct = QtGui.QAction(tr("Fit &Window to Image"), self)
self.fitToImageAct.setShortcut(tr("Ctrl+W"))
self.fitToImageAct.setEnabled(False)
#self.fitToImageAct.setCheckable(True)
self.fitToImageAct.triggered.connect(self.fitToImage)
self.fitToWindowAct = QtGui.QAction(tr("&Fit Image to Window"), self)
self.fitToWindowAct.setShortcut(tr("Ctrl+F"))
self.fitToWindowAct.setEnabled(False)
self.fitToWindowAct.setCheckable(True)
self.fitToWindowAct.triggered.connect(self.fitToWindow)
self.aboutAct = QtGui.QAction(tr("&About"), self)
self.aboutAct.triggered.connect(self.about)
if isinstance(self.parent, QtGui.QApplication):
self.exitAct = QtGui.QAction(tr("E&xit"), self)
self.exitAct.setShortcut(tr("Ctrl+Q"))
self.exitAct.triggered.connect(self.close)
self.aboutQtAct = QtGui.QAction(tr("About &Qt"), self)
self.aboutQtAct.triggered.connect(self.parent.aboutQt)
elif isinstance(self.parent, QtWidgets.QDialog):
self.acceptAct = QtGui.QAction(tr("&Accept"), self)
self.acceptAct.setShortcut(tr("Ctrl+A"))
self.acceptAct.triggered.connect(self.parent.accept)
self.rejectAct = QtGui.QAction(tr("&Reject"), self)
self.rejectAct.setShortcut(tr("Ctrl+Q"))
self.rejectAct.triggered.connect(self.parent.reject)
def createMenus(self):
self.fileMenu = QtGui.QMenu(tr("&File"), self)
self.fileMenu.addAction(self.openAct)
self.fileMenu.addAction(self.printAct)
self.fileMenu.addSeparator()
self.viewMenu = QtGui.QMenu(tr("&View"), self)
self.viewMenu.addAction(self.zoomInAct)
self.viewMenu.addAction(self.zoomOutAct)
self.viewMenu.addAction(self.normalSizeAct)
self.viewMenu.addSeparator()
self.viewMenu.addAction(self.fitToImageAct)
self.viewMenu.addAction(self.fitToWindowAct)
self.helpMenu = QtGui.QMenu(tr("&Help"), self)
self.helpMenu.addAction(self.aboutAct)
self.menuBar().addMenu(self.fileMenu)
self.menuBar().addMenu(self.viewMenu)
self.menuBar().addMenu(self.helpMenu)
if isinstance(self.parent, QtGui.QApplication):
self.fileMenu.addAction(self.exitAct)
self.helpMenu.addAction(self.aboutQtAct)
elif isinstance(self.parent, QtWidgets.QDialog):
self.fileMenu.addAction(self.acceptAct)
self.fileMenu.addAction(self.rejectAct)
def updateActions(self):
self.zoomInAct.setEnabled(not self.fitToWindowAct.isChecked())
self.zoomOutAct.setEnabled(not self.fitToWindowAct.isChecked())
self.normalSizeAct.setEnabled(not self.fitToWindowAct.isChecked())
self.fitToImageAct.setEnabled(not self.fitToWindowAct.isChecked())
def scaleImage(self, factor):
if not self.image.pixmap():
return
self.scaleFactor *= factor
self.image.resize(self.scaleFactor * self.image.pixmap().size())
self.adjustScrollBar(self.scroll.horizontalScrollBar(), factor)
self.adjustScrollBar(self.scroll.verticalScrollBar(), factor)
self.zoomInAct.setEnabled(self.scaleFactor < 3.0)
self.zoomOutAct.setEnabled(self.scaleFactor > 0.333)
def adjustScrollBar(self, scrollBar, factor):
scrollBar.setValue(int(factor * scrollBar.value() + ((factor - 1) * scrollBar.pageStep()/2)))
def main():
import sys
global app
app = QtGui.QApplication(sys.argv)
if len(sys.argv) > 1:
path = sys.argv[1]
else:
path = None
viewer = ImageViewer(app, path)
viewer.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()