Ejemplo n.º 1
0
class DefaultAttributeHandler(QGroupBox, AbstractAttributeHandler):
    def __init__(self, attribute, values, parent=None):
        QGroupBox.__init__(self, attribute, parent)
        self._attribute = attribute
        self._current_items = []
        self._defaults = {}
        self._inputField = None
        self._inputFieldType = None
        self._insertIndex = -1
        self._insertAtEnd = False
        self._shortcuts = {}

        # Setup GUI
        self._layout = FloatingLayout()
        self.setLayout(self._layout)
        self._buttons = {}

        # Add interface elements
        self.updateValues(values)

    def focusInputField(self, selectInput=True):
        if self._inputField is not None:
            if selectInput:
                self._inputField.selectAll()
            self._inputField.setFocus(Qt.ShortcutFocusReason)

    def addShortcut(self, shortcut, widget, value):
        if widget is not None:
            if shortcut not in self._shortcuts:
                sc = QShortcut(QKeySequence(shortcut), self)
                self._shortcuts[shortcut] = sc
                if isinstance(widget, QPushButton):
                    sc.activated.connect(
                        bind(
                            lambda w: w.click()
                            if not w.isChecked() else None, widget))
                elif isinstance(widget, QLineEdit):
                    sc.activated.connect(self.focusInputField)
            else:
                raise ImproperlyConfigured(
                    "Shortcut '%s' defined more than once" % shortcut)
        else:
            raise ImproperlyConfigured(
                "Shortcut '%s' defined for value '%s' which is hidden" %
                (shortcut, value))

    def updateValues(self, values):
        if isinstance(values, type):
            self.addInputField(values)
        else:
            for val in values:
                v = val
                shortcut = None
                widget = None

                # Handle the case of the value being a 2-tuple consisting of (value, shortcut)
                if type(val) is tuple or type(val) is list:
                    if len(val) == 2:
                        v = val[0]
                        shortcut = val[1]
                    else:
                        raise ImproperlyConfigured(
                            "Values must be types, strings, numbers, or tuples of length 2: '%s'"
                            % str(val))

                # Handle the case where value is a Python type
                if isinstance(v, type):
                    if v is float or v is int or v is str:
                        self.addInputField(v)
                        widget = self._inputField
                    else:
                        raise ImproperlyConfigured(
                            "Input field with type '%s' not supported" % v)

                # * marks the position where buttons for new values will be insered
                elif val == "*" or val == "<*":
                    self._insertIndex = self._layout.count()
                elif val == "*>":
                    self._insertIndex = self._layout.count()
                    self._insertAtEnd = True

                # Add the value button
                else:
                    self.addValue(v)
                    widget = self._buttons[v]

                # If defined, add the specified shortcut
                if shortcut is not None:
                    self.addShortcut(shortcut, widget, v)

    def defaults(self):
        return self._defaults

    def autoAddEnabled(self):
        return self._insertIndex >= 0

    def onInputFieldReturnPressed(self):
        val = str(self._inputField.text())
        self.addValue(val, True)
        for item in self._current_items:
            item[self._attribute] = val
        self.updateButtons()
        self.updateInputField()
        self._inputField.clearFocus()

    def addInputField(self, _type):
        if self._inputField is None:
            self._inputFieldType = _type
            self._inputField = QLineEdit()
            if _type is float:
                self._inputField.setValidator(QDoubleValidator())
            elif _type is int:
                self._inputField.setValidator(QIntValidator())

            self._layout.addWidget(self._inputField)
            self._inputField.returnPressed.connect(
                self.onInputFieldReturnPressed)
        elif self._inputFieldType is not _type:
            raise ImproperlyConfigured("Input field for attribute '%s' configured twice with different types %s != %s"\
                    % (self._attribute, self._inputFieldType, _type))

    def addValue(self, v, autoAddValue=False):
        if v in self._buttons: return
        if autoAddValue and self._insertIndex < 0: return
        button = QPushButton(v, self)
        button.setFlat(True)
        button.setCheckable(True)
        self._buttons[v] = button
        if autoAddValue:
            self._layout.insertWidget(self._insertIndex, button)
            if self._insertAtEnd:
                self._insertIndex += 1
        else:
            self._layout.addWidget(button)
        button.clicked.connect(bind(self.onButtonClicked, v))

    def reset(self):
        self._current_items = []
        for v, button in self._buttons.items():
            button.setChecked(False)
            button.setFlat(True)

    def getSelectedValues(self):
        return set([
            str(item[self._attribute]) for item in self._current_items
            if self._attribute in item and item[self._attribute] is not None
        ])

    def updateInputField(self):
        if self._inputField is not None:
            self._inputField.clear()
            selected_values = self.getSelectedValues()
            if len(selected_values) > 1:
                self._inputField.setPlaceholderText(", ".join(selected_values))
            elif len(selected_values) == 1:
                it = iter(selected_values)
                self._inputField.setText(next(it))

    def updateButtons(self):
        selected_values = self.getSelectedValues()
        for val, button in self._buttons.items():
            if val in selected_values:
                if len(selected_values) > 1:
                    button.setFlat(False)
                    button.setChecked(False)
                else:
                    button.setFlat(True)
                    button.setChecked(True)
            else:
                button.setFlat(True)
                button.setChecked(False)

    def setItems(self, items, showItemClasses=False):
        self.reset()
        if showItemClasses:
            title = ", ".join(set([item['class'] for item in items]))
            self.setTitle(self._attribute + " (" + title + ")")
        else:
            self.setTitle(self._attribute)

        self._current_items = items

        self.updateButtons()
        self.updateInputField()

    def onButtonClicked(self, val):
        attr = self._attribute
        LOG.debug("Button %s: %s clicked" % (attr, val))
        button = self._buttons[val]

        # Update model item
        for item in self._current_items:
            if button.isChecked():
                item[attr] = val
            else:
                item[attr] = None

        # Unpress all other buttons
        for v, but in self._buttons.items():
            but.setFlat(True)
            if but is not button:
                but.setChecked(False)

        # Update input field
        self.updateInputField()
