Esempio n. 1
0
    def load(self):
        all_tag_names = set()
        common_tags = None
        counts = dict()

        for file in self.files:
            tags = set()
            for name, values in file.metadata.rawitems():
                if not name.startswith("~"):
                    tags.add((name, tuple(sorted(values))))
                    all_tag_names.add(name)
                counts[name] = counts.get(name, 0) + 1
            if common_tags is None:
                common_tags = tags
            else:
                common_tags = common_tags.intersection(tags)

        common_tag_names = set([a for (a, b) in common_tags])
        different_tag_names = all_tag_names.difference(common_tag_names)

        total = len(self.files)
        for name in different_tag_names:
            item = QtGui.QTreeWidgetItem(self.ui.tags)
            item.setText(0, display_tag_name(name))
            item.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(name))
            font = item.font(1)
            font.setItalic(True)
            item.setFont(1, font)
            missing = total - counts[name]
            if not missing:
                value = ungettext("(different across %d file)",
                                 "(different across %d files)", total) % total
            else:
                value = ungettext("(missing from %d file)",
                                 "(missing from %d files)", missing) % missing
            item.setText(1, value)

        for name, values in common_tags:
            for value in values:
                item = QtGui.QTreeWidgetItem(self.ui.tags)
                item.setText(0, display_tag_name(name))
                item.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(name))
                item.setText(1, value)

        if len(self.files) == 1:
            if self.config.setting['enable_ratings']:
                ratings = self.files[0].metadata.getall('~rating')
                if len(ratings) > 0:
                    self.ui.rating.setRating(int(ratings[0]))
            for mime, data in self.files[0].metadata.images:
                item = QtGui.QListWidgetItem()
                pixmap = QtGui.QPixmap()
                pixmap.loadFromData(data)
                icon = QtGui.QIcon(pixmap)
                item.setIcon(icon)
                self.ui.artwork_list.addItem(item)
Esempio n. 2
0
    def load(self):
        all_tag_names = set()
        common_tags = None
        counts = dict()

        for file in self.files:
            tags = set()
            for name, values in file.metadata.rawitems():
                if not name.startswith("~"):
                    tags.add((name, tuple(sorted(values))))
                    all_tag_names.add(name)
                counts[name] = counts.get(name, 0) + 1
            if common_tags is None:
                common_tags = tags
            else:
                common_tags = common_tags.intersection(tags)

        common_tag_names = set([a for (a, b) in common_tags])
        different_tag_names = all_tag_names.difference(common_tag_names)

        total = len(self.files)
        for name in different_tag_names:
            item = QtGui.QTreeWidgetItem(self.ui.tags)
            item.setText(0, display_tag_name(name))
            item.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(name))
            font = item.font(1)
            font.setItalic(True)
            item.setFont(1, font)
            missing = total - counts[name]
            if not missing:
                value = ungettext("(different across %d file)",
                                  "(different across %d files)", total) % total
            else:
                value = ungettext("(missing from %d file)",
                                  "(missing from %d files)", missing) % missing
            item.setText(1, value)

        for name, values in common_tags:
            for value in values:
                item = QtGui.QTreeWidgetItem(self.ui.tags)
                item.setText(0, display_tag_name(name))
                item.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(name))
                item.setText(1, value)

        if len(self.files) == 1:
            if self.config.setting['enable_ratings']:
                ratings = self.files[0].metadata.getall('~rating')
                if len(ratings) > 0:
                    self.ui.rating.setRating(int(ratings[0]))
            for mime, data in self.files[0].metadata.images:
                item = QtGui.QListWidgetItem()
                pixmap = QtGui.QPixmap()
                pixmap.loadFromData(data)
                icon = QtGui.QIcon(pixmap)
                item.setIcon(icon)
                self.ui.artwork_list.addItem(item)
