#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
**notificationsManager.py**
**Platform:**
Windows, Linux, Mac Os X.
**Description:**
Defines the :class:`NotificationsManager` and :class:`Notification` classes.
**Others:**
"""
#**********************************************************************************************************************
#*** Future imports.
#**********************************************************************************************************************
from __future__ import unicode_literals
#**********************************************************************************************************************
#*** External imports.
#**********************************************************************************************************************
import time
from PyQt4.QtCore import Qt
from PyQt4.QtCore import QObject
from PyQt4.QtCore import pyqtSignal
from PyQt4.QtGui import QColor
#**********************************************************************************************************************
#*** Internal imports.
#**********************************************************************************************************************
import foundations.dataStructures
import foundations.exceptions
import foundations.verbose
from umbra.ui.widgets.notification_QLabel import Notification_QLabel
#**********************************************************************************************************************
#*** 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", "Notification", "NotificationsManager"]
LOGGER = foundations.verbose.installLogger()
#**********************************************************************************************************************
#*** Module classes and definitions.
#**********************************************************************************************************************
[docs]class Notification(foundations.dataStructures.Structure):
"""
Defines a storage object for :class:`NotificationsManager` class notification.
"""
def __init__(self, **kwargs):
"""
Initializes the class.
:param \*\*kwargs: message, time.
:type \*\*kwargs: dict
"""
LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__))
foundations.dataStructures.Structure.__init__(self, **kwargs)
[docs]class NotificationsManager(QObject):
"""
Defines the Application notifications manager.
"""
# Custom signals definitions.
notificationRegistered = pyqtSignal(Notification)
"""
This signal is emited by the :class:`NotificationsManager` class when a notification is registered. ( pyqtSignal )
:return: Current registered notification.
:rtype: Notification
"""
def __init__(self, parent=None):
"""
Initializes the class.
"""
LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__))
QObject.__init__(self, parent)
# --- Setting class attributes. ---
self.__container = parent
self.__notifications = []
self.__notifiers = []
self.__notifiersStackPadding = 10
self.__maximumNotifiers = 5
#******************************************************************************************************************
#*** 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 notifications(self):
"""
Property for **self.__notifications** attribute.
:return: self.__notifications.
:rtype: list
"""
return self.__notifications
@notifications.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
def notifications(self, value):
"""
Setter for **self.__notifications** attribute.
:param value: Attribute value.
:type value: list
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "notifications"))
@notifications.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def notifications(self):
"""
Deleter for **self.__notifications** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "notifications"))
@property
def notifiers(self):
"""
Property for **self.__notifiers** attribute.
:return: self.__notifiers.
:rtype: list
"""
return self.__notifiers
@notifiers.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
def notifiers(self, value):
"""
Setter for **self.__notifiers** attribute.
:param value: Attribute value.
:type value: list
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "notifiers"))
@notifiers.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def notifiers(self):
"""
Deleter for **self.__notifiers** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "notifiers"))
@property
def notifiersStackPadding(self):
"""
Property for **self.__notifiersStackPadding** attribute.
:return: self.__notifiersStackPadding.
:rtype: int
"""
return self.__notifiersStackPadding
@notifiersStackPadding.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(AssertionError)
def notifiersStackPadding(self, value):
"""
Setter for **self.__notifiersStackPadding** attribute.
:param value: Attribute value.
:type value: int
"""
if value is not None:
assert type(value) is int, "'{0}' attribute: '{1}' type is not 'int'!".format("notifiersStackPadding",
value)
assert value >= 0, "'{0}' attribute: '{1}' need to be positive!".format("notifiersStackPadding", value)
self.__notifiersStackPadding = value
@notifiersStackPadding.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
@property
def maximumNotifiers(self):
"""
Property for **self.__maximumNotifiers** attribute.
:return: self.__maximumNotifiers.
:rtype: int
"""
return self.__maximumNotifiers
@maximumNotifiers.setter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(AssertionError)
def maximumNotifiers(self, value):
"""
Setter for **self.__maximumNotifiers** attribute.
:param value: Attribute value.
:type value: int
"""
if value is not None:
assert type(value) is int, "'{0}' attribute: '{1}' type is not 'int'!".format("maximumNotifiers",
value)
assert value > 0, "'{0}' attribute: '{1}' need to be exactly positive!".format("maximumNotifiers", value)
self.__maximumNotifiers = value
@maximumNotifiers.deleter
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
[docs] def maximumNotifiers(self):
"""
Deleter for **self.__maximumNotifiers** attribute.
"""
raise foundations.exceptions.ProgrammingError(
"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "maximumNotifiers"))
#******************************************************************************************************************
#*** Class methods.
#******************************************************************************************************************
def __iter__(self):
"""
Reimplements the :meth:`object.__iter__` method.
:return: Notifications iterator.
:rtype: object
"""
return iter(self.__notifications)
def __len__(self):
"""
Reimplements the :meth:`object.__len__` method.
:return: Notifications count.
:rtype: int
"""
return len(self.__notifications)
def __notifier__fadedOut(self):
"""
Defines the slot triggered by **Notification_QLabel** Widget when faded out.
"""
if self.sender() in self.__notifiers:
self.__notifiers.pop(self.__notifiers.index(self.sender()))
def __offsetNotifiers(self, offset):
"""
Offsets existing notifiers.
:param offset: Offset.
:type offset: int
"""
overallOffset = offset
for notifier in self.__notifiers:
notifier.verticalOffset = overallOffset
notifier.refreshPosition()
overallOffset += offset
[docs] def listNotifications(self):
"""
Returns the registered notifications.
:return: Notifications list.
:rtype: list
"""
return [self.formatNotification(notification) for notification in self]
[docs] def isNotificationRegistered(self, notification):
"""
Returns if the given notification is registered.
:param notification: Notification.
:type notification: unicode
:return: Is notification registered.
:rtype: bool
"""
return notification in self
[docs] def registerNotification(self, notification):
"""
Registers given notification.
:param notification: Notification to register.
:type notification: Notification
:return: Method success.
:rtype: bool
"""
LOGGER.debug("> Registering notification: '{0}'.".format(notification))
self.__notifications.append(notification)
self.notificationRegistered.emit(notification)
return True
[docs] def notify(self, message, duration=3000, notificationClickedSlot=None, messageLevel="Information", **kwargs):
"""
Displays an Application notification.
:param message: Notification message.
:type message: unicode
:param duration: Notification display duration.
:type duration: int
:param notificationClickedSlot: Notification clicked slot.
:type notificationClickedSlot: object
:param messageLevel: Message level ( "Information", "Warning", "Exception" ).
:type messageLevel: unicode
:param \*\*kwargs: Keywords arguments.
:type \*\*kwargs: \*\*
:return: Method success.
:rtype: bool
"""
for notifier in self.__notifiers[self.__maximumNotifiers - 1:]:
notifier.duration=150
notifier.hideMessage()
notification = Notification(message=message, time=time.time())
self.registerNotification(notification)
notifier = Notification_QLabel(self.__container, **kwargs)
# Signals / Slots.
notifier.fadedOut.connect(self.__notifier__fadedOut)
self.__container.sizeChanged.connect(notifier.resizeEvent)
if notificationClickedSlot:
notifier.notificationClicked.connect(notificationClickedSlot)
else:
notifier.setAttribute(Qt.WA_TransparentForMouseEvents)
notifier.showMessage(message, duration)
self.__offsetNotifiers(-notifier.height() - self.__notifiersStackPadding)
self.__notifiers.insert(0, notifier)
if messageLevel == "Information":
LOGGER.info("{0} | '{1}'.".format(self.__class__.__name__, self.formatNotification(notification)))
elif messageLevel == "Warning":
LOGGER.warning("!> {0} | '{1}'.".format(self.__class__.__name__, self.formatNotification(notification)))
elif messageLevel == "Exception":
LOGGER.error("!> {0} | '{1}'.".format(self.__class__.__name__, self.formatNotification(notification)))
return True
[docs] def warnify(self, message, duration=3000, notificationClickedSlot=None, **kwargs):
"""
Displays an Application notification warning.
:param message: Notification message.
:type message: unicode
:param duration: Notification display duration.
:type duration: int
:param notificationClickedSlot: Notification clicked slot.
:type notificationClickedSlot: object
:param \*\*kwargs: Keywords arguments.
:type \*\*kwargs: \*\*
:return: Method success.
:rtype: bool
"""
return self.notify(message,
duration,
notificationClickedSlot,
messageLevel="Warning",
color=QColor(220, 128, 64),
backgroundColor=QColor(32, 32, 32),
borderColor=QColor(220, 128, 64),
**kwargs)
[docs] def exceptify(self, message, duration=3000, notificationClickedSlot=None, **kwargs):
"""
Displays an Application notification exception.
:param message: Notification message.
:type message: unicode
:param duration: Notification display duration.
:type duration: int
:param notificationClickedSlot: Notification clicked slot.
:type notificationClickedSlot: object
:param \*\*kwargs: Keywords arguments.
:type \*\*kwargs: \*\*
:return: Method success.
:rtype: bool
"""
return self.notify(message,
duration,
notificationClickedSlot,
messageLevel="Exception",
color=QColor(220, 64, 64),
backgroundColor=QColor(32, 32, 32),
borderColor=QColor(220, 64, 64),
**kwargs)