Ejemplo n.º 2
0
class DefaultAttributeHandler(QGroupBox, AbstractAttributeHandler):
    def __init__(self, attribute, values, parent=None):
        QGroupBox.__init__(self, attribute, parent)
        self._attribute = attribute
        self._current_items = []
        self._defaults = {}
        self._inputField = None
        self._inputFieldType = None
        self._insertIndex = -1
        self._insertAtEnd = False
        self._shortcuts = {}

        # Setup GUI
        self._layout = FloatingLayout()
        self.setLayout(self._layout)
        self._buttons = {}

        # Add interface elements
        self.updateValues(values)

    def focusInputField(self, selectInput=True):
        if self._inputField is not None:
            if selectInput:
                self._inputField.selectAll()
            self._inputField.setFocus(Qt.ShortcutFocusReason)

    def addShortcut(self, shortcut, widget, value):
        if widget is not None:
            if shortcut not in self._shortcuts:
                sc = QShortcut(QKeySequence(shortcut), self)
                self._shortcuts[shortcut] = sc
                if isinstance(widget, QPushButton):
                    sc.activated.connect(bind(lambda w: w.click() if not w.isChecked() else None, widget))
                elif isinstance(widget, QLineEdit):
                    sc.activated.connect(self.focusInputField)
            else:
                raise ImproperlyConfigured("Shortcut '%s' defined more than once" % shortcut)
        else:
            raise ImproperlyConfigured("Shortcut '%s' defined for value '%s' which is hidden" % (shortcut, value))

    def updateValues(self, values):
        if isinstance(values, type):
            self.addInputField(values)
        else:
            for val in values:
                v = val
                shortcut = None
                widget = None

                # Handle the case of the value being a 2-tuple consisting of (value, shortcut)
                if type(val) is tuple or type(val) is list:
                    if len(val) == 2:
                        v = val[0]
                        shortcut = val[1]
                    else:
                        raise ImproperlyConfigured("Values must be types, strings, numbers, or tuples of length 2: '%s'" % str(val))

                # Handle the case where value is a Python type
                if isinstance(v, type):
                    if v is float or v is int or v is str:
                        self.addInputField(v)
                        widget = self._inputField
                    else:
                        raise ImproperlyConfigured("Input field with type '%s' not supported" % v)

                # * marks the position where buttons for new values will be insered
                elif val == "*" or val == "<*":
                    self._insertIndex = self._layout.count()
                elif val == "*>":
                    self._insertIndex = self._layout.count()
                    self._insertAtEnd = True

                # Add the value button
                else:
                    self.addValue(v)
                    widget = self._buttons[v]

                # If defined, add the specified shortcut
                if shortcut is not None:
                    self.addShortcut(shortcut, widget, v)

    def defaults(self):
        return self._defaults

    def autoAddEnabled(self):
        return self._insertIndex >= 0

    def onInputFieldReturnPressed(self):
        val = str(self._inputField.text())
        self.addValue(val, True)
        for item in self._current_items:
            item[self._attribute] = val
        self.updateButtons()
        self.updateInputField()
        self._inputField.clearFocus()

    def addInputField(self, _type):
        if self._inputField is None:
            self._inputFieldType = _type
            self._inputField = QLineEdit()
            if _type is float:
                self._inputField.setValidator(QDoubleValidator())
            elif _type is int:
                self._inputField.setValidator(QIntValidator())

            self._layout.addWidget(self._inputField)
            self._inputField.returnPressed.connect(self.onInputFieldReturnPressed)
        elif self._inputFieldType is not _type:
            raise ImproperlyConfigured("Input field for attribute '%s' configured twice with different types %s != %s"\
                    % (self._attribute, self._inputFieldType, _type))

    def addValue(self, v, autoAddValue=False):
        if v in self._buttons: return
        if autoAddValue and self._insertIndex < 0: return
        button = QPushButton(v, self)
        button.setFlat(True)
        button.setCheckable(True)
        self._buttons[v] = button
        if autoAddValue:
            self._layout.insertWidget(self._insertIndex, button)
            if self._insertAtEnd:
                self._insertIndex += 1
        else:
            self._layout.addWidget(button)
        button.clicked.connect(bind(self.onButtonClicked, v))

    def reset(self):
        self._current_items = []
        for v, button in self._buttons.items():
            button.setChecked(False)
            button.setFlat(True)

    def getSelectedValues(self):
        return set([str(item[self._attribute]) for item in self._current_items if self._attribute in item and item[self._attribute] is not None])

    def updateInputField(self):
        if self._inputField is not None:
            self._inputField.clear()
            selected_values = self.getSelectedValues()
            if len(selected_values) > 1:
                self._inputField.setPlaceholderText(", ".join(selected_values))
            elif len(selected_values) == 1:
                it = iter(selected_values)
                self._inputField.setText(next(it))

    def updateButtons(self):
        selected_values = self.getSelectedValues()
        for val, button in self._buttons.items():
            if val in selected_values:
                if len(selected_values) > 1:
                    button.setFlat(False)
                    button.setChecked(False)
                else:
                    button.setFlat(True)
                    button.setChecked(True)
            else:
                button.setFlat(True)
                button.setChecked(False)

    def setItems(self, items, showItemClasses=False):
        self.reset()
        if showItemClasses:
            title = ", ".join(set([item['class'] for item in items]))
            self.setTitle(self._attribute + " (" + title + ")")
        else:
            self.setTitle(self._attribute)

        self._current_items = items

        self.updateButtons()
        self.updateInputField()

    def onButtonClicked(self, val):
        attr = self._attribute
        LOG.debug("Button %s: %s clicked" % (attr, val))
        button = self._buttons[val]

        # Update model item
        for item in self._current_items:
            if button.isChecked():
                item[attr] = val
            else:
                item[attr] = None

        # Unpress all other buttons
        for v, but in self._buttons.items():
            but.setFlat(True)
            if but is not button:
                but.setChecked(False)

        # Update input field
        self.updateInputField()
