From 8713db208e5f62d370123bbd2b15f7ceda6402d7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 4 Jun 2011 14:00:28 -0600 Subject: [PATCH 1/5] Add an action to remove all formats to the remove books button --- src/calibre/gui2/actions/delete.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/calibre/gui2/actions/delete.py b/src/calibre/gui2/actions/delete.py index 43465512e0..bef456033b 100644 --- a/src/calibre/gui2/actions/delete.py +++ b/src/calibre/gui2/actions/delete.py @@ -94,6 +94,9 @@ class DeleteAction(InterfaceAction): self.delete_menu.addAction( _('Remove all formats from selected books, except...'), self.delete_all_but_selected_formats) + self.delete_menu.addAction( + _('Remove all formats from selected books'), + self.delete_all_formats) self.delete_menu.addAction( _('Remove covers from selected books'), self.delete_covers) self.delete_menu.addSeparator() @@ -174,6 +177,28 @@ class DeleteAction(InterfaceAction): if ids: self.gui.tags_view.recount() + def delete_all_formats(self, *args): + ids = self._get_selected_ids() + if not ids: + return + if not confirm('

'+_('All formats for the selected books will ' + 'be deleted from your library.
' + 'The book metadata will be kept. Are you sure?') + +'

', 'delete_all_formats', self.gui): + return + db = self.gui.library_view.model().db + for id in ids: + fmts = db.formats(id, index_is_id=True, verify_formats=False) + if fmts: + for fmt in fmts.split(','): + self.gui.library_view.model().db.remove_format(id, fmt, + index_is_id=True, notify=False) + self.gui.library_view.model().refresh_ids(ids) + self.gui.library_view.model().current_changed(self.gui.library_view.currentIndex(), + self.gui.library_view.currentIndex()) + if ids: + self.gui.tags_view.recount() + def remove_matching_books_from_device(self, *args): if not self.gui.device_manager.is_device_connected: d = error_dialog(self.gui, _('Cannot delete books'), From c6733399f796c3a5f10d8ca5f7bff44f25d521f9 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 4 Jun 2011 14:14:20 -0600 Subject: [PATCH 2/5] Fix Newsweek --- recipes/newsweek.recipe | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/recipes/newsweek.recipe b/recipes/newsweek.recipe index a31706e257..0cae4275b0 100644 --- a/recipes/newsweek.recipe +++ b/recipes/newsweek.recipe @@ -69,7 +69,11 @@ class Newsweek(BasicNewsRecipe): for section, shref in self.newsweek_sections(): self.log('Processing section', section, shref) articles = [] - soups = [self.index_to_soup(shref)] + try: + soups = [self.index_to_soup(shref)] + except: + self.log.warn('Section %s not found, skipping'%section) + continue na = soups[0].find('a', rel='next') if na: soups.append(self.index_to_soup(self.BASE_URL+na['href'])) From 5e4e45ec92523f4e7b145d6f845160743600efbc Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 4 Jun 2011 19:26:15 -0600 Subject: [PATCH 3/5] Remove unneccessary import of PyQt --- src/calibre/utils/config_base.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/calibre/utils/config_base.py b/src/calibre/utils/config_base.py index 7660370353..ae2806176b 100644 --- a/src/calibre/utils/config_base.py +++ b/src/calibre/utils/config_base.py @@ -223,8 +223,7 @@ class OptionSet(object): if val is val is True or val is False or val is None or \ isinstance(val, (int, float, long, basestring)): return repr(val) - from PyQt4.QtCore import QString - if isinstance(val, QString): + if val.__class__.__name__ == 'QString' or hasattr(val, 'isNull'): return repr(unicode(val)) pickle = cPickle.dumps(val, -1) return 'cPickle.loads(%s)'%repr(pickle) From 3fb57e64f29eabf875fe8b6343df04d7817d75f7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 4 Jun 2011 19:55:19 -0600 Subject: [PATCH 4/5] ... --- src/calibre/utils/config_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/utils/config_base.py b/src/calibre/utils/config_base.py index ae2806176b..345caae384 100644 --- a/src/calibre/utils/config_base.py +++ b/src/calibre/utils/config_base.py @@ -223,7 +223,7 @@ class OptionSet(object): if val is val is True or val is False or val is None or \ isinstance(val, (int, float, long, basestring)): return repr(val) - if val.__class__.__name__ == 'QString' or hasattr(val, 'isNull'): + if val.__class__.__name__ == 'QString': return repr(unicode(val)) pickle = cPickle.dumps(val, -1) return 'cPickle.loads(%s)'%repr(pickle) From 4a8d33a4552535d88c5d4456287bbec32be73599 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 4 Jun 2011 22:25:46 -0600 Subject: [PATCH 5/5] Store translations compressed in the calibre install dir. Also remove the broken librarything executable. --- setup/translations.py | 17 ++++++++--- src/calibre/linux.py | 1 - src/calibre/translations/dynamic.py | 18 +++++++----- src/calibre/utils/localization.py | 45 ++++++++++++++++------------- 4 files changed, 49 insertions(+), 32 deletions(-) diff --git a/setup/translations.py b/setup/translations.py index 1f026555ec..3a33b7bcc4 100644 --- a/setup/translations.py +++ b/setup/translations.py @@ -85,7 +85,7 @@ class Translations(POT): def mo_file(self, po_file): locale = os.path.splitext(os.path.basename(po_file))[0] - return locale, os.path.join(self.DEST, locale, 'LC_MESSAGES', 'messages.mo') + return locale, os.path.join(self.DEST, locale, 'messages.mo') def run(self, opts): @@ -94,9 +94,8 @@ class Translations(POT): base = os.path.dirname(dest) if not os.path.exists(base): os.makedirs(base) - if self.newer(dest, f): - self.info('\tCompiling translations for', locale) - subprocess.check_call(['msgfmt', '-o', dest, f]) + self.info('\tCompiling translations for', locale) + subprocess.check_call(['msgfmt', '-o', dest, f]) if locale in ('en_GB', 'nds', 'te', 'yi'): continue pycountry = self.j(sysconfig.get_python_lib(), 'pycountry', @@ -123,6 +122,16 @@ class Translations(POT): shutil.copy2(f, dest) self.write_stats() + self.freeze_locales() + + def freeze_locales(self): + zf = self.DEST + '.zip' + from calibre import CurrentDir + from calibre.utils.zipfile import ZipFile, ZIP_DEFLATED + with ZipFile(zf, 'w', ZIP_DEFLATED) as zf: + with CurrentDir(self.DEST): + zf.add_dir('.') + shutil.rmtree(self.DEST) @property def stats(self): diff --git a/src/calibre/linux.py b/src/calibre/linux.py index 9e58d4f638..1686f66b22 100644 --- a/src/calibre/linux.py +++ b/src/calibre/linux.py @@ -23,7 +23,6 @@ entry_points = { 'calibre-server = calibre.library.server.main:main', 'lrf2lrs = calibre.ebooks.lrf.lrfparser:main', 'lrs2lrf = calibre.ebooks.lrf.lrs.convert_from:main', - 'librarything = calibre.ebooks.metadata.library_thing:main', 'calibre-debug = calibre.debug:main', 'calibredb = calibre.library.cli:main', 'calibre-parallel = calibre.utils.ipc.worker:main', diff --git a/src/calibre/translations/dynamic.py b/src/calibre/translations/dynamic.py index c1f368ff5a..4d65475ac0 100644 --- a/src/calibre/translations/dynamic.py +++ b/src/calibre/translations/dynamic.py @@ -5,10 +5,9 @@ Dynamic language lookup of translations for user-visible strings. __license__ = 'GPL v3' __copyright__ = '2008, Marshall T. Vandegrift ' -import os - +import cStringIO from gettext import GNUTranslations -from calibre.utils.localization import get_lc_messages_path +from calibre.utils.localization import get_lc_messages_path, ZipFile __all__ = ['translate'] @@ -21,10 +20,15 @@ def translate(lang, text): else: mpath = get_lc_messages_path(lang) if mpath is not None: - p = os.path.join(mpath, 'messages.mo') - if os.path.exists(p): - trans = GNUTranslations(open(p, 'rb')) - _CACHE[lang] = trans + with ZipFile(P('localization/locales.zip', + allow_user_override=False), 'r') as zf: + try: + buf = cStringIO.StringIO(zf.read(mpath + '/messages.mo')) + except: + pass + else: + trans = GNUTranslations(buf) + _CACHE[lang] = trans if trans is None: return getattr(__builtins__, '_', lambda x: x)(text) return trans.ugettext(text) diff --git a/src/calibre/utils/localization.py b/src/calibre/utils/localization.py index 92e6ea9b5e..a8285ad5a2 100644 --- a/src/calibre/utils/localization.py +++ b/src/calibre/utils/localization.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai -from __future__ import with_statement +from __future__ import absolute_import __license__ = 'GPL v3' __copyright__ = '2009, Kovid Goyal ' @@ -8,13 +8,14 @@ __docformat__ = 'restructuredtext en' import os, locale, re, cStringIO, cPickle from gettext import GNUTranslations +from zipfile import ZipFile _available_translations = None def available_translations(): global _available_translations if _available_translations is None: - stats = P('localization/stats.pickle') + stats = P('localization/stats.pickle', allow_user_override=False) if os.path.exists(stats): stats = cPickle.load(open(stats, 'rb')) else: @@ -49,21 +50,20 @@ def get_lang(): lang = 'en' return lang -def messages_path(lang): - return P('localization/locales/%s/LC_MESSAGES'%lang) - def get_lc_messages_path(lang): hlang = None - if lang in available_translations(): - hlang = lang - else: - xlang = lang.split('_')[0] - if xlang in available_translations(): - hlang = xlang - if hlang is not None: - return messages_path(hlang) - return None + if zf_exists(): + if lang in available_translations(): + hlang = lang + else: + xlang = lang.split('_')[0] + if xlang in available_translations(): + hlang = xlang + return hlang +def zf_exists(): + return os.path.exists(P('localization/locales.zip', + allow_user_override=False)) def set_translators(): # To test different translations invoke as @@ -79,12 +79,17 @@ def set_translators(): mpath = get_lc_messages_path(lang) if mpath is not None: - if buf is None: - buf = open(os.path.join(mpath, 'messages.mo'), 'rb') - mpath = mpath.replace(os.sep+'nds'+os.sep, os.sep+'de'+os.sep) - isof = os.path.join(mpath, 'iso639.mo') - if os.path.exists(isof): - iso639 = open(isof, 'rb') + with ZipFile(P('localization/locales.zip', + allow_user_override=False), 'r') as zf: + if buf is None: + buf = cStringIO.StringIO(zf.read(mpath + '/messages.mo')) + if mpath == 'nds': + mpath = 'de' + isof = mpath + '/iso639.mo' + try: + iso639 = cStringIO.StringIO(zf.read(isof)) + except: + pass # No iso639 translations for this lang if buf is not None: t = GNUTranslations(buf)