diff --git a/resources/recipes/wsj.recipe b/resources/recipes/wsj.recipe index 513d0a7024..09a160cd49 100644 --- a/resources/recipes/wsj.recipe +++ b/resources/recipes/wsj.recipe @@ -3,15 +3,16 @@ __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __docformat__ = 'restructuredtext en' + from calibre.web.feeds.news import BasicNewsRecipe # http://online.wsj.com/page/us_in_todays_paper.html class WallStreetJournal(BasicNewsRecipe): - title = 'The Wall Street Journal' + title = 'The Wall Street Journal (US)' __author__ = 'Kovid Goyal and Sujata Raman' - description = 'News and current affairs.' + description = 'News and current affairs' needs_subscription = True language = 'en' @@ -60,60 +61,54 @@ class WallStreetJournal(BasicNewsRecipe): return soup - def get_article_url(self, article): - try: - return article.feedburner_origlink.split('?')[0] - except AttributeError: - return article.link.split('?')[0] + def wsj_get_index(self): + return self.index_to_soup('http://online.wsj.com/page/us_in_todays_paper.html') + + def parse_index(self): + soup = self.wsj_get_index() + + left_column = soup.find( + text=lambda t: 'begin ITP Left Column' in str(t)) + + table = left_column.findNext('table') + + current_section = None + current_articles = [] + feeds = [] + for x in table.findAllNext(True): + if x.name == 'td' and x.get('class', None) == 'b13': + if current_articles and current_section: + feeds.append((current_section, current_articles)) + current_section = self.tag_to_string(x.a).strip() + current_articles = [] + self.log('\tProcessing section:', current_section) + if current_section is not None and x.name == 'a' and \ + x.get('class', None) == 'bold80': + title = self.tag_to_string(x) + url = x.get('href', False) + if not url or not title: + continue + url = url.partition('#')[0] + desc = '' + d = x.findNextSibling(True) + if d.get('class', None) == 'arialResize': + desc = self.tag_to_string(d) + desc = desc.partition(u'\u2022')[0] + self.log('\t\tFound article:', title) + self.log('\t\t\t', url) + if url.startswith('/'): + url = 'http://online.wsj.com'+url + if desc: + self.log('\t\t\t', desc) + current_articles.append({'title': title, 'url':url, + 'description':desc, 'date':''}) + + if current_articles and current_section: + feeds.append((current_section, current_articles)) + + return feeds def cleanup(self): self.browser.open('http://online.wsj.com/logout?url=http://online.wsj.com') - feeds = [ - #('Most Emailed - Day', 'http://online.wsj.com/xml/rss/3_7030.xml'), - #('Most Emailed - Week', 'http://online.wsj.com/xml/rss/3_7253.xml'), - #('Most Emailed - Month', 'http://online.wsj.com/xml/rss/3_7254.xml'), - (' Most Viewed - Day', 'http://online.wsj.com/xml/rss/3_7198.xml'), - (' Most Viewed - Week', 'http://online.wsj.com/xml/rss/3_7251.xml'), - #('Most Viewed - Month', 'http://online.wsj.com/xml/rss/3_7252.xml'), - ('Today\'s Newspaper - Page One', 'http://online.wsj.com/xml/rss/3_7205.xml'), - ('Today\'s Newspaper - Marketplace', 'http://online.wsj.com/xml/rss/3_7206.xml'), - ('Today\'s Newspaper - Money & Investing', 'http://online.wsj.com/xml/rss/3_7207.xml'), - ('Today\'s Newspaper - Personal Journal', 'http://online.wsj.com/xml/rss/3_7208.xml'), - ('Today\'s Newspaper - Weekend Journal', 'http://online.wsj.com/xml/rss/3_7209.xml'), - ('Opinion', 'http://online.wsj.com/xml/rss/3_7041.xml'), - ('News - U.S.: What\'s News', 'http://online.wsj.com/xml/rss/3_7011.xml'), - ('News - U.S. Business', 'http://online.wsj.com/xml/rss/3_7014.xml'), - ('News - Europe: What\'s News', 'http://online.wsj.com/xml/rss/3_7012.xml'), - ('News - Asia: What\'s News', 'http://online.wsj.com/xml/rss/3_7013.xml'), - ('News - World News', 'http://online.wsj.com/xml/rss/3_7085.xml'), - ('News - Economy', 'http://online.wsj.com/xml/rss/3_7086.xml'), - ('News - Earnings', 'http://online.wsj.com/xml/rss/3_7088.xml'), - ('News - Health', 'http://online.wsj.com/xml/rss/3_7089.xml'), - ('News - Law', 'http://online.wsj.com/xml/rss/3_7091.xml'), - ('News - Media & Marketing', 'http://online.wsj.com/xml/rss/3_7020.xml'), - ('Technology - What\'s News', 'http://online.wsj.com/xml/rss/3_7015.xml'), - ('Technology - Gadgets', 'http://online.wsj.com/xml/rss/3_7094.xml'), - ('Technology - Telecommunications', 'http://online.wsj.com/xml/rss/3_7095.xml'), - ('Technology - E-commerce/Media', 'http://online.wsj.com/xml/rss/3_7096.xml'), - ('Technology - Asia', 'http://online.wsj.com/xml/rss/3_7097.xml'), - ('Technology - Europe', 'http://online.wsj.com/xml/rss/3_7098.xml'), - ('Markets - News', 'http://online.wsj.com/xml/rss/3_7031.xml'), - ('Markets - Europe News', 'http://online.wsj.com/xml/rss/3_7101.xml'), - ('Markets - Asia News', 'http://online.wsj.com/xml/rss/3_7102.xml'), - ('Markets - Deals & Deal Makers', 'http://online.wsj.com/xml/rss/3_7099.xml'), - ('Markets - Hedge Funds', 'http://online.wsj.com/xml/rss/3_7199.xml'), - ('Personal Journal', 'http://online.wsj.com/xml/rss/3_7200.xml'), - ('Personal Journal - Money', 'http://online.wsj.com/xml/rss/3_7104.xml'), - ('Personal Journal - Health', 'http://online.wsj.com/xml/rss/3_7089.xml'), - ('Personal Journal - Autos', 'http://online.wsj.com/xml/rss/3_7092.xml'), - ('Personal Journal - Homes', 'http://online.wsj.com/xml/rss/3_7105.xml'), - ('Personal Journal - Travel', 'http://online.wsj.com/xml/rss/3_7106.xml'), - ('Personal Journal - Careers', 'http://online.wsj.com/xml/rss/3_7107.xml'), - ('Weekend & Leisure', 'http://online.wsj.com/xml/rss/3_7201.xml'), - ('Weekend & Leisure - Weekend Journal', 'http://online.wsj.com/xml/rss/3_7202.xml'), - ('Weekend & Leisure - Arts & Entertainment', 'http://online.wsj.com/xml/rss/3_7177.xml'), - ('Weekend & Leisure - Books', 'http://online.wsj.com/xml/rss/3_7203.xml'), - ('Weekend & Leisure - Sports', 'http://online.wsj.com/xml/rss/3_7204.xml'), - ] diff --git a/setup/build_environment.py b/setup/build_environment.py index 052bbf05ac..8b07c7f5f4 100644 --- a/setup/build_environment.py +++ b/setup/build_environment.py @@ -13,12 +13,9 @@ from PyQt4 import pyqtconfig from setup import isosx, iswindows, islinux -OSX_SDK = '/Developer/SDKs/MacOSX10.5.sdk' -if not os.path.exists(OSX_SDK): - OSX_SDK = '/Developer/SDKs/MacOSX10.4u.sdk' -leopard_build = '10.5' in OSX_SDK +OSX_SDK = '/Developer/SDKs/MacOSX10.4u.sdk' -os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.5' if leopard_build else '10.4' +os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.4' NMAKE = RC = msvc = MT = win_inc = win_lib = None if iswindows: @@ -117,24 +114,24 @@ if iswindows: podofo_inc = os.path.join(sw_inc_dir, 'podofo') podofo_lib = sw_lib_dir elif isosx: - fc_inc = '/Users/kovid/fontconfig/include/fontconfig' - fc_lib = '/Users/kovid/fontconfig/lib' + fc_inc = '/sw/include/fontconfig' + fc_lib = '/sw/lib' poppler_inc_dirs = consolidate('POPPLER_INC_DIR', - '/Volumes/sw/build/poppler-0.12.0/poppler:/Volumes/sw/build/poppler-0.12.0') + '/sw/build/poppler-0.12.2/poppler:/sw/build/poppler-0.12.2') popplerqt4_inc_dirs = poppler_inc_dirs + [poppler_inc_dirs[0]+'/qt4'] poppler_lib_dirs = consolidate('POPPLER_LIB_DIR', - '/Volumes/sw/lib') + '/sw/lib') popplerqt4_lib_dirs = poppler_lib_dirs poppler_libs = popplerqt4_libs = ['poppler'] - podofo_inc = '/usr/local/include/podofo' - podofo_lib = '/usr/local/lib' + podofo_inc = '/sw/podofo' + podofo_lib = '/sw/lib' magick_inc_dirs = consolidate('MAGICK_INC', - '/Users/kovid/ImageMagick/include/ImageMagick') + '/sw/include/ImageMagick') magick_lib_dirs = consolidate('MAGICK_LIB', - '/Users/kovid/ImageMagick/lib') + '/sw/lib') magick_libs = ['MagickWand', 'MagickCore'] - png_inc_dirs = consolidate('PNG_INC_DIR', '/usr/local/include') - png_lib_dirs = consolidate('PNG_LIB_DIR', '/usr/local/lib') + png_inc_dirs = consolidate('PNG_INC_DIR', '/sw/include') + png_lib_dirs = consolidate('PNG_LIB_DIR', '/sw/lib') png_libs = ['png12'] else: # Include directories diff --git a/setup/commands.py b/setup/commands.py index d5687bb1d5..d35e326ab1 100644 --- a/setup/commands.py +++ b/setup/commands.py @@ -83,7 +83,7 @@ linux_freeze2 = LinuxFreeze2() from setup.installer.osx import OSX, OSX32 osx = OSX() osx32 = OSX32() -from setup.installer.osx.freeze import OSX32_Freeze +from setup.installer.osx.app.main import OSX32_Freeze osx32_freeze = OSX32_Freeze() from setup.installer.windows import Win, Win32 diff --git a/setup/extensions.py b/setup/extensions.py index 84ae4afe6e..ba54b022c5 100644 --- a/setup/extensions.py +++ b/setup/extensions.py @@ -15,7 +15,7 @@ from setup import Command, islinux, isosx, SRC, iswindows from setup.build_environment import fc_inc, fc_lib, \ fc_error, poppler_libs, poppler_lib_dirs, poppler_inc_dirs, podofo_inc, \ podofo_lib, podofo_error, poppler_error, pyqt, OSX_SDK, NMAKE, \ - leopard_build, QMAKE, msvc, MT, win_inc, win_lib, png_inc_dirs, \ + QMAKE, msvc, MT, win_inc, win_lib, png_inc_dirs, \ magick_inc_dirs, magick_lib_dirs, png_lib_dirs, png_libs, \ magick_error, magick_libs, ft_lib_dirs, ft_libs, jpg_libs, jpg_lib_dirs MT @@ -156,7 +156,7 @@ if islinux: if isosx: - x, p = ('x86_64', 'ppc64') if leopard_build else ('i386', 'ppc') + x, p = ('i386', 'ppc') archs = ['-arch', x, '-arch', p, '-isysroot', OSX_SDK] cflags.append('-D_OSX') @@ -305,7 +305,7 @@ class Build(Command): obj_pat = 'release\\*.obj' if iswindows else '*.o' objects = glob.glob(obj_pat) if not objects or self.newer(objects, ext.sources+ext.headers): - archs = 'x86_64 ppc64' if leopard_build else 'x86 ppc' + archs = 'x86 ppc' pro = textwrap.dedent('''\ TARGET = %s TEMPLATE = lib @@ -316,9 +316,6 @@ class Build(Command): ''')%(ext.name, ' '.join(ext.headers), ' '.join(ext.sources), archs) open(ext.name+'.pro', 'wb').write(pro) subprocess.check_call([QMAKE, '-o', 'Makefile', ext.name+'.pro']) - if leopard_build: - raw = open('Makefile', 'rb').read() - open('Makefile', 'wb').write(raw.replace('ppc64', 'x86_64')) subprocess.check_call([make, '-f', 'Makefile']) objects = glob.glob(obj_pat) return list(map(self.a, objects)) @@ -354,12 +351,6 @@ class Build(Command): makefile.extra_lflags = qt_objects makefile.extra_include_dirs = ext.inc_dirs makefile.generate() - if leopard_build: - raw = open(mf, 'rb').read() - raw = raw.replace('ppc64 x86_64', 'x86_64') - for x in ('ppc64', 'ppc', 'i386'): - raw = raw.replace(x, 'x86_64') - open(mf, 'wb').write(raw) subprocess.check_call([make, '-f', mf], cwd=src_dir) shutil.copy2(module, dest) diff --git a/setup/installer/osx/__init__.py b/setup/installer/osx/__init__.py index e5e689244a..f68e984ef1 100644 --- a/setup/installer/osx/__init__.py +++ b/setup/installer/osx/__init__.py @@ -25,8 +25,9 @@ class OSX32(VMInstaller): description = 'Build 32 bit OS X binary installer' INSTALLER_EXT = 'dmg' - VM_NAME = 'tiger_build' + VM_NAME = 'leopard_build' VM = '/vmware/bin/%s'%VM_NAME + FREEZE_TEMPLATE = 'python -OO setup.py {freeze_command}' FREEZE_COMMAND = 'osx32_freeze' BUILD_PREFIX = VMInstaller.BUILD_PREFIX + ['source ~/.profile'] SHUTDOWN_CMD = ['sudo', 'halt'] diff --git a/setup/installer/osx/app/main.py b/setup/installer/osx/app/main.py index bde50376f7..4cf995683f 100644 --- a/setup/installer/osx/app/main.py +++ b/setup/installer/osx/app/main.py @@ -13,9 +13,13 @@ abspath, join, basename = os.path.abspath, os.path.join, os.path.basename from setup import __version__ as VERSION, __appname__ as APPNAME, basenames, \ modules as main_modules, Command, SRC, functions as main_functions LICENSE = open('LICENSE', 'rb').read() +MAGICK_HOME='@executable_path/../Frameworks/ImageMagick' ENV = dict( FC_CONFIG_DIR='@executable_path/../Resources/fonts', - MAGICK_HOME='@executable_path/../Frameworks/ImageMagick', + FC_CONFIG_FILE='@executable_path/../Resources/fonts/fonts.conf', + MAGICK_CONFIGURE_PATH=MAGICK_HOME+'/config', + MAGICK_CODER_MODULE_PATH=MAGICK_HOME+'/modules-Q16/coders', + MAGICK_CODER_FILTER_PATH=MAGICK_HOME+'/modules-Q16/filter', QT_PLUGIN_PATH='@executable_path/../MacOS', PYTHONIOENCODING='UTF-8', ) @@ -46,9 +50,9 @@ def compile_launcher_lib(contents_dir, gcc, base): src = join(base, 'util.c') cmd = [gcc] + '-Wall -arch i386 -arch ppc -dynamiclib -std=gnu99'.split() + [src] + \ ['-I'+base] + \ - ['-I%s/python/Python.framework/Headers'%SW] + \ + ['-I/Library/Frameworks/Python.framework/Versions/Current/Headers'] + \ '-current_version 1.0 -compatibility_version 1.0'.split() + \ - '-fvisibility=hidden -o'.split() + [dest, '-F%s/python'%SW] + \ + '-fvisibility=hidden -o'.split() + [dest] + \ ['-install_name', '@executable_path/../Frameworks/'+os.path.basename(dest)] + \ ['-framework', 'Python', '-framework', 'CoreFoundation', '-headerpad_max_install_names'] @@ -176,6 +180,8 @@ class Py2App(object): self.create_plist() self.add_python_framework() + self.add_site_packages() + self.add_stdlib() self.add_qt_frameworks() self.add_calibre_plugins() self.add_podofo() @@ -186,8 +192,6 @@ class Py2App(object): self.add_imagemagick() self.add_misc_libraries() - self.add_site_packages() - self.add_stdlib() self.add_resources() self.compile_py_modules() @@ -262,8 +266,10 @@ class Py2App(object): def get_local_dependencies(self, path_to_lib): for x in self.get_dependencies(path_to_lib): for y in (SW+'/lib/', '/usr/local/lib/', SW+'/qt/lib/', - SW+'/python/', SW+'/freetype/lib/'): + '/Library/Frameworks/Python.framework/', SW+'/freetype/lib/'): if x.startswith(y): + if y == '/Library/Frameworks/Python.framework/': + y = '/Library/Frameworks/' yield x, x[len(y):] break @@ -289,7 +295,7 @@ class Py2App(object): @flush def add_python_framework(self): info('\nAdding Python framework') - src = join(SW, 'python', 'Python.framework') + src = join('/Library/Frameworks', 'Python.framework') x = join(self.frameworks_dir, 'Python.framework') curr = os.path.realpath(join(src, 'Versions', 'Current')) currd = join(x, 'Versions', basename(curr)) @@ -302,6 +308,7 @@ class Py2App(object): @flush def add_qt_frameworks(self): + info('\nAdding Qt Framework') for f in ('QtCore', 'QtGui', 'QtXml', 'QtNetwork', 'QtSvg', 'QtWebkit', 'QtXmlPatterns', 'phonon'): self.add_qt_framework(f) @@ -360,7 +367,7 @@ class Py2App(object): CFBundlePackageType='APPL', CFBundleSignature='????', CFBundleExecutable='calibre', - LSMinimumSystemVersion='10.5.2', + LSMinimumSystemVersion='10.4.2', LSRequiresNativeExecution=True, NSAppleScriptEnabled=False, NSHumanReadableCopyright='Copyright 2008, Kovid Goyal', @@ -433,10 +440,7 @@ class Py2App(object): for x in ('Wand', 'Core'): self.install_dylib(os.path.join(SW, 'lib', 'libMagick%s.2.dylib'%x)) idir = glob.glob(os.path.join(SW, 'lib', 'ImageMagick-*'))[-1] - dest = os.path.join(self.frameworks_dir, 'ImageMagick', 'lib') - if not os.path.exists(dest): - os.makedirs(dest) - dest = os.path.join(dest, os.path.basename(idir)) + dest = os.path.join(self.frameworks_dir, 'ImageMagick') if os.path.exists(dest): shutil.rmtree(dest) shutil.copytree(idir, dest, True) @@ -461,12 +465,12 @@ class Py2App(object): paths = reversed(map(abspath, [x for x in sys.path if x.startswith('/')])) upaths = [] for x in paths: - if x.endswith('/PIL') or 'site-packages' not in x: - continue - if x not in upaths: + if x not in upaths and (x.endswith('.egg') or + x.endswith('/site-packages')): upaths.append(x) upaths.append(os.path.expanduser('~/build/calibre/src')) for x in upaths: + info('\t', x) tdir = None try: if not os.path.isdir(x): @@ -536,7 +540,7 @@ class Py2App(object): @flush def add_stdlib(self): info('\nAdding python stdlib') - src = join(SW, 'python/Python.framework/Versions/Current/lib/python') + src = '/Library/Frameworks/Python.framework/Versions/Current/lib/python' src += self.version_info dest = join(self.resources_dir, 'Python', 'lib', 'python') dest += self.version_info diff --git a/src/calibre/customize/profiles.py b/src/calibre/customize/profiles.py index 752a908c1c..18a80cb33d 100644 --- a/src/calibre/customize/profiles.py +++ b/src/calibre/customize/profiles.py @@ -363,7 +363,7 @@ class NookOutput(OutputProfile): description = _('This profile is intended for the B&N Nook.') # Screen size is a best guess - screen_size = (600, 800) + screen_size = (600, 770) dpi = 167 fbase = 16 fsizes = [12, 12, 14, 16, 18, 20, 22, 24] diff --git a/src/calibre/devices/cybookg3/driver.py b/src/calibre/devices/cybookg3/driver.py index 00cf99a8c4..97280f1e30 100644 --- a/src/calibre/devices/cybookg3/driver.py +++ b/src/calibre/devices/cybookg3/driver.py @@ -9,7 +9,6 @@ Device driver for Bookeen's Cybook Gen 3 ''' import os -from itertools import cycle from calibre import islinux from calibre.devices.usbms.driver import USBMS diff --git a/src/calibre/devices/nook/driver.py b/src/calibre/devices/nook/driver.py index 332c4d86eb..825096d31c 100644 --- a/src/calibre/devices/nook/driver.py +++ b/src/calibre/devices/nook/driver.py @@ -8,10 +8,7 @@ __docformat__ = 'restructuredtext en' Device driver for Barns and Nobel's Nook ''' -try: - from PIL import Image, ImageDraw -except ImportError: - import Image, ImageDraw +import os import cStringIO @@ -47,6 +44,13 @@ class NOOK(USBMS): SUPPORTS_SUB_DIRS = True def upload_cover(self, path, filename, metadata): + try: + from PIL import Image, ImageDraw + Image, ImageDraw + except ImportError: + import Image, ImageDraw + + coverdata = metadata.get('cover', None) if coverdata: cover = Image.open(cStringIO.StringIO(coverdata[2])) diff --git a/src/calibre/devices/usbms/driver.py b/src/calibre/devices/usbms/driver.py index f637ee2fa8..7556ff7dcf 100644 --- a/src/calibre/devices/usbms/driver.py +++ b/src/calibre/devices/usbms/driver.py @@ -111,7 +111,11 @@ class USBMS(CLI, Device): paths.append(filepath) self.put_file(infile, filepath, replace_file=True) - self.upload_cover(os.path.dirname(filepath), os.path.splitext(os.path.basename(filepath))[0], mdata) + try: + self.upload_cover(os.path.dirname(filepath), os.path.splitext(os.path.basename(filepath))[0], mdata) + except: # Failure to upload cover is not catastrophic + import traceback + traceback.print_exc() self.report_progress((i+1) / float(len(files)), _('Transferring books to device...')) diff --git a/src/calibre/ebooks/conversion/cli.py b/src/calibre/ebooks/conversion/cli.py index e319104562..fa1b4056db 100644 --- a/src/calibre/ebooks/conversion/cli.py +++ b/src/calibre/ebooks/conversion/cli.py @@ -203,9 +203,10 @@ def create_option_parser(args, log): log('Created by:', __author__) raise SystemExit(0) if '--list-recipes' in args: - from calibre.web.feeds.recipes import titles + from calibre.web.feeds.recipes.collection import get_builtin_recipe_titles log('Available recipes:') - for title in sorted(titles): + titles = sorted(get_builtin_recipe_titles()) + for title in titles: try: log('\t'+title) except: diff --git a/src/calibre/ebooks/epub/output.py b/src/calibre/ebooks/epub/output.py index 77a03916d8..064a1d1bdd 100644 --- a/src/calibre/ebooks/epub/output.py +++ b/src/calibre/ebooks/epub/output.py @@ -155,17 +155,19 @@ class EPUBOutput(OutputFormatPlugin): def convert(self, oeb, output_path, input_plugin, opts, log): self.log, self.opts, self.oeb = log, opts, oeb + self.workaround_ade_quirks() + self.workaround_webkit_quirks() + self.workaround_sony_quirks() + from calibre.ebooks.oeb.transforms.rescale import RescaleImages + RescaleImages()(oeb, opts) + + from calibre.ebooks.oeb.transforms.split import Split split = Split(not self.opts.dont_split_on_page_breaks, max_flow_size=self.opts.flow_size*1024 ) split(self.oeb, self.opts) - self.workaround_ade_quirks() - self.workaround_webkit_quirks() - self.workaround_sony_quirks() - from calibre.ebooks.oeb.transforms.rescale import RescaleImages - RescaleImages()(oeb, opts) self.insert_cover() with TemporaryDirectory('_epub_output') as tdir: diff --git a/src/calibre/ebooks/oeb/transforms/split.py b/src/calibre/ebooks/oeb/transforms/split.py index 52133c91d9..d8ba3e5b77 100644 --- a/src/calibre/ebooks/oeb/transforms/split.py +++ b/src/calibre/ebooks/oeb/transforms/split.py @@ -381,9 +381,9 @@ class FlowSplitter(object): p[i:i+1] = new_pres split_point, before = self.find_split_point(root) - self.log.debug('\t\t\tSplit point:', split_point.tag, tree.getpath(split_point)) if split_point is None: raise SplitError(self.item.href, root) + self.log.debug('\t\t\tSplit point:', split_point.tag, tree.getpath(split_point)) for t in self.do_split(tree, split_point, before): r = t.getroot() diff --git a/src/calibre/gui2/library.py b/src/calibre/gui2/library.py index 6a346950dd..f772f94bf0 100644 --- a/src/calibre/gui2/library.py +++ b/src/calibre/gui2/library.py @@ -693,6 +693,9 @@ class BooksView(TableView): self._model.current_changed) self.connect(self._model, SIGNAL('columns_sorted()'), self.columns_sorted, Qt.QueuedConnection) + hv = self.verticalHeader() + hv.setClickable(True) + hv.setCursor(Qt.PointingHandCursor) def columns_sorted(self): for i in range(self.model().columnCount(None)): diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 0fafb572c1..ad1e3938c4 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -552,6 +552,11 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): self.connect(self.scheduler, SIGNAL('start_recipe_fetch(PyQt_PyObject)'), self.download_scheduled_recipe, Qt.QueuedConnection) + self.library_view.verticalHeader().sectionClicked.connect(self.view_specific_book) + + for view in ('library', 'memory', 'card_a', 'card_b'): + view = getattr(self, view+'_view') + view.verticalHeader().sectionDoubleClicked.connect(self.view_specific_book) self.location_view.setCurrentIndex(self.location_view.model().index(0)) @@ -921,8 +926,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): ''' Add books from the local filesystem to either the library or the device. ''' - books = choose_files(self, 'add books dialog dir', 'Select books', - filters=[ + filters = [ (_('Books'), BOOK_EXTENSIONS), (_('EPUB Books'), ['epub']), (_('LRF Books'), ['lrf']), @@ -933,10 +937,15 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): (_('PDF Books'), ['pdf']), (_('Comics'), ['cbz', 'cbr', 'cbc']), (_('Archives'), ['zip', 'rar']), - ]) + ] + to_device = self.stack.currentIndex() != 0 + if to_device: + filters = [(_('Supported books'), self.device_manager.device.FORMATS)] + + books = choose_files(self, 'add books dialog dir', 'Select books', + filters=filters) if not books: return - to_device = self.stack.currentIndex() != 0 self._add_books(books, to_device) @@ -1442,7 +1451,12 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): def view_book(self, triggered): rows = self.current_view().selectionModel().selectedRows() + self._view_books(rows) + def view_specific_book(self, index): + self._view_books([index]) + + def _view_books(self, rows): if not rows or len(rows) == 0: self._launch_viewer() return @@ -1458,7 +1472,8 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): if self.current_view() is self.library_view: for row in rows: - row = row.row() + if hasattr(row, 'row'): + row = row.row() formats = self.library_view.model().db.formats(row) title = self.library_view.model().db.title(row) diff --git a/src/calibre/gui2/wizard/__init__.py b/src/calibre/gui2/wizard/__init__.py index ba2e071adf..533cce1723 100644 --- a/src/calibre/gui2/wizard/__init__.py +++ b/src/calibre/gui2/wizard/__init__.py @@ -96,6 +96,7 @@ class Nook(Sony505): id = 'nook' name = 'Nook' manufacturer = 'Barnes & Noble' + output_profile = 'nook' class CybookG3(Device): diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index dce8d73499..411e5ee98b 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -473,7 +473,7 @@ class LibraryDatabase2(LibraryDatabase): def upgrade_version_2(self): ''' Fix Foreign key constraints for deleting from link tables. ''' script = textwrap.dedent('''\ - DROP TRIGGER fkc_delete_books_%(ltable)s_link; + DROP TRIGGER IF EXISTS fkc_delete_books_%(ltable)s_link; CREATE TRIGGER fkc_delete_on_%(table)s BEFORE DELETE ON %(table)s BEGIN diff --git a/src/calibre/translations/calibre.pot b/src/calibre/translations/calibre.pot index b8ea646a3a..fe3fa203bc 100644 --- a/src/calibre/translations/calibre.pot +++ b/src/calibre/translations/calibre.pot @@ -5,8 +5,8 @@ msgid "" msgstr "" "Project-Id-Version: calibre 0.6.29\n" -"POT-Creation-Date: 2009-12-18 12:30+MST\n" -"PO-Revision-Date: 2009-12-18 12:30+MST\n" +"POT-Creation-Date: 2009-12-21 21:13+MST\n" +"PO-Revision-Date: 2009-12-21 21:13+MST\n" "Last-Translator: Automatically generated\n" "Language-Team: LANGUAGE\n" "MIME-Version: 1.0\n" @@ -21,13 +21,13 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/customize/__init__.py:44 #: /home/kovid/work/calibre/src/calibre/devices/jetbook/driver.py:94 -#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:53 +#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:54 #: /home/kovid/work/calibre/src/calibre/devices/prs505/books.py:58 #: /home/kovid/work/calibre/src/calibre/devices/prs505/books.py:199 #: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:767 #: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:770 #: /home/kovid/work/calibre/src/calibre/devices/usbms/driver.py:193 -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:410 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:414 #: /home/kovid/work/calibre/src/calibre/ebooks/fb2/input.py:67 #: /home/kovid/work/calibre/src/calibre/ebooks/fb2/input.py:69 #: /home/kovid/work/calibre/src/calibre/ebooks/html/input.py:319 @@ -115,8 +115,8 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:170 #: /home/kovid/work/calibre/src/calibre/gui2/library.py:392 #: /home/kovid/work/calibre/src/calibre/gui2/library.py:405 -#: /home/kovid/work/calibre/src/calibre/gui2/library.py:877 -#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1003 +#: /home/kovid/work/calibre/src/calibre/gui2/library.py:880 +#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1006 #: /home/kovid/work/calibre/src/calibre/gui2/viewer/main.py:179 #: /home/kovid/work/calibre/src/calibre/library/cli.py:281 #: /home/kovid/work/calibre/src/calibre/library/database.py:913 @@ -380,12 +380,15 @@ msgid "Communicate with the Blackberry smart phone." msgstr "" #: /home/kovid/work/calibre/src/calibre/devices/blackberry/driver.py:13 -#: /home/kovid/work/calibre/src/calibre/devices/iriver/driver.py:16 #: /home/kovid/work/calibre/src/calibre/devices/nuut2/driver.py:18 #: /home/kovid/work/calibre/src/calibre/devices/prs500/driver.py:88 msgid "Kovid Goyal" msgstr "" +#: /home/kovid/work/calibre/src/calibre/devices/boox/driver.py:17 +msgid "Communicate with the BOOX eBook reader." +msgstr "" + #: /home/kovid/work/calibre/src/calibre/devices/cybookg3/driver.py:22 msgid "Communicate with the Cybook Gen 3 eBook reader." msgstr "" @@ -439,19 +442,15 @@ msgstr "" msgid "Communicate with the JetBook eBook reader." msgstr "" -#: /home/kovid/work/calibre/src/calibre/devices/jetbook/driver.py:23 -msgid "James Ralston" -msgstr "" - -#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:21 +#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:22 msgid "Communicate with the Kindle eBook reader." msgstr "" -#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:66 +#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:67 msgid "Communicate with the Kindle 2 eBook reader." msgstr "" -#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:76 +#: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:77 msgid "Communicate with the Kindle DX eBook reader." msgstr "" @@ -605,71 +604,71 @@ msgstr "" msgid "Removing books from device metadata listing..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:196 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:200 msgid "Rendered %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:199 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:203 msgid "Failed %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:256 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:260 msgid "" "Failed to process comic: \n" "\n" "%s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:274 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:278 msgid "Number of colors for grayscale image conversion. Default: %default. Values of less than 256 may result in blurred text on your device if you are creating your comics in EPUB format." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:278 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:282 msgid "Disable normalize (improve contrast) color range for pictures. Default: False" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:281 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:285 msgid "Maintain picture aspect ratio. Default is to fill the screen." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:283 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:287 msgid "Disable sharpening." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:285 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:289 msgid "Disable trimming of comic pages. For some comics, trimming might remove content as well as borders." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:288 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:292 msgid "Don't split landscape images into two portrait images" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:290 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:294 msgid "Keep aspect ratio and scale image using screen height as image width for viewing in landscape mode." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:293 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:297 msgid "Used for right-to-left publications like manga. Causes landscape pages to be split into portrait pages from right to left." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:297 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:301 msgid "Enable Despeckle. Reduces speckle noise. May greatly increase processing time." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:300 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:304 msgid "Don't sort the files found in the comic alphabetically by name. Instead use the order they were added to the comic." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:304 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:308 msgid "The format that images in the created ebook are converted to. You can experiment to see which format gives you optimal size and look on your device." msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:308 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:312 msgid "Apply no processing to the image" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:434 -#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:445 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:438 +#: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:449 msgid "Page" msgstr "" @@ -728,7 +727,7 @@ msgstr "" msgid "List builtin recipes" msgstr "" -#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:251 +#: /home/kovid/work/calibre/src/calibre/ebooks/conversion/cli.py:252 msgid "Output saved to" msgstr "" @@ -1284,7 +1283,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:56 #: /home/kovid/work/calibre/src/calibre/gui2/library.py:159 #: /home/kovid/work/calibre/src/calibre/gui2/library.py:389 -#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1069 +#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1072 msgid "Title" msgstr "" @@ -1292,7 +1291,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/fetch_metadata.py:57 #: /home/kovid/work/calibre/src/calibre/gui2/library.py:160 #: /home/kovid/work/calibre/src/calibre/gui2/library.py:394 -#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1070 +#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1073 msgid "Author(s)" msgstr "" @@ -1319,8 +1318,8 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:370 #: /home/kovid/work/calibre/src/calibre/gui2/library.py:166 #: /home/kovid/work/calibre/src/calibre/gui2/library.py:339 -#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1013 -#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1073 +#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1016 +#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1076 #: /home/kovid/work/calibre/src/calibre/gui2/status.py:96 #: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:125 msgid "Tags" @@ -1339,7 +1338,7 @@ msgid "Language" msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:375 -#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1012 +#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1015 msgid "Timestamp" msgstr "" @@ -2186,7 +2185,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:67 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:67 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/search_item_ui.py:35 -#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:96 +#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:106 #: /home/kovid/work/calibre/src/calibre/gui2/wizard/send_email_ui.py:107 msgid "Form" msgstr "" @@ -2773,7 +2772,7 @@ msgid "RB Output" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/regex_builder.py:77 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1421 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1431 msgid "Choose the format to view" msgstr "" @@ -3266,7 +3265,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:85 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:86 #: /home/kovid/work/calibre/src/calibre/gui2/library.py:346 -#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1008 +#: /home/kovid/work/calibre/src/calibre/gui2/library.py:1011 #: /home/kovid/work/calibre/src/calibre/gui2/status.py:92 msgid "Path" msgstr "" @@ -3381,7 +3380,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:475 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:819 #: /home/kovid/work/calibre/src/calibre/gui2/ui.py:158 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1094 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:1104 #: /home/kovid/work/calibre/src/calibre/utils/ipc/job.py:53 msgid "Error" msgstr "" @@ -3451,7 +3450,7 @@ msgid "Access log:" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config/__init__.py:674 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:613 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:618 msgid "Failed to start content server" msgstr "" @@ -4037,7 +4036,7 @@ msgid "Choose formats for " msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single.py:136 -#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:925 +#: /home/kovid/work/calibre/src/calibre/gui2/ui.py:930 msgid "Books" msgstr "" @@ -4456,7 +4455,7 @@ msgid "Send test mail from %s to:" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/test_email_ui.py:52 -#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:105 +#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:115 msgid "&Test" msgstr "" @@ -4632,7 +4631,7 @@ msgstr "" msgid "Recipe source code (python)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:97 +#: /home/kovid/work/calibre/src/calibre/gui2/filename_pattern_ui.py:107 msgid "" "\n" "