class ServicesQWidget(QWidget):
    """
        Class wo create services QWidget
    """

    def __init__(self, parent=None):
        super(ServicesQWidget, self).__init__(parent)
        # Fields
        self.services = None
        self.services_tree_widget = QTreeWidget()
        self.services_list_widget = QListWidget()
        self.service_data_widget = ServiceDataQWidget()
        self.services_dashboard = ServicesDashboardQWidget()

    def initialize(self):
        """
        Initialize QWidget

        """

        layout = QGridLayout()
        self.setLayout(layout)
        layout.setContentsMargins(0, 0, 0, 0)

        # Services dashboard
        self.services_dashboard.initialize()
        for state in self.services_dashboard.states_btns:
            self.services_dashboard.states_btns[state].clicked.connect(
                lambda _, s=state: self.filter_services(state=s)
            )
        layout.addWidget(self.services_dashboard, 0, 0, 1, 2)
        layout.addWidget(get_frame_separator(), 1, 0, 1, 2)

        # Services QTreeWidget
        self.services_tree_widget.setIconSize(QSize(32, 32))
        self.services_tree_widget.setAlternatingRowColors(True)
        self.services_tree_widget.header().close()
        layout.addWidget(self.services_tree_widget, 2, 0, 1, 1)

        # Services QListWidget
        self.services_list_widget.clicked.connect(self.update_service_data)
        self.services_list_widget.hide()
        layout.addWidget(self.services_list_widget, 2, 0, 1, 1)

        # Service DataWidget
        self.service_data_widget.initialize()
        layout.addWidget(self.service_data_widget, 2, 1, 1, 1)

    def filter_services(self, state):
        """
        Filter services with the wanted state

        :param state: state of service: OK, WARNING, NOT_MONITORED, DOWNTIME
        :return:
        """

        # Clear QListWidget and update filter buttons of services dashboard
        self.services_list_widget.clear()
        for btn_state in self.services_dashboard.states_btns:
            if btn_state != state:
                self.services_dashboard.states_btns[btn_state].setChecked(False)

        # Update QWidgets
        if self.sender().isChecked():
            self.set_filter_items(state)
            self.services_tree_widget.hide()
            self.services_list_widget.show()
        else:
            self.services_tree_widget.show()
            self.services_list_widget.hide()

    def set_filter_items(self, state):
        """
        Add filter items to QListWidget corresponding to "state"

        :param state: state of service to filter
        :type state: str
        """

        services_added = False
        if state in 'NOT_MONITORED':
            for service in self.services:
                if not service.data['active_checks_enabled'] and \
                        not service.data['passive_checks_enabled']and \
                        not service.data['ls_downtimed'] and \
                        not service.data['ls_acknowledged']:
                    self.add_filter_item(service)
                    services_added = True
        elif state in 'DOWNTIME':
            for service in self.services:
                if service.data['ls_downtimed']:
                    self.add_filter_item(service)
                    services_added = True
        elif state in 'ACKNOWLEDGE':
            for service in self.services:
                if service.data['ls_acknowledged']:
                    self.add_filter_item(service)
                    services_added = True
        else:
            for service in self.services:
                if service.data['ls_state'] in state:
                    self.add_filter_item(service)
                    services_added = True

        if not services_added:
            not_added_item = QListWidgetItem()
            not_added_item.setData(Qt.DecorationRole, QIcon(settings.get_image('services_ok')))
            not_added_item.setData(Qt.DisplayRole, _('No such services to display...'))
            self.services_list_widget.addItem(not_added_item)

    def add_filter_item(self, filter_item):
        """
        Add filter item to QListWidget

        :param filter_item: filter item (service)
        :type filter_item: alignak_app.items.service.Service
        """

        item = QListWidgetItem()
        monitored = \
            filter_item.data['passive_checks_enabled'] + filter_item.data['active_checks_enabled']
        icon_name = get_icon_name(
            filter_item.item_type,
            filter_item.data['ls_state'],
            filter_item.data['ls_acknowledged'],
            filter_item.data['ls_downtimed'],
            monitored
        )
        item.setData(Qt.DecorationRole, QIcon(settings.get_image(icon_name)))
        item.setData(Qt.DisplayRole, filter_item.get_display_name())
        item.setData(Qt.UserRole, filter_item.item_id)
        item.setToolTip(filter_item.get_tooltip())

        self.services_list_widget.addItem(item)

    def update_widget(self, services):
        """
        Update the QTreeWidget and its items

        :param services: list of :class:`Services <alignak_app.items.service.Service>` items
        :type services: list
        """

        self.services = services

        # Update services dashboard
        self.services_dashboard.update_widget(self.services)

        # Clear QTreeWidget
        self.services_tree_widget.clear()
        self.services_tree_widget.setIconSize(QSize(16, 16))

        if self.services:
            # Set as "Global" aggregation who are empty
            for service in self.services:
                if not service.data['aggregation']:
                    service.data['aggregation'] = 'Global'

            # First sort list by state then by aggregation
            newlist = sorted(
                self.services,
                key=lambda s: itemgetter('ls_state', 'ls_acknowledged', 'aggregation')(s.data)
            )
            self.services = newlist

            # Get list of aggregations
            aggregations = []
            for service in self.services:
                if service.data['aggregation'] not in aggregations:
                    aggregations.append(service.data['aggregation'])

            # Add QTreeWidgetItems
            for aggregation in aggregations:
                main_tree = QTreeWidgetItem()
                main_tree.setText(0, aggregation)
                main_tree.setIcon(0, QIcon(settings.get_image('tree')))
                main_tree.setToolTip(0, aggregation)
                for service in self.services:
                    if service.data['aggregation'] == aggregation:
                        service_tree = ServiceTreeItem()
                        service_tree.initialize(service)
                        service_tree.setToolTip(0, service.get_tooltip())
                        self.services_tree_widget.clicked.connect(self.update_service_data)
                        main_tree.addChild(service_tree)

                self.services_tree_widget.addTopLevelItem(main_tree)

            self.service_data_widget.hide()
        else:
            # If no services, reset service item to None and hide data widget
            self.service_data_widget.service_item = None
            self.service_data_widget.hide()

    def update_service_data(self):  # pragma: no cover
        """
        Update ServiceDataqWidget

        """

        service_item = self.sender().currentItem()

        if isinstance(service_item, (ServiceTreeItem, QListWidgetItem)):
            service = None
            # Get service
            if isinstance(service_item, ServiceTreeItem):
                service = data_manager.get_item('service', '_id', service_item.service_id)
            elif isinstance(service_item, QListWidgetItem):
                service = data_manager.get_item('service', '_id', service_item.data(Qt.UserRole))
            if not service:
                service = self.service_data_widget.service_item

            # Update QWidgets
            self.services_tree_widget.setMaximumWidth(self.width() * 0.5)
            self.services_list_widget.setMaximumWidth(self.width() * 0.5)
            self.service_data_widget.setMaximumWidth(self.width() * 0.5)
            self.service_data_widget.update_widget(service)
            self.services_dashboard.update_widget(self.services)
            self.service_data_widget.show()

            # Update Service Items (ServiceTreeItem, QListWidgetItem)
            if isinstance(service_item, ServiceTreeItem):
                service_item.update_item()
            else:
                monitored = \
                    service.data['passive_checks_enabled'] + service.data['active_checks_enabled']
                icon_name = get_icon_name(
                    'service',
                    service.data['ls_state'],
                    service.data['ls_acknowledged'],
                    service.data['ls_downtimed'],
                    monitored
                )

                service_item.setData(Qt.DecorationRole, QIcon(settings.get_image(icon_name)))
                service_item.setData(Qt.DisplayRole, service.get_display_name())
                service_item.setToolTip(service.get_tooltip())