Ejemplo n.º 3
0
    def __init__(self, parent = None, mainwindow = None, exitDialogSlot = None, exitDialogSlotArg1 = None, exitDialogSlotArg2 = None):
        QWidget.__init__(self, parent)

        self._exitDialogSlot = exitDialogSlot
        self._exitDialogSlotArg1 = exitDialogSlotArg1
        self._exitDialogSlotArg2 = exitDialogSlotArg2
        self._mainwindow = mainwindow

        # self.setWindowFlags(QtCore.Qt.FramelessWindowHint|QtCore.Qt.Dialog)
        self.setWindowFlags(QtCore.Qt.Window|QtCore.Qt.WindowCloseButtonHint)

        # zx comment: must be ApplicationModal. otherwise, this dialog cannot block following codes in same thread
        self.setWindowModality(QtCore.Qt.ApplicationModal)
        self.setEnabled(True)

        self._gLayout = QVBoxLayout() # QGridLayout()
        self.checkbox_groups = []
        self.widgetsInfo = {}   # format: { widgetGroupName: [[widgetObj, widgetName], ....],  }
    
        for displayOrder, groupElementsList  in config.STATISTICS_PLUGIN_DISPLAY_ELEMENTS_DICT.items():
           groupName = groupElementsList[0]
           groupElementsList = groupElementsList[1]
           group_box = QGroupBox(str(groupName), self)
           flayout = FloatingLayout()

           # Create buttongroup
           checkbox_group = QButtonGroup(group_box)
           checkbox_group.setExclusive(False)
           checkboxs = []
           for i, token in enumerate(groupElementsList):
               # print "i = {} token = {}".format(i, token)

               if token == config.ANNOTATION_UPPER_COLOR_TOKEN or token == config.ANNOTATION_LOWER_COLOR_TOKEN or token == config.ANNOTATION_VEHICLE_COLOR_TOKEN:
                   if token == config.ANNOTATION_UPPER_COLOR_TOKEN or token == config.ANNOTATION_LOWER_COLOR_TOKEN:
                       editor = self._mainwindow.property_editor4
                   else:
                       editor = self._mainwindow.property_editor6
                   names_list, texts_list, displaycolors_list = editor.get_group_config(token)
                   for t, text in enumerate(texts_list):
                       checkbox = QCheckBox(text)

                       # get widget display color
                       if token == config.ANNOTATION_UPPER_COLOR_TOKEN or token == config.ANNOTATION_LOWER_COLOR_TOKEN or token == config.ANNOTATION_VEHICLE_COLOR_TOKEN:
                           thisCheckboxBkgColorChecked = displaycolors_list[t]
                           thisCheckboxBkgColor = thisCheckboxBkgColorChecked
                       else:
                           thisCheckboxBkgColorChecked = displaycolors_list[t]
                           thisCheckboxBkgColor = None

                           # calc widget text color
                           # thisCheckboxBkgColorChecked string pattern: #123456
                       txtColorChecked = None
                       if thisCheckboxBkgColorChecked is not None:
                           import math
                           rgba = utils.hexColorStrToRGBA(thisCheckboxBkgColorChecked)
                           distance = math.sqrt((rgba[0] - 255) ** 2 + (rgba[1] - 255) ** 2 + (rgba[2] - 255) ** 2)
                           txtColorChecked = '#ffffff' if distance > config.GUI_COLOR_TAG_TEXT_BLACKWHITE_TOGGLE_THRESHOLD else '#000000'

                       txtColor = txtColorChecked if token == config.ANNOTATION_UPPER_COLOR_TOKEN or token == config.ANNOTATION_LOWER_COLOR_TOKEN or token == config.ANNOTATION_VEHICLE_COLOR_TOKEN else None

                       desc = utils.set_qobj_stylesheet(checkbox, 'QCheckBox', thisCheckboxBkgColor,
                                                        txtColor, thisCheckboxBkgColorChecked,
                                                        txtColorChecked)
                       checkbox_group.addButton(checkbox)
                       flayout.addWidget(checkbox)
                       # print u"checkbox_group.addcheckbox {}".format(checkbox.text())
                       checkbox.clicked.connect(self.onClickedWidget)
                       checkbox.setChecked(False)
                       checkboxs.append([checkbox, names_list[t]])
               else:
                   checkbox = QCheckBox(token)
                   desc = utils.set_qobj_stylesheet(checkbox, 'QCheckBox', "#ffffff", "#000000", "#ffffff", "#000000")
                   checkbox_group.addButton(checkbox)
                   flayout.addWidget(checkbox)
                   # print "checkbox_group.addButton {}".format(checkbox)
                   checkbox.clicked.connect(self.onClickedWidget)
                   checkboxs.append([checkbox, token])

              
           all = QRadioButton("All")
           desc = utils.set_qobj_stylesheet(all, 'QRadioButton', "#ffffff", "#000000", "#ffffff", "#000000")
           checkbox_group.addButton(all)
           flayout.addWidget(all)
           all.clicked.connect(self.selectAllWidgetsInCurrentGroup)
           checkboxs.append([all, "all"])
           group_box.setLayout(flayout)
           # add this checkboxgroup to layout
           self._gLayout.addWidget(group_box)
           
           self.checkbox_groups.append(checkbox_group)
           self.widgetsInfo[groupName] = checkboxs

        self._filtersGoup = QGroupBox("Filters", self)
        self._filtersGoup_layout = QHBoxLayout()
        self._filtersGoup.setLayout(self._filtersGoup_layout)
        self._gLayout.addWidget(self._filtersGoup)

        self._buttonStatisticWithFilterWidget = QPushButton("STATISTICS with filters")
        utils.set_qobj_stylesheet(self._buttonStatisticWithFilterWidget, 'QPushButton', '#C0C0C0', '#ff0000', '#909090', '#0080FF')
        self._buttonStatisticWithFilterWidget.clicked.connect(self.onClickedStatisticWithFilter)
        self._filtersGoup_layout.addWidget(self._buttonStatisticWithFilterWidget)

        """
        self._buttonStatisticAllColorsWidget = QPushButton("STATISTICS all colors")
        utils.set_qobj_stylesheet(self._buttonStatisticAllColorsWidget, 'QPushButton', '#C0C0C0', '#ff0000', '#909090', '#0080FF')
        self._buttonStatisticAllColorsWidget.clicked.connect(self.onClickedStatisticAllColors)
        self._filtersGoup_layout.addWidget(self._buttonStatisticAllColorsWidget)
        """

        self._buttonApplyFilterOnViewModeWidget = QPushButton("Apply filters on view mode")
        utils.set_qobj_stylesheet(self._buttonApplyFilterOnViewModeWidget, 'QPushButton', '#C0C0C0', '#ff0000', '#909090', '#0080FF')
        self._buttonApplyFilterOnViewModeWidget.clicked.connect(self.onClickedApplyFilterOnViewMode)
        self._filtersGoup_layout.addWidget(self._buttonApplyFilterOnViewModeWidget)

        self._statLabelWidget = QLabel(u'<font color="red">{}</font>'.format("statistics result"))
        self._statLabelWidget.setFont(QFont("Timers", 16, QFont.Bold))
        self._gLayout.addWidget(self._statLabelWidget)

        self._statResultTxtWidget = QTextEdit('')
        self._gLayout.addWidget(self._statResultTxtWidget)


        self.setLayout(self._gLayout)
        self.setWindowTitle(config.STATISTIC_OR_APPLY_OBJVIEWFILTER_FOR_CUR_JSON_FILE_PLUGIN_DISPLAYTEXT)
        self.resize(1000, 800)

        utils.centerGuiWidget(self)
        return
Ejemplo n.º 4
0
class CheckboxListWidget(QGroupBox):
    def enableAll(self, enabled=True):
        for cbn, cbw in self.checkboxWidgetsInfo.items():
            cbw[0].setEnabled(enabled)

    def enable(self, checkBoxName, checked=True):
        cb = self.checkboxWidgetsInfo.get(checkBoxName, None)
        if cb is not None:
            cb[0].setEnabled(checked)

    # set all checkboxs' check status
    def setCheckedAll(self, checked=True):
        for cbn, cbw in self.checkboxWidgetsInfo.items():
            cbw[0].setChecked(checked)

        if not checked:
            self._checked_checkbox_widgets = []

    # set one single specific checkbox's check status
    def setCheckedCheckbox(self, checkBoxName, checked=True):
        cb = self.checkboxWidgetsInfo.get(checkBoxName, None)
        if cb is not None:
            checkboxWidget = cb[0]
            # LOG.info("{} CheckboxListWidget.setCheckedCheckbox for checkboxname {}  checked {} ..".format(self.idName, checkBoxName, checked))
            checkboxWidget.setChecked(checked)

    # set some specific checkboxs' check status
    def setCheckedCheckboxs(self, checkBoxNamesList, checked=True):
        self._checked_checkbox_widgets = []
        if checkBoxNamesList is None:
            return
        for cbn in checkBoxNamesList:
            cw = self.checkboxWidgetsInfo.get(cbn, None)
            # LOG.info("{} self.checkboxWidgetsInfo = {} checkBoxNamesList = {}..".format(self.idName, self.checkboxWidgetsInfo, checkBoxNamesList))
            # LOG.info("{} CheckboxListWidget.setCheckedCheckboxs :  cbn {} cw {}..".format(self.idName, cbn, cw))
            if cw is not None:
                checkboxWidget = cw[0]
                # LOG.info("{} CheckboxListWidget.setCheckedCheckboxs for checkboxname {}  checked {} ..".format(self.idName, checkboxWidget, checked))
                checkboxWidget.setChecked(checked)
                if checked:
                    self._checked_checkbox_widgets.append(checkboxWidget)

        return self._checked_checkbox_widgets

    def setMaxCheckedNum(self, num):
        self._maxCheckedNum = num

    def setMaxSeperateWidgetNum(self, num):
        self._maxSeperateWidgetNum = num

    def __init__(self,
                 checkboxGroupName,
                 checkboxGroupText,
                 isExclusive,
                 checkGroupDescListTuple,
                 checkboxStateChangedSignal,
                 thisGroup_maxCheckedNum=100,
                 thisGroup_maxSeperateWidgetNum=100,
                 parent=None):
        QGroupBox.__init__(self, checkboxGroupText, parent)
        qss = "QGroupBox::title {subcontrol-origin: margin; subcontrol-position: top left; padding: 0 3px; color : red; font-weight:bold; }"
        self.setStyleSheet(qss)

        self.flayout = FloatingLayout()
        self.flayout.setSpacing(40)
        self.flayout.setMargin(4)

        self.groupName = str(checkboxGroupName)

        self.checkGroupDescListTuple = checkGroupDescListTuple
        self.checkboxStateChangedSignal = checkboxStateChangedSignal

        self.checkbox_group = QButtonGroup()
        self.checkbox_group.setExclusive(isExclusive)
        self.isExclusive = isExclusive

        self.checkboxWidgetsInfo = {
        }  # dict. checkboxWidgetsInfo[checkboxName] = [checkboxWidget, checkboxText, checkboxColor, checkboxStyleSheet]
        self.popupWidgetsInfo = {
        }  # dict. popupWidgetsInfo[popupbutton_name] = [*, *, * , * , *]

        self._maxCheckedNum = thisGroup_maxCheckedNum
        self._maxSeperateWidgetNum = thisGroup_maxSeperateWidgetNum

        self._checked_checkbox_widgets = []

        # create all checkboxes in this group
        optCnt = 0
        defaultCheckboxName = None
        firstCheckboxName = None
        for checkboxOption in checkGroupDescListTuple:

            thisCheckboxName = checkboxOption[config.METADATA_ATTR_VALUE_TOKEN]
            thisCheckboxText = checkboxOption[
                config.METADATA_DISPLAYTEXT_TOKEN]
            thisCheckboxIsDefault = checkboxOption.get(
                config.METADATA_IS_DEFAULT_TOKEN, False)
            defaultCheckboxName = thisCheckboxName if thisCheckboxIsDefault else defaultCheckboxName
            firstCheckboxName = thisCheckboxName if firstCheckboxName is None else firstCheckboxName

            if (checkboxGroupName
                    == config.ANNOTATION_PERSONBIKE_TYPE_GROUP_TOKEN) or (
                        checkboxGroupName
                        == config.ANNOTATION_VEHICLE_TYPE_GROUP_TOKEN):
                checkboxWidgetMinWidthInPixels = 52
            else:
                checkboxWidgetMinWidthInPixels = 38

            # get widget display color
            _thisCheckboxBkgColor = None
            _thisCheckboxBkgColorChecked = checkboxOption.get(
                config.COLOR_ATTR_RGB_VALUE_TOKEN, None)
            if _thisCheckboxBkgColorChecked:
                _thisCheckboxBkgColor = _thisCheckboxBkgColorChecked
            else:
                _thisCheckboxBkgColorChecked = checkboxOption.get(
                    config.METADATA_DISPLAYCOLOR_TOKEN, None)

            # print u"thisCheckboxName = {} thisCheckboxText = {} _thisCheckboxBkgColor = {} _thisCheckboxBkgColorChecked = {}".format(

