# -*- coding: utf-8 -*-

# Copyright (c) 2004 - 2006 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing an Action class substituting QAction.

This substitution is neccessary in order to support alternate keyboard
shortcuts.
"""

from qt import QAction, QActionGroup, QObject, QIconSet

class ArgumentsError(RuntimeError):
    """
    Class implementing an exception, which is raised, if the wrong number of arguments are given.
    """
    def __init__(self, error):
        """
        Constructor
        """
        self.errorMessage = unicode(error)
        
    def __repr__(self):
        """
        Private method returning a representation of the exception.
        
        @return string representing the error message
        """
        return unicode(self.errorMessage)
        
    def __str__(self):
        """
        Private method returning a string representation of the exception.
        
        @return string representing the error message
        """
        return str(self.errorMessage)
        
class E3Action(QObject):
    """
    Class implementing an Action class substituting QAction.
    """
    def __init__(self, *args):
        """
        Constructor
        
        @param args argument list of the constructor. This list is one of
            <ul>
            <li>text (string or QString), icon (QIconSet), menu text (string or QString), 
                accelarator (QKeySequence), alternative accelerator (QKeySequence), 
                parent (QObject), name (string or QString), toggle (boolean)</li>
            <li>text (string or QString), icon (QIconSet), menu text (string or QString), 
                accelarator (QKeySequence), alternative accelerator (QKeySequence), 
                parent (QObject), name (string or QString)</li>
            <li>text (string or QString), menu text (string or QString), 
                accelarator (QKeySequence), alternative accelerator (QKeySequence), 
                parent (QObject), name (string or QString), toggle (boolean)</li>
            <li>text (string or QString), menu text (string or QString), 
                accelarator (QKeySequence), alternative accelerator (QKeySequence), 
                parent (QObject), name (string or QString)</li>
            </ul>
        """
        if isinstance(args[1], QIconSet):
            iconset = args[1]
            incr = 1
        else:
            iconset = None
            incr = 0
        if len(args) < 6+incr:
            raise ArgumentsError("Not enough arguments, %d expected, got %d" % \
                                 (6+incr, len(args)+incr))
        elif len(args) > 7+incr:
            raise ArgumentsError("Too many arguments, max. %d expected, got %d" % \
                                 (7+incr, len(args)+incr))
            
        parent = args[4+incr]
        QObject.__init__(self, parent, args[5+incr])
        
        if isinstance(parent, E3ActionGroup):
            actParent, altActParent = parent.getActionGroups()
        else:
            actParent, altActParent = self, self
            
        try:
            self.mainAction = QAction(args[1+incr], args[2+incr], actParent)
            self.mainAction.setText(args[0])
            self.altAction = QAction(args[1+incr], args[3+incr], altActParent)
            self.altAction.setText(args[0])
        except TypeError:   # it is probably Qt < 3.2.0
            self.mainAction = QAction(args[0], args[1+incr], args[2+incr], actParent)
            self.altAction = QAction(args[0], args[1+incr], args[3+incr], altActParent)
        
        if iconset:
            self.mainAction.setIconSet(iconset)
            
        if len(args) == 7+incr:
            self.mainAction.setToggleAction(args[6+incr])
            self.altAction.setToggleAction(args[6+incr])
        
    def setStatusTip(self, text):
        """
        Public slot to set the text of the status tip.
        
        @param text text to be shown (string or QString)
        """
        self.mainAction.setStatusTip(text)
        
    def statusTip(self):
        """
        Public method to retrieve the text for the status tip.
        
        @return text for the status tip (QString)
        """
        return self.mainAction.statusTip()
        
    def setWhatsThis(self, text):
        """
        Public slot to set the text of the What's This help.
        
        @param text text to be shown (string or QString)
        """
        self.mainAction.setWhatsThis(text)
        
    def whatsThis(self):
        """
        Public method to retrieve the text for the What's This help.
        
        @return text for the What's This help (QString)
        """
        self.mainAction.whatsThis()
        
    def setIconSet(self, iconSet):
        """
        Public slot to set the icon set.
        
        @param iconSet the new icon set (QIconSet)
        """
        self.mainAction.setIconSet(iconSet)
        
    def setEnabled(self, on):
        """
        Public slot to set the enabled status.
        
        @param on the enabled status (boolean)
        """
        self.mainAction.setEnabled(on)
        self.altAction.setEnabled(on)
        
    def setOn(self, on):
        """
        Public slot to set the toggle status.
        
        @param on the toggle status (boolean)
        """
        self.mainAction.setOn(on)
        self.altAction.setOn(on)
        
    def isOn(self):
        """
        Public slot to retrieve the toggle status.
        
        @return the toggle status (boolean)
        """
        return self.mainAction.isOn()
        
    def setAccel(self, accel):
        """
        Public slot to set the accelerator.
        
        @param accel the accelerator (QKeySequence)
        """
        self.mainAction.setAccel(accel)
        
    def accel(self):
        """
        Public method to retrieve the accelerator.
        
        @return the accelerator (QKeySequence)
        """
        return self.mainAction.accel()
        
    def setAlternateAccel(self, accel):
        """
        Public slot to set the alternative accelerator.
        
        @param accel the alternative accelerator (QKeySequence)
        """
        self.altAction.setAccel(accel)
        
    def alternateAccel(self):
        """
        Public method to retrieve the alternative accelerator.
        
        @return the alternative accelerator (QKeySequence)
        """
        return self.altAction.accel()
        
    def text(self):
        """
        Public method to retrieve the actions text.
        
        @return the actions text (QString)
        """
        return self.mainAction.text()
        
    def menuText(self):
        """
        Public method to retrieve the actions menu text.
        
        @return the menu text (QString)
        """
        return self.mainAction.menuText()
        
    def addTo(self, widget):
        """
        Public method to add this action to a widget.
        
        @param widget widget to add to (QWidget)
        """
        self.mainAction.addTo(widget)
        
    def connectIt(self, *args):
        """
        Public method to connect signals of the action to a receiver.
        
        @param args argument list. This is one of
            <ul>
            <li>signal (SIGNAL), receiving member (Python slot)</li>
            <li>signal (SIGNAL), receiver (QObject), member (SLOT)</li>
            </ul>
        """
        # signal, receiver
        # signal, object, receiver
        if len(args) < 2 or len(args) > 3:
            raise ArgumentsError("Incorrect number of arguments")
        if len(args) == 2:
            self.connect(self.mainAction, args[0], args[1])
            self.connect(self.altAction, args[0], args[1])
        elif len(args) == 3:
            self.connect(self.mainAction, args[0], args[1], args[2])
            self.connect(self.altAction, args[0], args[1], args[2])
        
    def mapIt(self, mapper, mapping):
        """
        Public method to set a mapping for the action.
        
        @param mapper reference to the mapper object (QSignalMapper)
        @param mapping identifier the id of the mapping (integer, string or QString)
        """
        mapper.setMapping(self.mainAction, mapping)
        mapper.setMapping(self.altAction, mapping)

class E3ActionGroup(QObject):
    """
    Class implementing an ActionGroup class substituting QActionGroup.
    """
    def __init__(self, parent, name = None, exclusive = 0):
        """
        Constructor
        
        @param parent parent object of the action group (QObject)
        @param name name of the action group object (string or QString)
        @param exclusive flag indicating an exclusive action group (boolean)
        """
        QObject.__init__(self, parent, name)
        
        self.mainActionGroup = QActionGroup(self, None, exclusive)
        self.altActionGroup = QActionGroup(self, None, exclusive)
        
    def setEnabled(self, on):
        """
        Public slot to set the enabled status.
        
        @param on the enabled status (boolean)
        """
        self.mainActionGroup.setEnabled(on)
        self.altActionGroup.setEnabled(on)
        
    def addTo(self, widget):
        """
        Public method to add this action group to a widget.
        
        @param widget widget to add to (QWidget)
        """
        self.mainActionGroup.addTo(widget)
        
    def getMainActionGroup(self):
        """
        Public method to retrieve the primary action group object.
        
        @return primary action group (QActionGroup)
        """
        return self.mainActionGroup
        
    def getAlternateActionGroup(self):
        """
        Public method to retrieve the alternative action group object.
        
        @return alternative action group (QActionGroup)
        """
        return self.altActionGroup
        
    def getActionGroups(self):
        """
        Public method to retrieve the underlying action group objects.
        
        @return tuple containing the underlying action groups
            (tuple of two QActionGroup)
        """
        return (self.mainActionGroup, self.altActionGroup)
