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])
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
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
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())
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("----------------------------------------")
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())