# thisCheckboxName, thisCheckboxText, _thisCheckboxBkgColor, _thisCheckboxBkgColorChecked)

            thisCheckboxBkgColor = None
            if _thisCheckboxBkgColor:
                dummy, thisCheckboxBkgColor = utils.getColorDesc(
                    _thisCheckboxBkgColor)

            thisCheckboxBkgColorChecked = None
            if _thisCheckboxBkgColorChecked:
                dummy, thisCheckboxBkgColorChecked = utils.getColorDesc(
                    _thisCheckboxBkgColorChecked)

            # calc widget text color
            # thisCheckboxBkgColorChecked string pattern: #123456
            txtColorChecked = None
            if thisCheckboxBkgColorChecked is not None:
                import math
                rgba = utils.hexColorStrToRGBA(thisCheckboxBkgColorChecked)
                distance = math.sqrt((rgba[0] - 255)**2 + (rgba[1] - 255)**2 +
                                     (rgba[2] - 255)**2)
                txtColorChecked = '#ffffff' if distance > config.GUI_COLOR_TAG_TEXT_BLACKWHITE_TOGGLE_THRESHOLD else '#000000'

            txtColor = txtColorChecked if checkboxGroupName == config.ANNOTATION_UPPER_COLOR_TOKEN or checkboxGroupName == config.ANNOTATION_LOWER_COLOR_TOKEN or checkboxGroupName == config.ANNOTATION_VEHICLE_COLOR_TOKEN else None

            # add widget to this group
            if optCnt < thisGroup_maxSeperateWidgetNum:
                self.add_checkbox(thisCheckboxName, thisCheckboxText,
                                  thisCheckboxBkgColor, txtColor,
                                  thisCheckboxBkgColorChecked, txtColorChecked,
                                  checkboxWidgetMinWidthInPixels)
            else:
                self.add_popup_button(
                    config.GUI_MORE_WIDGET_DISPLAYTEXT,
                    thisCheckboxName,
                    thisCheckboxText,
                    popupbutton_background_color="#808080",
                    popupbutton_text_color="#ffffff",
                    checkbox_background_color=thisCheckboxBkgColor,
                    checkbox_text_color=txtColor)

            optCnt += 1

        self._defaultCheckboxName = firstCheckboxName if defaultCheckboxName is None else defaultCheckboxName
        # print "CheckboxListWidget {}: defaultCheckboxName {}".format(self.groupName, self._defaultCheckboxName)

        # if self.groupName == "helmetcolor":
        #     unsetwidgetInfo = self.checkboxWidgetsInfo.get(config.TAG_UNSET_TOKEN, None)
        #     if unsetwidgetInfo: unsetwidgetInfo[0].hide()

        # thisGroupWidget.add_checkbox("Unset", u"Unset")
        self.setLayout(self.flayout)
        return

    def create_checkbox(self,
                        checkbox_name,
                        checkbox_text,
                        checkbox_background_color=None,
                        checkbox_text_color=None,
                        checkbox_background_color_checked=None,
                        checkbox_text_color_checked=None,
                        widget_minWidthInPixels=36):
        checkboxWidget = QCheckBox(checkbox_text)

        # print "checkbox_background_color {} checkbox_text_color {} checkbox_background_color_checked {} checkbox_text_color_checked {}".format(
        #        checkbox_background_color, checkbox_text_color, checkbox_background_color_checked, checkbox_text_color_checked)

        desc = utils.set_qobj_stylesheet(
            checkboxWidget,
            'QCheckBox',
            checkbox_background_color,
            checkbox_text_color,
            checkbox_background_color_checked,
            checkbox_text_color_checked,
            min_width_pixels=widget_minWidthInPixels)
        checkboxWidget.setCheckable(True)
        checkboxWidget.clicked.connect(self.onClickedWidget)

        return checkboxWidget, desc

    def add_popup_button(self,
                         popup_button_name,
                         checkbox_name,
                         checkbox_text,
                         popupbutton_background_color=None,
                         popupbutton_text_color=None,
                         checkbox_background_color=None,
                         checkbox_text_color=None):
        # LOG.info(u"create_popup_button with popup_button_name = {} checkbox_name = {} checkbox_text = {} checkbox_background_color = {} checkbox_text_color = {}".format( \
        #    popup_button_name, checkbox_name, checkbox_text, checkbox_background_color, checkbox_text_color))

        popWidgetsInfo = self.popupWidgetsInfo.get(popup_button_name, None)
        if popWidgetsInfo is None:
            pbWidget = QPushButton(popup_button_name)
            # LOG.info(u"popupbutton_background_color {} popupbutton_text_colr {}".format(popupbutton_background_color, popupbutton_text_color))
            utils.set_qobj_stylesheet(pbWidget, 'QPushButton',
                                      popupbutton_background_color,
                                      popupbutton_text_color,
                                      popupbutton_background_color,
                                      popupbutton_text_color)
            self.flayout.addWidget(pbWidget)

            if pbWidget is None:
                print "Create QPushButton with name {} failed!".format(
                    popup_button_name)
                return
            mnWidget = QMenu(pbWidget)
            if mnWidget is None:
                print "Create QMenu attached with QPushButton of name {} failed!".format(
                    popup_button_name)
                return
            pbWidget.setMenu(mnWidget)
            actsWidgetList = []
            actsNameList = []
            actsTextList = []
            actsColorList = []
            actsStyleSheetList = []
        else:
            pbWidget = popWidgetsInfo[popupWidgetsInfo_pushButtonWidget_idx]
            mnWidget = popWidgetsInfo[popupWidgetsInfo_menuWidget_idx]
            actsWidgetList = popWidgetsInfo[
                popupWidgetsInfo_actionsWidgetList_idx]
            actsNameList = popWidgetsInfo[popupWidgetsInfo_actionsNameList_idx]
            actsTextList = popWidgetsInfo[popupWidgetsInfo_actionsTextList_idx]
            actsColorList = popWidgetsInfo[
                popupWidgetsInfo_actionsColorList_idx]
            actsStyleSheetList = popWidgetsInfo[
                popupWidgetsInfo_actionsWidgetStyleSheet_idx]

        actWidgetAction = QWidgetAction(mnWidget)
        actWidget = QWidget()
        actLayout = QVBoxLayout()
        actLayout.setMargin(2)
        actLayout.setSpacing(2)

        actBtnWidget = QCheckBox(checkbox_text)
        # for these widgets inside QWidgetAction, spacing and margin are controlled by actLayout.setMargin() and actLayout.setSpacing()
        utils.set_qobj_stylesheet(actBtnWidget,
                                  'QCheckBox',
                                  checkbox_background_color,
                                  checkbox_text_color,
                                  checkbox_background_color,
                                  checkbox_text_color,
                                  margin_pixels=0,
                                  padding_pixels=0)
        actLayout.addWidget(actBtnWidget)
        actWidget.setLayout(actLayout)
        actWidgetAction.setDefaultWidget(actWidget)
        mnWidget.addAction(actWidgetAction)

        desc = None
        actBtnWidget.setCheckable(True)
        actBtnWidget.clicked.connect(self.onClickedWidget)
        actsWidgetList.append(actBtnWidget)

        actsNameList.append(checkbox_name)
        actsTextList.append(checkbox_text)
        actsColorList.append(checkbox_background_color)
        actsStyleSheetList.append(desc)

        if popWidgetsInfo is None:
            popWidgetsInfo = [None, None, None, None, None, None, None]

        popWidgetsInfo[popupWidgetsInfo_pushButtonWidget_idx] = pbWidget
        popWidgetsInfo[popupWidgetsInfo_menuWidget_idx] = mnWidget
        popWidgetsInfo[popupWidgetsInfo_actionsWidgetList_idx] = actsWidgetList
        popWidgetsInfo[popupWidgetsInfo_actionsNameList_idx] = actsNameList
        popWidgetsInfo[popupWidgetsInfo_actionsTextList_idx] = actsTextList
        popWidgetsInfo[popupWidgetsInfo_actionsColorList_idx] = actsColorList
        popWidgetsInfo[
            popupWidgetsInfo_actionsWidgetStyleSheet_idx] = actsStyleSheetList

        self.popupWidgetsInfo[popup_button_name] = popWidgetsInfo

        return

    def add_checkbox(self,
                     checkbox_name,
                     checkbox_text,
                     background_color=None,
                     text_color=None,
                     background_color_checked=None,
                     text_color_checked=None,
                     widget_minWidthInPixels=36):
        checkboxWidget, checkboxStyleSheet = self.create_checkbox(
            checkbox_name,
            checkbox_text,
            background_color,
            text_color,
            background_color_checked,
            text_color_checked,
            widget_minWidthInPixels=widget_minWidthInPixels)
        self.checkboxWidgetsInfo[checkbox_name] = [
            checkboxWidget, checkbox_text, background_color_checked,
            checkboxStyleSheet
        ]
        self.flayout.addWidget(checkboxWidget)
        self.checkbox_group.addButton(checkboxWidget)

        return checkboxWidget

    def get_checkbox(self, checkbox_name):
        return self.checkboxWidgetsInfo[checkbox_name]

    # return (names_list, texts_list, displaycolors_list)
    def get_config(self):
        names = []
        texts = []
        displaycolors = []
        for checkboxOption in self.checkGroupDescListTuple:
            thisCheckboxName = checkboxOption[config.METADATA_ATTR_VALUE_TOKEN]
            names.append(thisCheckboxName)
            thisCheckboxText = checkboxOption[
                config.METADATA_DISPLAYTEXT_TOKEN]
            texts.append(thisCheckboxText)
            thisCheckboxDisplayColor = checkboxOption.get(
                config.METADATA_DISPLAYCOLOR_TOKEN, None)
            if thisCheckboxDisplayColor is None:
                thisCheckboxDisplayColor = checkboxOption.get(
                    config.COLOR_ATTR_RGB_VALUE_TOKEN, None)
            # print u"name = {} text = {} color = {}".format(thisCheckboxName, thisCheckboxText, thisCheckboxDisplayColor)
            displaycolors.append(thisCheckboxDisplayColor)
        return names, texts, displaycolors

    # return names_list
    def get_checkboxs_name(self):
        names = []
        for checkboxOption in self.checkGroupDescListTuple:
            thisCheckboxName = checkboxOption[config.METADATA_ATTR_VALUE_TOKEN]
            names.append(thisCheckboxName)
        return names

    def onClickedWidget(self):
        widget = self.sender()

        if widget.isChecked():
            (num, widgets) = self.get_checked_widgets_number()
            # print "\nget_checked_widgets_number {} maxCheckedNum {} len(_checked_checkbox_widgets) {}".format(num, self._maxCheckedNum, len(self._checked_checkbox_widgets))
            # for index, item in enumerate(self._checked_checkbox_widgets):
            #    print u"before: checked_checkbox_widgets[{}] - {}".format(index, item.text())

            # if current checked widgets exceed allowed max number, set state of oldest N widgets in checked_widgets record list to False and remove it from checked_widgets record list
            if self._maxCheckedNum < num:
                if (self._checked_checkbox_widgets is not None) and (
                        len(self._checked_checkbox_widgets) >=
                    (num - self._maxCheckedNum)):
                    for i in xrange(num - self._maxCheckedNum):
                        # print u"set checked_checkbox_widgets[{}] - {} -- unchecked".format(i, self._checked_checkbox_widgets[i].text())
                        self._checked_checkbox_widgets[i].setChecked(False)
                    del self._checked_checkbox_widgets[0:(num -
                                                          self._maxCheckedNum)]

            # record current selected widgets to checked_widgets record list
            if widget not in self._checked_checkbox_widgets:
                self._checked_checkbox_widgets.append(widget)
        else:
            # print "some widget is unchecked..."
            if widget in self._checked_checkbox_widgets:
                self._checked_checkbox_widgets.remove(widget)
            # for index, item in enumerate(self._checked_checkbox_widgets):
            #   print u"after: checked_checkbox_widgets[{}] - {}".format(index, item.text())

        # for index, item in enumerate(self._checked_checkbox_widgets):
        #    print u"after: checked_checkbox_widgets[{}] - {}".format(index, item.text())

        self.sendCheckedSignal()
        return

    def getCheckedWidgetsOptionInfo(self):
        # print "get getCheckedWidgetsOptionInfo.."
        namesList = self.get_checked_widgets_name()
        # print "get getCheckedWidgetsOptionInfo... checkGroupDescListTuple = {}".format(self.checkGroupDescListTuple)
        checkedWidgetsOptions = {}
        options = []
        if not namesList:
            return self.groupName, checkedWidgetsOptions

        for checkedWidgetName in namesList:
            for option in self.checkGroupDescListTuple:
                if option[
                        config.METADATA_ATTR_VALUE_TOKEN] == checkedWidgetName:
                    options.append(option.copy())

        checkedWidgetsOptions[self.groupName] = options
        # print "get getCheckedWidgetsOptionInfo.. name = {} checkedWidgetsOptions = {}".format(self.groupName, checkedWidgetsOptions)
        return self.groupName, checkedWidgetsOptions

    def sendCheckedSignal(self):
        checkedGroupName, checkedWidgetsOptions = self.getCheckedWidgetsOptionInfo(
        )
        # print "group {}: sendCheckedSignal {} ... checkedGroupName {} checkedWidgetsOptions {}...".format( self.groupName, self.checkboxStateChangedSignal, checkedGroupName, checkedWidgetsOptions)

        #if checkedWidgetsOptions:
        if True:
            self.checkboxStateChangedSignal.emit(checkedGroupName,
                                                 checkedWidgetsOptions)
        return

    def get_checked_widgets_number(self):
        number = 0
        widgets = []
        for widgetInfo in self.checkboxWidgetsInfo.values():
            if widgetInfo[0].isChecked():
                number += 1
                widgets.append(widgetInfo[0])

        for widgetInfo in self.popupWidgetsInfo.values():
            for actionWidget in widgetInfo[
                    popupWidgetsInfo_actionsWidgetList_idx]:
                if actionWidget.isChecked():
                    number += 1
                    widgets.append(actionWidget)

        return number, widgets

    def get_checked_widgets_name(self):
        namesList = []
        for widgetName, widgetInfo in self.checkboxWidgetsInfo.items():
            if widgetInfo[0].isChecked():
                name = widgetName
                namesList.append(name)

        for widgetInfo in self.popupWidgetsInfo.values():
            for actionWidget in widgetInfo[
                    popupWidgetsInfo_actionsWidgetList_idx]:
                if actionWidget.isChecked():
                    name = widgetInfo[popupWidgetsInfo_actionsNameList_idx]
                    namesList.append(name)

        return namesList

    def get_checked_widgets_attrDesc(self):
        descsDict = {}
        for widgetName, widgetInfo in self.checkboxWidgetsInfo.items():
            if widgetInfo[0].isChecked():
                desc = [None, None, None, None, None]
                desc[
                    checkedWidgetsAttrDescList_checkedWidget_idx] = widgetInfo[
                        0]
                desc[
                    checkedWidgetsAttrDescList_checkedWidgetText_idx] = widgetInfo[
                        1]
                desc[
                    checkedWidgetsAttrDescList_checkedWidgetColor_idx] = widgetInfo[
                        2]
                desc[
                    checkedWidgetsAttrDescList_checkedWidgetStyleSheet_idx] = widgetInfo[
                        3]
                descsDict[widgetName] = desc

        for widgetInfo in self.popupWidgetsInfo.values():
            for actionWidget in widgetInfo[
                    popupWidgetsInfo_actionsWidgetList_idx]:
                if actionWidget.isChecked():
                    idx = widgetInfo[
                        popupWidgetsInfo_actionsWidgetList_idx].index(
                            actionWidget)
                    desc = [None, None, None, None, None]
                    desc[
                        checkedWidgetsAttrDescList_checkedWidget_idx] = actionWidget
                    desc[
                        checkedWidgetsAttrDescList_checkedWidgetText_idx] = widgetInfo[
                            popupWidgetsInfo_actionsTextList_idx][idx]
                    desc[
                        checkedWidgetsAttrDescList_checkedWidgetColor_idx] = widgetInfo[
                            popupWidgetsInfo_actionsColorList_idx][idx]
                    desc[
                        checkedWidgetsAttrDescList_checkedWidgetStyleSheet_idx] = widgetInfo[
                            popupWidgetsInfo_actionsWidgetStyleSheet_idx]
                    desc[
                        checkedWidgetsAttrDescList_checkedWidgetPopupParentWidget_idx] = widgetInfo[
                            popupWidgetsInfo_pushButtonWidget_idx]
                    widgetName = widgetInfo[
                        popupWidgetsInfo_actionsNameList_idx][idx]
                    descsDict[widgetName] = desc

        return descsDict

    def get_widget_name(self, widgetObj):
        for key, val in self.checkboxWidgetsInfo.items():
            if widgetObj is val[0]:
                return key

        for key, val in self.popupWidgetsInfo.items():
            # print ("[ZXD] CheckboxListWidget.get_checkbox_name ... popupWidgetsInfo.key {} val {} widgetObj {} 'widgetObj is val[0]' = {} 'widgetObj == val[0]' = {}").format(key, val, widgetObj, widgetObj is val[0], widgetObj == val[0] )
            if widgetObj in val[popupWidgetsInfo_actionsWidgetList_idx]:
                idx = val[popupWidgetsInfo_actionsWidgetList_idx].index(
                    widgetObj)
                return val[popupWidgetsInfo_actionsNameList_idx]

        return None
