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

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

"""
Module implementing a compatability interface class to QextScintilla.
"""

import sys

from qt import Qt, QKeyEvent, QEvent, qApp, SIGNAL
from qtext import QextScintilla, \
    QSCINTILLA_VERSION as QextQSCINTILLA_VERSION, QSCINTILLA_VERSION_STR


def QSCINTILLA_VERSION():
    """
    Module function to return the QScintilla version.
    
    If the installed QScintilla is a snapshot version, then assume it is
    of the latest release and return a version number of 0x99999.
    
    @return QScintilla version (integer)
    """
    if QSCINTILLA_VERSION_STR.startswith('snapshot'):
        return 0x99999
    else:
        return QextQSCINTILLA_VERSION
    
class QextScintillaCompat(QextScintilla):
    """
    Class implementing a compatability interface to QextScintilla.
    
    This class implements all the functions, that were added to
    QextScintilla incrementally. This class ensures compatibility
    to older versions of QextScintilla.
    """
    def __init__(self, parent=None, name=None, flags=0):
        """
        Constructor
        
        @param parent parent widget (QWidget)
        @param name name of this instance (string or QString)
        @param flags window flags
        """
        QextScintilla.__init__(self, parent, name, flags)
        
        # workaround for a bug in version <= 1.5.1
        self._modified = 0
        self.connect(self, SIGNAL('modificationChanged(bool)'), 
                    self._handleModificationChanged)
        
        # workaround for an initialization bug in version <= 1.4
        self.clearStyles()
    
    # workaround for a bug in version <= 1.5.1
    def _handleModificationChanged(self, m):
        """
        Private slot to handle the modificationChanged signal. 
        
        It emits the signal modificationStatusChanged with parameters
        m and self.
        
        @param m modification status
        """
        self._modified = m
        
    def isModified(self):
        """
        Public method to retrieve the modification status.
        
        @return flag indicating the modification status (boolean)
        """
        return self._modified
        
    def setModified(self, m):
        """
        Public method to set the modification status.
        
        @param m flag indicating the new modification status
        """
        self._modified = m
        QextScintilla.setModified(self, m)
    
    # workaround for a bug in setLexer() in version <= 1.4
    def setLexer(self, lex = None):
        """
        Public method to set the lexer.
        
        @param lex the lexer to be set or None to reset it.
        """
        QextScintilla.setLexer(self, lex)
        if lex is None:
            self.clearStyles()
        
    def clearStyles(self):
        """
        Public method to set the styles according the selected Qt style.
        """
        colorGroup = qApp.palette().active()
        self.SendScintilla(QextScintilla.SCI_STYLESETFORE,
            QextScintilla.STYLE_DEFAULT, colorGroup.text())
        self.SendScintilla(QextScintilla.SCI_STYLESETBACK,
            QextScintilla.STYLE_DEFAULT, colorGroup.base())
        self.SendScintilla(QextScintilla.SCI_STYLECLEARALL)
        self.SendScintilla(QextScintilla.SCI_CLEARDOCUMENTSTYLE)
        
        self.setMarginsForegroundColor(colorGroup.foreground())
        self.setMarginsBackgroundColor(colorGroup.background())
        self.setFoldMarginColors(colorGroup.midlight(),
                                 colorGroup.midlight())
    
    # methods below have been added to QScintilla starting with version after 1.3
    if "setEdgeMode" not in QextScintilla.__dict__:
        def setEdgeMode(self, edgeMode):
            """
            Public method to set the edge mode.
            
            @param edgeMode mode to be set
            """
            self.SendScintilla(QextScintilla.SCI_SETEDGEMODE, edgeMode)
            
    if "setEdgeColumn" not in QextScintilla.__dict__:
        def setEdgeColumn(self, column):
            """
            Public method to set the edge column.
            
            @param column column number to be set for the edge mode (integer)
            """
            self.SendScintilla(QextScintilla.SCI_SETEDGECOLUMN, column)
            
    if "setEdgeColor" not in QextScintilla.__dict__:
        def setEdgeColor(self, colour):
            """
            Public method to set the color of the edge mode highlight.
            
            @param colour colour to be set (QColor)
            """
            self.SendScintilla(QextScintilla.SCI_SETEDGECOLOUR, colour)
            
    if "setWrapMode" not in QextScintilla.__dict__:
        def setWrapMode(self, mode):
            """
            Public slot to set the wrap mode of the text display.
            
            @param mode wrap mode (QextScintilla.WrapNone or
                QextScintilla.WrapWord)
            """
            self.SendScintilla(QextScintilla.SCI_SETWRAPMODE, mode)
        
    if "resetSelectionForegroundColor" not in QextScintilla.__dict__:
        def resetSelectionForegroundColor(self):
            """
            Public method to reset the foreground color of the selection.
            """
            self.SendScintilla(QextScintilla.SCI_SETSELFORE, 0)
        
        # compatibility method to correct a bug under win32
        if sys.platform == "win32":
            def keyPressEvent(self, event):
                """
                Workaround for QScintilla <= 1.3 bug w/ keyboard layouts 
                having a AltGr key in win32: 
                AltGr is reported as state == Qt.ControlButton | Qt.AltButton,
                but QScintilla expects (Unix-style) Qt.MetaButton. Just 
                translate states for infected QScintilla versions.
        
                Reimplemented from QextScintilla.keyPressEvent
        
                @param event reference to the key press event (QKeyEvent)
                @author Torsten Marek, 2004-08-22
                """
                if event.state() == Qt.AltButton | Qt.ControlButton:
                    newevent = QKeyEvent(QEvent.KeyPress,
                                         event.key(),
                                         event.ascii(),
                                         Qt.MetaButton,
                                         event.text())
                    event = newevent
                QextScintilla.keyPressEvent(self, event)

    # methods below have been added to QScintilla starting with version after 1.2
    if "setSelectionBackgroundColor" not in QextScintilla.__dict__:
        def setSelectionBackgroundColor(self, colour):
            """
            Public method to set the background color of the selection.
            
            @param colour colour to be set (QColor)
            """
            self.SendScintilla(QextScintilla.SCI_SETSELBACK, 1, colour)
            
    if "setSelectionForegroundColor" not in QextScintilla.__dict__:
        def setSelectionForegroundColor(self, colour):
            """
            Public method to set the foreground color of the selection.
            
            @param colour colour to be set (QColor)
            """
            self.SendScintilla(QextScintilla.SCI_SETSELFORE, 1, colour)
            
    if "setCaretForegroundColor" not in QextScintilla.__dict__:
        def setCaretForegroundColor(self, colour):
            """
            Public method to set the foreground color of the caret.
            
            @param colour colour to be set (QColor)
            """
            self.SendScintilla(QextScintilla.SCI_SETCARETFORE, colour)
            
    if "setCaretLineBackgroundColor" not in QextScintilla.__dict__:
        def setCaretLineBackgroundColor(self, colour):
            """
            Public method to set the background color of the caret line.
            
            @param colour colour to be set (QColor)
            """
            self.SendScintilla(QextScintilla.SCI_SETCARETLINEBACK, colour)
            
    if "setCaretLineVisible" not in QextScintilla.__dict__:
        def setCaretLineVisible(self, enable):
            """
            Public method to enable the highlighting of the caret line.
            
            @param enable flag indicating the highlighting state to be set (boolean)
            """
            self.SendScintilla(QextScintilla.SCI_SETCARETLINEVISIBLE, enable)
            
    if "setCaretWidth" not in QextScintilla.__dict__:
        def setCaretWidth(self, width):
            """
            Public method to enable the highlighting of the caret line.
            
            @param width width of the caret (integer - 0, 1, 2 or 3)
            """
            if width < 0:
                width = 0
            elif width > 3:
                width = 3
            self.SendScintilla(QextScintilla.SCI_SETCARETWIDTH, width)
            
    if "recolor" not in QextScintilla.__dict__:
        def recolor(self, start = 0, end = -1):
            """
            Public method to recolor the given region.
            
            @param start linenumber where to start recolourisation (integer)
            @param end linenumber where to end recolourisation (integer)
            """
            self.SendScintilla(QextScintilla.SCI_COLOURISE, start, end)

    # interface methods to the standard keyboard command set
    def clearAlternateKeys(self):
        """
        Protected method to clear the alternate key commands.
        """
        if "clearAlternateKeys" not in self.standardCommands().__dict__:
            # clear each alternate key for QScintilla versions <= 1.3
            for cmd in self.standardCommands().commands():
                cmd.setAlternateKey(0)
        else:
            # call into the QextScintillaCommandSet
            self.standardCommands().clearAlternateKeys()
    
