Пример #1
0
 def setFont(self, font):
     """Set the font selector to the given font.
     
     Arguments:
         font -- the QFont to set.
     """
     fontInfo = QFontInfo(font)
     family = fontInfo.family()
     matches = self.familyList.findItems(family, Qt.MatchExactly)
     if matches:
         self.familyList.setCurrentItem(matches[0])
         self.familyList.scrollToItem(matches[0],
                                      QAbstractItemView.PositionAtTop)
     style = QFontDatabase().styleString(fontInfo)
     matches = self.styleList.findItems(style, Qt.MatchExactly)
     if matches:
         self.styleList.setCurrentItem(matches[0])
         self.styleList.scrollToItem(matches[0])
     else:
         self.styleList.setCurrentRow(0)
         self.styleList.scrollToItem(self.styleList.currentItem())
     size = repr(fontInfo.pointSize())
     matches = self.sizeList.findItems(size, Qt.MatchExactly)
     if matches:
         self.sizeList.setCurrentItem(matches[0])
         self.sizeList.scrollToItem(matches[0])
Пример #2
0
 def __init__(self, di, prefix, sortcus, sortdies):
     QAbstractItemModel.__init__(self)
     self.prefix = prefix
     self.top_dies = [
         decorate_die(CU.get_top_DIE(), i) for (i, CU) in enumerate(di._CUs)
     ]
     self.highlight_condition = None
     fi = QFontInfo(QApplication.font())
     self.bold_font = QFont(fi.family(), fi.pointSize(), QFont.Bold)
     self.blue_brush = QBrush(Qt.GlobalColor.blue)
     self.sortcus = sortcus
     self.sortdies = sortdies
Пример #3
0
def getFont():
    preferredFamilies = [
        'Inconsolata', 'Consolas', 'Deja Vu Sans Mono', 'Droid Sans Mono',
        'Proggy', 'Monofur', 'Profont', 'Monaco', 'Andale Mono', 'Courier'
    ]
    font = QFont()
    for family in preferredFamilies:
        logger.debug("Attempting to choose {}".format(family))
        font = QFont()
        font.setFamily('Consolas')
        fontInfo = QFontInfo(font)
        if fontInfo.family() == family:
            logger.info("Succeeded in choosing family {}".format(family))
            break
    font.setPointSize(14)
    return font
Пример #4
0
    def doubleClickedCB(self, model_index):
        """Double click handler for the property table"""

        # Get translation object
        _ = get_app()._tr

        # Get data model and selection
        model = self.clip_properties_model.model

        row = model_index.row()
        selected_label = model.item(row, 0)
        self.selected_item = model.item(row, 1)

        if selected_label:
            cur_property = selected_label.data()
            property_type = cur_property[1]["type"]

            if property_type == "color":
                # Get current value of color
                red = cur_property[1]["red"]["value"]
                green = cur_property[1]["green"]["value"]
                blue = cur_property[1]["blue"]["value"]

                # Show color dialog
                currentColor = QColor(red, green, blue)
                log.debug("Launching ColorPicker for %s", currentColor.name())
                ColorPicker(
                    currentColor, parent=self, title=_("Select a Color"),
                    callback=self.color_callback)
                return

            elif property_type == "font":
                # Get font from user
                current_font_name = cur_property[1].get("memo", "sans")
                current_font = QFont(current_font_name)
                font, ok = QFontDialog.getFont(current_font, caption=("Change Font"))

                # Update font
                if ok and font:
                    fontinfo = QFontInfo(font)
                    # TODO: pass font details to value_updated so we can set multiple values
                    font_details = { "font_family": fontinfo.family(),
                                     "font_style": fontinfo.styleName(),
                                     "font_weight": fontinfo.weight(),
                                     "font_size_pixel": fontinfo.pixelSize() }
                    self.clip_properties_model.value_updated(self.selected_item, value=fontinfo.family())
