:version: $RCSfile: index.rst,v $ $Revision: 693361f85272 $ $Date: 2010/08/23 15:08:52 $

======================
 Implementation Notes
======================

Qt Programming Notes
====================

.. currentmodule:: imageviewer

The :mod:`imageviewer` module demonstrates:

+ Using |QGraphicsView| to implement zooming & panning of a
  |QPixmap|. This works much faster for large images at high zoom levels
  than :fs:`PyQt4\\examples\\widgets\\imageviewer.pyw` which uses a
  :qtref:`QLabel <qlabel>`. The Qt documentation for the slower
  ImageViewer example is at the `nokia website
  <http://doc.qt.nokia.com/latest/widgets-imageviewer.html>`_.

+ Keeping track of scroll and view transform changes so other classes
  can implement synchronized zooming and panning of multiple views.

+ Zooming by :kbd:`Ctrl+Mouse wheel` rolling in
  :meth:`SynchableGraphicsView.wheelEvent` (|QGraphicsView| already
  handles vertical scrolling by rolling the mouse wheel, and horizontal
  scrolling via :kbd:`Alt+Mouse wheel` rolling)

.. currentmodule:: mdiimageviewer

The :mod:`mdiimageviewer` module demonstrates:

+ Synchronized zooming and panning of multiple image viewers.

+ Activating ``QtGui.QGraphicsView.ScrollHandDrag`` while the
  :kbd:`Space` key is held down in :meth:`MdiChild.keyPressEvent`.

  The documentation at
  http://doc.qt.nokia.com/latest/qwidget.html#keyReleaseEvent is a bit
  unclear. It means that ``keyReleaseEvents`` are normally not passed on
  to other classes since the default implementation is to ``accept()``
  the event.

  You have to override ``keyPressEvent`` and call ``event.ignore()`` to
  allow ``keyPressEvent``\ s to be seen by other classes.

+ Using :qtref:`QSignalMapper <qsignalmapper>` to implement a Recently
  Used Files list on the :guilabel:`File` menu in
  :meth:`MDIImageViewerWindow.updateRecentFileActions`.

+ Using :qtref:`QSignalMapper <qsignalmapper>` to call methods ---
  specified by string --- of the currently active subwindow in
  :meth:`MDIImageViewerWindow.createMappedAction`.

+ Using `shortcutContext
  <http://doc.qt.nokia.com/latest/qaction.html#shortcutContext-prop>`_
  in :meth:`MDIImageViewerWindow.createActions` to avoid
  ``QAction::eventFilter: Ambiguous shortcut overload: Ctrl+F4``
  messages::

     self._closeAct = QtGui.QAction(
         "Cl&ose", self,
         shortcut=QtGui.QKeySequence.Close,
         shortcutContext=QtCore.Qt.WidgetShortcut,
         statusTip="Close the active window",
         triggered=self._mdiArea.closeActiveSubWindow)

+ Activating the window system menu of MDI subwindows via
  :kbd:`Ctrl+Space` (:kbd:`Alt+Space` activates the Main Window system
  menu) in :meth:`MDIImageViewerWindow.createActions`. A |QAction| is
  created and ``addAction()`` of |QMainWindow| is used rather than
  adding it to a |QMenu| (since we don't want it to be a visible menu
  item).

+ Using the status bar to display image information for the currently
  active subwindow in :meth:`MDIImageViewerWindow.updateStatusBar`.
 
+ Using Qt resource files for menu icons.

+ Saving application window size & position in
  :meth:`MDIImageViewerWindow.writeSettings`.

+ Saving File Open dialog size, position & state (including selected
  filter name) in :meth:`MDIImageViewerWindow.saveDialogState`.


PyQt Programming Notes
======================

The following is done to use the more pythonic :pyqt4ref:`PyQt API
version 2 <selecting-incompatible-apis>` whether or not you are using
Python 2 or Python 3::

   import sip
   sip.setapi('QDate', 2)
   sip.setapi('QTime', 2)
   sip.setapi('QDateTime', 2)
   sip.setapi('QUrl', 2)
   sip.setapi('QTextStream', 2)
   sip.setapi('QVariant', 2)
   sip.setapi('QString', 2)

