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

"""
Options model


The options model hosts a single widget containing all options that can be
adjusted for the dialog

"""

from PyQt4 import QtCore, QtGui
from Ui_chartables_options import Ui_CT_OptionsWidget
#***********************************************************************
# application options class
#***********************************************************************
DEFAULT_LOCALE  = "en"



class Options(object):
    """Package wide options class"""


    CTF_NONE = 0

    CTF_FACTORY = 0x1                                                                                                          # remembers last selected factory
    CTF_TYPE = 0x2                                                                                                            # remembers last selected type
    CTF_MODEL = 0x4                                                                                                          # remembers last selected model
    CTF_MODELS = 0x8                                                                                                                # remembers all selected models
    CTF_MASK_STATE = CTF_FACTORY | CTF_TYPE |  CTF_MODEL | CTF_MODELS

    CTF_SHOWCHARHEX = 0x200          # shows hex on charset tables
    CTF_SHOWCHARINT = 0x400          # shows int on charset tables
    CTF_SHOWCHARABBR = 0x800          # shows abbreviated name on charset tables
    CTF_SHOWCHARNAME = 0x1000          # shows name on charset tables
    
    CTF_MASK_CHARS = CTF_SHOWCHARHEX | CTF_SHOWCHARINT | \
                                        CTF_SHOWCHARABBR | CTF_SHOWCHARNAME

    CTF_SHOWCOLORNAMES = 0x10000                    # shows color names on color tables
    CTF_SHOWCMYCOLORS = 0x20000                    # shows Cmy colors on color tables
    CTF_SHOWHLSCOLORS = 0x40000                    # shows Hls colors on color tables
    CTF_SHOWHTMLCOLORS = 0x80000                    # shows Hls colors on color tables
    CTF_SHOWRGBCOLORS = 0x100000                    # shows Hls colors on color tables
    CTF_MASK_COLORS = CTF_SHOWCOLORNAMES | CTF_SHOWHLSCOLORS | \
                                    CTF_SHOWCMYCOLORS | CTF_SHOWHTMLCOLORS | CTF_SHOWRGBCOLORS

    CTF_SHOWENTITYHEX = 0x10000                      # shows hex on entity tables
    CTF_SHOWENTITYINT = 0x20000                      # shows int on entity tables
    CFT_MASK_ENTITIES = CTF_SHOWENTITYHEX | CTF_SHOWENTITYINT


    CTF_MASK_ALL = CTF_MASK_STATE | CTF_MASK_CHARS | CTF_MASK_COLORS | \
                                    CFT_MASK_ENTITIES


    CTFEX_NONE = 0x0
    CTFEX_NOLANGUAGESELECT = 0x1    # hides language selection combo
    CTFEX_NOTRANSLATE = 0x2                # does not translate the ui at startup
                                                                # use along with CTFEX_NOLANGUAGESELECT


    
    # leave out some of the slowing down stuff by default
    CTF_MASK_DEFAULT = CTF_MASK_ALL & ~(CTF_SHOWCHARNAME)
    
        
    def __init__(
            self, parent, 
            flags=CTF_MASK_DEFAULT, 
            localeName="en", 
            flagsEx=CTFEX_NONE
            ):
        """
        constructor

        @param flags one or more of the CTF_* flags. For details see source.

        Currently defined attributes:<br>
        flags = holds one or more of the CTF_* flags<br>
        flagsEx = runtime flags<br>
        locale = locale for translations<br>
        areatips = AraTip class to show tips for truncated items<br>
        """

        
        
        self.parent = parent
        self.flags = flags
        self.flagsEx = flagsEx
        self.localeName = localeName
        self.language = None

        self.areatips = None
                
    
#*********************************************************************************
# options ui
#*********************************************************************************
ID_CKLASTTAB = "ckLastTab"
ID_CKLASTTYPE = "ckLastType"
ID_CKLASTMODEL = "ckLastTable"
ID_CKLASTMODELS = "ckAllTables"

ID_CKSHOWCHARHEX = "ckShowCharHex"
ID_CKSHOWCHARINT = "ckShowCharInt"
ID_CKSHOWCHARABBR = "ckShowCharAbbr"
ID_CKSHOWCHARNAME = "ckShowCharName"