예제 #2
0
class CollapsibleDialog(QDialog):
    """a dialog to which collapsible sections can be added;
    reimplement define_sections() to define sections and
        add them as (title, widget) tuples to self.sections
     
    reimplemented from http://www.fancyaddress.com/blog/qt-2/create-something-like-the-widget-box-as-in-the-qt-designer/
    """
    def __init__(self, parent = None):
        super().__init__(parent)
        self.tree = QTreeWidget()
        self.tree.setHeaderHidden(True)
        layout = QVBoxLayout()
        layout.addWidget(self.tree)
        self.setLayout(layout)
        self.tree.setIndentation(0)
        self.sections = []
        self.section_dic = {}
        self.define_sections()
        self.add_sections()
         
    def add_sections(self):
        """adds a collapsible sections for every 
        (title, widget) tuple in self.sections
        """
        for (i, (title, widget)) in enumerate(self.sections):
            button = self.add_button(title)
            section = self.add_widget(button, widget)
            button.addChild(section)
            if i == 0:
                button.setExpanded(True)
            self.section_dic[i] = (button, section)
 
    def define_sections(self):
        """reimplement this to define all your sections
        and add them as (title, widget) tuples to self.sections
        """
        widget = QFrame(self.tree)
        layout = QHBoxLayout(widget)
        layout.addWidget(QLabel("Bla"))
        layout.addWidget(QLabel("Blubb"))
        title = "Section 1"
        self.sections.append((title, widget))
 
    def add_button(self, title):
        """creates a QTreeWidgetItem containing a button 
        to expand or collapse its section
        """
        item = QTreeWidgetItem()
        self.tree.addTopLevelItem(item)
        self.tree.setItemWidget(item, 0, SectionExpandButton(item, text = title))
        return item
 
    def add_widget(self, button, widget):
        """creates a QWidgetItem containing the widget,
        as child of the button-QWidgetItem
        """
        section = QTreeWidgetItem(button)
        section.setDisabled(True)
        self.tree.setItemWidget(section, 0, widget)
        return section
     
    @pyqtSlot(int, int)
    def proceed_sections(self, old_section, new_section):
        """collapses old section and expands next section
        """
        (button_new, _) = self.section_dic[new_section]
        (button_old, _) = self.section_dic[old_section]
        button_new.setExpanded(True)
        button_old.setExpanded(False)
        try:
            self.sender().setChecked(False) # if sent from a button, un-press it
        except:
            pass
예제 #3
0
class ServicesQWidget(QWidget):
    """
        Class wo create services QWidget
    """
    def __init__(self, parent=None):
        super(ServicesQWidget, self).__init__(parent)
        # Fields
        self.services = None
        self.services_tree_widget = QTreeWidget()
        self.services_list_widget = QListWidget()
        self.service_data_widget = ServiceDataQWidget()
        self.services_dashboard = ServicesDashboardQWidget()

    def initialize(self):
        """
        Initialize QWidget

        """

        layout = QGridLayout()
        self.setLayout(layout)
        layout.setContentsMargins(0, 0, 0, 0)

        # Services dashboard
        self.services_dashboard.initialize()
        for state in self.services_dashboard.states_btns:
            self.services_dashboard.states_btns[state].clicked.connect(
                lambda _, s=state: self.filter_services(state=s))
        layout.addWidget(self.services_dashboard, 0, 0, 1, 2)
        layout.addWidget(get_frame_separator(), 1, 0, 1, 2)

        # Services QTreeWidget
        self.services_tree_widget.setIconSize(QSize(32, 32))
        self.services_tree_widget.setAlternatingRowColors(True)
        self.services_tree_widget.header().close()
        layout.addWidget(self.services_tree_widget, 2, 0, 1, 1)

        # Services QListWidget
        self.services_list_widget.clicked.connect(self.update_service_data)
        self.services_list_widget.hide()
        layout.addWidget(self.services_list_widget, 2, 0, 1, 1)

        # Service DataWidget
        self.service_data_widget.initialize()
        layout.addWidget(self.service_data_widget, 2, 1, 1, 1)

    def filter_services(self, state):
        """
        Filter services with the wanted state

        :param state: state of service: OK, WARNING, NOT_MONITORED, DOWNTIME
        :return:
        """

        # Clear QListWidget and update filter buttons of services dashboard
        self.services_list_widget.clear()
        for btn_state in self.services_dashboard.states_btns:
            if btn_state != state:
                self.services_dashboard.states_btns[btn_state].setChecked(
                    False)

        # Update QWidgets
        if self.sender().isChecked():
            self.set_filter_items(state)
            self.services_tree_widget.hide()
            self.services_list_widget.show()
        else:
            self.services_tree_widget.show()
            self.services_list_widget.hide()

    def set_filter_items(self, state):
        """
        Add filter items to QListWidget corresponding to "state"

        :param state: state of service to filter
        :type state: str
        """

        services_added = False
        if state in 'NOT_MONITORED':
            for service in self.services:
                if not service.data['active_checks_enabled'] and \
                        not service.data['passive_checks_enabled']and \
                        not service.data['ls_downtimed'] and \
                        not service.data['ls_acknowledged']:
                    self.add_filter_item(service)
                    services_added = True
        elif state in 'DOWNTIME':
            for service in self.services:
                if service.data['ls_downtimed']:
                    self.add_filter_item(service)
                    services_added = True
        elif state in 'ACKNOWLEDGE':
            for service in self.services:
                if service.data['ls_acknowledged']:
                    self.add_filter_item(service)
                    services_added = True
        else:
            for service in self.services:
                if service.data['ls_state'] in state:
                    self.add_filter_item(service)
                    services_added = True

        if not services_added:
            not_added_item = QListWidgetItem()
            not_added_item.setData(Qt.DecorationRole,
                                   QIcon(settings.get_image('services_ok')))
            not_added_item.setData(Qt.DisplayRole,
                                   _('No such services to display...'))
            self.services_list_widget.addItem(not_added_item)

    def add_filter_item(self, filter_item):
        """
        Add filter item to QListWidget

        :param filter_item: filter item (service)
        :type filter_item: alignak_app.items.service.Service
        """

        item = QListWidgetItem()
        monitored = \
            filter_item.data['passive_checks_enabled'] + filter_item.data['active_checks_enabled']
        icon_name = get_icon_name(filter_item.item_type,
                                  filter_item.data['ls_state'],
                                  filter_item.data['ls_acknowledged'],
                                  filter_item.data['ls_downtimed'], monitored)
        item.setData(Qt.DecorationRole, QIcon(settings.get_image(icon_name)))
        item.setData(Qt.DisplayRole, filter_item.get_display_name())
        item.setData(Qt.UserRole, filter_item.item_id)
        item.setToolTip(filter_item.get_tooltip())

        self.services_list_widget.addItem(item)

    def update_widget(self, services):
        """
        Update the QTreeWidget and its items

        :param services: list of :class:`Services <alignak_app.items.service.Service>` items
        :type services: list
        """

        self.services = services

        # Update services dashboard
        self.services_dashboard.update_widget(self.services)

        # Clear QTreeWidget
        self.services_tree_widget.clear()
        self.services_tree_widget.setIconSize(QSize(16, 16))

        if self.services:
            # Set as "Global" aggregation who are empty
            for service in self.services:
                if not service.data['aggregation']:
                    service.data['aggregation'] = 'Global'

            # First sort list by state then by aggregation
            newlist = sorted(self.services,
                             key=lambda s: itemgetter(
                                 'ls_state', 'ls_acknowledged', 'aggregation')
                             (s.data))
            self.services = newlist

            # Get list of aggregations
            aggregations = []
            for service in self.services:
                if service.data['aggregation'] not in aggregations:
                    aggregations.append(service.data['aggregation'])

            # Add QTreeWidgetItems
            for aggregation in aggregations:
                main_tree = QTreeWidgetItem()
                main_tree.setText(0, aggregation)
                main_tree.setIcon(0, QIcon(settings.get_image('tree')))
                main_tree.setToolTip(0, aggregation)
                for service in self.services:
                    if service.data['aggregation'] == aggregation:
                        service_tree = ServiceTreeItem()
                        service_tree.initialize(service)
                        service_tree.setToolTip(0, service.get_tooltip())
                        self.services_tree_widget.clicked.connect(
                            self.update_service_data)
                        main_tree.addChild(service_tree)

                self.services_tree_widget.addTopLevelItem(main_tree)

            self.service_data_widget.hide()
        else:
            # If no services, reset service item to None and hide data widget
            self.service_data_widget.service_item = None
            self.service_data_widget.hide()

    def update_service_data(self):  # pragma: no cover
        """
        Update ServiceDataqWidget

        """

        service_item = self.sender().currentItem()

        if isinstance(service_item, (ServiceTreeItem, QListWidgetItem)):
            service = None
            # Get service
            if isinstance(service_item, ServiceTreeItem):
                service = data_manager.get_item('service', '_id',
                                                service_item.service_id)
            elif isinstance(service_item, QListWidgetItem):
                service = data_manager.get_item('service', '_id',
                                                service_item.data(Qt.UserRole))
            if not service:
                service = self.service_data_widget.service_item

            # Update QWidgets
            self.services_tree_widget.setMaximumWidth(self.width() * 0.5)
            self.services_list_widget.setMaximumWidth(self.width() * 0.5)
            self.service_data_widget.setMaximumWidth(self.width() * 0.5)
            self.service_data_widget.update_widget(service)
            self.services_dashboard.update_widget(self.services)
            self.service_data_widget.show()

            # Update Service Items (ServiceTreeItem, QListWidgetItem)
            if isinstance(service_item, ServiceTreeItem):
                service_item.update_item()
            else:
                monitored = \
                    service.data['passive_checks_enabled'] + service.data['active_checks_enabled']
                icon_name = get_icon_name('service', service.data['ls_state'],
                                          service.data['ls_acknowledged'],
                                          service.data['ls_downtimed'],
                                          monitored)

                service_item.setData(Qt.DecorationRole,
                                     QIcon(settings.get_image(icon_name)))
                service_item.setData(Qt.DisplayRole,
                                     service.get_display_name())
                service_item.setToolTip(service.get_tooltip())