I use the :pyqt4ref:`new-style signal/slot mechanism
<new-style-signal-and-slot-support>`::

   self._mdiArea.subWindowActivated.connect(self.subWindowActivated)

rather than the :pyqt4ref:`older mechanism
<old-style-signal-and-slot-support>`::

   QtCore.QObject.connect(self._mdiArea, QtCore.SIGNAL("subWindowActivated()"), self, QtCore.SLOT("subWindowActivated()"))


I used :pyqt4ref:`pyrcc4 <pyrcc4>` to convert a Qt resource collection
file :fs:`icons.qrc` into :fs:`icons_rc.py` which can be imported into
any python file. For example the icon :fs:`exit.png` can then be
referenced simply by doing::

   import icons_rc
   ...
   self._exitAct = QtGui.QAction(
       QtGui.QIcon(':/exit.png'),
       "E&xit", self,
       shortcut=QtGui.QKeySequence.Quit,
       statusTip="Exit the application",
       triggered=QtGui.qApp.closeAllWindows)


Python Programming Notes
========================

The following is done to allow Python 3 syntax even when running Python
2.6+::

   from __future__ import division
   from __future__ import print_function
   from __future__ import unicode_literals
   from future_builtins import *

In theory these programs should work equally well under Python 3 but
that hasn't been tested yet.


Sphinx Documentation Notes
==========================

I've written all the project documentation (including these web pages)
using `Sphinx <http://sphinx.pocoo.org>`_ --- the source files can be
found on `here
<http://github.com/tpgit/MDIImageViewer/tree/master/sphinx/>`_.

The Sphinx techniques demonstrated are:

+ Generating an "orphan" Home page that uses a custom sidebar.

+ Using the `autodoc extension
  <http://sphinx.pocoo.org/ext/autodoc.html>`_ to generate the :doc:`module
  documentation <modules>`.

+ Using the `inheritance diagram extension
  <http://sphinx.pocoo.org/ext/inheritance.html>`_ to add inheritance
  diagrams to the :doc:`module documentation <modules>`.

+ Using the `extlinks extension
  <http://sphinx.pocoo.org/ext/extlinks.html>`_ to shorten references to
  the `PyQt v4 - Python Bindings for Qt v4: Reference Guide
  <http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/pyqt4ref.html>`_
  and the `Qt Class Documentation
  <http://doc.qt.nokia.com/latest/classes.html>`_.

+ Creating a custom theme (based of the `default
  <http://sphinx.pocoo.org/theming.html#builtin-themes>`_ theme) to have
  a custom footer with the `Creative Commons Attribution 3.0
  <http://creativecommons.org/licenses/by/3.0/us/>`_ Licence & logo
  rather than a copyright notice. I also have a custom ``css`` file to
  style some elements differently than the defaults.

+ Using a global Table of Contents in the sidebar navigation panel with
  the current page indicated with a yellowish bullet. Most of the sites
  I've seen use the local TOC which means you have to jump back to their
  separate Table of Contents page to get a site overview.

+ Using the ``rst_prolog`` :fs:`conf.py` setting to create a custom
  ``role`` that can be used in any of the source directory's :fs:`.rst`
  files.

+ Using the ``rst_prolog`` :fs:`conf.py` setting to create quick
  replacements for common Qt Class documentation links. For example,
  ``|QGraphicsView|`` generates the following link:
  |QGraphicsView|. These replacements even work inside Python
  docstrings.

Project Hosting on GitHub Notes
===============================

You can directly use Sphinx generated pages as `GitHub Pages
<http://pages.github.com/>`_, but as the "Using Jekyll For Complex
Layouts" section explains:

   "As of December 27, 2009, you can completely opt-out of Jekyll
   processing by creating a file named :fs:`.nojekyll` in the root of
   your pages repo and pushing that to GitHub. This should only be
   necessary if your site uses directories that begin with an
   underscore, as Jekyll sees these as special dirs and does not copy
   them to the final destination."

Since Sphinx generates a number of subdirectories that start with ``_``
in its build directory, adding :fs:`.nojekyll` is thus required.

..
   Local Variables:
   coding: utf-8
   mode: rst
   indent-tabs-mode: nil
   sentence-end-double-space: t
   fill-column: 72
   mode: auto-fill
   standard-indent: 3
   tab-stop-list: (3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60)
   End: