
"""Class :py:class:`QWTable` is a QTableView->QWidget for tree model
======================================================================

Usage ::

    # Run test: python lcls2/psdaq/psdaq/control_gui/QWTable.py

    from psdaq.control_gui.QWTable import QWTable
    w = QWTable()

Created on 2019-03-28 by Mikhail Dubrovin
Re-designed after copy psana/graphqt/QWTable.py -> psdaq/control_gui/
"""

import logging
logger = logging.getLogger(__name__)

from PyQt5.QtWidgets import QTableView, QVBoxLayout, QAbstractItemView, QSizePolicy
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtCore import Qt, QModelIndex

from psdaq.control_gui.QWIcons import icon


class QWTable(QTableView):

    def __init__(self, **kwargs):

        parent = kwargs.get('parent', None)

        QTableView.__init__(self, parent)
        self._name = self.__class__.__name__

        icon.set_icons()

        self.is_connected_item_changed = False

        self._si_model = QStandardItemModel()
        self.set_selection_mode()
        self.fill_table_model(**kwargs) # defines self._si_model
        self.setModel(self._si_model)
        self.connect_control()
        self.set_style()


    def connect_control(self):
        self.connect_item_selected_to(self.on_item_selected)
        self.clicked.connect(self.on_click)
        self.doubleClicked.connect(self.on_double_click)
        self.connect_item_changed_to(self.on_item_changed)


    #def __del__(self):
    #    QTableView.__del__(self) - it does not have __del__


    def set_selection_mode(self, smode=QAbstractItemView.ExtendedSelection):
        logger.debug('Set selection mode: %s'%smode)
        self.setSelectionMode(smode)


    def connect_item_changed_to(self, recipient):
        self._si_model.itemChanged.connect(recipient)
        self.is_connected_item_changed = True


    def disconnect_item_changed_from(self, recipient):
        if self.is_connected_item_changed:
            self._si_model.itemChanged.disconnect(recipient)
            self.is_connected_item_changed = False


    def connect_item_selected_to(self, recipient):
        self.selectionModel().currentChanged[QModelIndex, QModelIndex].connect(recipient)


    def disconnect_item_selected_from(self, recipient):
        #self.selectionModel().selectionChanged[QModelIndex, QModelIndex].disconnect(recipient)
        self.selectionModel().currentChanged[QModelIndex, QModelIndex].disconnect(recipient)


    def set_style(self):
        self.setStyleSheet("QTableView::item:hover{background-color:#00FFAA;}")
        #self.setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Fixed)
        self.set_exact_widget_size()


    def set_exact_widget_size(self):
        """set window size exactly matching actual size of QTableView.
        """
        self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.resizeColumnsToContents()
        self.setFixedSize(self.horizontalHeader().length()+self.verticalHeader().width(),\
                          self.verticalHeader().length()+self.horizontalHeader().height())


    def fill_table_model(self, **kwargs):
        self.clear_model()
        self._si_model.setHorizontalHeaderLabels(['col0', 'col1', 'col2', 'col3', 'col4'])
        self._si_model.setVerticalHeaderLabels(['row0', 'row1', 'row2', 'row3'])
        for row in range(0, 4):
            for col in range(0, 6):
                item = QStandardItem("itemA %d %d"%(row,col))
                item.setIcon(icon.icon_table)
                item.setCheckable(True)
                self._si_model.setItem(row,col,item)
                if col==2: item.setIcon(icon.icon_folder_closed)
                if col==3: item.setText('Some text')
                #self._si_model.appendRow(item)


    def clear_model(self):
        rows,cols = self._si_model.rowCount(), self._si_model.columnCount()
        self._si_model.removeRows(0, rows)
        self._si_model.removeColumns(0, cols)


    def selected_indexes(self):
        return self.selectedIndexes()


    def selected_items(self):
        indexes =  self.selectedIndexes()
        return [self._si_model.itemFromIndex(i) for i in self.selectedIndexes()]


    def getFullNameFromItem(self, item):
        #item = self._si_model.itemFromIndex(ind)
        ind   = self._si_model.indexFromItem(item)
        return self.getFullNameFromIndex(ind)


    def getFullNameFromIndex(self, ind):
        item = self._si_model.itemFromIndex(ind)
        if item is None: return None
        self._full_name = item.text()
        self._getFullName(ind)
        return self._full_name


    def _getFullName(self, ind):
        ind_par  = self._si_model.parent(ind)
        if(ind_par.column() == -1):
            item = self._si_model.itemFromIndex(ind)
            self.full_name = '/' + self._full_name
            #logger.debug('Item full name:' + self._full_name)
            return self._full_name
        else:
            item_par = self._si_model.itemFromIndex(ind_par)
            self._full_name = item_par.text() + '/' + self._full_name
            self._getFullName(ind_par)


