def __init__(self, window, parent=None): super().__init__(parent) self.window = window self.create_icons() self.views = [FileTreeView(window, self), AlbumTreeView(window, self)] self.views[0].itemSelectionChanged.connect(self.update_selection_0) self.views[1].itemSelectionChanged.connect(self.update_selection_1) self._selected_view = 0 self._ignore_selection_changes = False TreeItem.window = window TreeItem.base_color = self.palette().base().color() TreeItem.text_color = self.palette().text().color() TreeItem.text_color_secondary = self.palette() \ .brush(QtGui.QPalette.Disabled, QtGui.QPalette.Text).color() TrackItem.track_colors = { File.NORMAL: interface_colors.get_qcolor('entity_saved'), File.CHANGED: TreeItem.text_color, File.PENDING: interface_colors.get_qcolor('entity_pending'), File.ERROR: interface_colors.get_qcolor('entity_error'), } FileItem.file_colors = { File.NORMAL: TreeItem.text_color, File.CHANGED: TreeItem.text_color, File.PENDING: interface_colors.get_qcolor('entity_pending'), File.ERROR: interface_colors.get_qcolor('entity_error'), }
def __init__(self, window, parent=None): super().__init__(parent) self.setChildrenCollapsible(False) self.window = window self.create_icons() self._views = [FileTreeView(window, self), AlbumTreeView(window, self)] self._selected_view = self._views[0] self._ignore_selection_changes = False def _view_update_selection(view): if not self._ignore_selection_changes: self._ignore_selection_changes = True self._update_selection(view) self._ignore_selection_changes = False for view in self._views: view.itemSelectionChanged.connect(partial(_view_update_selection, view)) TreeItem.window = window TreeItem.base_color = self.palette().base().color() TreeItem.text_color = self.palette().text().color() TreeItem.text_color_secondary = self.palette() \ .brush(QtGui.QPalette.Disabled, QtGui.QPalette.Text).color() TrackItem.track_colors = defaultdict(lambda: TreeItem.text_color, { File.NORMAL: interface_colors.get_qcolor('entity_saved'), File.CHANGED: TreeItem.text_color, File.PENDING: interface_colors.get_qcolor('entity_pending'), File.ERROR: interface_colors.get_qcolor('entity_error'), }) FileItem.file_colors = defaultdict(lambda: TreeItem.text_color, { File.NORMAL: TreeItem.text_color, File.CHANGED: TreeItem.text_color, File.PENDING: interface_colors.get_qcolor('entity_pending'), File.ERROR: interface_colors.get_qcolor('entity_error'), })
def _setup_formats(self): interface_colors.load_from_config() self.formats = {} for level, feat in log.levels_features.items(): text_fmt = QtGui.QTextCharFormat() text_fmt.setFontFamily(FONT_FAMILY_MONOSPACE) text_fmt.setForeground(interface_colors.get_qcolor(feat.color_key)) self.formats[level] = text_fmt
def _setup_formats(self): interface_colors.load_from_config() self.formats = {} font = QtGui.QFont() font.setFamily("Monospace") for level, feat in log.levels_features.items(): text_fmt = QtGui.QTextCharFormat() text_fmt.setFont(font) text_fmt.setForeground(interface_colors.get_qcolor(feat.color_key)) self.formats[level] = text_fmt
def test_interface_colors(self): with self.assertRaises(UnknownColorException): interface_colors.get_color('testcolor') self.assertEqual(interface_colors.get_color('entity_error'), _DEFAULT_COLORS['entity_error'].value) interface_colors.load_from_config() self.assertEqual(interface_colors.get_color('entity_error'), '#abcdef') self.assertEqual(interface_colors.get_colors()['entity_error'], '#abcdef') interface_colors.set_color('entity_error', '#000000') interface_colors.save_to_config() self.assertEqual(config.setting['interface_colors']['entity_error'], '#000000') self.assertNotIn('unknowncolor', config.setting['interface_colors']) self.assertEqual( interface_colors.get_color_description('entity_error'), _DEFAULT_COLORS['entity_error'].description) self.assertEqual(interface_colors.get_qcolor('entity_error'), QColor('#000000'))
def test_interface_colors(self): for key in ('interface_colors', 'interface_colors_dark'): interface_colors = InterfaceColors( dark_theme=key == 'interface_colors_dark') with self.assertRaises(UnknownColorException): interface_colors.get_color('testcolor') default_colors = interface_colors.default_colors self.assertEqual(interface_colors.get_color('entity_error'), default_colors['entity_error'].value) interface_colors.load_from_config() self.assertEqual(interface_colors.get_color('entity_error'), '#abcdef') self.assertEqual(interface_colors.get_colors()['entity_error'], '#abcdef') interface_colors.set_color('entity_error', '#000000') self.assertTrue(interface_colors.save_to_config()) self.assertEqual(config.setting[key]['entity_error'], '#000000') self.assertNotIn('unknowncolor', config.setting[key]) self.assertEqual( interface_colors.get_color_description('entity_error'), default_colors['entity_error'].description) self.assertEqual(interface_colors.get_qcolor('entity_error'), QColor('#000000'))
def _update_tags(self, new_selection=True, drop_album_caches=False): self.selection_mutex.lock() files = self.files tracks = self.tracks self.selection_mutex.unlock() if not (files or tracks): return None if new_selection or drop_album_caches: self._single_file_album = len(set([file.metadata["album"] for file in files])) == 1 self._single_track_album = len(set([track.metadata["album"] for track in tracks])) == 1 while not new_selection: # Just an if with multiple exit points # If we are dealing with the same selection # skip updates unless it we are dealing with a single file/track if len(files) == 1: break if len(tracks) == 1: break # Or if we are dealing with a single cluster/album if self._single_file_album: break if self._single_track_album: break return self.tag_diff self.colors = { TagStatus.NOCHANGE: self.palette().color(QtGui.QPalette.Text), TagStatus.REMOVED: QtGui.QBrush(interface_colors.get_qcolor('tagstatus_removed')), TagStatus.ADDED: QtGui.QBrush(interface_colors.get_qcolor('tagstatus_added')), TagStatus.CHANGED: QtGui.QBrush(interface_colors.get_qcolor('tagstatus_changed')) } config = get_config() tag_diff = TagDiff(max_length_diff=config.setting["ignore_track_duration_difference_under"]) orig_tags = tag_diff.orig new_tags = tag_diff.new tag_diff.objects = len(files) clear_existing_tags = config.setting["clear_existing_tags"] top_tags = config.setting['metadatabox_top_tags'] top_tags_set = set(top_tags) for file in files: new_metadata = file.new_metadata orig_metadata = file.orig_metadata tags = set(list(new_metadata.keys()) + list(orig_metadata.keys())) for name in filter(lambda x: not x.startswith("~") and file.supports_tag(x), tags): new_values = new_metadata.getall(name) orig_values = orig_metadata.getall(name) if not clear_existing_tags and not new_values: new_values = list(orig_values or [""]) removed = name in new_metadata.deleted_tags tag_diff.add(name, orig_values, new_values, True, removed, top_tags=top_tags_set) tag_diff.add("~length", str(orig_metadata.length), str(new_metadata.length), removable=False, readonly=True) for track in tracks: if track.num_linked_files == 0: for name, new_values in track.metadata.rawitems(): if not name.startswith("~"): if name in track.orig_metadata: orig_values = track.orig_metadata.getall(name) else: orig_values = new_values tag_diff.add(name, orig_values, new_values, True) length = str(track.metadata.length) tag_diff.add("~length", length, length, removable=False, readonly=True) tag_diff.objects += 1 all_tags = set(list(orig_tags.keys()) + list(new_tags.keys())) common_tags = [tag for tag in top_tags if tag in all_tags] tag_names = common_tags + sorted(all_tags.difference(common_tags), key=lambda x: display_tag_name(x).lower()) if config.persist["show_changes_first"]: tags_by_status = {} for tag in tag_names: tags_by_status.setdefault(tag_diff.tag_status(tag), []).append(tag) for status in (TagStatus.CHANGED, TagStatus.ADDED, TagStatus.REMOVED, TagStatus.NOCHANGE): tag_diff.tag_names += tags_by_status.pop(status, []) else: tag_diff.tag_names = [ tag for tag in tag_names if tag_diff.status[tag] != TagStatus.EMPTY] return tag_diff
def _update_tags(self): self.selection_mutex.lock() files = self.files tracks = self.tracks self.selection_mutex.unlock() if not (files or tracks): return None self.colors = { TagStatus.NOCHANGE: self.palette().color(QtGui.QPalette.Text), TagStatus.REMOVED: QtGui.QBrush(interface_colors.get_qcolor('tagstatus_removed')), TagStatus.ADDED: QtGui.QBrush(interface_colors.get_qcolor('tagstatus_added')), TagStatus.CHANGED: QtGui.QBrush(interface_colors.get_qcolor('tagstatus_changed')) } tag_diff = TagDiff(max_length_diff=config. setting["ignore_track_duration_difference_under"]) orig_tags = tag_diff.orig new_tags = tag_diff.new # existing_tags are orig_tags that would not be overwritten by # any new_tags, assuming clear_existing_tags is disabled. existing_tags = set() tag_diff.objects = len(files) clear_existing_tags = config.setting["clear_existing_tags"] for file in files: new_metadata = file.new_metadata orig_metadata = file.orig_metadata tags = set(list(new_metadata.keys()) + list(orig_metadata.keys())) for name in filter( lambda x: not x.startswith("~") and file.supports_tag(x), tags): new_values = new_metadata.getall(name) orig_values = orig_metadata.getall(name) if not ((new_values and name not in existing_tags) or clear_existing_tags): new_values = list(orig_values or [""]) existing_tags.add(name) removed = name in new_metadata.deleted_tags tag_diff.add(name, orig_values, new_values, True, removed) tag_diff.add("~length", str(orig_metadata.length), str(new_metadata.length), False) for track in tracks: if track.num_linked_files == 0: for name, values in track.metadata.rawitems(): if not name.startswith("~"): tag_diff.add(name, values, values, True) length = str(track.metadata.length) tag_diff.add("~length", length, length, False) tag_diff.objects += 1 all_tags = set(list(orig_tags.keys()) + list(new_tags.keys())) common_tags = [ tag for tag in config.setting['metadatabox_top_tags'] if tag in all_tags ] tag_names = common_tags + sorted( all_tags.difference(common_tags), key=lambda x: display_tag_name(x).lower()) if config.persist["show_changes_first"]: tags_by_status = {} for tag in tag_names: tags_by_status.setdefault(tag_diff.tag_status(tag), []).append(tag) for status in (TagStatus.CHANGED, TagStatus.ADDED, TagStatus.REMOVED, TagStatus.NOCHANGE): tag_diff.tag_names += tags_by_status.pop(status, []) else: tag_diff.tag_names = [ tag for tag in tag_names if tag_diff.status[tag] != TagStatus.EMPTY ] return tag_diff