ID_CKSHOWCOLORNAMES = "ckShowColorNames"
ID_CKSHOWCMYCOLORS = "ckShowCmyColors"
ID_CKSHOWHLSCOLORS = "ckShowHlsColors"
ID_CKSHOWHTMLCOLORS = "ckShowHtmlColors"
ID_CKSHOWRGBCOLORS = "ckShowRgbColors"

ID_CKSHOWENTITYHEX = "ckShowEntityHex"
ID_CKSHOWENTITYINT = "ckShowEntityInt"

ID_LABEL_LANGUAGESELECT = "labelLanguageSelect"
ID_CMB_LANGUAGESELECT = "cmbLanguageSelect"

LANGUAGE_SELECT = (
        ID_LABEL_LANGUAGESELECT,
        ID_CMB_LANGUAGESELECT
        )

# mapping CheckBox --> CTF_* flag
CHECKS = (
    (ID_CKLASTTAB, Options.CTF_FACTORY),
    (ID_CKLASTTYPE, Options.CTF_TYPE),
    (ID_CKLASTMODEL, Options.CTF_MODEL),
    (ID_CKLASTMODELS, Options.CTF_MODELS),
    
    (ID_CKSHOWCHARHEX, Options.CTF_SHOWCHARHEX),
    (ID_CKSHOWCHARINT, Options.CTF_SHOWCHARINT),
    (ID_CKSHOWCHARABBR, Options.CTF_SHOWCHARABBR),
    (ID_CKSHOWCHARNAME, Options.CTF_SHOWCHARNAME),

    (ID_CKSHOWCOLORNAMES, Options.CTF_SHOWCOLORNAMES),
    (ID_CKSHOWCMYCOLORS, Options.CTF_SHOWCMYCOLORS),
    (ID_CKSHOWHLSCOLORS, Options.CTF_SHOWHLSCOLORS),
    (ID_CKSHOWHTMLCOLORS, Options.CTF_SHOWHTMLCOLORS),
    (ID_CKSHOWRGBCOLORS, Options.CTF_SHOWRGBCOLORS),

    (ID_CKSHOWENTITYHEX, Options.CTF_SHOWENTITYHEX),
    (ID_CKSHOWENTITYINT, Options.CTF_SHOWENTITYINT),

    )

#***********************************************************************
# lightweight wrapper for checkboxes
#***********************************************************************
class _CheckBox(object):
    """Wrapper class for checkboxes"""

    def __init__(self, checkBox, bit, options):
        """
        constructor

        @param checkBox checkbox to wrap
        @param bi bit the checkbox sets
        @param options options instance that holds bitflags to set
        """

        self.checkBox = checkBox
        self.bit = bit
        self.options = options

        if options.flags & bit:
            state = QtCore.Qt.Checked
        else:
            state = QtCore.Qt.Unchecked
        self.checkBox.setCheckState(state)
        self.checkBox.connect(
                                        self.checkBox,
                                        QtCore.SIGNAL("stateChanged(int)"),
                                        self._onStateChanged
                                        )


    def _onStateChanged(self, state):
        """protected method called when the state of the wrapped checkbox changes"""
        if state == QtCore.Qt.Checked:
            self.options.flags |= self.bit
        else:
            self.options.flags &= ~self.bit


