mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
KG revisions
This commit is contained in:
commit
c5ac3d0348
@ -17,7 +17,7 @@ class Gizmodo(BasicNewsRecipe):
|
|||||||
max_articles_per_feed = 100
|
max_articles_per_feed = 100
|
||||||
no_stylesheets = True
|
no_stylesheets = True
|
||||||
encoding = 'utf-8'
|
encoding = 'utf-8'
|
||||||
use_embedded_content = True
|
use_embedded_content = False
|
||||||
language = 'en'
|
language = 'en'
|
||||||
masthead_url = 'http://cache.gawkerassets.com/assets/gizmodo.com/img/logo.png'
|
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} '
|
extra_css = ' body{font-family: "Lucida Grande",Helvetica,Arial,sans-serif} img{margin-bottom: 1em} '
|
||||||
@ -30,8 +30,10 @@ class Gizmodo(BasicNewsRecipe):
|
|||||||
}
|
}
|
||||||
|
|
||||||
remove_attributes = ['width','height']
|
remove_attributes = ['width','height']
|
||||||
remove_tags = [dict(name='div',attrs={'class':'feedflare'})]
|
keep_only_tags = [dict(attrs={'class':'content permalink'})]
|
||||||
remove_tags_after = dict(name='div',attrs={'class':'feedflare'})
|
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')]
|
feeds = [(u'Articles', u'http://feeds.gawker.com/gizmodo/full')]
|
||||||
|
|
||||||
|
@ -52,10 +52,12 @@ class Vreme(BasicNewsRecipe):
|
|||||||
def parse_index(self):
|
def parse_index(self):
|
||||||
articles = []
|
articles = []
|
||||||
soup = self.index_to_soup(self.INDEX)
|
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']):
|
for item in soup.findAll(['h3','h4']):
|
||||||
description = ''
|
description = u''
|
||||||
title_prefix = ''
|
title_prefix = u''
|
||||||
feed_link = item.find('a')
|
feed_link = item.find('a')
|
||||||
if feed_link and feed_link.has_key('href') and feed_link['href'].startswith('/cms/view.php'):
|
if feed_link and feed_link.has_key('href') and feed_link['href'].startswith('/cms/view.php'):
|
||||||
url = self.INDEX + feed_link['href']
|
url = self.INDEX + feed_link['href']
|
||||||
@ -67,7 +69,7 @@ class Vreme(BasicNewsRecipe):
|
|||||||
,'url' :url
|
,'url' :url
|
||||||
,'description':description
|
,'description':description
|
||||||
})
|
})
|
||||||
return [(soup.head.title.string, articles)]
|
return [('Nedeljnik Vreme', articles)]
|
||||||
|
|
||||||
remove_tags = [
|
remove_tags = [
|
||||||
dict(name=['object','link'])
|
dict(name=['object','link'])
|
||||||
@ -76,11 +78,3 @@ class Vreme(BasicNewsRecipe):
|
|||||||
|
|
||||||
def print_version(self, url):
|
def print_version(self, url):
|
||||||
return url + '&print=yes'
|
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
|
|
||||||
|
@ -6,8 +6,7 @@ __docformat__ = 'restructuredtext en'
|
|||||||
Device driver for the SONY devices
|
Device driver for the SONY devices
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import os
|
import os, time, re
|
||||||
import re
|
|
||||||
|
|
||||||
from calibre.devices.usbms.driver import USBMS
|
from calibre.devices.usbms.driver import USBMS
|
||||||
from calibre.devices.prs505 import MEDIA_XML
|
from calibre.devices.prs505 import MEDIA_XML
|
||||||
@ -66,6 +65,41 @@ class PRS505(USBMS):
|
|||||||
def windows_filter_pnp_id(self, pnp_id):
|
def windows_filter_pnp_id(self, pnp_id):
|
||||||
return '_LAUNCHER' in 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'''<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<cache xmlns="http://www.kinoma.com/FskCache/1">
|
||||||
|
</cache>
|
||||||
|
'''.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):
|
def get_device_information(self, end_session=True):
|
||||||
return (self.gui_name, '', '', '')
|
return (self.gui_name, '', '', '')
|
||||||
|
|
||||||
|
@ -415,10 +415,11 @@ class XMLCache(object):
|
|||||||
prints('\tmtime', strftime(os.path.getmtime(path)))
|
prints('\tmtime', strftime(os.path.getmtime(path)))
|
||||||
record.set('date', date)
|
record.set('date', date)
|
||||||
record.set('size', str(os.stat(path).st_size))
|
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
|
ts = book.title_sort
|
||||||
if not ts:
|
if not ts:
|
||||||
ts = title_sort(book.title)
|
ts = title_sort(title)
|
||||||
record.set('titleSorter', ts)
|
record.set('titleSorter', ts)
|
||||||
record.set('author', authors_to_string(book.authors))
|
record.set('author', authors_to_string(book.authors))
|
||||||
ext = os.path.splitext(path)[1]
|
ext = os.path.splitext(path)[1]
|
||||||
|
@ -226,7 +226,7 @@ class GuiRunner(QObject):
|
|||||||
self.splash_pixmap = QPixmap()
|
self.splash_pixmap = QPixmap()
|
||||||
self.splash_pixmap.load(I('library.png'))
|
self.splash_pixmap.load(I('library.png'))
|
||||||
self.splash_screen = QSplashScreen(self.splash_pixmap,
|
self.splash_screen = QSplashScreen(self.splash_pixmap,
|
||||||
Qt.SplashScreen|Qt.WindowStaysOnTopHint)
|
Qt.SplashScreen)
|
||||||
self.splash_screen.showMessage(_('Starting %s: Loading books...') %
|
self.splash_screen.showMessage(_('Starting %s: Loading books...') %
|
||||||
__appname__)
|
__appname__)
|
||||||
self.splash_screen.show()
|
self.splash_screen.show()
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
<normaloff>:/images/library.png</normaloff>:/images/library.png</iconset>
|
<normaloff>:/images/library.png</normaloff>:/images/library.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget">
|
<widget class="QWidget" name="centralwidget">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
<item>
|
<item>
|
||||||
@ -304,12 +304,10 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="Splitter" name="vertical_splitter">
|
<widget class="Splitter" name="vertical_splitter">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>100</verstretch>
|
<verstretch>100</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
@ -317,6 +315,9 @@
|
|||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<widget class="QWidget" name="layoutWidget">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
<widget class="QStackedWidget" name="stack">
|
<widget class="QStackedWidget" name="stack">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
@ -328,7 +329,7 @@
|
|||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="library">
|
<widget class="QWidget" name="library">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="Splitter" name="horizontal_splitter">
|
<widget class="Splitter" name="horizontal_splitter">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@ -539,8 +540,6 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="StatusBar" name="status_bar" native="true"/>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="SideBar" name="sidebar" native="true">
|
<widget class="SideBar" name="sidebar" native="true">
|
||||||
@ -550,9 +549,18 @@
|
|||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>30</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="StatusBar" name="status_bar" native="true"/>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -9,12 +9,6 @@ The database used to store ebook metadata
|
|||||||
import os, sys, shutil, cStringIO, glob,functools, traceback
|
import os, sys, shutil, cStringIO, glob,functools, traceback
|
||||||
from itertools import repeat
|
from itertools import repeat
|
||||||
from math import floor
|
from math import floor
|
||||||
try:
|
|
||||||
from PIL import Image as PILImage
|
|
||||||
PILImage
|
|
||||||
except ImportError:
|
|
||||||
import Image as PILImage
|
|
||||||
|
|
||||||
|
|
||||||
from PyQt4.QtGui import QImage
|
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.config import prefs
|
||||||
from calibre.utils.search_query_parser import saved_searches
|
from calibre.utils.search_query_parser import saved_searches
|
||||||
from calibre.ebooks import BOOK_EXTENSIONS, check_ebook_format
|
from calibre.ebooks import BOOK_EXTENSIONS, check_ebook_format
|
||||||
|
from calibre.utils.magick_draw import save_cover_data_to
|
||||||
|
|
||||||
if iswindows:
|
if iswindows:
|
||||||
import calibre.utils.winshell as winshell
|
import calibre.utils.winshell as winshell
|
||||||
@ -475,11 +469,9 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
if callable(getattr(data, 'save', None)):
|
if callable(getattr(data, 'save', None)):
|
||||||
data.save(path)
|
data.save(path)
|
||||||
else:
|
else:
|
||||||
f = data
|
if callable(getattr(data, 'read', None)):
|
||||||
if not callable(getattr(data, 'read', None)):
|
data = data.read()
|
||||||
f = cStringIO.StringIO(data)
|
save_cover_data_to(data, path)
|
||||||
im = PILImage.open(f)
|
|
||||||
im.convert('RGB').save(path, 'JPEG')
|
|
||||||
|
|
||||||
def book_on_device(self, id):
|
def book_on_device(self, id):
|
||||||
if callable(self.book_on_device_func):
|
if callable(self.book_on_device_func):
|
||||||
|
@ -127,10 +127,7 @@ class ContentServer(object):
|
|||||||
cherrypy.log('User agent: '+ua)
|
cherrypy.log('User agent: '+ua)
|
||||||
|
|
||||||
if want_opds:
|
if want_opds:
|
||||||
return self.stanza(search=kwargs.get('search', None), sortby=kwargs.get('sortby',None), authorid=kwargs.get('authorid',None),
|
return self.opds(version=0)
|
||||||
tagid=kwargs.get('tagid',None),
|
|
||||||
seriesid=kwargs.get('seriesid',None),
|
|
||||||
offset=kwargs.get('offset', 0))
|
|
||||||
|
|
||||||
if want_mobile:
|
if want_mobile:
|
||||||
return self.mobile()
|
return self.mobile()
|
||||||
|
@ -157,7 +157,9 @@ If you get timeout errors while browsing the calibre catalog in Stanza, try incr
|
|||||||
Alternative for the iPad
|
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?
|
How do I use |app| with my Android phone?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -212,6 +212,23 @@ def create_cover_page(top_lines, logo_path, width=590, height=750,
|
|||||||
p.DestroyMagickWand(canvas)
|
p.DestroyMagickWand(canvas)
|
||||||
return ans
|
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():
|
def test():
|
||||||
import subprocess
|
import subprocess
|
||||||
with TemporaryFile('.png') as f:
|
with TemporaryFile('.png') as f:
|
||||||
|
@ -11,7 +11,7 @@ from lxml import html
|
|||||||
|
|
||||||
from calibre.web.feeds.feedparser import parse
|
from calibre.web.feeds.feedparser import parse
|
||||||
from calibre.utils.logging import default_log
|
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
|
from calibre.utils.date import dt_factory, utcnow, local_tz
|
||||||
|
|
||||||
class Article(object):
|
class Article(object):
|
||||||
@ -53,12 +53,17 @@ class Article(object):
|
|||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def formatted_date(self):
|
def formatted_date(self):
|
||||||
|
|
||||||
def fget(self):
|
def fget(self):
|
||||||
if self._formatted_date is None:
|
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
|
return self._formatted_date
|
||||||
|
|
||||||
def fset(self, val):
|
def fset(self, val):
|
||||||
|
if isinstance(val, unicode):
|
||||||
self._formatted_date = val
|
self._formatted_date = val
|
||||||
|
|
||||||
return property(fget=fget, fset=fset)
|
return property(fget=fget, fset=fset)
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
|
Loading…
x
Reference in New Issue
Block a user