#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
**views.py**
**Platform:**
Windows, Linux, Mac Os X.
**Description:**
This module defines the Application Views classes.
**Others:**
"""
#**********************************************************************************************************************
#*** External imports.
#**********************************************************************************************************************
import inspect
import logging
import re
from PyQt4.QtCore import QEvent
from PyQt4.QtCore import QObject
from PyQt4.QtGui import QItemSelection
from PyQt4.QtGui import QItemSelectionModel
from PyQt4.QtGui import QListView
from PyQt4.QtGui import QTreeView
#**********************************************************************************************************************
#*** Internal imports.
#**********************************************************************************************************************
import foundations.core as core
import foundations.exceptions
import foundations.walkers
import umbra.ui.common
from umbra.globals.constants import Constants
#**********************************************************************************************************************
#*** Module attributes.
#**********************************************************************************************************************
__author__ = "Thomas Mansencal"
__copyright__ = "Copyright (C) 2008 - 2012 - Thomas Mansencal"
__license__ = "GPL V3.0 - http://www.gnu.org/licenses/"
__maintainer__ = "Thomas Mansencal"
__email__ = "thomas.mansencal@gmail.com"
__status__ = "Production"
__all__ = ["LOGGER",
"getNodes",
"filterNodes",
"getViewNodesFromIndexes",
"getViewSelectedNodes",
"ReadOnlyFilter",
"selectViewIndexes",
"Abstract_QListView",
"Abstract_QTreeView"]
LOGGER = logging.getLogger(Constants.logger)
#**********************************************************************************************************************
#*** Module classes and definitions.
#**********************************************************************************************************************
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, Exception)
[docs]def getNodes(view):
"""
This method returns the given View nodes.
:param view: View. ( QWidget )
:return: View nodes. ( List )
"""
return [node for node in foundations.walkers.nodesWalker(view.model().rootNode)]
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, Exception)
[docs]def filterNodes(view, pattern, attribute, flags=re.IGNORECASE):
"""
This method filters the given View nodes on given attribute using given pattern.
:param view: View. ( QWidget )
:param pattern: Filtering pattern. ( String )
:param attribute: Filtering attribute. ( String )
:param flags: Regex filtering flags. ( Integer )
:return: View filtered nodes. ( List )
"""
return [node for node in getNodes(view) if re.search(pattern, getattr(node, attribute), flags)]
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, NotImplementedError)
#*** Sphinx: Decorator commented for auto-documentation purpose. # TODO: Implement a way to invalidate indexes in the cache, disabling the cache until yet.
#*** Sphinx: Decorator commented for auto-documentation purpose. # @core.memoize(None)
[docs]def getViewNodesFromIndexes(view, *indexes):
"""
This method returns the given View nodes from given indexes.
:param view: View. ( QWidget )
:param \*indexes: Indexes. ( List )
:return: View nodes. ( Dictionary )
"""
nodes = {}
model = view.model()
if not model:
return nodes
if not hasattr(model, "getNode"):
raise NotImplementedError(
"{0} | '{1}' Model doesn't implement a 'getNode' method!".format(inspect.getmodulename(__file__), model))
if not hasattr(model, "getAttribute"):
raise NotImplementedError(
"{0} | '{1}' Model doesn't implement a 'getAttribute' method!".format(inspect.getmodulename(__file__), model))
for index in indexes:
node = view.model().getNode(index)
if not node in nodes:
nodes[node] = []
attribute = view.model().getAttribute(node, index.column())
attribute and nodes[node].append(attribute)
return nodes
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, Exception)
[docs]def getViewSelectedNodes(view):
"""
This method returns the given View selected nodes.
:param view: View. ( QWidget )
:return: View selected nodes. ( Dictionary )
"""
return getViewNodesFromIndexes(view, *view.selectedIndexes())
[docs]class ReadOnlyFilter(QObject):
"""
This class is a `QObject <http://doc.qt.nokia.com/qobject.html>`_ subclass used as an event filter
for the :class:`Abstract_QListView` and :class:`Abstract_QTreeView` classes.
"""
# @core.executionTrace
[docs] def eventFilter(self, object, event):
"""
This method reimplements the **QObject.eventFilter** method.
:param object: Object. ( QObject )
:param event: Event. ( QEvent )
:return: Event filtered. ( Boolean )
"""
if event.type() == QEvent.MouseButtonDblClick:
view = object.parent()
if view.readOnly:
self.__raiseUserError(view)
return True
return False
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(umbra.ui.common.notifyExceptionHandler,
#*** Sphinx: Decorator commented for auto-documentation purpose. False,
#*** Sphinx: Decorator commented for auto-documentation purpose. foundations.exceptions.UserError)
def __raiseUserError(self, view) :
"""
This method raises an error if the given view has been set read only and the user attempted to edit its content.
:param view: View. ( QWidget )
"""
raise foundations.exceptions.UserError("{0} | Cannot perform action, '{1}' View has been set read only!".format(
self.__class__.__name__, view.objectName() or view))
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, Exception)
[docs]def selectViewIndexes(view, indexes, flags=QItemSelectionModel.Select | QItemSelectionModel.Rows):
"""
This method selects given view indexes.
:param view: View. ( QWidget )
:param indexes: Indexes to select. ( List )
:param flags: Selection flags. ( QItemSelectionModel.SelectionFlags )
:return: Definition success. ( Boolean )
"""
if view.selectionModel():
selection = QItemSelection()
for index in indexes:
selection.merge(QItemSelection(index, index), flags)
view.selectionModel().select(selection, flags)
return True
[docs]class Abstract_QListView(QListView):
"""
This class is a `QListView <http://doc.qt.nokia.com/qlistview.html>`_ subclass used as base
by others Application views classes.
"""
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
def __init__(self, parent=None, readOnly=False):
"""
.. Sphinx: Statements updated for auto-documentation purpose.
:param parent: Object parent. ( QObject )
:param readOnly: View is read only. ( Boolean )
"""
LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__))
QListView.__init__(self, parent)
# --- Setting class attributes. ---
self.__readOnly = readOnly
Abstract_QListView.__initializeUi(self)
#******************************************************************************************************************
#*** Attributes properties.
#******************************************************************************************************************
@property
def readOnly(self):
"""
This method is the property for **self.__readOnly** attribute.
:return: self.__readOnly. ( Boolean )
"""
return self.__readOnly
@readOnly.setter
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, AssertionError)
def readOnly(self, value):
"""
This method is the setter method for **self.__readOnly** attribute.
:param value: Attribute value. ( Boolean )
"""
if value is not None:
assert type(value) is bool, "'{0}' attribute: '{1}' type is not 'bool'!".format("readOnly", value)
self.__readOnly = value
@readOnly.deleter
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, foundations.exceptions.ProgrammingError)
[docs] def readOnly(self):
"""
This method is the deleter method for **self.__readOnly** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "readOnly"))
#******************************************************************************************************************
#*** Class methods.
#******************************************************************************************************************
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
def __initializeUi(self):
"""
This method initializes the View ui.
"""
self.viewport().installEventFilter(ReadOnlyFilter(self))
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, Exception)
[docs] def getNodes(self):
"""
This method returns the View nodes.
:return: View nodes. ( List )
"""
return getNodes(self)
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, Exception)
[docs] def filterNodes(self, pattern, attribute, flags=re.IGNORECASE):
"""
This method filters the View nodes on given attribute using given pattern.
:param pattern: Filtering pattern. ( String )
:param attribute: Filtering attribute. ( String )
:param flags: Regex filtering flags. ( Integer )
:return: View filtered nodes. ( List )
"""
return filterNodes(self, pattern, attribute, flags)
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, Exception)
[docs] def getSelectedNodes(self):
"""
This method returns the View selected nodes.
:return: View selected nodes. ( Dictionary )
"""
return getViewSelectedNodes(self)
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
[docs] def selectIndexes(self, indexes, flags=QItemSelectionModel.Select | QItemSelectionModel.Rows):
"""
This method selects given indexes.
:param indexes: Indexes to select. ( List )
:param flags: Selection flags. ( QItemSelectionModel.SelectionFlags )
:return: Method success. ( Boolean )
"""
return selectViewIndexes(self, indexes, flags)
[docs]class Abstract_QTreeView(QTreeView):
"""
This class is a `QTreeView <http://doc.qt.nokia.com/qtreeview.html>`_ subclass used as base
by others Application views classes.
"""
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
def __init__(self, parent=None, readOnly=False):
"""
.. Sphinx: Statements updated for auto-documentation purpose.
:param parent: Object parent. ( QObject )
:param readOnly: View is read only. ( Boolean )
"""
LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__))
QTreeView.__init__(self, parent)
# --- Setting class attributes. ---
self.__readOnly = readOnly
Abstract_QTreeView.__initializeUi(self)
#******************************************************************************************************************
#*** Attributes properties.
#******************************************************************************************************************
@property
def readOnly(self):
"""
This method is the property for **self.__readOnly** attribute.
:return: self.__readOnly. ( Boolean )
"""
return self.__readOnly
@readOnly.setter
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, AssertionError)
def readOnly(self, value):
"""
This method is the setter method for **self.__readOnly** attribute.
:param value: Attribute value. ( Boolean )
"""
if value is not None:
assert type(value) is bool, "'{0}' attribute: '{1}' type is not 'bool'!".format("readOnly", value)
self.__readOnly = value
@readOnly.deleter
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, foundations.exceptions.ProgrammingError)
[docs] def readOnly(self):
"""
This method is the deleter method for **self.__readOnly** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "readOnly"))
#******************************************************************************************************************
#*** Class methods.
#******************************************************************************************************************
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
def __initializeUi(self):
"""
This method initializes the Widget ui.
"""
self.viewport().installEventFilter(ReadOnlyFilter(self))
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, Exception)
[docs] def getNodes(self):
"""
This method returns the View nodes.
:return: View nodes. ( List )
"""
return getNodes(self)
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, Exception)
[docs] def filterNodes(self, pattern, attribute, flags=re.IGNORECASE):
"""
This method filters the View nodes on given attribute using given pattern.
:param pattern: Filtering pattern. ( String )
:param attribute: Filtering attribute. ( String )
:param flags: Regex filtering flags. ( Integer )
:return: View filtered nodes. ( List )
"""
return filterNodes(self, pattern, attribute, flags)
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
#*** Sphinx: Decorator commented for auto-documentation purpose. @foundations.exceptions.exceptionsHandler(None, False, Exception)
[docs] def getSelectedNodes(self):
"""
This method returns the View selected nodes.
:return: View selected nodes. ( Dictionary )
"""
return getViewSelectedNodes(self)
#*** Sphinx: Decorator commented for auto-documentation purpose. @core.executionTrace
[docs] def selectIndexes(self, indexes, flags=QItemSelectionModel.Select | QItemSelectionModel.Rows):
"""
This method selects given indexes.
:param indexes: Indexes to select. ( List )
:param flags: Selection flags. ( QItemSelectionModel.SelectionFlags )
:return: Method success. ( Boolean )
"""
return selectViewIndexes(self, indexes, flags)