mirror of
				https://github.com/kovidgoyal/calibre.git
				synced 2025-11-03 19:17:02 -05:00 
			
		
		
		
	Transliterate filenames before saving to device
This commit is contained in:
		
							parent
							
								
									47da65b4c9
								
							
						
					
					
						commit
						1c3a870814
					
				@ -10,7 +10,7 @@ from PyQt4.QtGui import QPixmap, QColor, QPainter, QMenu, QIcon, QMessageBox, \
 | 
				
			|||||||
from PyQt4.QtSvg import QSvgRenderer
 | 
					from PyQt4.QtSvg import QSvgRenderer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from calibre import __version__, __appname__, islinux, sanitize_file_name, \
 | 
					from calibre import __version__, __appname__, islinux, sanitize_file_name, \
 | 
				
			||||||
                    Settings, iswindows, isosx
 | 
					                    Settings, iswindows, isosx, preferred_encoding
 | 
				
			||||||
from calibre.ptempfile import PersistentTemporaryFile
 | 
					from calibre.ptempfile import PersistentTemporaryFile
 | 
				
			||||||
from calibre.ebooks.metadata.meta import get_metadata, get_filename_pat, set_filename_pat
 | 
					from calibre.ebooks.metadata.meta import get_metadata, get_filename_pat, set_filename_pat
 | 
				
			||||||
from calibre.devices.errors import FreeSpaceError
 | 
					from calibre.devices.errors import FreeSpaceError
 | 
				
			||||||
@ -45,6 +45,7 @@ from calibre.ebooks.metadata import MetaInformation
 | 
				
			|||||||
from calibre.ebooks import BOOK_EXTENSIONS
 | 
					from calibre.ebooks import BOOK_EXTENSIONS
 | 
				
			||||||
from calibre.ebooks.lrf import preferred_source_formats as LRF_PREFERRED_SOURCE_FORMATS
 | 
					from calibre.ebooks.lrf import preferred_source_formats as LRF_PREFERRED_SOURCE_FORMATS
 | 
				
			||||||
from calibre.parallel import JobKilled
 | 
					from calibre.parallel import JobKilled
 | 
				
			||||||
 | 
					from calibre.utils.filenames import ascii_filename
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Main(MainWindow, Ui_MainWindow):
 | 
					class Main(MainWindow, Ui_MainWindow):
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -661,10 +662,9 @@ class Main(MainWindow, Ui_MainWindow):
 | 
				
			|||||||
                if not a:
 | 
					                if not a:
 | 
				
			||||||
                    a = 'Unknown'
 | 
					                    a = 'Unknown'
 | 
				
			||||||
                prefix = sanitize_file_name(t+' - '+a)
 | 
					                prefix = sanitize_file_name(t+' - '+a)
 | 
				
			||||||
                if isinstance(prefix, unicode):
 | 
					                if not isinstance(prefix, unicode):
 | 
				
			||||||
                    prefix = prefix.encode('ascii', 'ignore')
 | 
					                    prefix = prefix.decode(preferred_encoding, 'replace')
 | 
				
			||||||
                else:
 | 
					                prefix = ascii_filename(prefix)
 | 
				
			||||||
                    prefix = prefix.decode('ascii', 'ignore').encode('ascii', 'ignore')
 | 
					 | 
				
			||||||
                names.append('%s_%d%s'%(prefix, id, os.path.splitext(f)[1]))
 | 
					                names.append('%s_%d%s'%(prefix, id, os.path.splitext(f)[1]))
 | 
				
			||||||
        remove = [self.library_view.model().id(r) for r in rows] if delete_from_library else []
 | 
					        remove = [self.library_view.model().id(r) for r in rows] if delete_from_library else []
 | 
				
			||||||
        self.upload_books(gf, names, good, on_card, memory=(_files, remove))
 | 
					        self.upload_books(gf, names, good, on_card, memory=(_files, remove))
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import StringIO, traceback, sys
 | 
					import StringIO, traceback, sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from PyQt4.Qt import QMainWindow, QString, Qt, QFont
 | 
					from PyQt4.Qt import QMainWindow, QString, Qt, QFont, QCoreApplication, SIGNAL
 | 
				
			||||||