예제 #4
0
class Database_maint_frame(QMainWindow):

    FROM, SUBJECT, DATE = range(3)
    
    def __init__(self, database_driver=None):
        
        # create application object
        app = QApplication(sys.argv)
        super().__init__()
        
        self.__title='Database maintain'
        self.__posx=200
        self.__posy=200
        self.__width=1080
        self.__height=720
        
        # Validation for database driver
        self.__database_driver = None
        if database_driver and isinstance(database_driver, IDatabase_driver):
            # set database driver
            self.__database_driver = database_driver
            
        # opened tables
        self.__opened_tables = []
        
        # set style sheet
        self.set_stylesheet()
        # initialize method
        self.initUI()
        
        sys.exit(app.exec_()) 
        
        
    def initUI(self):
        '''
        UI initialize
        '''
        # set the window position(x,y) and size
        self.setGeometry(self.__posx, self.__posy, self.__width, self.__height)  
        # set the window title
        self.setWindowTitle(self.__title)
        
        # update window status
        self.update_status('Loading...')
        
        # add menu bar
        self.__mainMenu = self.menuBar()
        self.__fileMenu = self.__mainMenu.addMenu('File')
        self.__editMenu = self.__mainMenu.addMenu('Edit')
        self.__viewMenu = self.__mainMenu.addMenu('View')
        self.__searchMenu = self.__mainMenu.addMenu('Search')
        self.__toolsMenu = self.__mainMenu.addMenu('Tools')
        self.__helpMenu = self.__mainMenu.addMenu('Help')
        
        # add frame
        self.__lefttop_square = QFrame(self)
        self.__lefttop_square.setGeometry(10, 30, 230, 150)
        self.__leftbtm_square = QFrame(self)
        self.__leftbtm_square.setGeometry(10, 190, 230, 510)
        self.__right_square = QFrame(self)
        self.__right_square.setGeometry(250, 30, 820, 670)
        
        # add database combobox and add items
        self.__db_comboBox = QComboBox(self.__lefttop_square)
        self.__db_comboBox.setGeometry(QRect(15, 30, 200, 30))
        self.__db_comboBox.setObjectName(("comboBox"))
        # load data
        self.on_load_combolist(self.__db_comboBox)  # load event
        
        # add datatable treeview and add items
        self.__tb_treeview = QTreeWidget(self.__leftbtm_square)
        self.__tb_treeview.setGeometry(15, 30, 200, 440) 
        self.__tb_treeview_root = QTreeWidgetItem(self.__tb_treeview)
        self.__tb_treeview_root.setText(0, "Tables")
        self.__tb_treeview_root.setText(1, "root")
        self.__tb_treeview.addTopLevelItem(self.__tb_treeview_root) 
        self.__tb_treeview.expandAll()
        self.__tb_treeview.setHeaderHidden(True)
        
        # add tab
        self.__tab = QTabWidget(self.__right_square)
        self.__tab.setGeometry(10, 10, 800, 620)
        
        # add datagrid buttons
        self.__new_rec_btn = QPushButton('New',self)
        self.__new_rec_btn.setToolTip('Add a new record')
        self.__new_rec_btn.resize(60, 30)
        self.__new_rec_btn.move(400,665)
        self.__new_rec_btn.clicked.connect(self.click_new_rec_btn) # button click event
        
        self.__del_rec_btn = QPushButton('Delete',self)
        self.__del_rec_btn.setToolTip('Delete a new record')
        self.__del_rec_btn.resize(60, 30)
        self.__del_rec_btn.move(470,665)
        
        # event
        self.__del_rec_btn.clicked.connect(self.click_del_rec_btn) # button click event
        self.__db_comboBox.currentIndexChanged.connect(self.on_combox_selection_change) # selection change event
        self.__tb_treeview.doubleClicked.connect(self.on_treeview_doubleClick) # selection change event
        
        # show the window
        self.show()
    
    
    def set_stylesheet(self):
        '''
        set the style sheet from qss and icons
        '''
        # get the relative project path
        fileconstant = File_constant()
        root_path = os.path.dirname(os.path.abspath(__file__))
        proj_path = root_path[:root_path.index(fileconstant.MY_PROJECT_PACKAGE)]
        # set the qss
        qss_path = proj_path + "\\src\\main\\pydev\\com\\ftd\\resource\\style\\StyleSheet.qss"
        self.setStyleSheet(open(qss_path, "r").read())
        # set the window icon
        icon_path = proj_path + "\\src\\main\\pydev\\com\\ftd\\resource\\icons\\title_icon.jpg"
        self.setWindowIcon(QIcon(icon_path))
        
    
    def update_status(self, status):
        '''
        update the window status
        '''
        self.statusBar().showMessage(status)
        
    
    def closeEvent(self, event):
        '''
        window close event
        '''
        reply = QMessageBox.question(self, 'Message', 'Do you want to quit?', QMessageBox.Yes | QMessageBox.No,QMessageBox.Yes)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()
        
    
    def click_new_rec_btn(self):
        '''
        new button click
        '''
        print('NEW BUTTON')
        
    
    def click_del_rec_btn(self):
        '''
        delete button click
        '''
        print('DELETE BUTTON')
    
    
    def on_load_combolist(self, parent):
        '''
        combobox load event
        '''
        self.load_databases(parent)
        
    
    def load_databases(self, parent):
        '''
        load the database name list and append into combolist
        '''
        if not self.__database_driver:
            QMessageBox.warning(self, 'Warning', "Invalid database driver, please check.", QMessageBox.Ok)
            return
            
        result, database_list, message = self.__database_driver.get_database_list()
        if not result:
            QMessageBox.critical(self, 'Error', message, QMessageBox.Ok)
        else:
            if len(database_list) > 0:
                parent.addItem("")
                for name in database_list:
                    parent.addItem(name)
            else:
                QMessageBox.warning(self, 'Warning', "Database is empty.", QMessageBox.Ok)
    
    
    def on_combox_selection_change(self):
        '''
        combobox selection change event
        '''
        if not self.__database_driver:
            return
        
        self.clear_treeview_nodes()
        
        if not self.__db_comboBox.currentText():
            return
        
        table_list = self.__database_driver.get_table_list(self.__db_comboBox.currentText())
        
        self.create_treeview_nodes(table_list)
    
    
    def clear_treeview_nodes(self):
        '''
        clear nodes from datatable treeview
        '''
        if self.__tb_treeview_root:
            while self.__tb_treeview_root.childCount() > 0:
                self.__tb_treeview_root.removeChild(self.__tb_treeview_root.takeChild(0))
        
    
    def create_treeview_nodes(self, nodelist=None):
        '''
        append nodes into datatable treeview
        '''
        if nodelist:
            for table in nodelist:
                child = QTreeWidgetItem(self.__tb_treeview_root) 
                child.setText(0,table)
                child.setText(1,'child')

    
    def on_treeview_doubleClick(self):
        '''
        treeview selection double click event
        '''
        if self.__tb_treeview.currentItem():
            hititem = self.__tb_treeview.currentItem()
            
            if hititem.text(1) == 'root':
                return
            
            if hititem.text(0) in self.__opened_tables:
                return
            
            columns = []
            column_types = []
            records = []
            try:
                # load the datatable record
                columns, column_types, records = self.__database_driver.get_records(self.__db_comboBox.currentText(), hititem.text(0))
            except Exception as e:
                QMessageBox.warning(self, 'Warning', "Table load failed, please retry.", QMessageBox.Ok)
                print('expect:', e)
                return
            
            # record the selected table
            self.__opened_tables.append(hititem.text(0))
            # render grid
            self.render_table_grid(hititem.text(0), columns, column_types, records)
            
            
    def render_table_grid(self, datatablename, columns, column_types, table_records):
        '''
        render the grid
        '''
        # Create table
        self.__datatable = QTableWidget()
        
        # render the columns
        self.__datatable.setRowCount(len(table_records))
        self.__datatable.setColumnCount(len(columns))
        self.__datatable.setHorizontalHeaderLabels(columns)
        
        # render the grid cells
        if table_records and len(table_records) > 0:
            rows_count = len(table_records)
            column_count = len(columns)
            for i in range(0, rows_count):  # Rows
                for j in range(0, column_count):  # Columns
                    self.__datatable.setItem(i , j, QTableWidgetItem(str(table_records[i][j])))
        
        # render grid style
        self.__datatable.setAlternatingRowColors(True)
        self.__datatable.horizontalHeader().setObjectName("dt_hheader")
        self.__datatable.verticalHeader().setObjectName("dt_vheader")
        self.__datatable.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)
        
        self.__datatable.doubleClicked.connect(self.on_gridcell_click) # double click event
  
        # Create tab
        self.__tab.addTab(self.__datatable, datatablename)
           
    
    def on_gridcell_click(self):
        for currentQTableWidgetItem in self.__datatable.selectedItems():
            print(currentQTableWidgetItem.row(), currentQTableWidgetItem.column(), currentQTableWidgetItem.text())