Esempio n. 3
0
    def _update_items(self, result=None, error=None):
        if self.editing:
            return

        if not (self.files or self.tracks):
            result = None

        self.tag_diff = result

        if result is None:
            self.setRowCount(0)
            return

        self.setRowCount(len(result.tag_names))

        orig_flags = QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled
        new_flags = orig_flags | QtCore.Qt.ItemIsEditable

        for i, name in enumerate(result.tag_names):
            tag_item = self.item(i, 0)
            orig_item = self.item(i, 1)
            new_item = self.item(i, 2)
            if not tag_item:
                tag_item = QtWidgets.QTableWidgetItem()
                tag_item.setFlags(orig_flags)
                font = tag_item.font()
                font.setBold(True)
                tag_item.setFont(font)
                self.setItem(i, 0, tag_item)
            if not orig_item:
                orig_item = QtWidgets.QTableWidgetItem()
                orig_item.setFlags(orig_flags)
                self.setItem(i, 1, orig_item)
            if not new_item:
                new_item = QtWidgets.QTableWidgetItem()
                self.setItem(i, 2, new_item)
            tag_item.setText(display_tag_name(name))
            self.set_item_value(orig_item, self.tag_diff.orig, name)
            if name == "~length":
                new_item.setFlags(orig_flags)
            else:
                new_item.setFlags(new_flags)
            self.set_item_value(new_item, self.tag_diff.new, name)

            font = new_item.font()
            if result.tag_status(name) == TagStatus.Removed:
                font.setStrikeOut(True)
            else:
                font.setStrikeOut(False)

            new_item.setFont(font)

            color = self.colors.get(result.tag_status(name),
                                    self.colors[TagStatus.NoChange])
            orig_item.setForeground(color)
            new_item.setForeground(color)
Esempio n. 4
0
    def _update_items(self, result=None, error=None):
        if self.editing:
            return

        if not (self.files or self.tracks):
            result = None

        self.tag_diff = result

        if result is None:
            self.setRowCount(0)
            return

        self.setRowCount(len(result.tag_names))

        orig_flags = QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled
        new_flags = orig_flags | QtCore.Qt.ItemIsEditable

        for i, name in enumerate(result.tag_names):
            tag_item = self.item(i, 0)
            orig_item = self.item(i, 1)
            new_item = self.item(i, 2)
            if not tag_item:
                tag_item = QtWidgets.QTableWidgetItem()
                tag_item.setFlags(orig_flags)
                font = tag_item.font()
                font.setBold(True)
                tag_item.setFont(font)
                self.setItem(i, 0, tag_item)
            if not orig_item:
                orig_item = QtWidgets.QTableWidgetItem()
                orig_item.setFlags(orig_flags)
                self.setItem(i, 1, orig_item)
            if not new_item:
                new_item = QtWidgets.QTableWidgetItem()
                self.setItem(i, 2, new_item)
            tag_item.setText(display_tag_name(name))
            self.set_item_value(orig_item, self.tag_diff.orig, name)
            if name == "~length":
                new_item.setFlags(orig_flags)
            else:
                new_item.setFlags(new_flags)
            self.set_item_value(new_item, self.tag_diff.new, name)

            font = new_item.font()
            if result.tag_status(name) == TagStatus.REMOVED:
                font.setStrikeOut(True)
            else:
                font.setStrikeOut(False)

            new_item.setFont(font)

            color = self.colors.get(result.tag_status(name),
                                    self.colors[TagStatus.NOCHANGE])
            orig_item.setForeground(color)
            new_item.setForeground(color)
Esempio n. 5
0
 def add_tag(self):
     dialog = EditTagDialog('', None, self)
     if dialog.exec_():
         name = dialog.name
         value = dialog.value
         item = QtGui.QTreeWidgetItem(self.ui.tags)
         item.setText(0, display_tag_name(name))
         item.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(name))
         item.setText(1, value)
         self.changed.add(name)
Esempio n. 6
0
 def add_tag(self):
     dialog = EditTagDialog('', None, self)
     if dialog.exec_():
         name = dialog.name
         value = dialog.value
         item = QtGui.QTreeWidgetItem(self.ui.tags)
         item.setText(0, display_tag_name(name))
         item.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(name))
         item.setText(1, value)
         self.changed.add(name)