Пример #5
0
 def reportCodeViewerProperties(self, font):
     wposition = self.pos()
     font_info = QFontInfo(font)
     print("---------- Code Viewer Report ----------")
     print("Size: width: %d, height: %d" % (self.width, self.height))
     print("Top-Left position in screen: (%d, %d)" %
           (wposition.x(), wposition.y()))
     print("Top-Right position in screen: (%d, %d)" %
           (wposition.x() + self.width, wposition.y()))
     print("Bottom-Left position in screen: (%d, %d)" %
           (wposition.x(), wposition.y() + self.height))
     print("Bottom-Right position in screen: (%d, %d)" %
           (wposition.x() + self.width, wposition.y() + self.height))
     print("---------- Side Bar    Report ----------")
     print("Size: width: %d, height: %d" %
           (self.listWidth, self.editorHeight))
     print("Top-Left position in screen: (%d, %d)" %
           (wposition.x(), wposition.y()))
     print("Top-Right position in screen: (%d, %d)" %
           (wposition.x() + self.listWidth, wposition.y()))
     print("Bottom-Left position in screen: (%d, %d)" %
           (wposition.x(), wposition.y() + self.editorHeight))
     print("Bottom-Right position in screen: (%d, %d)" %
           (wposition.x() + self.listWidth,
            wposition.y() + self.editorHeight))
     print("---------- Code Editor Report ----------")
     print("Size: width: %d, height: %d" %
           (self.editorWidth, self.editorHeight))
     print("Margins: %f pixels" % self.editor.document().documentMargin())
     print("Top-Left position in screen: (%d, %d)" %
           (wposition.x() + self.listWidth, wposition.y()))
     print(
         "Top-Right position in screen: (%d, %d)" %
         (wposition.x() + self.listWidth + self.editorWidth, wposition.y()))
     print("Bottom-Left position in screen: (%d, %d)" %
           (wposition.x() + self.listWidth,
            wposition.y() + self.editorHeight))
     print("Bottom-Right position in screen: (%d, %d)" %
           (wposition.x() + self.listWidth + self.editorWidth,
            wposition.y() + self.editorHeight))
     print("Padding: left: %d, top: %d, bottom: %d, right: %d" %
           (self.padding_left, self.padding_top, self.padding_bottom,
            self.padding_right))
     print("---------- Font report (font) ----------")
     print("font family: %s" % font.family())
     print("font pixelSize: %f" % font.pixelSize())
     print("font pointSize: %f" % font.pointSize())
     print("font pointSizeF: %f" % font.pointSizeF())
     print("QFont.pixelSize(): %f" % font.pixelSize())
     print("---------- QFontInfo   (font) ----------")
     print("family(): %s" % font_info.family())
     print("pixelSize(): %f" % font_info.pixelSize())
     print("pointSize(): %f" % font_info.pointSize())
     print("pointSizeF(): %f" % font_info.pointSizeF())
     print("QFontInfo.pixelSize(): %d" % font_info.pixelSize())
     print("---------- QFontMetrics (font) ---------")
     print("QFontMetrics.lineSpacing(): %f" %
           QFontMetrics(font).lineSpacing())
     print("QFontMetrics.leading(): %f" % QFontMetrics(font).leading())
     print("QFontMetrics.height(): %f" % QFontMetrics(font).height())
     print("---------- Eye tracking area  ----------")
     x1 = wposition.x() + self.listWidth + self.padding_left
     y1 = wposition.y() + self.padding_top
     x2 = wposition.x(
     ) + self.listWidth + self.editorWidth - self.padding_right
     y2 = wposition.y() + self.editorHeight - self.padding_bottom
     self.editor.x_offset = x1  # For the eye tracker, as it uses the entire screen
     self.editor.y_offset = y1  # For the eye tracker, as it uses the entire screen
     self.editor.most_right_x = x2
     self.editor.most_bottom_y = y2
     print("Size: width: %d, height: %d" % (x2 - x1, y2 - y1))
     print("Top-Left position in screen: (%d, %d)" % (x1, y1))
     print("Top-Right position in screen: (%d, %d)" % (x2, y1))
     print("Bottom-Left position in screen: (%d, %d)" % (x1, y2))
     print("Bottom-Right position in screen: (%d, %d)" % (x2, y2))
     print("x_offset = %d" % x1)
     print("y_offset = %d" % y1)
     print("---------- Status Bar  Report ----------")
     print("Size: width: %d, height: %d" %
           (self.width, self.status_bar_height))
     print("Top-Left position in screen: (%d, %d)" %
           (wposition.x(), wposition.y() + self.editorHeight))
     print("Top-Right position in screen: (%d, %d)" %
           (wposition.x() + self.width, wposition.y() + self.editorHeight))
     print("Bottom-Left position in screen: (%d, %d)" %
           (wposition.x(),
            wposition.y() + self.editorHeight + self.status_bar_height))
     print("Bottom-Right position in screen: (%d, %d)" %
           (wposition.x() + self.width,
            wposition.y() + self.editorHeight + self.status_bar_height))
     print("----------------------------------------")