Ejemplo n.º 5
0
class checkBoxListWidget(QGroupBox):
    # groupSelectionChanged = pyqtSignal(str, object)

    def enableAll(self, enabled=True):
        for cbn, cbw in self.checkboxWidgetsInfo.items():
            cbw[0].setEnabled(enabled)

    def enable(self, checkBoxName, checked=True):
        cb = self.checkboxWidgetsInfo.get(checkBoxName, None)
        if cb is not None:
            cb[0].setEnabled(checked)

    def setCheckedAll(self, checked=True):
        for cbn, cbw in self.checkboxWidgetsInfo.items():
            cbw[0].setChecked(checked)
        if not checked:
            self._checked_checkbox_widgets = []

    def setCheckedCheckbox(self, checkBoxName, checked=True):
        cb = self.checkboxWidgetsInfo.get(checkBoxName, None)
        if cb is not None:
            checkboxWidget = cb[0]
            # LOG.info("{} checkBoxListWidget.setChecked for checkboxname {}  checked {} ..".format(self.name, checkBoxName, checked))
            checkboxWidget.setChecked(checked)

    def setCheckedCheckboxs(self, checkBoxNamesList, checked=True):
        self._checked_checkbox_widgets = []
        if checkBoxNamesList is None:
            return
        for cbn in checkBoxNamesList:
            cw = self.checkboxWidgetsInfo.get(cbn, None)
            # LOG.info("{} self.checkboxWidgetsInfo = {} checkBoxNamesList = {}..".format(self.name, self.checkboxWidgetsInfo, checkBoxNamesList))
            # LOG.info("{} checkBoxListWidget.setCheckedCheckboxs :  cbn {} cw {}..".format(self.name, cbn, cw))
            if cw is not None:
                checkboxWidget = cw[0]
                # LOG.info("{} checkBoxListWidget.setChecked for checkboxname {}  checked {} ..".format(self.name, checkboxWidget, checked))
                checkboxWidget.setChecked(checked)
                if checked:
                    self._checked_checkbox_widgets.append(checkboxWidget)

        return self._checked_checkbox_widgets

    def setMaxCheckedNum(self, num):
        self._maxCheckedNum = num

    def setMaxSeperateWidgetNum(self, num):
        self._maxSeperateWidgetNum = num

    def __init__(self,
                 name,
                 text,
                 isExclusive,
                 thisGroupOption,
                 stateChanged,
                 parent=None):
        QGroupBox.__init__(self, text, parent)
        qss = "QGroupBox::title {subcontrol-origin: margin; subcontrol-position: top left; padding: 0 3px; color : red; font-weight:bold; }"
        self.setStyleSheet(qss)

        self.flayout = FloatingLayout()
        self.flayout.setSpacing(40)
        self.flayout.setMargin(4)

        self.name = str(name)
        self.text = text

        self.groupOptionDescListTuple = thisGroupOption
        self.stateChanged = stateChanged

        self.checkbox_group = QButtonGroup()
        self.checkbox_group.setExclusive(isExclusive)
        self.isExclusive = isExclusive

        self.checkboxWidgetsInfo = {
        }  # dict. checkboxWidgetsInfo[checkboxName] = [checkboxWidget, checkboxText, checkboxStyleSheet]
        self.popupWidgetsInfo = {
        }  # dict. popupWidgetsInfo[popupbutton_name] = [*, *, * , * , *]

        self._maxCheckedNum = 100
        self._maxSeperateWidgetNum = 100

        self._checked_checkbox_widgets = []

    def create_checkbox(self,
                        checkbox_name,
                        checkbox_text,
                        checkbox_background_color=None,
                        checkbox_text_color=None,
                        checkbox_background_color_checked=None,
                        checkbox_text_color_checked=None,
                        widget_minWidthInPixels=36):
        checkboxWidget = QCheckBox(checkbox_text)
        # print "checkbox_background_color {} checkbox_text_color {} checkbox_background_color_checked {} checkbox_text_color_checked {}".format(
        # checkbox_background_color, checkbox_text_color, checkbox_background_color_checked, checkbox_text_color_checked)

        desc = utils.set_qobj_stylesheet(
            checkboxWidget,
            'QCheckBox',
            checkbox_background_color,
            checkbox_text_color,
            checkbox_background_color_checked,
            checkbox_text_color_checked,
            min_width_pixels=widget_minWidthInPixels)

        checkboxWidget.setCheckable(True)
        checkboxWidget.clicked.connect(self.onClickedWidget)

        return checkboxWidget, desc

    def add_popup_button(self,
                         popup_button_name,
                         checkbox_name,
                         checkbox_text,
                         popupbutton_background_color=None,
                         popupbutton_text_color=None,
                         checkbox_background_color=None,
                         checkbox_text_color=None):
        # LOG.info(u"create_popup_button with popup_button_name = {} checkbox_name = {} checkbox_text = {} checkbox_background_color = {} checkbox_text_color = {}".format( \
        #    popup_button_name, checkbox_name, checkbox_text, checkbox_background_color, checkbox_text_color))

        popWidgetsInfo = self.popupWidgetsInfo.get(popup_button_name, None)
        if popWidgetsInfo is None:
            pbWidget = QPushButton(popup_button_name)
            # LOG.info(u"popupbutton_background_color {} popupbutton_text_colr {}".format(popupbutton_background_color, popupbutton_text_color))
            utils.set_qobj_stylesheet(pbWidget, 'QPushButton',
                                      popupbutton_background_color,
                                      popupbutton_text_color,
                                      popupbutton_background_color,
                                      popupbutton_text_color)
            self.flayout.addWidget(pbWidget)

            if pbWidget is None:
                print "Create QPushButton with name {} failed!".format(
                    popup_button_name)
                return
            mnWidget = QMenu(pbWidget)
            if mnWidget is None:
                print "Create QMenu attached with QPushButton of name {} failed!".format(
                    popup_button_name)
                return
            pbWidget.setMenu(mnWidget)
            actsWidgetList = []
            actsNameList = []
            actsTextList = []
            actsStyleSheetList = []
        else:
            pbWidget = popWidgetsInfo[popupWidgetsInfo_pushButtonWidget_idx]
            mnWidget = popWidgetsInfo[popupWidgetsInfo_menuWidget_idx]
            actsWidgetList = popWidgetsInfo[
                popupWidgetsInfo_actionsWidgetList_idx]
            actsNameList = popWidgetsInfo[popupWidgetsInfo_actionsNameList_idx]
            actsTextList = popWidgetsInfo[popupWidgetsInfo_actionsTextList_idx]
            actsStyleSheetList = popWidgetsInfo[
                popupWidgetsInfo_actionsWidgetStyleSheet_idx]

        actWidgetAction = QWidgetAction(mnWidget)
        actWidget = QWidget()
        actLayout = QVBoxLayout()
        actLayout.setMargin(2)
        actLayout.setSpacing(2)

        actBtnWidget = QCheckBox(checkbox_text)
        # for these widgets inside QWidgetAction, spacing and margin are controlled by actLayout.setMargin() and actLayout.setSpacing()
        utils.set_qobj_stylesheet(actBtnWidget,
                                  'QCheckBox',
                                  checkbox_background_color,
                                  checkbox_text_color,
                                  checkbox_background_color,
                                  checkbox_text_color,
                                  margin_pixels=0,
                                  padding_pixels=0)
        actLayout.addWidget(actBtnWidget)
        actWidget.setLayout(actLayout)
        actWidgetAction.setDefaultWidget(actWidget)
        mnWidget.addAction(actWidgetAction)

        desc = None
        actBtnWidget.setCheckable(True)
        actBtnWidget.clicked.connect(self.onClickedWidget)
        actsWidgetList.append(actBtnWidget)

        actsNameList.append(checkbox_name)
        actsTextList.append(checkbox_text)
        actsStyleSheetList.append(desc)

        if popWidgetsInfo is None:
            popWidgetsInfo = [None, None, None, None, None, None]

        popWidgetsInfo[popupWidgetsInfo_pushButtonWidget_idx] = pbWidget
        popWidgetsInfo[popupWidgetsInfo_menuWidget_idx] = mnWidget
        popWidgetsInfo[popupWidgetsInfo_actionsWidgetList_idx] = actsWidgetList
        popWidgetsInfo[popupWidgetsInfo_actionsNameList_idx] = actsNameList
        popWidgetsInfo[popupWidgetsInfo_actionsTextList_idx] = actsTextList
        popWidgetsInfo[
            popupWidgetsInfo_actionsWidgetStyleSheet_idx] = actsStyleSheetList

        self.popupWidgetsInfo[popup_button_name] = popWidgetsInfo

        return

    def add_checkbox(self,
                     checkbox_name,
                     checkbox_text,
                     background_color=None,
                     text_color=None,
                     background_color_checked=None,
                     text_color_checked=None,
                     widget_minWidthInPixels=36):
        checkboxWidget, checkboxStyleSheet = self.create_checkbox(
            checkbox_name,
            checkbox_text,
            background_color,
            text_color,
            background_color_checked,
            text_color_checked,
            widget_minWidthInPixels=widget_minWidthInPixels)
        self.checkboxWidgetsInfo[checkbox_name] = [
            checkboxWidget, checkbox_text, checkboxStyleSheet
        ]
        self.flayout.addWidget(checkboxWidget)
        self.checkbox_group.addButton(checkboxWidget)

        return checkboxWidget

    def get_checkbox(self, checkbox_name):
        return self.checkboxWidgetsInfo[checkbox_name]

    # return (names_list, texts_list, displaycolors_list)
    def get_config(self):
        names = []
        texts = []
        displaycolors = []
        for checkboxOption in self.groupOptionDescListTuple:
            thisCheckboxName = checkboxOption[config.METADATA_ATTR_VALUE_TOKEN]
            names.append(thisCheckboxName)
            thisCheckboxText = checkboxOption[
                config.METADATA_DISPLAYTEXT_TOKEN]
            texts.append(thisCheckboxText)
            thisCheckboxDisplayColor = checkboxOption.get(
                config.METADATA_DISPLAYCOLOR_TOKEN, None)
            if thisCheckboxDisplayColor is None:
                thisCheckboxDisplayColor = checkboxOption.get(
                    config.COLOR_ATTR_RGB_VALUE_TOKEN, None)
            # print u"name = {} text = {} color = {}".format(thisCheckboxName, thisCheckboxText, thisCheckboxDisplayColor)
            displaycolors.append(thisCheckboxDisplayColor)
        return names, texts, displaycolors

    def onClickedWidget(self):
        widget = self.sender()

        if widget.isChecked():
            (num, widgets) = self.get_checked_widgets_number()
            # print "\nget_checked_widgets_number {} maxCheckedNum {} len(_checked_checkbox_widgets) {}".format(num, self._maxCheckedNum, len(self._checked_checkbox_widgets))
            # for index, item in enumerate(self._checked_checkbox_widgets):
            #    print u"before: checked_checkbox_widgets[{}] - {}".format(index, item.text())

            # if current checked widgets exceed allowed max number, set state of oldest N widgets in checked_widgets record list to False and remove it from checked_widgets record list
            if self._maxCheckedNum < num:
                if (self._checked_checkbox_widgets is not None) and (
                        len(self._checked_checkbox_widgets) >=
                    (num - self._maxCheckedNum)):
                    for i in xrange(num - self._maxCheckedNum):
                        # print u"set checked_checkbox_widgets[{}] - {} -- unchecked".format(i, self._checked_checkbox_widgets[i].text())
                        self._checked_checkbox_widgets[i].setChecked(False)
                    del self._checked_checkbox_widgets[0:(num -
                                                          self._maxCheckedNum)]

            # record current selected widgets to checked_widgets record list
            if widget not in self._checked_checkbox_widgets:
                self._checked_checkbox_widgets.append(widget)
        else:
            # print "some widget is unchecked..."
            if widget in self._checked_checkbox_widgets:
                self._checked_checkbox_widgets.remove(widget)
            # for index, item in enumerate(self._checked_checkbox_widgets):
            #   print u"after: checked_checkbox_widgets[{}] - {}".format(index, item.text())

        # for index, item in enumerate(self._checked_checkbox_widgets):
        #    print u"after: checked_checkbox_widgets[{}] - {}".format(index, item.text())

        self.sendCheckedSignal()
        return

    def getCheckedWidgetsOptionInfo(self):
        # print "get sendCheckedSignal.."
        descs = self.get_checked_widgets_attrDesc()
        # print "get sendCheckedSignal.. groupOptionDescListTuple = {}".format(self.groupOptionDescListTuple)
        checkedWidgetsOptions = {}
        options = []
        if not descs:
            return self.name, checkedWidgetsOptions

        for checkedWidgetName in descs.keys():
            for option in self.groupOptionDescListTuple:
                if option[
                        config.METADATA_ATTR_VALUE_TOKEN] == checkedWidgetName:
                    options.append(option.copy())

        checkedWidgetsOptions[self.name] = options
        # print "get sendCheckedSignal.. name = {} checkedWidgetsOptions = {}".format(self.name, checkedWidgetsOptions)
        return self.name, checkedWidgetsOptions

    def sendCheckedSignal(self):
        checkedGroupName, checkedWidgetsOptions = self.getCheckedWidgetsOptionInfo(
        )
        # print "sendCheckedSignal ... checkedGroupName {} checkedWidgetsOptions {}...".format(checkedGroupName, checkedWidgetsOptions)

        #if checkedWidgetsOptions:
        if True:
            self.stateChanged.emit(checkedGroupName, checkedWidgetsOptions)
        return

    def get_checked_widgets_number(self):
        number = 0
        widgets = []
        for widgetInfo in self.checkboxWidgetsInfo.values():
            if widgetInfo[0].isChecked():
                number += 1
                widgets.append(widgetInfo[0])

        for widgetInfo in self.popupWidgetsInfo.values():
            for actionWidget in widgetInfo[
                    popupWidgetsInfo_actionsWidgetList_idx]:
                if actionWidget.isChecked():
                    number += 1
                    widgets.append(actionWidget)

        return number, widgets

    def get_checked_widgets_name(self):
        namesList = []
        for widgetName, widgetInfo in self.checkboxWidgetsInfo.items():
            if widgetInfo[0].isChecked():
                name = widgetName
                namesList.append(name)

        for widgetInfo in self.popupWidgetsInfo.values():
            for actionWidget in widgetInfo[
                    popupWidgetsInfo_actionsWidgetList_idx]:
                if actionWidget.isChecked():
                    name = widgetInfo[popupWidgetsInfo_actionsNameList_idx]
                    namesList.append(name)

        return namesList

    def get_checked_widgets_attrDesc(self):
        descsDict = {}
        for widgetName, widgetInfo in self.checkboxWidgetsInfo.items():
            if widgetInfo[0].isChecked():
                desc = [None, None, None, None]
                desc[
                    checkedWidgetsAttrDescList_checkedWidget_idx] = widgetInfo[
                        0]
                desc[
                    checkedWidgetsAttrDescList_checkedWidgetText_idx] = widgetInfo[
                        1]
                desc[
                    checkedWidgetsAttrDescList_checkedWidgetStyleSheet_idx] = widgetInfo[
                        2]
                descsDict[widgetName] = desc

        for widgetInfo in self.popupWidgetsInfo.values():
            for actionWidget in widgetInfo[
                    popupWidgetsInfo_actionsWidgetList_idx]:
                if actionWidget.isChecked():
                    idx = widgetInfo[
                        popupWidgetsInfo_actionsWidgetList_idx].index(
                            actionWidget)
                    desc = [None, None, None, None]
                    desc[
                        checkedWidgetsAttrDescList_checkedWidget_idx] = actionWidget
                    desc[
                        checkedWidgetsAttrDescList_checkedWidgetText_idx] = widgetInfo[
                            popupWidgetsInfo_actionsTextList_idx][idx]
                    desc[
                        checkedWidgetsAttrDescList_checkedWidgetStyleSheet_idx] = widgetInfo[
                            popupWidgetsInfo_actionsWidgetStyleSheet_idx]
                    desc[
                        checkedWidgetsAttrDescList_checkedWidgetPopupParentWidget_idx] = widgetInfo[
                            popupWidgetsInfo_pushButtonWidget_idx]
                    widgetName = widgetInfo[
                        popupWidgetsInfo_actionsNameList_idx][idx]
                    descsDict[widgetName] = desc

        return descsDict

    def get_widget_name(self, widgetObj):
        for key, val in self.checkboxWidgetsInfo.items():
            # print ("[ZXD] checkboxListWidget.get_checkbox_name ... checkboxWidgetsInfo.key {} val {} widgetObj {} 'widgetObj is val[0]' = {} 'widgetObj == val[0]' = {}").format(key, val, widgetObj, widgetObj is val[0], widgetObj == val[0] )
            if widgetObj is val[0]:
                return key

        for key, val in self.popupWidgetsInfo.items():
            # print ("[ZXD] checkboxListWidget.get_checkbox_name ... popupWidgetsInfo.key {} val {} widgetObj {} 'widgetObj is val[0]' = {} 'widgetObj == val[0]' = {}").format(key, val, widgetObj, widgetObj is val[0], widgetObj == val[0] )
            if widgetObj in val[popupWidgetsInfo_actionsWidgetList_idx]:
                idx = val[popupWidgetsInfo_actionsWidgetList_idx].index(
                    widgetObj)
                return val[popupWidgetsInfo_actionsNameList_idx]

        return None