Esempio n. 7
0
    def _update_items(self, result=None, error=None):
        if result is None or error is not None:
            self.tag_diff.clear()
            self.tag_names = None
            self.setRowCount(0)
            self.updating = False
            if self.update_pending:
                self.update()
            return

        self.itemChanged.disconnect(self.item_changed)
        self.setRowCount(len(self.tag_names))

        orig_flags = QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled
        new_flags = orig_flags | QtCore.Qt.ItemIsEditable

        for i, name in enumerate(self.tag_names):
            length = name == "~length"
            tag_item = self.item(i, 0)
            orig_item = self.item(i, 1)
            new_item = self.item(i, 2)
            if not tag_item:
                tag_item = QtGui.QTableWidgetItem()
                tag_item.setFlags(orig_flags)
                font = tag_item.font()
                font.setBold(True)
                tag_item.setFont(font)
                self.setItem(i, 0, tag_item)
            if not orig_item:
                orig_item = QtGui.QTableWidgetItem()
                orig_item.setFlags(orig_flags)
                self.setItem(i, 1, orig_item)
            if not new_item:
                new_item = QtGui.QTableWidgetItem()
                self.setItem(i, 2, new_item)
            tag_item.setText(display_tag_name(name))
            self.set_item_value(orig_item, self.tag_diff.orig, name)
            new_item.setFlags(orig_flags if length else new_flags)
            self.set_item_value(new_item, self.tag_diff.new, name)

            color = self.colors.get(self.tag_status(name),
                    self.colors[TagStatus.NoChange])
            orig_item.setForeground(color)
            new_item.setForeground(color)

        self.itemChanged.connect(self.item_changed)
        self.updating = False
        if self.update_pending:
            self.update()
Esempio n. 8
0
    def _update_items(self, result=None, error=None):
        if result is None or error is not None:
            self.orig_tags.clear()
            self.new_tags.clear()
            self.tag_names = None
            self.setRowCount(0)
            self.updating = False
            if self.update_pending:
                self.update()
            return

        self._item_signals = False
        self.setRowCount(len(self.tag_names))
        flags = QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled

        for i, name in enumerate(self.tag_names):
            if self.tag_status(name) == "empty":
                continue
            tag_item = self.item(i, 0)
            orig_item = self.item(i, 1)
            new_item = self.item(i, 2)
            if not tag_item:
                tag_item = QtGui.QTableWidgetItem()
                tag_item.setFlags(QtCore.Qt.ItemIsEnabled)
                font = tag_item.font()
                font.setBold(True)
                tag_item.setFont(font)
                self.setItem(i, 0, tag_item)
            if not orig_item:
                orig_item = QtGui.QTableWidgetItem()
                orig_item.setFlags(flags)
                self.setItem(i, 1, orig_item)
            if not new_item:
                new_item = QtGui.QTableWidgetItem()
                self.setItem(i, 2, new_item)
            new_item.setFlags(flags if name == "~length" else flags | QtCore.Qt.ItemIsEditable)
            tag_item.setText(display_tag_name(name))
            self.set_item_value(orig_item, self.orig_tags, name)
            if new_item != self._editing:
                self.set_item_value(new_item, self.new_tags, name)
                self.set_row_colors(i)

        self._item_signals = True
        self.updating = False
        if self.update_pending:
            self.update()
Esempio n. 9
0
    def _update_items(self, result=None, error=None):
        if result is None or error is not None:
            self.orig_tags.clear()
            self.new_tags.clear()
            self.tag_names = None
            self.setRowCount(0)
            self.updating = False
            if self.update_pending:
                self.update()
            return

        self.itemChanged.disconnect(self.item_changed)
        self.setRowCount(len(self.tag_names))
        flags = QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled

        for i, name in enumerate(self.tag_names):
            tag_item = self.item(i, 0)
            orig_item = self.item(i, 1)
            new_item = self.item(i, 2)
            if not tag_item:
                tag_item = QtGui.QTableWidgetItem()
                tag_item.setFlags(flags)
                font = tag_item.font()
                font.setBold(True)
                tag_item.setFont(font)
                self.setItem(i, 0, tag_item)
            if not orig_item:
                orig_item = QtGui.QTableWidgetItem()
                orig_item.setFlags(flags)
                self.setItem(i, 1, orig_item)
            if not new_item:
                new_item = QtGui.QTableWidgetItem()
                self.setItem(i, 2, new_item)
            tag_item.setText(display_tag_name(name))
            self.set_item_value(orig_item, self.orig_tags, name)
            new_item.setFlags(flags if name == "~length" else flags
                              | QtCore.Qt.ItemIsEditable)
            self.set_item_value(new_item, self.new_tags, name)
            self.set_row_colors(i)

        self.itemChanged.connect(self.item_changed)
        self.updating = False
        if self.update_pending:
            self.update()