from calibre.gui2.dialogs.conversion_error import ConversionErrorDialog
 | 
					from calibre.gui2.dialogs.conversion_error import ConversionErrorDialog
 | 
				
			||||||
from calibre import OptionParser
 | 
					from calibre import OptionParser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -36,11 +36,17 @@ class MainWindow(QMainWindow):
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    def __init__(self, opts, parent=None):
 | 
					    def __init__(self, opts, parent=None):
 | 
				
			||||||
        QMainWindow.__init__(self, parent)
 | 
					        QMainWindow.__init__(self, parent)
 | 
				
			||||||
 | 
					        app = QCoreApplication.instance()
 | 
				
			||||||
 | 
					        if app is not None:
 | 
				
			||||||
 | 
					            self.connect(app, SIGNAL('unixSignal(int)'), self.unix_signal)
 | 
				
			||||||
        if getattr(opts, 'redirect', False):
 | 
					        if getattr(opts, 'redirect', False):
 | 
				
			||||||
            self.__console_redirect = DebugWindow(self)
 | 
					            self.__console_redirect = DebugWindow(self)
 | 
				
			||||||
            sys.stdout = sys.stderr = self.__console_redirect
 | 
					            sys.stdout = sys.stderr = self.__console_redirect
 | 
				
			||||||
            self.__console_redirect.show()
 | 
					            self.__console_redirect.show()
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    def unix_signal(self, signal):
 | 
				
			||||||
 | 
					        print 'Received signal:', repr(signal)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    def unhandled_exception(self, type, value, tb):
 | 
					    def unhandled_exception(self, type, value, tb):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            sio = StringIO.StringIO()
 | 
					            sio = StringIO.StringIO()
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										88
									
								
								src/calibre/utils/filenames.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/calibre/utils/filenames.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					'''
 | 
				
			||||||
 | 
					Make strings safe for use as ASCII filenames, while trying to preserve as much 
 | 
				
			||||||
 | 
					meaning as possible.
 | 
				
			||||||
 | 
					'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import re, string
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					MAP = {
 | 
				
			||||||
 | 
					        u"‘" : u"'",
 | 
				
			||||||
 | 
					        u"’" : u"'",
 | 
				
			||||||
 | 
					        u"«" : u'"',
 | 
				
			||||||
 | 
					        u"»" : u'"',
 | 
				
			||||||
 | 
					        u"…" : u"...",
 | 
				
			||||||
 | 
					        u"№" : u"#",
 | 
				
			||||||
 | 
					        u"Щ" : u"Sch",
 | 
				
			||||||
 | 
					        u"Щ" : u"SCH",
 | 
				
			||||||
 | 
					        u"Ё" : u"Yo",
 | 
				
			||||||
 | 
					        u"Ё" : u"YO",
 | 
				
			||||||
 | 
					        u"Ж" : u"Zh",
 | 
				
			||||||
 | 
					        u"Ж" : u"ZH",
 | 
				
			||||||
 | 
					        u"Ц" : u"Ts",
 | 
				
			||||||
 | 
					        u"Ц" : u"TS",
 | 
				
			||||||
 | 
					        u"Ч" : u"Ch",
 | 
				
			||||||
 | 
					        u"Ч" : u"CH",
 | 
				
			||||||
 | 
					        u"Ш" : u"Sh",
 | 
				
			||||||
 | 
					        u"Ш" : u"SH",
 | 
				
			||||||
 | 
					        u"Ы" : u"Yi",
 | 
				
			||||||
 | 
					        u"Ы" : u"YI",
 | 
				
			||||||
 | 
					        u"Ю" : u"Yu",
 | 
				
			||||||
 | 
					        u"Ю" : u"YU",
 | 
				
			||||||
 | 
					        u"Я" : u"Ya",
 | 
				
			||||||
 | 
					        u"Я" : u"YA",
 | 
				
			||||||
 | 
					        u"Б" : u"B",
 | 
				
			||||||
 | 
					        u"Г" : u"G",
 | 
				
			||||||
 | 
					        u"Д" : u"D",
 | 
				
			||||||
 | 
					        u"И" : u"I",
 | 
				
			||||||
 | 
					        u"Й" : u"J",
 | 
				
			||||||
 | 
					        u"К" : u"K",
 | 
				
			||||||
 | 
					        u"Л" : u"L",
 | 
				
			||||||
 | 
					        u"П" : u"P",
 | 
				
			||||||
 | 
					        u"Ф" : u"F",
 | 
				
			||||||
 | 
					        u"Э" : u"E",
 | 
				
			||||||
 | 
					        u"Ъ" : u"`",
 | 
				
			||||||
 | 
					        u"Ь" : u"'",
 | 
				
			||||||
 | 
					        u"щ" : u"sch",
 | 
				
			||||||
 | 
					        u"ё" : u"yo",
 | 
				
			||||||
 | 
					        u"ж" : u"zh",
 | 
				
			||||||
 | 
					        u"ц" : u"ts",
 | 
				
			||||||
 | 
					        u"ч" : u"ch",
 | 
				
			||||||
 | 
					        u"ш" : u"sh",
 | 
				
			||||||
 | 
					        u"ы" : u"yi",
 | 
				
			||||||
 | 
					        u"ю" : u"yu",
 | 
				
			||||||
 | 
					        u"я" : u"ya",
 | 
				
			||||||
 | 
					        u"б" : u"b",
 | 
				
			||||||
 | 
					        u"в" : u"v",
 | 
				
			||||||
 | 
					        u"г" : u"g",
 | 
				
			||||||
 | 
					        u"д" : u"d",
 | 
				
			||||||
 | 
					        u"з" : u"z",
 | 
				
			||||||
 | 
					        u"и" : u"i",
 | 
				
			||||||
 | 
					        u"й" : u"j",
 | 
				
			||||||
 | 
					        u"к" : u"k",
 | 
				
			||||||
 | 
					        u"л" : u"l",
 | 
				
			||||||
 | 
					        u"м" : u"m",
 | 
				
			||||||
 | 
					        u"н" : u"n",
 | 
				
			||||||
 | 
					        u"о" : u"o",
 | 
				
			||||||
 | 
					        u"п" : u"p",
 | 
				
			||||||
 | 
					        u"т" : u"t",
 | 
				
			||||||
 | 
					        u"ф" : u"f",
 | 
				
			||||||
 | 
					        u"э" : u"e",
 | 
				
			||||||
 | 
					        u"ъ" : u"`",
 | 
				
			||||||
 | 
					        u"ь" : u"'",
 | 
				
			||||||
 | 
					        }  #: Translation table
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for c in string.whitespace:
 | 
				
			||||||
 | 
					    MAP[c] = ' '
 | 
				
			||||||
 | 
					PAT = re.compile('['+u''.join(MAP.keys())+']')
 | 
				
			||||||
 | 
					print repr('['+u''.join(MAP.keys())+']')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def ascii_filename(orig):
 | 
				
			||||||
 | 
					    orig =  PAT.sub(lambda m:MAP[m.group()], orig)
 | 
				
			||||||
 | 
					    buf = []
 | 
				
			||||||
 | 
					    for i in range(len(orig)):
 | 
				
			||||||
 | 
					        val = ord(orig[i])
 | 
				
			||||||
 | 
					        buf.append('_' if val < 33 or val > 126 else orig[i])
 | 
				
			||||||
 | 
					    return (''.join(buf)).encode('ascii')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user