#!/usr/bin/env python

#############################################################################
##
## Copyright (C) 2005-2005 Trolltech AS. All rights reserved.
##
## This file is part of the example classes of the Qt Toolkit.
##
## This file may be used under the terms of the GNU General Public
## License version 2.0 as published by the Free Software Foundation
## and appearing in the file LICENSE.GPL included in the packaging of
## this file.  Please review the following information to ensure GNU
## General Public Licensing requirements will be met:
## http://www.trolltech.com/products/qt/opensource.html
##
## If you are unsure which license is appropriate for your use, please
## review the following information:
## http://www.trolltech.com/products/qt/licensing.html or contact the
## sales department at sales@trolltech.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################

import sys
from PyQt4 import QtCore, QtGui


class ImageViewer(QtGui.QMainWindow):
    def __init__(self, parent = None):
        QtGui.QMainWindow.__init__(self, parent)

        self.printer = QtGui.QPrinter()
        self.scaleFactor = 1.0

        self.imageLabel = QtGui.QLabel()
        self.imageLabel.setBackgroundRole(QtGui.QPalette.Base)
        self.imageLabel.setSizePolicy(QtGui.QSizePolicy.Ignored, QtGui.QSizePolicy.Ignored)
        self.imageLabel.setScaledContents(True)

        self.scrollArea = QtGui.QScrollArea()
        self.scrollArea.setBackgroundRole(QtGui.QPalette.Dark)
        self.scrollArea.setWidget(self.imageLabel)
        self.setCentralWidget(self.scrollArea)

        self.createActions()
        self.createMenus()

        self.setWindowTitle(self.tr("Image Viewer"))
        self.resize(500, 400)

    def open(self):
        fileName = QtGui.QFileDialog.getOpenFileName(self, self.tr("Open File"),
                                                     QtCore.QDir.currentPath())
        if not fileName.isEmpty():
            image = QtGui.QImage(fileName)
            if image.isNull():
                QtGui.QMessageBox.information(self, self.tr("Image Viewer"),
                                              self.tr("Cannot load %1.").arg(fileName))
                return

            self.imageLabel.setPixmap(QtGui.QPixmap.fromImage(image))
            self.scaleFactor = 1.0

            self.printAct.setEnabled(True)
            self.fitToWindowAct.setEnabled(True)
            self.updateActions()

            if not self.fitToWindowAct.isChecked():
                self.imageLabel.adjustSize()

    def print_(self):
        dialog = QtGui.QPrintDialog(self.printer, self)
        if dialog.exec_():
            painter = QtGui.QPainter()
            painter.begin(self.printer)
            rect = painter.viewport()
            size = self.imageLabel.pixmap().size()
            size.scale(rect.size(), QtCore.Qt.KeepAspectRatio)
            painter.setViewport(rect.x(), rect.y(), size.width(), size.height())
            painter.setWindow(self.imageLabel.pixmap().rect())
            painter.drawPixmap(0, 0, self.imageLabel.pixmap())

    def zoomIn(self):
        self.scaleImage(1.25)

    def zoomOut(self):
        self.scaleImage(0.8)

    def normalSize(self):
        self.imageLabel.adjustSize()
        self.scaleFactor = 1.0

    def fitToWindow(self):
        fitToWindow = self.fitToWindowAct.isChecked()
        self.scrollArea.setWidgetResizable(fitToWindow)
        if not fitToWindow:
            self.imageLabel.adjustSize()

        self.updateActions()

    def about(self):
        QtGui.QMessageBox.about(self, self.tr("About Image Viewer"), self.tr(
              "<p>The <b>Image Viewer</b> 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(self.tr("&Open..."), self)
        self.openAct.setShortcut(self.tr("Ctrl+O"))
        self.connect(self.openAct, QtCore.SIGNAL("triggered()"), self.open)

        self.printAct = QtGui.QAction(self.tr("&Print..."), self)
        self.printAct.setShortcut(self.tr("Ctrl+P"))
        self.printAct.setEnabled(False)
        self.connect(self.printAct, QtCore.SIGNAL("triggered()"), self.print_)

        self.exitAct = QtGui.QAction(self.tr("E&xit"), self)
        self.exitAct.setShortcut(self.tr("Ctrl+Q"))
        self.connect(self.exitAct, QtCore.SIGNAL("triggered()"), self, QtCore.SLOT("close()"))

        self.zoomInAct = QtGui.QAction(self.tr("Zoom &In (25%)"), self)
        self.zoomInAct.setShortcut(self.tr("Ctrl++"))
        self.zoomInAct.setEnabled(False)
        self.connect(self.zoomInAct, QtCore.SIGNAL("triggered()"), self.zoomIn)

        self.zoomOutAct = QtGui.QAction(self.tr("Zoom &Out (25%)"), self)
        self.zoomOutAct.setShortcut(self.tr("Ctrl+-"))
        self.zoomOutAct.setEnabled(False)
        self.connect(self.zoomOutAct, QtCore.SIGNAL("triggered()"), self.zoomOut)

        self.normalSizeAct = QtGui.QAction(self.tr("&Normal Size"), self)
        self.normalSizeAct.setShortcut(self.tr("Ctrl+S"))
        self.normalSizeAct.setEnabled(False)
        self.connect(self.normalSizeAct, QtCore.SIGNAL("triggered()"), self.normalSize)

        self.fitToWindowAct = QtGui.QAction(self.tr("&Fit to Window"), self)
        self.fitToWindowAct.setEnabled(False)
        self.fitToWindowAct.setCheckable(True)
        self.fitToWindowAct.setShortcut(self.tr("Ctrl+F"))
        self.connect(self.fitToWindowAct, QtCore.SIGNAL("triggered()"), self.fitToWindow)

        self.aboutAct = QtGui.QAction(self.tr("&About"), self)
        self.connect(self.aboutAct, QtCore.SIGNAL("triggered()"), self.about)

        self.aboutQtAct = QtGui.QAction(self.tr("About &Qt"), self)
        self.connect(self.aboutQtAct, QtCore.SIGNAL("triggered()"), QtGui.qApp, QtCore.SLOT("aboutQt()"))

    def createMenus(self):
        self.fileMenu = QtGui.QMenu(self.tr("&File"), self)
        self.fileMenu.addAction(self.openAct)
        self.fileMenu.addAction(self.printAct)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.exitAct)

        self.viewMenu = QtGui.QMenu(self.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.fitToWindowAct)

        self.helpMenu = QtGui.QMenu(self.tr("&Help"), self)
        self.helpMenu.addAction(self.aboutAct)
        self.helpMenu.addAction(self.aboutQtAct)

        self.menuBar().addMenu(self.fileMenu)
        self.menuBar().addMenu(self.viewMenu)
        self.menuBar().addMenu(self.helpMenu)

    def updateActions(self):
        self.zoomInAct.setEnabled(not self.fitToWindowAct.isChecked())
        self.zoomOutAct.setEnabled(not self.fitToWindowAct.isChecked())
        self.normalSizeAct.setEnabled(not self.fitToWindowAct.isChecked())

    def scaleImage(self, factor):
        self.scaleFactor *= factor
        self.imageLabel.resize(self.scaleFactor * self.imageLabel.pixmap().size())

        self.adjustScrollBar(self.scrollArea.horizontalScrollBar(), factor)
        self.adjustScrollBar(self.scrollArea.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)))


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    imageViewer = ImageViewer()
    imageViewer.show()
    sys.exit(app.exec_())
