Add Local Files cover art provider and its options

This commit is contained in:
Laurent Monin
2015-07-03 17:40:03 +02:00
parent 10b375ccb9
commit 222e2bcae9
5 changed files with 252 additions and 0 deletions

View File

@@ -164,12 +164,14 @@ class CoverArtProvider(object):
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,

View File

@@ -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, parent=None):
super(ProviderOptionsLocal, self).__init__(parent)
self.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))

View File

@@ -47,6 +47,7 @@ class CoverOptionsPage(OptionsPage):
('Amazon', True),
('Whitelist', True),
('CaaReleaseGroup', False),
('Local', False),
]),
]

View File

@@ -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."))

View File

@@ -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>