#!/usr/bin/env python3
"""
Module PYSIDE2TABLE -- Python PySide2 Table Objects
Sub-Package GUI.TOOLKITS.PYSIDE2 of Package PLIB3 -- Python GUI Toolkits
Copyright (C) 2008-2019 by Peter A. Donis

Released under the GNU General Public License, Version 2
See the LICENSE and README files for more information

This module contains the PySide GUI objects for the table widgets.
"""

from PySide2 import QtGui as qtg, QtWidgets as qt

from plib.gui.defs import *
from plib.gui._widgets import table

from ._pyside2common import _PQtSequenceMeta, _PQtClientWidget, _qtalignmap


class PQtTableLabels(table.PTableLabelsBase):
    
    label_list = None
    labels_initialized = False
    
    def _update(self, data):
        # Hack to get around weirdness in PySide table widget API
        self.label_list = [str(value) for value in data]
        table.PTableLabelsBase._update(self, data)
    
    def _set_label(self, index, label):
        if self.label_list is not None:
            # First time setting labels, do it this way
            self.table.setHorizontalHeaderLabels(self.label_list)
            self.label_list = None
        if self.labels_initialized:
            # This allows labels to be changed after the initial setup
            item = self.table.horizontalHeaderItem(index)
            item.setText(label)
        elif index == (len(self) - 1):
            # End of initial run
            self.labels_initialized = True
    
    def _set_width(self, index, width):
        if width > 0:
            self.table.horizontalHeader().setSectionResizeMode(
                index,
                qt.QHeaderView.Interactive
            )
            self.table.horizontalHeader().resizeSection(index, width)
        else:
            self.table.horizontalHeader().setSectionResizeMode(
                index,
                qt.QHeaderView.ResizeToContents
            )
    
    def _set_align(self, index, align):
        self.table.horizontalHeaderItem(index).setTextAlignment(
            _qtalignmap[align])
        # Table cells will align themselves when added
    
    def _set_readonly(self, index, readonly):
        pass


class PQtTable(_PQtClientWidget, qt.QTableWidget, table.PTableBase, metaclass=_PQtSequenceMeta):
    
    labelsclass = PQtTableLabels
    
    event_signals = (SIGNAL_CELLCHANGED,)
    
    def __init__(self, parent, labels=None, data=None, target=None):
        qt.QTableWidget.__init__(self, parent)
        self.setSortingEnabled(False)
        # Used by ugly hack in default fg and bk color methods, below
        pal = self.palette()
        self._def_fgcolor = pal.color(self.foregroundRole())
        self._def_bkcolor = pal.color(self.backgroundRole())
        # Used by ugly hack in setup_notify, below
        self._setting_colors = False
        
        # This will initialize data (if any)
        table.PTableBase.__init__(self, parent, labels, data, target)
    
    def setup_notify(self, signal, target):
        # Hack to mask out table changed events fired when cell colors are
        # changed (the PySide API says this shouldn't happen but it does,
        # go figure)
        if signal == SIGNAL_TABLECHANGED:
            def _wrapper(row, col):
                if not self._setting_colors:
                    target(row, col)
            actual_target = _wrapper
        else:
            actual_target = target
        _PQtClientWidget.setup_notify(self, signal, actual_target)
    
    def _get_item(self, row, col):
        result = self.item(row, col)
        if not isinstance(result, qt.QTableWidgetItem):
            result = qt.QTableWidgetItem()
            self.setItem(row, col, result)
        return result
    
    def _set_header_font_object(self, font_name, font_size, bold, italic):
        self.horizontalHeader().setFont(self._qt_font_object(
            font_name, font_size, bold, italic))
    
    def _get_cell(self, row, col):
        return self._get_item(row, col).text()
    
    def _set_cell(self, row, col, value):
        item = self._get_item(row, col)
        item.setText(str(value))
        # FIXME: it would be nice if this could be done once instead of
        # per item
        item.setTextAlignment(self.horizontalHeaderItem(col).textAlignment())
    
    def rowcount(self):
        return self.rowCount()
    
    def colcount(self):
        return self.columnCount()
    
    def set_colcount(self, count):
        self.setColumnCount(count)
    
    def current_row(self):
        return self.currentRow()
    
    def current_col(self):
        return self.currentColumn()
    
    def _insert_row(self, index):
        self.insertRow(index)
    
    def _remove_row(self, index):
        self.removeRow(index)
    
    def set_min_size(self, width, height):
        self.setMinimumSize(width, height)
    
    def topmargin(self):
        return 0  # self.topMargin()
    
    def leftmargin(self):
        return 0  # self.leftMargin()
    
    def rowheight(self, row):
        return self.rowHeight(row)
    
    def colwidth(self, col):
        return self.columnWidth(col)
    
    def default_fgcolor(self):
        return self._def_fgcolor
    
    def default_bkcolor(self):
        return self._def_bkcolor
    
    def set_text_fgcolor(self, row, col, color):
        item = self._get_item(row, col)
        self._setting_colors = True
        item.setForeground(qtg.QBrush(self._mapped_color(color)))
        self._setting_colors = False
    
    def set_cell_bkcolor(self, row, col, color):
        item = self._get_item(row, col)
        self._setting_colors = True
        item.setBackground(qtg.QBrush(self._mapped_color(color)))
        self._setting_colors = False
