Skip to content

Commit

Permalink
PICARD-187: Support for manually removing cover art
Browse files Browse the repository at this point in the history
PICARD-187: Support for manually removing cover art

finishing PICARD-187
  • Loading branch information
ShubhamBhut committed Mar 29, 2024
1 parent 8af19d4 commit 7ebc65d
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 1 deletion.
5 changes: 5 additions & 0 deletions picard/formats/apev2.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,11 @@ def _remove_deleted_tags(self, metadata, tags):
if real_name in tags:
del tags[real_name]

if self.metadata.images._deleted:
for tag in tags:
if tag.lower().startswith('cover art'):
del tags[tag]

def _get_tag_name(self, name):
if name in self.__casemap:
return self.__casemap[name]
Expand Down
2 changes: 2 additions & 0 deletions picard/formats/asf.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ def _remove_deleted_tags(self, metadata, tags):
real_name = self._get_tag_name(tag)
if real_name and real_name in tags:
del tags[real_name]
if self.metadata.images._deleted:
del tags['WM/Picture']

@classmethod
def supports_tag(cls, name):
Expand Down
5 changes: 5 additions & 0 deletions picard/formats/id3.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,11 @@ def _remove_deleted_tags(self, metadata, tags):
except KeyError:
pass

if self.metadata.images._deleted:
for key, frame in list(tags.items()):
if frame.FrameID == 'APIC':
del tags[key]

@classmethod
def supports_tag(cls, name):
return ((name and not name.startswith('~') and name not in UNSUPPORTED_TAGS)
Expand Down
3 changes: 3 additions & 0 deletions picard/formats/mp4.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@ def _remove_deleted_tags(self, metadata, tags):
if tag not in {'totaltracks', 'totaldiscs'}:
del tags[real_name]

if self.metadata.images._deleted:
del tags['covr']

@classmethod
def supports_tag(cls, name):
return (name
Expand Down
13 changes: 12 additions & 1 deletion picard/formats/vorbis.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ def _save(self, filename, metadata):
base64.b64encode(picture.write()).decode('ascii'))

file.tags.update(tags)

self._clear_cover_art(file)
self._remove_deleted_tags(metadata, file.tags)

kwargs = {}
Expand Down Expand Up @@ -358,6 +358,17 @@ def _remove_deleted_tags(self, metadata, tags):
del tags[tag]
del tags[real_name]

def _clear_cover_art(self, file):
is_flac = self._File == mutagen.flac.FLAC

if self.metadata.images._deleted:
if is_flac:
file.clear_pictures()
else:
for tag in file:
if tag.lower().startswith('metadata_block_picture'):
del file.tags[tag]

def _get_tag_name(self, name):
if name == '~rating':
config = get_config()
Expand Down
48 changes: 48 additions & 0 deletions picard/ui/coverartbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,11 @@ def open_release_page(self):
lookup.album_lookup(self.release)


def image_delete(obj, image):
obj.metadata.images.strip_selected_image(image)
obj.metadata_images_changed.emit()


def set_image_replace(obj, coverartimage):
obj.metadata.images.strip_front_images()
obj.metadata.images.append(coverartimage)
Expand Down Expand Up @@ -545,6 +550,43 @@ def load_remote_image(self, url, data):
log.warning("Can't load image: %s", e)
return

def delete_cover_art(self):
if not self.item or not self.item.metadata.images:
return

cover_art_list = [image.source or _("Unnamed Cover Art") for image in self.item.metadata.images]

selected_item, ok_pressed = QtWidgets.QInputDialog.getItem(self, _("Delete Cover Art"),
_("Select the cover art image to delete:"),
cover_art_list, 0, False)
if ok_pressed:
selected_image_index = cover_art_list.index(selected_item)
selected_image = self.item.metadata.images[selected_image_index]
if not isinstance(self.item, File):
self.delete_cover_art_for_item(self.item, selected_image)
for file in self.get_files_to_process():
self.delete_cover_art_for_item(file, selected_image)
self.update()
self.item.update()

def get_files_to_process(self):
if isinstance(self.item, (Album, FileListItem)):
return self.item.iterfiles()
elif isinstance(self.item, File):
return [self.item]

def delete_cover_art_for_item(self, item, selected_image):
metadata = item.metadata
if not metadata or not metadata.images:
return

try:
image_delete(item, selected_image)
self.set_item(item)
self.cover_art.set_metadata(metadata)
except ValueError as e:
QtWidgets.QMessageBox.warning(self, _("Error"), str(e))

def _try_load_remote_image(self, url, data):
coverartimage = CoverArtImage(
url=url.toString(),
Expand Down Expand Up @@ -634,6 +676,12 @@ def contextMenuEvent(self, event):
show_more_details_action.triggered.connect(self.show_cover_art_info)
menu.addAction(show_more_details_action)

if self.item and self.item.can_show_coverart:
name = _("Delete cover art")
delete_cover_art_action = QtGui.QAction(name, self.parent)
delete_cover_art_action.triggered.connect(self.delete_cover_art)
menu.addAction(delete_cover_art_action)

if self.orig_cover_art.isVisible():
name = _("Keep original cover art")
use_orig_value_action = QtGui.QAction(name, self.parent)
Expand Down
8 changes: 8 additions & 0 deletions picard/util/imagelist.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def __init__(self, iterable=()):
self._images = list(iterable)
self._hash_dict = {}
self._changed = True
self._deleted = False

def __len__(self):
return len(self._images)
Expand All @@ -50,6 +51,7 @@ def __delitem__(self, index):

def insert(self, index, value):
self._changed = True
self._deleted = False
return self._images.insert(index, value)

def __repr__(self):
Expand Down Expand Up @@ -95,6 +97,12 @@ def strip_front_images(self):
self._images = [image for image in self._images if not image.is_front_image()]
self._changed = True

def strip_selected_image(self, image):
if image in self._images:
self._images.remove(image)
if len(self._images) == 0:
self._deleted = True

def hash_dict(self):
if self._changed:
self._hash_dict = {img.datahash.hash(): img for img in self._images}
Expand Down

0 comments on commit 7ebc65d

Please sign in to comment.