From 55abbef7115deaf0b8686d8bc2418c509f37611d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Sun, 4 Mar 2007 09:58:14 +0100 Subject: [PATCH] Added file naming format tester. (#2448) --- picard/file.py | 57 ++++++++++++++++++++- picard/ui/options/naming.py | 38 ++++++++++++++ picard/ui/ui_options_naming.py | 56 +++++++++++++++++++-- ui/options_naming.ui | 91 ++++++++++++++++++++++++++++++++-- 4 files changed, 234 insertions(+), 8 deletions(-) diff --git a/picard/file.py b/picard/file.py index d6777f303..3c9917abc 100644 --- a/picard/file.py +++ b/picard/file.py @@ -21,13 +21,25 @@ import glob import os.path import shutil +import sys import traceback from PyQt4 import QtCore from picard.metadata import Metadata from picard.ui.item import Item +from picard.script import ScriptParser from picard.similarity import similarity2 -from picard.util import LockableObject, encode_filename, decode_filename, format_time, partial from picard.util.thread import spawn, proxy_to_main +from picard.util import ( + decode_filename, + encode_filename, + make_short_filename, + replace_win32_incompat, + replace_non_ascii, + sanitize_filename, + partial, + format_time, + LockableObject, + ) class File(LockableObject, Item): @@ -117,6 +129,49 @@ class File(LockableObject, Item): """Save the metadata.""" raise NotImplementedError + def make_filename(self, settings=None): + """Constructs file name based on metadata and file naming formats.""" + + if settings is None: + settings = self.config.setting + + filename = self.filename + metadata = Metadata() + metadata.copy(self.metadata) + + if settings["move_files"]: + new_dirname = settings["move_files_to"] + else: + new_dirname = os.path.dirname(filename) + old_dirname = new_dirname + new_filename, ext = os.path.splitext(os.path.basename(filename)) + + if settings["rename_files"]: + # replace incompatible characters + for name in metadata.keys(): + value = metadata[name] + if isinstance(value, basestring): + value = sanitize_filename(value) + if settings["windows_compatible_filenames"] or sys.platform == "win32": + value = replace_win32_incompat(value) + if settings["ascii_filenames"]: + value = replace_non_ascii(value) + metadata[name] = value + # expand the naming format + if metadata['compilation'] == '1': + format = settings['va_file_naming_format'] + else: + format = settings['file_naming_format'] + new_filename = ScriptParser().eval(format, metadata) + if not settings['move_files']: + new_filename = os.path.basename(new_filename) + new_filename = make_short_filename(new_dirname, new_filename) + # win32 compatibility fixes + if settings['windows_compatible_filenames'] or sys.platform == 'win32': + new_filename = new_filename.replace('./', '_/').replace('.\\', '_\\') + + return os.path.join(new_dirname, new_filename + ext) + def save_images(self): """Save the cover images to disk.""" if not "~artwork" in self.metadata: diff --git a/picard/ui/options/naming.py b/picard/ui/options/naming.py index 45845f0b2..0277a00d1 100644 --- a/picard/ui/options/naming.py +++ b/picard/ui/options/naming.py @@ -21,6 +21,7 @@ import os.path import sys from PyQt4 import QtCore, QtGui from picard.config import BoolOption, TextOption +from picard.file import File from picard.script import ScriptParser from picard.ui.options import OptionsPage, OptionsCheckError, register_options_page from picard.ui.ui_options_naming import Ui_NamingOptionsPage @@ -55,6 +56,7 @@ class NamingOptionsPage(OptionsPage): self.connect(self.ui.va_file_naming_format_default, QtCore.SIGNAL("clicked()"), self.set_va_file_naming_format_default) self.connect(self.ui.move_files_to_browse, QtCore.SIGNAL("clicked()"), self.move_files_to_browse) self.connect(self.ui.move_additional_files, QtCore.SIGNAL("clicked()"), self.update_move_additional_files) + self.connect(self.ui.test_button, QtCore.SIGNAL("clicked()"), self.test) def load(self): if sys.platform == "win32": @@ -118,5 +120,41 @@ class NamingOptionsPage(OptionsPage): def update_move_additional_files(self): self.ui.move_additional_files_pattern.setEnabled(self.ui.move_additional_files.isChecked()) + def test(self): + settings = { + 'windows_compatible_filenames': self.ui.windows_compatible_filenames.isChecked(), + 'ascii_filenames': self.ui.ascii_filenames.isChecked(), + 'rename_files': self.ui.rename_files.isChecked(), + 'move_files': self.ui.move_files.isChecked(), + 'file_naming_format': unicode(self.ui.file_naming_format.text()), + 'va_file_naming_format': unicode(self.ui.va_file_naming_format.text()), + 'move_files_to': os.path.normpath(unicode(self.ui.move_files_to.text())), + } + + file = File("ticket_to_ride.mp3") + file.metadata['album'] = 'Help!' + file.metadata['title'] = 'Ticket to Ride' + file.metadata['artist'] = 'The Beatles' + file.metadata['albumartist'] = 'The Beatles' + file.metadata['tracknumber'] = '7' + file.metadata['totaltracks'] = '14' + file.metadata['date'] = '1965-08-06' + file.metadata['~extension'] = 'mp3' + filename = file.make_filename(settings=settings) + self.ui.example_filename.setText(filename) + + file = File("track05.mp3") + file.metadata['album'] = 'Explosive Doowops, Volume 4' + file.metadata['title'] = 'Why? Oh Why?' + file.metadata['artist'] = 'The Fantasys' + file.metadata['albumartist'] = 'Various Artists' + file.metadata['tracknumber'] = '5' + file.metadata['totaltracks'] = '26' + file.metadata['date'] = '1999-02-03' + file.metadata['compilation'] = '1' + file.metadata['~extension'] = 'mp3' + filename = file.make_filename(settings=settings) + self.ui.example_va_filename.setText(filename) + register_options_page(NamingOptionsPage) diff --git a/picard/ui/ui_options_naming.py b/picard/ui/ui_options_naming.py index ece7ad2ff..b43f5cbaf 100644 --- a/picard/ui/ui_options_naming.py +++ b/picard/ui/ui_options_naming.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'ui/options_naming.ui' # -# Created: Sat Mar 3 19:09:31 2007 +# Created: Sun Mar 4 09:56:45 2007 # by: PyQt4 UI code generator 4.1 # # WARNING! All changes made in this file will be lost! @@ -13,7 +13,7 @@ from PyQt4 import QtCore, QtGui class Ui_NamingOptionsPage(object): def setupUi(self, NamingOptionsPage): NamingOptionsPage.setObjectName("NamingOptionsPage") - NamingOptionsPage.resize(QtCore.QSize(QtCore.QRect(0,0,348,397).size()).expandedTo(NamingOptionsPage.minimumSizeHint())) + NamingOptionsPage.resize(QtCore.QSize(QtCore.QRect(0,0,396,519).size()).expandedTo(NamingOptionsPage.minimumSizeHint())) self.vboxlayout = QtGui.QVBoxLayout(NamingOptionsPage) self.vboxlayout.setMargin(9) @@ -102,8 +102,52 @@ class Ui_NamingOptionsPage(object): self.vboxlayout1.addWidget(self.delete_empty_dirs) self.vboxlayout.addWidget(self.move_files) - spacerItem = QtGui.QSpacerItem(330,20,QtGui.QSizePolicy.Minimum,QtGui.QSizePolicy.Expanding) - self.vboxlayout.addItem(spacerItem) + self.groupBox = QtGui.QGroupBox(NamingOptionsPage) + self.groupBox.setObjectName("groupBox") + + self.gridlayout1 = QtGui.QGridLayout(self.groupBox) + self.gridlayout1.setMargin(9) + self.gridlayout1.setSpacing(2) + self.gridlayout1.setObjectName("gridlayout1") + + self.label = QtGui.QLabel(self.groupBox) + self.label.setObjectName("label") + self.gridlayout1.addWidget(self.label,0,0,1,2) + + self.example_va_filename = QtGui.QLabel(self.groupBox) + + font = QtGui.QFont(self.example_va_filename.font()) + font.setItalic(True) + self.example_va_filename.setFont(font) + self.example_va_filename.setTextFormat(QtCore.Qt.PlainText) + self.example_va_filename.setWordWrap(True) + self.example_va_filename.setObjectName("example_va_filename") + self.gridlayout1.addWidget(self.example_va_filename,3,0,1,2) + + self.label_5 = QtGui.QLabel(self.groupBox) + self.label_5.setObjectName("label_5") + self.gridlayout1.addWidget(self.label_5,2,0,1,2) + + self.example_filename = QtGui.QLabel(self.groupBox) + + font = QtGui.QFont(self.example_filename.font()) + font.setItalic(True) + self.example_filename.setFont(font) + self.example_filename.setTextFormat(QtCore.Qt.PlainText) + self.example_filename.setWordWrap(True) + self.example_filename.setObjectName("example_filename") + self.gridlayout1.addWidget(self.example_filename,1,0,1,2) + + spacerItem = QtGui.QSpacerItem(301,20,QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Minimum) + self.gridlayout1.addItem(spacerItem,4,1,1,1) + + self.test_button = QtGui.QPushButton(self.groupBox) + self.test_button.setObjectName("test_button") + self.gridlayout1.addWidget(self.test_button,4,0,1,1) + self.vboxlayout.addWidget(self.groupBox) + + spacerItem1 = QtGui.QSpacerItem(311,20,QtGui.QSizePolicy.Minimum,QtGui.QSizePolicy.Expanding) + self.vboxlayout.addItem(spacerItem1) self.label_4.setBuddy(self.va_file_naming_format) self.label_3.setBuddy(self.file_naming_format) self.label_2.setBuddy(self.move_files_to_browse) @@ -131,4 +175,8 @@ class Ui_NamingOptionsPage(object): self.move_files_to_browse.setText(_(u"Browse...")) self.move_additional_files.setText(_(u"Move additional files:")) self.delete_empty_dirs.setText(_(u"Delete empty directories")) + self.groupBox.setTitle(_(u"Example")) + self.label.setText(_(u"File name:")) + self.label_5.setText(_(u"Multiple artist file name:")) + self.test_button.setText(_(u"&Test")) diff --git a/ui/options_naming.ui b/ui/options_naming.ui index 0a9140a5a..cdf4aa27d 100644 --- a/ui/options_naming.ui +++ b/ui/options_naming.ui @@ -5,8 +5,8 @@ 0 0 - 348 - 397 + 396 + 519 @@ -153,6 +153,91 @@ + + + + Example + + + + 9 + + + 2 + + + + + File name: + + + + + + + + true + + + + + + + Qt::PlainText + + + true + + + + + + + Multiple artist file name: + + + + + + + + true + + + + + + + Qt::PlainText + + + true + + + + + + + Qt::Horizontal + + + + 301 + 20 + + + + + + + + &Test + + + + + + @@ -160,7 +245,7 @@ - 330 + 311 20