class ConfigWidget(QWidget):

    def __init__(self, plugin_action):
        QWidget.__init__(self)
        self.plugin_action = plugin_action
        self.gui = plugin_action.gui
        self._initialise_layout()
        self.blank_icon = QIcon(I('blank.png'))

        fav_menus = plugin_prefs[STORE_MENUS]
        # Rebuild this into a map for comparison purposes
        lookup_menu_map = self._build_lookup_menu_map(fav_menus)
        self._populate_actions_tree(lookup_menu_map)
        self.items_list.populate_list(fav_menus)

        # Hook up our events
        self.tv.itemChanged.connect(self._tree_item_changed)
        self.items_list.currentRowChanged.connect(self._update_button_states)
        self._update_button_states()

    def _initialise_layout(self):
        layout = QHBoxLayout(self)
        self.setLayout(layout)

        self.tv = QTreeWidget(self.gui)
        self.tv.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
        self.tv.header().hide()
        layout.addWidget(self.tv, 1)

        self.items_list = FavMenusListWidget(self.gui)
        self.items_list.setIconSize(QSize(ICON_SIZE, ICON_SIZE))
        layout.addWidget(self.items_list, 1)

        button_layout = QVBoxLayout()
        layout.addLayout(button_layout)

        self.up_btn = QToolButton(self.gui)
        self.up_btn.setIcon(get_icon('arrow-up.png'))
        self.up_btn.setToolTip('Move the selected menu item up')
        self.up_btn.clicked.connect(self._move_item_up)
        self.down_btn = QToolButton(self.gui)
        self.down_btn.setIcon(get_icon('arrow-down.png'))
        self.down_btn.setToolTip('Move the selected menu item down')
        self.down_btn.clicked.connect(self._move_item_down)
        self.remove_btn = QToolButton(self.gui)
        self.remove_btn.setIcon(get_icon('trash.png'))
        self.remove_btn.setToolTip('Remove the selected item from the menu')
        self.remove_btn.clicked.connect(self._remove_item)
        self.sep_btn = QToolButton(self.gui)
        self.sep_btn.setIcon(get_icon('plus.png'))
        self.sep_btn.setToolTip('Add a separator to the menu following the selected item')
        self.sep_btn.clicked.connect(self._add_separator)
        self.rename_btn = QToolButton(self.gui)
        self.rename_btn.setIcon(get_icon('edit-undo.png'))
        self.rename_btn.setToolTip('Rename the menu item for when it appears on your Favourites menu')
        self.rename_btn.clicked.connect(self._rename_item)
        button_layout.addWidget(self.up_btn)
        button_layout.addStretch(1)
        button_layout.addWidget(self.rename_btn)
        button_layout.addStretch(1)
        button_layout.addWidget(self.sep_btn)
        button_layout.addStretch(1)
        button_layout.addWidget(self.remove_btn)
        button_layout.addStretch(1)
        button_layout.addWidget(self.down_btn)

    def _move_item_up(self):
        idx = self.items_list.currentRow()
        if idx > 0:
            self.items_list.swap_list_widgets(idx-1)
            self.items_list.setCurrentRow(idx-1)
            self._update_button_states()

    def _move_item_down(self):
        idx = self.items_list.currentRow()
        if idx < self.items_list.count() - 1:
            self.items_list.swap_list_widgets(idx)
            self.items_list.setCurrentRow(idx+1)
            self._update_button_states()

    def _add_separator(self):
        idx = self.items_list.currentRow()
        self.items_list.populate_list_item(None, idx)
        self.items_list.setCurrentRow(idx+1)

    def _remove_item(self):

        def find_child(twi, paths):
            for i in range(0, twi.childCount()):
                c = twi.child(i)
                text = unicode(c.text(0))
                if text == paths[0]:
                    if len(paths) == 1:
                        return c
                    else:
                        return find_child(c, paths[1:])

        idx = self.items_list.currentRow()
        if idx < 0:
            return
        item = self.items_list.currentItem()
        data = convert_qvariant(item.data(Qt.UserRole))
        if data is not None:
            # Not removing a separator
            fav_menu = data[0]
            # Lookup the item to uncheck it.
            self.tv.blockSignals(True)
            paths = fav_menu['path']
            plugin = paths[0]
            # Find the top-level item for the plugin
            tree_item = None
            if plugin in self.top_level_items_map:
                tree_item = self.top_level_items_map[plugin]
                if len(paths) > 1:
                    tree_item = find_child(tree_item, paths[1:])
                if tree_item is not None:
                    tree_item.setCheckState(0, Qt.Unchecked)
            self.tv.blockSignals(False)
        self.items_list.takeItem(idx)
        self._update_button_states()

    def _rename_item(self):
        idx = self.items_list.currentRow()
        if idx < 0:
            return
        item = self.items_list.currentItem()
        data = convert_qvariant(item.data(Qt.UserRole))
        if data is not None:
            self.items_list.editItem(item)

    def _update_button_states(self):
        idx = self.items_list.currentRow()
        self.up_btn.setEnabled(idx > 0)
        self.down_btn.setEnabled(idx < self.items_list.count() - 1)
        self.remove_btn.setEnabled(self.items_list.count() > 0)
        self.sep_btn.setEnabled(self.items_list.count() > 0)
        data = None
        if idx >= 0:
            item = self.items_list.currentItem()
            data = convert_qvariant(item.data(Qt.UserRole))
        self.rename_btn.setEnabled(data is not None)

    def _build_lookup_menu_map(self, fav_menus):
        m = {}
        for fav_menu in fav_menus:
            if fav_menu is None:
                continue
            path = fav_menu['path']
            plugin = path[0]
            if plugin not in m:
                m[plugin] = []
            fav_menu['paths_text'] = '|'.join(path[1:])
            m[plugin].append(fav_menu)
        return m

    def _get_scaled_icon(self, icon):
        if icon.isNull():
            return self.blank_icon
        # We need the icon scaled to 16x16
        src = icon.pixmap(ICON_SIZE, ICON_SIZE)
        if src.width() == ICON_SIZE and src.height() == ICON_SIZE:
            return icon
        # Need a new version of the icon
        pm = QPixmap(ICON_SIZE, ICON_SIZE)
        pm.fill(Qt.transparent)
        p = QPainter(pm)
        p.drawPixmap(QPoint((ICON_SIZE - src.width()) / 2, (ICON_SIZE - src.height()) / 2), src)
        p.end()
        return QIcon(pm)

    def _populate_actions_tree(self, lookup_menu_map):
        # Lets re-sort the keys so that items will appear on screen sorted
        # by their display name (not by their key)
        skeys_map = {}
        for plugin_name, iaction in six.iteritems(self.gui.iactions):
            if plugin_name == self.plugin_action.name:
                continue
            if 'toolbar' in iaction.dont_add_to and 'toolbar-device' in iaction.dont_add_to:
                print(('Not adding:', plugin_name))
                continue
            display_name = unicode(iaction.qaction.text())
            if plugin_name == 'Choose Library':
                display_name = 'Library'
            skeys_map[display_name] = (plugin_name, iaction.qaction)
        # Add a special case item for the location manager
        skeys_map['Location Manager'] = ('Location Manager', None)

        self.top_level_items_map = {}
        for display_name in sorted(skeys_map.keys()):
            plugin_name, qaction = skeys_map[display_name]
            possible_menus = lookup_menu_map.get(plugin_name, [])

            # Create a node for our top level plugin name
            tl = Item()
            tl.setText(0, display_name)
            tl.setData(0, Qt.UserRole, plugin_name)
            if plugin_name == 'Location Manager':
                # Special case handling
                tl.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
                tl.setCheckState(0, Qt.PartiallyChecked)
                tl.setIcon(0, self._get_scaled_icon(get_icon('reader.png')))
                # Put all actions except library within this node.
                actions = self.gui.location_manager.all_actions[1:]
                self._populate_action_children(actions, tl, possible_menus, [], plugin_name,
                                               is_location_mgr_child=True)
            else:
                # Normal top-level checkable plugin iaction handling
                tl.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
                tl.setCheckState(0, Qt.Unchecked)
                tl.setIcon(0, self._get_scaled_icon(qaction.icon()))

                # Lookup to see if we have a menu item for this top-level plugin
                if possible_menus:
                    fav_menu = self._is_in_menu(possible_menus)
                    if fav_menu is not None:
                        fav_menu['icon'] = tl.icon(0)
                        tl.setCheckState(0, Qt.Checked)
                m = qaction.menu()
                if m:
                    # Iterate through all the children of this node
                    self._populate_action_children(QMenu.actions(m), tl,
                                                   possible_menus, [], plugin_name)

            self.tv.addTopLevelItem(tl)
            self.top_level_items_map[plugin_name] = tl

    def _populate_action_children(self, children, parent, possible_menus, paths,
                                  plugin_name, is_location_mgr_child=False):
        for ac in children:
            if ac.isSeparator():
                continue
            if not ac.isVisible() and not is_location_mgr_child:
                # That is special case of location mgr visibility, since it has child
                # actions that will not be visible if device not plugged in at the
                # moment but we want to always be able to configure them.
                continue
            text = get_safe_title(ac)

            it = Item(parent)
            it.setText(0, text)
            it.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
            it.setCheckState(0, Qt.Unchecked)
            it.setIcon(0, self._get_scaled_icon(ac.icon()))

            new_paths = list(paths)
            new_paths.append(text)
            if possible_menus:
                fav_menu = self._is_in_menu(possible_menus, new_paths)
                if fav_menu is not None:
                    fav_menu['icon'] = it.icon(0)
                    it.setCheckState(0, Qt.Checked)
            if ac.menu():
                self._populate_action_children(QMenu.actions(ac.menu()), it,
                                               possible_menus, new_paths, plugin_name)

    def _is_in_menu(self, possible_menus, paths=[]):
        path_text = '|'.join(paths)
        for x in range(0, len(possible_menus)):
            fav_menu = possible_menus[x]
            if fav_menu['paths_text'] == path_text:
                del possible_menus[x]
                return fav_menu
        return None

    def _tree_item_changed(self, item, column):
        # Checkstate has been changed - are we adding or removing this item?
        if unicode(item.text(column)) == 'Location Manager':
            # Special case of not allowing this since it is not a "real" plugin,
            # just a special placeholder used for configuring menus that resolves
            # down to a collection of underlying actions.
            self.tv.blockSignals(True)
            item.setCheckState(column, Qt.PartiallyChecked)
            self.tv.blockSignals(False)
            return

        is_checked = item.checkState(column) == Qt.Checked
        paths = []
        fav_menu = {'icon':    item.icon(column),
                    'display': unicode(item.text(column)),
                    'path':    paths}
        while True:
            parent = item.parent()
            if parent is None:
                paths.insert(0, convert_qvariant(item.data(column, Qt.UserRole)))
                break
            else:
                paths.insert(0, unicode(item.text(column)))
            item = parent

        if is_checked:
            # We want to add this item to the list
            self.items_list.populate_list_item(fav_menu)
            self.items_list.setCurrentRow(self.items_list.count() -1)
        else:
            # We want to remove the matching item from the list
            self.items_list.remove_matching_item(fav_menu)
            self._update_button_states()

    def save_settings(self):
        plugin_prefs[STORE_MENUS] = self.items_list.get_fav_menus()