#*********************************************************************************
# options widget
#*********************************************************************************
# bit hckish here to adjust height/width of the table cell to our widget
# if table has gridlines resizeEvent will be called recursively
# unless we pull a bit in the other direction via
# self.table.setRowHeight(0, event.size().height() -1)
#
# TODO: test if it works in a font change or whatever
#
class CT_OptionsWidget(QtGui.QWidget, Ui_CT_OptionsWidget):
    """Widget containing options"""

    def __init__(self, table, options):
        """
        constructor

        @param table table that should host the widget
        @param options options instance
        @signal "languageChanged(QString&)" emited whenever the user changes
                language settings. The new localeName e.g. "en" or "de" will be 
                passed as parameter.
        """

        QtGui.QWidget.__init__(self, table)
        self.table = table
        self.options = options
        self.languageNames = None
        self.setupUi()

    def setupUi(self):
        Ui_CT_OptionsWidget.setupUi(self, self)

       # adjust table
        #self.table.setShowGrid(False)                 ##
        

        # init checkboxes
        self.checks = []
        for n, (idControl, bit) in enumerate(CHECKS):
            ck = _CheckBox(self.controlById(idControl), bit, self.options)
            self.checks.append(ck)

        # init language select
        if self.options.flagsEx & self.options.CTFEX_NOLANGUAGESELECT:
            for idControl in LANGUAGE_SELECT:
                self.controlById(idControl).setVisible(False)
        
            


    def onLanguageChanged(self, index):
        self.emit(
            QtCore.SIGNAL("languageChanged(QString&)"), 
            self.languageNames[index][1]
            )
        #self.retranslateUi(self)


    def populateLanguageSelectionCombo(self):
        cmbLanguageSelect = self.controlById(ID_CMB_LANGUAGESELECT)
        cmbLanguageSelect.disconnect(
                    cmbLanguageSelect,
                    QtCore.SIGNAL("currentIndexChanged(int)"),
                    self.onLanguageChanged
                    )
                
        self.languageNames = self.options.language.listNames()
        self.languageNames.sort()
        cmbLanguageSelect.clear()
        selection = 0
        for n, (translated, localeName) in enumerate(self.languageNames):
            cmbLanguageSelect.addItem(translated)
            if localeName == self.options.localeName:
                selection = n
        cmbLanguageSelect.setCurrentIndex(selection)
        
        cmbLanguageSelect.connect(
                    cmbLanguageSelect,
                    QtCore.SIGNAL("currentIndexChanged(int)"),
                    self.onLanguageChanged
                    )
    
    
    def retranslateUi(self, parent):
        Ui_CT_OptionsWidget.retranslateUi(self, parent)
        if not self.options.flagsEx & self.options.CTFEX_NOLANGUAGESELECT:
            self.populateLanguageSelectionCombo()

            
    def controlById(self, idControl):
        return getattr(self, idControl)


#*********************************************************************************
# delagate to handle OptionsWidget
#*********************************************************************************
class Delegate(QtGui.QItemDelegate):
    """QItemDelegate implementation to handle owner drawing"""

    
    def __init__(self, table):
        QtGui.QItemDelegate.__init__(self, table)
        self.table = table
        self._aboutToBeRemoved = False

    
    def aboutToBeRemoved(self, table):
        """
        public method used to tell the model that it is about to be removed from 
        a table    
        
        @param table table it is being removed from
        """
        self._aboutToBeRemoved=True
    
    def updateEditorGeometry(self, editor, option, index):
        # have to adjust cell and editor (our optionsWidget) here.
        # Otherwise we get into trouble on language changes with
        # the widget not being resized correctly
        
        if self._aboutToBeRemoved:
            #self.table.setColumnWidth(0, 0)
            #self.table.setRowHeight(0, 0)
            editor.resize(QtCore.QSize(0, 0))
            return
                    
        else:
            size = editor.sizeHint()
            editor.resize(size)
            #print editor.size().width(), editor.size().height()
            self.table.setColumnWidth(0, size.width())
            self.table.setRowHeight(0, size.height())
        
        
    def paint(self, painter, option, index):
        """QItemDelegate.paint() implementation"""
        
        # no additional drawing please
        return None

#***********************************************************************
# model to handle our options widget
#***********************************************************************
class OptionsModel(QtCore.QAbstractTableModel):
    """Model implementation holding dialog options"""


    def __init__(self, table, options):
        """
        constructor

        @param parent parent of the model
        @param options options instance
        @signal "languageChanged()" emited whenever the user changes
                language settings
        """


        QtCore.QAbstractTableModel.__init__(self, table)

        self.options = options
        self.optionsWidget = None
        self.table = table
        
        table.setVerticalScrollMode(table.ScrollPerPixel)
        table.setHorizontalScrollMode(table.ScrollPerPixel)
        table.setShowGrid(False)
        
        table.setModel(self)
        self.optionsWidget = CT_OptionsWidget(table, self.options)
        table.setIndexWidget(self.index(0, 0), self.optionsWidget)
        table.setItemDelegate(Delegate(table))
        
        self.optionsWidget.setAutoFillBackground(True)
        
        table.horizontalHeader().setVisible(False)

    
    def getOptionsWidget(self):
        """returns the widget used to display options"""
        return self.optionsWidget
    
        
    def data(self, options, role):
        """QAbstractTableModel.data() implementation"""
        return QtCore.QVariant()
    
    def headerData(self, section, orientation, role):
        """QAbstractTableModel.headerData() implementation"""
        return QtCore.QVariant()
    
        
    def rowCount(self, parent):
        """QAbstractTableModel.rowCount() implementation"""
        return 1


    def columnCount(self, parent):
        """QAbstractTableModel.columnCount() implementation"""
        return 1