#    def resizeEvent(self, e):
#        logger.debug('resizeEvent')
#        QTableView.resizeEvent(self, e)


    def closeEvent(self, event): # if the x is clicked
        logger.debug('closeEvent')
        QTableView.closeEvent(self, event)


    def on_click(self, index):
        item = self._si_model.itemFromIndex(index)
        msg = 'on_click: item in row:%02d text: %s' % (index.row(), item.text())
        logger.debug(msg)


    def on_double_click(self, index):
        item = self._si_model.itemFromIndex(index)
        msg = 'on_double_click: item in row:%02d text: %s' % (index.row(), item.text())
        logger.debug(msg)


    def on_item_selected(self, ind_sel, ind_desel):
        #logger.debug("ind   selected: ", ind_sel.row(),  ind_sel.column())
        #logger.debug("ind deselected: ", ind_desel.row(),ind_desel.column())
        item = self._si_model.itemFromIndex(ind_sel)
        logger.debug('on_item_selected: "%s" is selected' % (item.text() if item is not None else None))
        #logger.debug('on_item_selected: %s' % self.getFullNameFromItem(item))


    def on_item_changed(self, item):
        state = ['UNCHECKED', 'TRISTATE', 'CHECKED'][item.checkState()]
        logger.debug('abstract on_item_changed: "%s" at state %s' % (self.getFullNameFromItem(item), state))


    def process_selected_items(self):
        selitems = self.selected_items()
        msg = '%d Selected items:' % len(selitems)
        for i in selitems:
            msg += '\n  %s' % i.text()
        logger.info(msg)


    if __name__ == '__main__':

      def keyPressEvent(self, e):
        logger.info('keyPressEvent, key=%s' % e.key())
        if   e.key() == Qt.Key_Escape:
            self.close()

        elif e.key() == Qt.Key_S:
            self.process_selected_items()

        else:
            logger.info('Keys:'\
               '\n  ESC - exit'\
               '\n  S - show selected items'\
               '\n')


if __name__ == '__main__':
    import sys
    from PyQt5.QtWidgets import QApplication

    logging.basicConfig(format='%(asctime)s %(name)s %(levelname)s: %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG)
    app = QApplication(sys.argv)
    w = QWTable()
    #w.setGeometry(100, 100, 700, 300)
    w.setWindowTitle('QWTable')
    w.move(100,50)
    w.show()
    app.exec_()
    del w
    del app

# EOF


[((17, 9, 17, 36), 'logging.getLogger', 'logging.getLogger', ({(17, 27, 17, 35): '__name__'}, {}), '(__name__)', False, 'import logging\n'), ((221, 4, 221, 122), 'logging.basicConfig', 'logging.basicConfig', (), '', False, 'import logging\n'), ((222, 10, 222, 32), 'PyQt5.QtWidgets.QApplication', 'QApplication', ({(222, 23, 222, 31): 'sys.argv'}, {}), '(sys.argv)', False, 'from PyQt5.QtWidgets import QApplication\n'), ((32, 8, 32, 41), 'PyQt5.QtWidgets.QTableView.__init__', 'QTableView.__init__', ({(32, 28, 32, 32): 'self', (32, 34, 32, 40): 'parent'}, {}), '(self, parent)', False, 'from PyQt5.QtWidgets import QTableView, QVBoxLayout, QAbstractItemView, QSizePolicy\n'), ((35, 8, 35, 24), 'psdaq.control_gui.QWIcons.icon.set_icons', 'icon.set_icons', ({}, {}), '()', False, 'from psdaq.control_gui.QWIcons import icon\n'), ((39, 25, 39, 45), 'PyQt5.QtGui.QStandardItemModel', 'QStandardItemModel', ({}, {}), '()', False, 'from PyQt5.QtGui import QStandardItemModel, QStandardItem\n'), ((164, 8, 164, 42), 'PyQt5.QtWidgets.QTableView.closeEvent', 'QTableView.closeEvent', ({(164, 30, 164, 34): 'self', (164, 36, 164, 41): 'event'}, {}), '(self, event)', False, 'from PyQt5.QtWidgets import QTableView, QVBoxLayout, QAbstractItemView, QSizePolicy\n'), ((106, 23, 106, 61), 'PyQt5.QtGui.QStandardItem', 'QStandardItem', ({(106, 37, 106, 60): "'itemA %d %d' % (row, col)"}, {}), "('itemA %d %d' % (row, col))", False, 'from PyQt5.QtGui import QStandardItemModel, QStandardItem\n')]