#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
**layoutsManager.py**
**Platform:**
Windows, Linux, Mac Os X.
**Description:**
Defines the :class:`LayoutsManager` and :class:`Layout` classes.
**Others:**
"""
#**********************************************************************************************************************
#*** Future imports.
#**********************************************************************************************************************
from __future__ import unicode_literals
#**********************************************************************************************************************
#*** External imports.
#**********************************************************************************************************************
from PyQt4.QtCore import QObject
from PyQt4.QtCore import pyqtSignal
#**********************************************************************************************************************
#*** Internal imports.
#**********************************************************************************************************************
import foundations.dataStructures
import foundations.exceptions
import foundations.verbose
import umbra.exceptions
from umbra.globals.uiConstants import UiConstants
#**********************************************************************************************************************
#*** Module attributes.
#**********************************************************************************************************************
__author__ = "Thomas Mansencal"
__copyright__ = "Copyright (C) 2008 - 2014 - Thomas Mansencal"
__license__ = "GPL V3.0 - http://www.gnu.org/licenses/"
__maintainer__ = "Thomas Mansencal"
__email__ = "[email protected]"
__status__ = "Production"
__all__ = ["LOGGER", "Layout", "LayoutsManager"]
LOGGER = foundations.verbose.installLogger()
#**********************************************************************************************************************
#*** Module classes and definitions.
#**********************************************************************************************************************
[docs]class Layout(foundations.dataStructures.Structure):
"""
Defines a storage object for :class:`LayoutsManager` class layout.
"""
def __init__(self, **kwargs):
"""
Initializes the class.
:param \*\*kwargs: name, identity, shortcut.
:type \*\*kwargs: dict
"""
LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__))
foundations.dataStructures.Structure.__init__(self, **kwargs)
[docs]class LayoutsManager(QObject):
"""
Defines the Application layouts manager.
"""
layoutRestored = pyqtSignal(unicode)
"""
This signal is emited by the :class:`LayoutsManager` class when the current layout has been restored. ( pyqtSignal )
:return: Current layout.
:rtype: unicode
"""
layoutStored = pyqtSignal(unicode)
"""
This signal is emited by the :class:`LayoutsManager` class when the current layout has been stored. ( pyqtSignal )
:return: Current layout.
:rtype: unicode
"""
def __init__(self, parent=None):
"""
Initializes the class.
:param parent: Object parent.
:type parent: QObject
"""
LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__))
QObject.__init__(self, parent)
# --- Setting class attributes. ---
self.__container = parent
self.__settings = self.__container.settings
self.__layouts = {}
self.__currentLayout = None
self.__restoreGeometryOnLayoutChange = False
self.registerLayout(UiConstants.startupLayout, Layout(name="Startup",
identity=UiConstants.startupLayout,
shortcut=None))
#******************************************************************************************************************
#*** Attributes properties.
#******************************************************************************************************************
@property
def container(self):
"""
Property for **self.__container** attribute.
:return: self.__container.
:rtype: QObject
"""
return self.__container
@container.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
def container(self, value):
"""
Setter for **self.__container** attribute.
:param value: Attribute value.
:type value: QObject
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "container"))
@container.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def container(self):
"""
Deleter for **self.__container** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "container"))
@property
def settings(self):
"""
Property for **self.__settings** attribute.
:return: self.__settings.
:rtype: Preferences
"""
return self.__settings
@settings.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
def settings(self, value):
"""
Setter for **self.__settings** attribute.
:param value: Attribute value.
:type value: Preferences
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "settings"))
@settings.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def settings(self):
"""
Deleter for **self.__settings** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "settings"))
@property
def layouts(self):
"""
Property for **self.__layouts** attribute.
:return: self.__layouts.
:rtype: dict
"""
return self.__layouts
@layouts.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
def layouts(self, value):
"""
Setter for **self.__layouts** attribute.
:param value: Attribute value.
:type value: dict
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "layouts"))
@layouts.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def layouts(self):
"""
Deleter for **self.__layouts** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "layouts"))
@property
def currentLayout(self):
"""
Property for **self.__currentLayout** attribute.
:return: self.__currentLayout.
:rtype: tuple or list
"""
return self.__currentLayout
@currentLayout.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
def currentLayout(self, value):
"""
Setter for **self.__currentLayout** attribute.
:param value: Attribute value.
:type value: tuple or list
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "currentLayout"))
@currentLayout.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def currentLayout(self):
"""
Deleter for **self.__currentLayout** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "currentLayout"))
@property
def restoreGeometryOnLayoutChange(self):
"""
Property for **self.__restoreGeometryOnLayoutChange** attribute.
:return: self.__restoreGeometryOnLayoutChange.
:rtype: bool
"""
return self.__restoreGeometryOnLayoutChange
@restoreGeometryOnLayoutChange.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(AssertionError)
def restoreGeometryOnLayoutChange(self, value):
"""
Setter for **self.__restoreGeometryOnLayoutChange** attribute.
:param value: Attribute value.
:type value: bool
"""
if value is not None:
assert type(value) is bool, "'{0}' attribute: '{1}' type is not 'bool'!".format(
"restoreGeometryOnLayoutChange", value)
self.__restoreGeometryOnLayoutChange = value
@restoreGeometryOnLayoutChange.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def restoreGeometryOnLayoutChange(self):
"""
Deleter for **self.__restoreGeometryOnLayoutChange** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "restoreGeometryOnLayoutChange"))
#******************************************************************************************************************
#*** Class methods.
#******************************************************************************************************************
def __getitem__(self, layout):
"""
Reimplements the :meth:`object.__getitem__` method.
:param layout: Layout name.
:type layout: unicode
:return: Layout.
:rtype: Layout
"""
return self.__layouts.__getitem__(layout)
def __setitem__(self, name, layout):
"""
Reimplements the :meth:`object.__setitem__` method.
:param name: Layout name.
:type name: unicode
:param layout: Layout.
:type layout: Layout
"""
self.registerLayout(name, layout)
def __iter__(self):
"""
Reimplements the :meth:`object.__iter__` method.
:return: Layouts iterator.
:rtype: object
"""
return self.__layouts.iteritems()
def __contains__(self, layout):
"""
Reimplements the :meth:`object.__contains__` method.
:param layout: Layout name.
:type layout: unicode
:return: Layout existence.
:rtype: bool
"""
return layout in self.__layouts
def __len__(self):
"""
Reimplements the :meth:`object.__len__` method.
:return: Layouts count.
:rtype: int
"""
return len(self.__layouts)
[docs] def get(self, layout, default=None):
"""
Returns given layout value.
:param layout: Layout name.
:type layout: unicode
:param default: Default value if layout is not found.
:type default: object
:return: Action.
:rtype: QAction
"""
try:
return self.__getitem__(layout)
except KeyError as error:
return default
[docs] def listLayouts(self):
"""
Returns the registered layouts.
:return: Registered layouts.
:rtype: list
"""
return sorted(self.__layouts.keys())
[docs] def isLayoutRegistered(self, name):
"""
Returns if the given layout name is registered.
:param name: Layout name.
:type name: unicode
:return: Is layout registered.
:rtype: bool
"""
return name in self
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(umbra.exceptions.LayoutRegistrationError)
[docs] def registerLayout(self, name, layout):
"""
Registers given layout.
:param name: Layout name.
:type name: unicode
:param layout: Layout object.
:type layout: Layout
:return: Method success.
:rtype: bool
"""
if name in self:
raise umbra.exceptions.LayoutRegistrationError("{0} | '{1}' layout is already registered!".format(
self.__class__.__name__, name))
self.__layouts[name] = layout
return True
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(umbra.exceptions.LayoutRegistrationError)
[docs] def unregisterLayout(self, name):
"""
Unregisters given layout.
:param name: Layout name.
:type name: unicode
:param layout: Layout object.
:type layout: Layout
:return: Method success.
:rtype: bool
"""
if not name in self:
raise umbra.exceptions.LayoutRegistrationError("{0} | '{1}' layout is not registered!".format(
self.__class__.__name__, name))
del(self.__layouts[name])
return True
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(umbra.exceptions.LayoutExistError)
[docs] def restoreLayout(self, name, *args):
"""
Restores given layout.
:param name: Layout name.
:type name: unicode
:param \*args: Arguments.
:type \*args: \*
:return: Method success.
:rtype: bool
"""
layout = self.__layouts.get(name)
if not layout:
raise umbra.exceptions.LayoutExistError("{0} | '{1}' layout isn't registered!".format(
self.__class__.__name__, name))
LOGGER.debug("> Restoring layout '{0}'.".format(name))
for component, profile in self.__container.componentsManager:
if profile.category == "QWidget" and component not in self.__container.visibleComponents:
interface = self.__container.componentsManager.getInterface(component)
interface and interface.hide()
self.__currentLayout = name
self.__container.centralWidget().setVisible(
self.__settings.getKey("Layouts", "{0}_centralWidget".format(name)).toBool())
self.__container.restoreState(
self.__settings.getKey("Layouts", "{0}_windowState".format(name)).toByteArray())
self.__restoreGeometryOnLayoutChange and \
self.__container.restoreGeometry(
self.__settings.getKey("Layouts", "{0}_geometry".format(name)).toByteArray())
self.layoutRestored.emit(self.__currentLayout)
return True
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(umbra.exceptions.LayoutExistError)
[docs] def storeLayout(self, name, *args):
"""
Stores given layout.
:param name: Layout name.
:type name: unicode
:param \*args: Arguments.
:type \*args: \*
:return: Method success.
:rtype: bool
"""
layout = self.__layouts.get(name)
if not layout:
raise umbra.exceptions.LayoutExistError("{0} | '{1}' layout isn't registered!".format(
self.__class__.__name__, name))
LOGGER.debug("> Storing layout '{0}'.".format(name))
self.__currentLayout = name
self.__settings.setKey("Layouts", "{0}_geometry".format(name), self.__container.saveGeometry())
self.__settings.setKey("Layouts", "{0}_windowState".format(name), self.__container.saveState())
self.__settings.setKey("Layouts", "{0}_centralWidget".format(name), self.__container.centralWidget().isVisible())
self.layoutStored.emit(self.__currentLayout)
return True
[docs] def restoreStartupLayout(self):
"""
Restores the startup layout.
:return: Method success.
:rtype: bool
"""
LOGGER.debug("> Restoring startup layout.")
if self.restoreLayout(UiConstants.startupLayout):
not self.__restoreGeometryOnLayoutChange and self.__container.restoreGeometry(
self.__settings.getKey("Layouts", "{0}_geometry".format(UiConstants.startupLayout)).toByteArray())
return True
[docs] def storeStartupLayout(self):
"""
Stores the startup layout.
:return: Method success.
:rtype: bool
"""
LOGGER.debug("> Storing startup layout.")
return self.storeLayout(UiConstants.startupLayout)