Esempio n. 10
0
 def edit_tag(self, item=None, column=None):
     if item is None:
         items = self.ui.tags.selectedItems()
         if not items:
             return
         item = items[0]
     name = unicode(item.data(0, QtCore.Qt.UserRole).toString())
     value = item.text(1)
     dialog = EditTagDialog(name, value, self)
     if dialog.exec_():
         if value != dialog.value:
             name = dialog.name
             value = dialog.value
             item.setText(0, display_tag_name(name))
             item.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(name))
             font = item.font(1)
             font.setItalic(False)
             item.setFont(1, font)
             item.setText(1, value)
             self.changed.add(name)
Esempio n. 11
0
 def edit_tag(self, item=None, column=None):
     if item is None:
         items = self.ui.tags.selectedItems()
         if not items:
             return
         item = items[0]
     name = unicode(item.data(0, QtCore.Qt.UserRole).toString())
     value = item.text(1)
     dialog = EditTagDialog(name, value, self)
     if dialog.exec_():
         if value != dialog.value or name != dialog.name:
             name = dialog.name
             value = dialog.value
             item.setText(0, display_tag_name(name))
             item.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(name))
             font = item.font(1)
             font.setItalic(False)
             item.setFont(1, font)
             item.setText(1, value)
             self.changed.add(name)
Esempio n. 12
0
    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

        tag_diff = TagDiff()
        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(new_metadata.keys() + 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 dict.iteritems(track.metadata):
                    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(orig_tags.keys() + new_tags.keys())
        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
Esempio n. 13
0
 def test_display_tag_name(self):
     self.assertEqual('Artist', display_tag_name('artist'))
     self.assertEqual('Lyrics', display_tag_name('lyrics:'))
     self.assertEqual('Comment [Foo]', display_tag_name('comment:Foo'))
Esempio n. 14
0
 def get_display_name(self, item):
     return display_tag_name(item)
Esempio n. 15
0
 def get_tooltip(self, position):
     if self._doc.characterAt(position) != '%':
         return None
     tag = self._read_allowed_chars(position + 1)
     return display_tag_name(tag)
Esempio n. 16
0
    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
Esempio n. 17
0
    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
Esempio n. 18
0
    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

        tag_diff = TagDiff()
        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(new_metadata.keys() + 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 dict.iteritems(track.metadata):
                    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(orig_tags.keys() + new_tags.keys())
        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
Esempio n. 19
0
    def _update_items(self, result=None, error=None):
        if self.editing:
            return

        if not (self.files or self.tracks):
            result = None

        self.tag_diff = result

        if result is None:
            self.setRowCount(0)
            return

        self.setRowCount(len(result.tag_names))

        orig_flags = QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled
        new_flags = orig_flags | QtCore.Qt.ItemIsEditable

        for i, name in enumerate(result.tag_names):
            tag_item = self.item(i, 0)
            orig_item = self.item(i, 1)
            new_item = self.item(i, 2)
            if not tag_item:
                tag_item = QtWidgets.QTableWidgetItem()
                tag_item.setFlags(orig_flags)
                font = tag_item.font()
                font.setBold(True)
                tag_item.setFont(font)
                self.setItem(i, 0, tag_item)
            if not orig_item:
                orig_item = QtWidgets.QTableWidgetItem()
                orig_item.setFlags(orig_flags)
                self.setItem(i, 1, orig_item)
            if not new_item:
                new_item = QtWidgets.QTableWidgetItem()
                self.setItem(i, 2, new_item)
            tag_item.setText(display_tag_name(name))
            self.set_item_value(orig_item, self.tag_diff.orig, name)
            if name == "~length":
                new_item.setFlags(orig_flags)
            else:
                new_item.setFlags(new_flags)
            self.set_item_value(new_item, self.tag_diff.new, name)

            font = new_item.font()
            if result.tag_status(name) == TagStatus.REMOVED:
                font.setStrikeOut(True)
            else:
                font.setStrikeOut(False)

            new_item.setFont(font)

            color = self.colors.get(result.tag_status(name),
                                    self.colors[TagStatus.NOCHANGE])
            orig_item.setForeground(color)
            new_item.setForeground(color)

            alignment = QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop
            tag_item.setTextAlignment(alignment)
            orig_item.setTextAlignment(alignment)
            new_item.setTextAlignment(alignment)

            # Expand the row for multiline content, but limit the maximum
            # row height.
            row_height = min(self.sizeHintForRow(i), 160)
            self.setRowHeight(i, row_height)