Пример #6
0
    def contextMenuEvent(self, event):
        """ Display context menu """
        # Get property being acted on
        index = self.indexAt(event.pos())
        if not index.isValid():
            event.ignore()
            return

        # Get data model and selection
        idx = self.indexAt(event.pos())
        row = idx.row()
        selected_label = idx.model().item(row, 0)
        selected_value = idx.model().item(row, 1)
        self.selected_item = selected_value
        frame_number = self.clip_properties_model.frame_number

        # Get translation object
        _ = get_app()._tr

        # If item selected
        if selected_label:
            # Get data from selected item
            cur_property = selected_label.data()
            property_name = cur_property[1]["name"]
            self.property_type = cur_property[1]["type"]
            points = cur_property[1]["points"]
            self.choices = cur_property[1]["choices"]
            property_key = cur_property[0]
            clip_id, item_type = selected_value.data()
            log.info("Context menu shown for %s (%s) for clip %s on frame %s" % (property_name, property_key, clip_id, frame_number))
            log.info("Points: %s" % points)

            # Clear menu if models updated
            if self.menu_reset:
                self.choices = []
                self.menu_reset = False

            # Handle parent effect options
            if property_key == "parent_effect_id" and not self.choices:
                clip_choices = [{
                    "name": "None",
                    "value": "None",
                    "selected": False,
                    "icon": QIcon()
                }]
                # Instantiate the timeline
                timeline_instance = get_app().window.timeline_sync.timeline
                # Instantiate this effect
                effect = timeline_instance.GetClipEffect(clip_id)
                effect_json = json.loads(effect.Json())

                # Loop through timeline's clips
                for clip_instance in timeline_instance.Clips():
                    clip_instance_id = clip_instance.Id()
                    # Avoid parent a clip effect to it's own effect
                    if (clip_instance_id != effect.ParentClipId()):
                        # Clip's propertyJSON data
                        clip_instance_data = Clip.get(id = clip_instance_id).data
                        # Path to the clip file
                        clip_instance_path = clip_instance_data["reader"]["path"]
                        # Iterate through all clip files on the timeline
                        for clip_number in range(self.files_model.rowCount()):
                            clip_index = self.files_model.index(clip_number, 0)
                            clip_name = clip_index.sibling(clip_number, 1).data()
                            clip_path = os.path.join(clip_index.sibling(clip_number, 4).data(), clip_name)
                            # Check if the timeline's clip file name matches the clip the user selected
                            if (clip_path == clip_instance_path):
                                # Generate the clip icon to show in the selection menu
                                clip_instance_icon = clip_index.data(Qt.DecorationRole)
                        effect_choices = [{"name": "None",
                                            "value": "None",
                                            "selected": False,
                                            "icon": QIcon()}]
                        # Iterate through clip's effects
                        for effect_data in clip_instance_data["effects"]:
                            # Make sure the user can only set a parent effect of the same type as this effect
                            if effect_data['class_name'] == effect_json['class_name']:
                                effect_id = effect_data["id"]
                                effect_name = effect_data['class_name']
                                effect_icon = QIcon(QPixmap(os.path.join(info.PATH, "effects", "icons", "%s.png" % effect_data['class_name'].lower())))
                                effect_choices.append({"name": effect_id,
                                                "value": effect_id,
                                                "selected": False,
                                                "icon": effect_icon})
                        self.choices.append({"name": _(clip_instance_data["title"]),
                                            "value": effect_choices,
                                            "selected": False,
                                            "icon": clip_instance_icon})


            # Handle selected object options (ObjectDetection effect)
            if property_key == "selected_object_index" and not self.choices:
                # Get all visible object's indexes
                timeline_instance = get_app().window.timeline_sync.timeline
                # Instantiate the effect
                effect = timeline_instance.GetClipEffect(clip_id)
                # Get the indexes and IDs of the visible objects
                visible_objects = json.loads(effect.GetVisibleObjects(frame_number))
                # Add visible objects as choices
                object_index_choices = []
                for object_index in visible_objects["visible_objects_index"]:
                    object_index_choices.append({
                                "name": str(object_index),
                                "value": str(object_index),
                                "selected": False,
                                "icon": QIcon()
                            })
                self.choices.append({"name": _("Detected Objects"), "value": object_index_choices, "selected": False, "icon": None})

            # Handle property to set the Tracked Object's child clip
            if property_key == "child_clip_id" and not self.choices:
                clip_choices = [{
                    "name": "None",
                    "value": "None",
                    "selected": False,
                    "icon": QIcon()
                }]
                # Instantiate the timeline
                timeline_instance = get_app().window.timeline_sync.timeline
                current_effect = timeline_instance.GetClipEffect(clip_id)

                # Loop through timeline's clips
                for clip_instance in timeline_instance.Clips():
                    clip_instance_id = clip_instance.Id()

                    # Avoid attach a clip to it's own object
                    if (clip_instance_id != clip_id and (current_effect and clip_instance_id != current_effect.ParentClip().Id())):
                        # Clip's propertyJSON data
                        clip_instance_data = Clip.get(id = clip_instance_id).data
                        # Path to the clip file
                        clip_instance_path = clip_instance_data["reader"]["path"]
                        # Iterate through all clip files on the timeline
                        for clip_number in range(self.files_model.rowCount()):
                            clip_index = self.files_model.index(clip_number, 0)
                            clip_name = clip_index.sibling(clip_number, 1).data()
                            clip_path = os.path.join(clip_index.sibling(clip_number, 4).data(), clip_name)
                            # Check if the timeline's clip file name matches the clip the user selected
                            if (clip_path == clip_instance_path):
                                # Generate the clip icon to show in the selection menu
                                clip_instance_icon = clip_index.data(Qt.DecorationRole)
                                self.choices.append({"name": clip_instance_data["title"],
                                              "value": clip_instance_id,
                                              "selected": False,
                                              "icon": clip_instance_icon})

            # Handle clip attach options
            if property_key == "parentObjectId" and not self.choices:
                # Add all Clips as choices - initialize with None
                tracked_choices = [{
                    "name": "None",
                    "value": "None",
                    "selected": False,
                    "icon": QIcon()
                }]
                clip_choices = [{
                    "name": "None",
                    "value": "None",
                    "selected": False,
                    "icon": QIcon()
                }]
                # Instantiate the timeline
                timeline_instance = get_app().window.timeline_sync.timeline
                # Loop through timeline's clips
                for clip_instance in timeline_instance.Clips():
                    clip_instance_id = clip_instance.Id()
                    # Avoid attach a clip to it's own object
                    if (clip_instance_id != clip_id):
                        # Clip's propertyJSON data
                        clip_instance_data = Clip.get(id = clip_instance_id).data
                        # Path to the clip file
                        clip_instance_path = clip_instance_data["reader"]["path"]
                        # Iterate through all clip files on the timeline
                        for clip_number in range(self.files_model.rowCount()):
                            clip_index = self.files_model.index(clip_number, 0)
                            clip_name = clip_index.sibling(clip_number, 1).data()
                            clip_path = os.path.join(clip_index.sibling(clip_number, 4).data(), clip_name)
                            # Check if the timeline's clip file name matches the clip the user selected
                            if (clip_path == clip_instance_path):
                                # Generate the clip icon to show in the selection menu
                                clip_instance_icon = clip_index.data(Qt.DecorationRole)
                                clip_choices.append({"name": clip_instance_data["title"],
                                              "value": clip_instance_id,
                                              "selected": False,
                                              "icon": clip_instance_icon})
                        # Get the pixmap of the clip icon
                        icon_size = 72
                        icon_pixmap = clip_instance_icon.pixmap(icon_size, icon_size)
                        # Add tracked objects to the selection menu
                        tracked_objects = []
                        for effect in clip_instance_data["effects"]:
                            # Check if effect has a tracked object
                            if effect.get("has_tracked_object"):
                                # Instantiate the effect
                                effect_instance = timeline_instance.GetClipEffect(effect["id"])
                                # Get the visible object's ids
                                visible_objects_id = json.loads(effect_instance.GetVisibleObjects(frame_number))["visible_objects_id"]
                                for object_id in visible_objects_id:
                                    # Get the Tracked Object properties
                                    object_properties = json.loads(timeline_instance.GetTrackedObjectValues(object_id, 0))
                                    x1 = object_properties['x1']
                                    y1 = object_properties['y1']
                                    x2 = object_properties['x2']
                                    y2 = object_properties['y2']
                                    # Get the tracked object's icon from the clip's icon
                                    tracked_object_icon = icon_pixmap.copy(QRect(x1*icon_size, y1*icon_size, (x2-x1)*icon_size, (y2-y1)*icon_size)).scaled(icon_size, icon_size)
                                    tracked_objects.append({"name": str(object_id),
                                                            "value": str(object_id),
                                                            "selected": False,
                                                            "icon": QIcon(tracked_object_icon)})
                        tracked_choices.append({"name": clip_instance_data["title"],
                                              "value": tracked_objects,
                                              "selected": False,
                                              "icon": clip_instance_icon})
                self.choices.append({"name": _("Tracked Objects"), "value": tracked_choices, "selected": False, "icon": None})
                self.choices.append({"name": _("Clips"), "value": clip_choices, "selected": False, "icon": None})

            # Handle reader type values
            if self.property_type == "reader" and not self.choices:
                # Add all files
                file_choices = []
                for i in range(self.files_model.rowCount()):
                    idx = self.files_model.index(i, 0)
                    if not idx.isValid():
                        continue
                    icon = idx.data(Qt.DecorationRole)
                    name = idx.sibling(i, 1).data()
                    path = os.path.join(idx.sibling(i, 4).data(), name)

                    # Append file choice
                    file_choices.append({"name": name,
                                         "value": path,
                                         "selected": False,
                                         "icon": icon
                                         })

                # Add root file choice
                self.choices.append({"name": _("Files"), "value": file_choices, "selected": False, icon: None})

                # Add all transitions
                trans_choices = []
                for i in range(self.transition_model.rowCount()):
                    idx = self.transition_model.index(i, 0)
                    if not idx.isValid():
                        continue
                    icon = idx.data(Qt.DecorationRole)
                    name = idx.sibling(i, 1).data()
                    path = idx.sibling(i, 3).data()

                    # Append transition choice
                    trans_choices.append({"name": name,
                                          "value": path,
                                          "selected": False,
                                          "icon": icon
                                          })

                # Add root transitions choice
                self.choices.append({"name": _("Transitions"), "value": trans_choices, "selected": False})

            # Handle reader type values
            if property_name == "Track" and self.property_type == "int" and not self.choices:
                # Populate all display track names
                all_tracks = get_app().project.get("layers")
                display_count = len(all_tracks)
                for track in reversed(sorted(all_tracks, key=itemgetter('number'))):
                    # Append track choice
                    track_name = track.get("label") or _("Track %s") % display_count
                    self.choices.append({"name": track_name, "value": track.get("number"), "selected": False, "icon": None})
                    display_count -= 1
                return

            elif self.property_type == "font":
                # Get font from user
                current_font_name = cur_property[1].get("memo", "sans")
                current_font = QFont(current_font_name)
                font, ok = QFontDialog.getFont(current_font, caption=("Change Font"))

                # Update font
                if ok and font:
                    fontinfo = QFontInfo(font)
                    self.clip_properties_model.value_updated(self.selected_item, value=fontinfo.family())

            # Define bezier presets
            bezier_presets = [
                (0.250, 0.100, 0.250, 1.000, _("Ease (Default)")),
                (0.420, 0.000, 1.000, 1.000, _("Ease In")),
                (0.000, 0.000, 0.580, 1.000, _("Ease Out")),
                (0.420, 0.000, 0.580, 1.000, _("Ease In/Out")),

                (0.550, 0.085, 0.680, 0.530, _("Ease In (Quad)")),
                (0.550, 0.055, 0.675, 0.190, _("Ease In (Cubic)")),
                (0.895, 0.030, 0.685, 0.220, _("Ease In (Quart)")),
                (0.755, 0.050, 0.855, 0.060, _("Ease In (Quint)")),
                (0.470, 0.000, 0.745, 0.715, _("Ease In (Sine)")),
                (0.950, 0.050, 0.795, 0.035, _("Ease In (Expo)")),
                (0.600, 0.040, 0.980, 0.335, _("Ease In (Circ)")),
                (0.600, -0.280, 0.735, 0.045, _("Ease In (Back)")),

                (0.250, 0.460, 0.450, 0.940, _("Ease Out (Quad)")),
                (0.215, 0.610, 0.355, 1.000, _("Ease Out (Cubic)")),
                (0.165, 0.840, 0.440, 1.000, _("Ease Out (Quart)")),
                (0.230, 1.000, 0.320, 1.000, _("Ease Out (Quint)")),
                (0.390, 0.575, 0.565, 1.000, _("Ease Out (Sine)")),
                (0.190, 1.000, 0.220, 1.000, _("Ease Out (Expo)")),
                (0.075, 0.820, 0.165, 1.000, _("Ease Out (Circ)")),
                (0.175, 0.885, 0.320, 1.275, _("Ease Out (Back)")),

                (0.455, 0.030, 0.515, 0.955, _("Ease In/Out (Quad)")),
                (0.645, 0.045, 0.355, 1.000, _("Ease In/Out (Cubic)")),
                (0.770, 0.000, 0.175, 1.000, _("Ease In/Out (Quart)")),
                (0.860, 0.000, 0.070, 1.000, _("Ease In/Out (Quint)")),
                (0.445, 0.050, 0.550, 0.950, _("Ease In/Out (Sine)")),
                (1.000, 0.000, 0.000, 1.000, _("Ease In/Out (Expo)")),
                (0.785, 0.135, 0.150, 0.860, _("Ease In/Out (Circ)")),
                (0.680, -0.550, 0.265, 1.550, _("Ease In/Out (Back)"))
            ]

            # Add menu options for keyframes
            menu = QMenu(self)
            if self.property_type == "color":
                Color_Action = menu.addAction(_("Select a Color"))
                Color_Action.triggered.connect(functools.partial(self.Color_Picker_Triggered, cur_property))
                menu.addSeparator()
            if points > 1:
                # Menu items only for multiple points
                Bezier_Menu = menu.addMenu(self.bezier_icon, _("Bezier"))
                for bezier_preset in bezier_presets:
                    preset_action = Bezier_Menu.addAction(bezier_preset[4])
                    preset_action.triggered.connect(functools.partial(
                        self.Bezier_Action_Triggered, bezier_preset))
                Linear_Action = menu.addAction(self.linear_icon, _("Linear"))
                Linear_Action.triggered.connect(self.Linear_Action_Triggered)
                Constant_Action = menu.addAction(self.constant_icon, _("Constant"))
                Constant_Action.triggered.connect(self.Constant_Action_Triggered)
                menu.addSeparator()
            if points >= 1:
                # Menu items for one or more points
                Insert_Action = menu.addAction(_("Insert Keyframe"))
                Insert_Action.triggered.connect(self.Insert_Action_Triggered)
                Remove_Action = menu.addAction(_("Remove Keyframe"))
                Remove_Action.triggered.connect(self.Remove_Action_Triggered)
                menu.popup(event.globalPos())

            # Menu for choices
            if not self.choices:
                return
            for choice in self.choices:
                if type(choice["value"]) != list:
                    # Just add root choice item
                    Choice_Action = menu.addAction(_(choice["name"]))
                    Choice_Action.setData(choice["value"])
                    Choice_Action.triggered.connect(self.Choice_Action_Triggered)
                    continue

                # Add sub-choice items (for nested choice lists)
                # Divide into smaller QMenus (since large lists cover the entire screen)
                # For example: Transitions -> 1 -> sub items
                SubMenu = None
                if choice["icon"] is not None:
                    SubMenuRoot = menu.addMenu(choice["icon"], choice["name"])
                else:
                    SubMenuRoot = menu.addMenu(choice["name"])

                SubMenuSize = 25
                SubMenuNumber = 0
                if len(choice["value"]) > SubMenuSize:
                    SubMenu = SubMenuRoot.addMenu(str(SubMenuNumber))
                else:
                    SubMenu = SubMenuRoot
                for i, sub_choice in enumerate(choice["value"], 1):
                    # Divide SubMenu if it's item is a list
                    if type(sub_choice["value"]) == list:
                        SubSubMenu = SubMenu.addMenu(sub_choice["icon"], sub_choice["name"])
                        for sub_sub_choice in sub_choice["value"]:
                            Choice_Action = SubSubMenu.addAction(
                                sub_sub_choice["icon"], sub_sub_choice["name"])
                            Choice_Action.setData(sub_sub_choice["value"])
                            Choice_Action.triggered.connect(self.Choice_Action_Triggered)
                    else:
                        if i % SubMenuSize == 0:
                            SubMenuNumber += 1
                            SubMenu = SubMenuRoot.addMenu(str(SubMenuNumber))
                        Choice_Action = SubMenu.addAction(
                            sub_choice["icon"], _(sub_choice["name"]))
                        Choice_Action.setData(sub_choice["value"])
                        Choice_Action.triggered.connect(self.Choice_Action_Triggered)

            # Show choice menuk
            menu.popup(event.globalPos())