diff --git a/resources/recipes/gizmodo.recipe b/resources/recipes/gizmodo.recipe index 6f6e6ae0cf..4233ef66b7 100644 --- a/resources/recipes/gizmodo.recipe +++ b/resources/recipes/gizmodo.recipe @@ -17,7 +17,7 @@ class Gizmodo(BasicNewsRecipe): max_articles_per_feed = 100 no_stylesheets = True encoding = 'utf-8' - use_embedded_content = True + use_embedded_content = False language = 'en' masthead_url = 'http://cache.gawkerassets.com/assets/gizmodo.com/img/logo.png' extra_css = ' body{font-family: "Lucida Grande",Helvetica,Arial,sans-serif} img{margin-bottom: 1em} ' @@ -29,9 +29,11 @@ class Gizmodo(BasicNewsRecipe): , 'language' : language } - remove_attributes = ['width','height'] - remove_tags = [dict(name='div',attrs={'class':'feedflare'})] - remove_tags_after = dict(name='div',attrs={'class':'feedflare'}) + remove_attributes = ['width','height'] + keep_only_tags = [dict(attrs={'class':'content permalink'})] + remove_tags_before = dict(name='h1') + remove_tags = [dict(attrs={'class':'contactinfo'})] + remove_tags_after = dict(attrs={'class':'contactinfo'}) feeds = [(u'Articles', u'http://feeds.gawker.com/gizmodo/full')] diff --git a/resources/recipes/vreme.recipe b/resources/recipes/vreme.recipe index a54353b78c..197c20f108 100644 --- a/resources/recipes/vreme.recipe +++ b/resources/recipes/vreme.recipe @@ -52,10 +52,12 @@ class Vreme(BasicNewsRecipe): def parse_index(self): articles = [] soup = self.index_to_soup(self.INDEX) - + cover_item = soup.find('div',attrs={'id':'najava'}) + if cover_item: + self.cover_url = self.INDEX + cover_item.img['src'] for item in soup.findAll(['h3','h4']): - description = '' - title_prefix = '' + description = u'' + title_prefix = u'' feed_link = item.find('a') if feed_link and feed_link.has_key('href') and feed_link['href'].startswith('/cms/view.php'): url = self.INDEX + feed_link['href'] @@ -67,7 +69,7 @@ class Vreme(BasicNewsRecipe): ,'url' :url ,'description':description }) - return [(soup.head.title.string, articles)] + return [('Nedeljnik Vreme', articles)] remove_tags = [ dict(name=['object','link']) @@ -76,11 +78,3 @@ class Vreme(BasicNewsRecipe): def print_version(self, url): return url + '&print=yes' - - def get_cover_url(self): - cover_url = None - soup = self.index_to_soup(self.INDEX) - cover_item = soup.find('div',attrs={'id':'najava'}) - if cover_item: - cover_url = self.INDEX + cover_item.img['src'] - return cover_url diff --git a/src/calibre/devices/prs505/driver.py b/src/calibre/devices/prs505/driver.py index bd06d2d7e1..5a820b3ed8 100644 --- a/src/calibre/devices/prs505/driver.py +++ b/src/calibre/devices/prs505/driver.py @@ -6,8 +6,7 @@ __docformat__ = 'restructuredtext en' Device driver for the SONY devices ''' -import os -import re +import os, time, re from calibre.devices.usbms.driver import USBMS from calibre.devices.prs505 import MEDIA_XML @@ -66,6 +65,41 @@ class PRS505(USBMS): def windows_filter_pnp_id(self, pnp_id): return '_LAUNCHER' in pnp_id + def post_open_callback(self): + + def write_cache(prefix): + try: + cachep = os.path.join(prefix, *(CACHE_XML.split('/'))) + if not os.path.exists(cachep): + dname = os.path.dirname(cachep) + if not os.path.exists(dname): + try: + os.makedirs(dname, mode=0777) + except: + time.sleep(5) + os.makedirs(dname, mode=0777) + with open(cachep, 'wb') as f: + f.write(u''' + + + '''.encode('utf8')) + return True + except: + import traceback + traceback.print_exc() + return False + + # Make sure we don't have the launcher partition + # as one of the cards + + if self._card_a_prefix is not None: + if not write_cache(self._card_a_prefix): + self._card_a_prefix = None + if self._card_b_prefix is not None: + if not write_cache(self._card_b_prefix): + self._card_b_prefix = None + + def get_device_information(self, end_session=True): return (self.gui_name, '', '', '') diff --git a/src/calibre/devices/prs505/sony_cache.py b/src/calibre/devices/prs505/sony_cache.py index 177a741e0d..0292a275d7 100644 --- a/src/calibre/devices/prs505/sony_cache.py +++ b/src/calibre/devices/prs505/sony_cache.py @@ -415,10 +415,11 @@ class XMLCache(object): prints('\tmtime', strftime(os.path.getmtime(path))) record.set('date', date) record.set('size', str(os.stat(path).st_size)) - record.set('title', book.title) + title = book.title if book.title else _('Unknown') + record.set('title', title) ts = book.title_sort if not ts: - ts = title_sort(book.title) + ts = title_sort(title) record.set('titleSorter', ts) record.set('author', authors_to_string(book.authors)) ext = os.path.splitext(path)[1] diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 29ae1875c8..ba40c0c92b 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -226,7 +226,7 @@ class GuiRunner(QObject): self.splash_pixmap = QPixmap() self.splash_pixmap.load(I('library.png')) self.splash_screen = QSplashScreen(self.splash_pixmap, - Qt.SplashScreen|Qt.WindowStaysOnTopHint) + Qt.SplashScreen) self.splash_screen.showMessage(_('Starting %s: Loading books...') % __appname__) self.splash_screen.show() diff --git a/src/calibre/gui2/main.ui b/src/calibre/gui2/main.ui index 8c1d1bf787..1abaf53d3c 100644 --- a/src/calibre/gui2/main.ui +++ b/src/calibre/gui2/main.ui @@ -28,7 +28,7 @@ :/images/library.png:/images/library.png - + @@ -305,78 +305,79 @@ - - - - - - 0 - 100 - - - - Qt::Vertical - - - - - 100 - 100 - - - - 0 - - - - - - - Qt::Horizontal - - - - - - - true - - - true - - - true - - - true - - - - + + + + 0 + 100 + + + + Qt::Vertical + + + + + + + + 100 + 100 + + + + 0 + + + + + + + Qt::Horizontal + + + + + + + true + + + true + + + true + + + true + + + + Sort by &popularity - - - - - 0 - - - - Match any + + + + + 0 - - - - Match all - - - - - + + + Match any + + + + + Match all + + + + + Create, edit, and delete user categories @@ -385,10 +386,49 @@ Manage &user categories - - + + + + + + + 100 + 10 + + + + true + + + true + + + false + + + QAbstractItemView::DragDrop + + + true + + + QAbstractItemView::SelectRows + + + false + + + false + + - + + + + + + + 100 @@ -420,139 +460,107 @@ false - - - + + + + + + + + + + 10 + 10 + + + + true + + + true + + + false + + + QAbstractItemView::DragDrop + + + true + + + QAbstractItemView::SelectRows + + + false + + + false + + + + + + + + + + + + 10 + 10 + + + + true + + + true + + + false + + + QAbstractItemView::DragDrop + + + true + + + QAbstractItemView::SelectRows + + + false + + + false + + + + + - - - - - - - 100 - 10 - - - - true - - - true - - - false - - - QAbstractItemView::DragDrop - - - true - - - QAbstractItemView::SelectRows - - - false - - - false - - - - + + + + + + 0 + 0 + + + + + 30 + 0 + + - - - - - - - 10 - 10 - - - - true - - - true - - - false - - - QAbstractItemView::DragDrop - - - true - - - QAbstractItemView::SelectRows - - - false - - - false - - - - - - - - - - - - 10 - 10 - - - - true - - - true - - - false - - - QAbstractItemView::DragDrop - - - true - - - QAbstractItemView::SelectRows - - - false - - - false - - - - - - - - - - - - - - 0 - 0 - - - - - + + + + + diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 29e1901ce2..f1eeb23643 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -9,12 +9,6 @@ The database used to store ebook metadata import os, sys, shutil, cStringIO, glob,functools, traceback from itertools import repeat from math import floor -try: - from PIL import Image as PILImage - PILImage -except ImportError: - import Image as PILImage - from PyQt4.QtGui import QImage @@ -37,7 +31,7 @@ from calibre.utils.date import utcnow, now as nowf, utcfromtimestamp from calibre.utils.config import prefs from calibre.utils.search_query_parser import saved_searches from calibre.ebooks import BOOK_EXTENSIONS, check_ebook_format - +from calibre.utils.magick_draw import save_cover_data_to if iswindows: import calibre.utils.winshell as winshell @@ -475,11 +469,9 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): if callable(getattr(data, 'save', None)): data.save(path) else: - f = data - if not callable(getattr(data, 'read', None)): - f = cStringIO.StringIO(data) - im = PILImage.open(f) - im.convert('RGB').save(path, 'JPEG') + if callable(getattr(data, 'read', None)): + data = data.read() + save_cover_data_to(data, path) def book_on_device(self, id): if callable(self.book_on_device_func): diff --git a/src/calibre/library/server/content.py b/src/calibre/library/server/content.py index 12bd786322..4dd32eb284 100644 --- a/src/calibre/library/server/content.py +++ b/src/calibre/library/server/content.py @@ -127,10 +127,7 @@ class ContentServer(object): cherrypy.log('User agent: '+ua) if want_opds: - return self.stanza(search=kwargs.get('search', None), sortby=kwargs.get('sortby',None), authorid=kwargs.get('authorid',None), - tagid=kwargs.get('tagid',None), - seriesid=kwargs.get('seriesid',None), - offset=kwargs.get('offset', 0)) + return self.opds(version=0) if want_mobile: return self.mobile() diff --git a/src/calibre/manual/faq.rst b/src/calibre/manual/faq.rst index 99afc32b18..833d99f28e 100644 --- a/src/calibre/manual/faq.rst +++ b/src/calibre/manual/faq.rst @@ -157,7 +157,9 @@ If you get timeout errors while browsing the calibre catalog in Stanza, try incr Alternative for the iPad ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -As of |app| version 0.7.0, on windows and OS X you can plugin your iPad into the computer using its charging cable, and |app| will detect it and show you a list of books on the iPad. You can then use the Send to device button to send books directly to iBooks on the iPad. +As of |app| version 0.7.0, you can plugin your iPad into the computer using its charging cable, and |app| will detect it and show you a list of books on the iPad. You can then use the Send to device button to send books directly to iBooks on the iPad. + +This method only works on Windows XP and higher and OS X 10.5 and higher. Linux is not supported (iTunes is not available in linux) and OS X 10.4 is not supported. How do I use |app| with my Android phone? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/calibre/utils/magick_draw.py b/src/calibre/utils/magick_draw.py index aeb5bb2268..c4a6c1d76e 100644 --- a/src/calibre/utils/magick_draw.py +++ b/src/calibre/utils/magick_draw.py @@ -212,6 +212,23 @@ def create_cover_page(top_lines, logo_path, width=590, height=750, p.DestroyMagickWand(canvas) return ans +def save_cover_data_to(data, path, bgcolor='white'): + ''' + Saves image in data to path, in the format specified by the path + extension. Composes the image onto a blank cancas so as to + properly convert transparent images. + ''' + with open(path, 'wb') as f: + f.write(data) + with p.ImageMagick(): + img = load_image(path) + canvas = create_canvas(p.MagickGetImageWidth(img), + p.MagickGetImageHeight(img), bgcolor) + compose_image(canvas, img, 0, 0) + p.MagickWriteImage(canvas, path) + p.DestroyMagickWand(img) + p.DestroyMagickWand(canvas) + def test(): import subprocess with TemporaryFile('.png') as f: diff --git a/src/calibre/web/feeds/__init__.py b/src/calibre/web/feeds/__init__.py index bcb8c2d74f..da7122c491 100644 --- a/src/calibre/web/feeds/__init__.py +++ b/src/calibre/web/feeds/__init__.py @@ -11,7 +11,7 @@ from lxml import html from calibre.web.feeds.feedparser import parse from calibre.utils.logging import default_log -from calibre import entity_to_unicode +from calibre import entity_to_unicode, strftime from calibre.utils.date import dt_factory, utcnow, local_tz class Article(object): @@ -53,12 +53,17 @@ class Article(object): @dynamic_property def formatted_date(self): + def fget(self): if self._formatted_date is None: - self._formatted_date = self.localtime.strftime(" [%a, %d %b %H:%M]") + self._formatted_date = strftime(" [%a, %d %b %H:%M]", + t=self.localtime.timetuple()) return self._formatted_date + def fset(self, val): - self._formatted_date = val + if isinstance(val, unicode): + self._formatted_date = val + return property(fget=fget, fset=fset) @dynamic_property