def __init__(self, files, parent=None): QtGui.QDialog.__init__(self, parent) self.ui = Ui_TagEditorDialog() self.ui.setupUi(self) title = _("Details") + " - " total = len(files) if total == 1: title += files[0].base_filename else: title += ungettext("%d file", "%d files", total) % total self.setWindowTitle(title) self.ui.buttonbox.addButton(StandardButton(StandardButton.OK), QtGui.QDialogButtonBox.AcceptRole) self.ui.buttonbox.addButton(StandardButton(StandardButton.CANCEL), QtGui.QDialogButtonBox.RejectRole) self.connect(self.ui.buttonbox, QtCore.SIGNAL('accepted()'), self, QtCore.SLOT('accept()')) self.connect(self.ui.buttonbox, QtCore.SIGNAL('rejected()'), self, QtCore.SLOT('reject()')) self.connect(self.ui.tags_add, QtCore.SIGNAL('clicked()'), self.add_tag) self.connect(self.ui.tags_edit, QtCore.SIGNAL('clicked()'), self.edit_tag) self.connect(self.ui.tags_delete, QtCore.SIGNAL('clicked()'), self.delete_tag) self.connect(self.ui.tags, QtCore.SIGNAL("itemActivated (QTreeWidgetItem*, int)"), self.edit_tag) self.ui.tags.setSortingEnabled(True) self.ui.tags.sortByColumn(0, QtCore.Qt.AscendingOrder) if self.config.setting['enable_ratings']: self.ui.rating.setMaximum(self.config.setting['rating_steps'] - 1) else: self.ui.ratingLabel.hide() self.ui.rating.hide() self.changed = set() self.files = files self.load() self.load_info()
class TagEditor(QtGui.QDialog): def __init__(self, files, parent=None): QtGui.QDialog.__init__(self, parent) self.ui = Ui_TagEditorDialog() self.ui.setupUi(self) title = _("Details") + " - " total = len(files) if total == 1: title += files[0].base_filename else: title += ungettext("%d file", "%d files", total) % total self.setWindowTitle(title) self.ui.buttonbox.addButton(StandardButton(StandardButton.OK), QtGui.QDialogButtonBox.AcceptRole) self.ui.buttonbox.addButton(StandardButton(StandardButton.CANCEL), QtGui.QDialogButtonBox.RejectRole) self.connect(self.ui.buttonbox, QtCore.SIGNAL('accepted()'), self, QtCore.SLOT('accept()')) self.connect(self.ui.buttonbox, QtCore.SIGNAL('rejected()'), self, QtCore.SLOT('reject()')) self.connect(self.ui.tags_add, QtCore.SIGNAL('clicked()'), self.add_tag) self.connect(self.ui.tags_edit, QtCore.SIGNAL('clicked()'), self.edit_tag) self.connect(self.ui.tags_delete, QtCore.SIGNAL('clicked()'), self.delete_tag) self.connect(self.ui.tags, QtCore.SIGNAL("itemActivated (QTreeWidgetItem*, int)"), self.edit_tag) self.ui.tags.setSortingEnabled(True) self.ui.tags.sortByColumn(0, QtCore.Qt.AscendingOrder) if self.config.setting['enable_ratings']: self.ui.rating.setMaximum(self.config.setting['rating_steps'] - 1) else: self.ui.ratingLabel.hide() self.ui.rating.hide() self.changed = set() self.files = files self.load() self.load_info() def accept(self): self.save() self.tagger.selected_metadata_changed.emit() QtGui.QDialog.accept(self) 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) def save(self): metadata = Metadata() for i in range(self.ui.tags.topLevelItemCount()): item = self.ui.tags.topLevelItem(i) name = unicode(item.data(0, QtCore.Qt.UserRole).toString()) if name in self.changed: value = unicode(item.text(1)) metadata.add(name, value) # Rate the different tracks if self.config.setting['enable_ratings']: rating = self.ui.rating.getRating() metadata['~rating'] = unicode(rating) tracks = set([ file.parent for file in self.files if isinstance(file.parent, Track) ]) ratings = {} for track in tracks: ratings[('recording', track.id)] = rating track.metadata['~rating'] = rating if self.config.setting['submit_ratings']: self.tagger.xmlws.submit_ratings(ratings, None) for file in self.files: for name in self.changed: try: del file.metadata[name] except KeyError: pass file.metadata.update(metadata) file.update() 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) 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) def delete_tag(self): items = self.ui.tags.selectedItems() for item in items: name = unicode(item.data(0, QtCore.Qt.UserRole).toString()) index = self.ui.tags.indexOfTopLevelItem(item) self.ui.tags.takeTopLevelItem(index) self.changed.add(name) def load_info(self): total = len(self.files) if total == 1: file = self.files[0] info = [] info.append((_('Filename:'), file.filename)) if '~format' in file.orig_metadata: info.append((_('Format:'), file.orig_metadata['~format'])) try: size = os.path.getsize(encode_filename(file.filename)) if size < 1024: size = '%d B' % size elif size < 1024 * 1024: size = '%0.1f kB' % (size / 1024.0) else: size = '%0.1f MB' % (size / 1024.0 / 1024.0) info.append((_('Size:'), size)) except: pass if file.orig_metadata.length: info.append( (_('Length:'), format_time(file.orig_metadata.length))) if '~#bitrate' in file.orig_metadata: info.append((_('Bitrate:'), '%d kbps' % file.orig_metadata['~#bitrate'])) if '~#sample_rate' in file.orig_metadata: info.append((_('Sample rate:'), '%d Hz' % file.orig_metadata['~#sample_rate'])) if '~#bits_per_sample' in file.orig_metadata: info.append((_('Bits per sample:'), str(file.orig_metadata['~#bits_per_sample']))) if '~#channels' in file.orig_metadata: ch = file.orig_metadata['~#channels'] if ch == 1: ch = _('Mono') elif ch == 2: ch = _('Stereo') else: ch = str(ch) info.append((_('Channels:'), ch)) text = '<br/>'.join(map(lambda i: '<b>%s</b><br/>%s' % i, info)) self.ui.info.setText(text) else: self.ui.info.setText( ungettext("%d file", "%d files", total) % total)
class TagEditor(QtGui.QDialog): def __init__(self, files, parent=None): QtGui.QDialog.__init__(self, parent) self.ui = Ui_TagEditorDialog() self.ui.setupUi(self) title = _("Details") + " - " total = len(files) if total == 1: title += files[0].base_filename else: title += ungettext("%d file", "%d files", total) % total self.setWindowTitle(title) self.ui.buttonbox.addButton(StandardButton(StandardButton.OK), QtGui.QDialogButtonBox.AcceptRole) self.ui.buttonbox.addButton(StandardButton(StandardButton.CANCEL), QtGui.QDialogButtonBox.RejectRole) self.connect(self.ui.buttonbox, QtCore.SIGNAL('accepted()'), self, QtCore.SLOT('accept()')) self.connect(self.ui.buttonbox, QtCore.SIGNAL('rejected()'), self, QtCore.SLOT('reject()')) self.connect(self.ui.tags_add, QtCore.SIGNAL('clicked()'), self.add_tag) self.connect(self.ui.tags_edit, QtCore.SIGNAL('clicked()'), self.edit_tag) self.connect(self.ui.tags_delete, QtCore.SIGNAL('clicked()'), self.delete_tag) self.connect(self.ui.tags, QtCore.SIGNAL("itemActivated (QTreeWidgetItem*, int)"), self.edit_tag) self.ui.tags.setSortingEnabled(True) self.ui.tags.sortByColumn(0, QtCore.Qt.AscendingOrder) if self.config.setting['enable_ratings']: self.ui.rating.setMaximum(self.config.setting['rating_steps'] - 1) else: self.ui.ratingLabel.hide() self.ui.rating.hide() self.changed = set() self.files = files self.load() self.load_info() def accept(self): self.save() QtGui.QDialog.accept(self) 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) def save(self): metadata = Metadata() for i in range(self.ui.tags.topLevelItemCount()): item = self.ui.tags.topLevelItem(i) name = unicode(item.data(0, QtCore.Qt.UserRole).toString()) if name in self.changed: value = unicode(item.text(1)) metadata.add(name, value) # Rate the different tracks if self.config.setting['enable_ratings']: rating = self.ui.rating.getRating() metadata['~rating'] = unicode(rating) tracks = set([file.parent for file in self.files if isinstance(file.parent, Track)]) ratings = {} for track in tracks: ratings[('recording', track.id)] = rating track.metadata['~rating'] = rating if self.config.setting['submit_ratings']: self.tagger.xmlws.submit_ratings(ratings, None) for file in self.files: for name in self.changed: try: del file.metadata[name] except KeyError: pass file.metadata.update(metadata) file.update() 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) 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) def delete_tag(self): items = self.ui.tags.selectedItems() for item in items: name = unicode(item.data(0, QtCore.Qt.UserRole).toString()) index = self.ui.tags.indexOfTopLevelItem(item) self.ui.tags.takeTopLevelItem(index) self.changed.add(name) def load_info(self): total = len(self.files) if total == 1: file = self.files[0] info = [] info.append((_('Filename:'), file.filename)) if '~format' in file.orig_metadata: info.append((_('Format:'), file.orig_metadata['~format'])) try: size = os.path.getsize(encode_filename(file.filename)) if size < 1024: size = '%d B' % size elif size < 1024 * 1024: size = '%0.1f kB' % (size / 1024.0) else: size = '%0.1f MB' % (size / 1024.0 / 1024.0) info.append((_('Size:'), size)) except: pass if file.orig_metadata.length: info.append((_('Length:'), format_time(file.orig_metadata.length))) if '~#bitrate' in file.orig_metadata: info.append((_('Bitrate:'), '%d kbps' % file.orig_metadata['~#bitrate'])) if '~#sample_rate' in file.orig_metadata: info.append((_('Sample rate:'), '%d Hz' % file.orig_metadata['~#sample_rate'])) if '~#bits_per_sample' in file.orig_metadata: info.append((_('Bits per sample:'), str(file.orig_metadata['~#bits_per_sample']))) if '~#channels' in file.orig_metadata: ch = file.orig_metadata['~#channels'] if ch == 1: ch = _('Mono') elif ch == 2: ch = _('Stereo') else: ch = str(ch) info.append((_('Channels:'), ch)) text = '<br/>'.join(map(lambda i: '<b>%s</b><br/>%s' % i, info)) self.ui.info.setText(text) else: self.ui.info.setText(ungettext("%d file", "%d files", total) % total)