Skip to content

Commit

Permalink
Add Local Files cover art provider and its options
Browse files Browse the repository at this point in the history
  • Loading branch information
zas committed Jul 2, 2015
1 parent ae4379a commit 0ca1e9b
Show file tree
Hide file tree
Showing 4 changed files with 251 additions and 0 deletions.
2 changes: 2 additions & 0 deletions picard/coverart/providers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,14 @@ def match_url_relations(self, relation_types, func):
self.error(traceback.format_exc())


from picard.coverart.providers.local import CoverArtProviderLocal
from picard.coverart.providers.caa import CoverArtProviderCaa
from picard.coverart.providers.amazon import CoverArtProviderAmazon
from picard.coverart.providers.whitelist import CoverArtProviderWhitelist
from picard.coverart.providers.caa_release_group import CoverArtProviderCaaReleaseGroup

__providers = [
CoverArtProviderLocal,
CoverArtProviderCaa,
CoverArtProviderAmazon,
CoverArtProviderWhitelist,
Expand Down
99 changes: 99 additions & 0 deletions picard/coverart/providers/local.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# -*- coding: utf-8 -*-
#
# Picard, the next-generation MusicBrainz tagger
# Copyright (C) 2015 Laurent Monin
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

import os
import re
import traceback
from PyQt4 import QtCore, QtGui
from picard import config, log
from picard.coverart.providers import CoverArtProvider, ProviderOptions
from picard.coverart.image import CoverArtImageFromFile
from picard.coverart.utils import CAA_TYPES
from picard.ui.ui_provider_options_local import Ui_LocalOptions


class ProviderOptionsLocal(ProviderOptions):
"""
Options for Local Files cover art provider
"""

_DEFAULT_LOCAL_COVER_ART_REGEX = '^(?:cover|folder|albumart)(.*)\.(?:jpe?g|png|gif|tiff?)$'

options = [
config.TextOption("setting", "local_cover_regex",
_DEFAULT_LOCAL_COVER_ART_REGEX),
]

_options_ui = Ui_LocalOptions

def __init__(self, options_page, parent=None):
super(ProviderOptionsLocal, self).__init__(options_page, parent)
self.options_page.init_regex_checker(self.ui.local_cover_regex_edit, self.ui.local_cover_regex_error)
self.ui.local_cover_regex_default.clicked.connect(self.set_local_cover_regex_default)

def set_local_cover_regex_default(self):
self.ui.local_cover_regex_edit.setText(self._DEFAULT_LOCAL_COVER_ART_REGEX)

def load(self):
self.ui.local_cover_regex_edit.setText(config.setting["local_cover_regex"])

def save(self):
config.setting["local_cover_regex"] = unicode(self.ui.local_cover_regex_edit.text())


class CoverArtProviderLocal(CoverArtProvider):

"""Get cover art from local files"""

NAME = "Local"
TITLE = N_(u"Local Files")
OPTIONS = ProviderOptionsLocal

_types_split_re = re.compile('[^a-z0-9]', re.IGNORECASE)
_known_types = set([t['name'] for t in CAA_TYPES])

def enabled(self):
enabled = CoverArtProvider.enabled(self)
return enabled and not self.coverart.front_image_found

def queue_images(self):
_match_re = re.compile(config.setting['local_cover_regex'], re.IGNORECASE)
dirs_done = {}

for file in self.album.iterfiles():
current_dir = os.path.dirname(file.filename)
if current_dir in dirs_done:
continue
dirs_done[current_dir] = True
for root, dirs, files in os.walk(current_dir):
for filename in files:
m = _match_re.search(filename)
if not m:
continue
filepath = os.path.join(current_dir, root, filename)
if os.path.exists(filepath):
types = self.get_types(m.group(1)) or [ u'front' ]
self.queue_put(CoverArtImageFromFile(filepath,
types=types,
support_types=True))
return CoverArtProvider.FINISHED

def get_types(self, string):
found = set([x.lower() for x in self._types_split_re.split(string) if x])
return list(found.intersection(self._known_types))
67 changes: 67 additions & 0 deletions picard/ui/ui_provider_options_local.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-

# Automatically generated - don't edit.
# Use `python setup.py build_ui` to update it.

from PyQt4 import QtCore, QtGui

try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s

try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)

class Ui_LocalOptions(object):
def setupUi(self, LocalOptions):
LocalOptions.setObjectName(_fromUtf8("LocalOptions"))
LocalOptions.resize(472, 215)
self.verticalLayout = QtGui.QVBoxLayout(LocalOptions)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.local_cover_regex_label = QtGui.QLabel(LocalOptions)
self.local_cover_regex_label.setObjectName(_fromUtf8("local_cover_regex_label"))
self.verticalLayout.addWidget(self.local_cover_regex_label)
self.local_cover_regex_edit = QtGui.QLineEdit(LocalOptions)
self.local_cover_regex_edit.setObjectName(_fromUtf8("local_cover_regex_edit"))
self.verticalLayout.addWidget(self.local_cover_regex_edit)
self.horizontalLayout_2 = QtGui.QHBoxLayout()
self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
self.local_cover_regex_error = QtGui.QLabel(LocalOptions)
self.local_cover_regex_error.setText(_fromUtf8(""))
self.local_cover_regex_error.setObjectName(_fromUtf8("local_cover_regex_error"))
self.horizontalLayout_2.addWidget(self.local_cover_regex_error)
self.local_cover_regex_default = QtGui.QPushButton(LocalOptions)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.local_cover_regex_default.sizePolicy().hasHeightForWidth())
self.local_cover_regex_default.setSizePolicy(sizePolicy)
self.local_cover_regex_default.setObjectName(_fromUtf8("local_cover_regex_default"))
self.horizontalLayout_2.addWidget(self.local_cover_regex_default)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.note = QtGui.QLabel(LocalOptions)
font = QtGui.QFont()
font.setItalic(True)
self.note.setFont(font)
self.note.setWordWrap(True)
self.note.setObjectName(_fromUtf8("note"))
self.verticalLayout.addWidget(self.note)
spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)

self.retranslateUi(LocalOptions)
QtCore.QMetaObject.connectSlotsByName(LocalOptions)

def retranslateUi(self, LocalOptions):
LocalOptions.setWindowTitle(_("Form"))
self.local_cover_regex_label.setText(_("Local cover art files match the following regular expression:"))
self.local_cover_regex_default.setText(_("Default"))
self.note.setText(_("First group in the regular expression, if any, will be used as type, ie. cover-back-spine.jpg will be set as types Back + Spine. If no type is found, it will default to Front type."))

83 changes: 83 additions & 0 deletions ui/provider_options_local.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LocalOptions</class>
<widget class="QWidget" name="LocalOptions">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>472</width>
<height>215</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="local_cover_regex_label">
<property name="text">
<string>Local cover art files match the following regular expression:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="local_cover_regex_edit"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="local_cover_regex_error">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="local_cover_regex_default">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Default</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="note">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>First group in the regular expression, if any, will be used as type, ie. cover-back-spine.jpg will be set as types Back + Spine. If no type is found, it will default to Front type.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

0 comments on commit 0ca1e9b

Please sign in to comment.