mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
0.9.16
This commit is contained in:
commit
efd98fe54c
@ -19,6 +19,64 @@
|
||||
# new recipes:
|
||||
# - title:
|
||||
|
||||
- version: 0.9.16
|
||||
date: 2013-01-25
|
||||
|
||||
new features:
|
||||
- title: "News download: Add support for logging in to sites that require javascript for their logins."
|
||||
tickets: [1101809]
|
||||
|
||||
- title: "News download: Do not convert all downloaded images to JPG format. This fixes the problem of PNG images with transparent backgrounds being rendered with black backgrounds"
|
||||
|
||||
- title: "CHM Input: Support hierarchical table of contents. Do not generate an inline table of contents when a metadata table of contents is present. Also correctly decode the text in the table of contents"
|
||||
|
||||
- title: "Get Books: Add the beam-ebooks.de store"
|
||||
|
||||
- title: "Make custom yes/no columns using icons put text values under the icons."
|
||||
|
||||
- title: "Driver for LG E400 and SayCoolA710"
|
||||
tickets: [1103741,1104528]
|
||||
|
||||
- title: "Speed up device connection when there are lots of books on the device by not generating cover thumbnails unless they are actually needed."
|
||||
|
||||
- title: "Have the metadata download dialog remember its last used size."
|
||||
tickets: [1101150]
|
||||
|
||||
bug fixes:
|
||||
- title: "Fix deleting a custom column that was used in a column coloring rule makes the column coloring preferences panel unusable"
|
||||
tickets: [1103504]
|
||||
|
||||
- title: "Store caches outside the config directory for non-portable calibre installs"
|
||||
|
||||
- title: "PDF Output: Dont crash if the user has a font on his system that is missing the OS/2 table"
|
||||
tickets: [1102403]
|
||||
|
||||
- title: "Conversion: Do not error out because of an error in user supplied search replace rules."
|
||||
tickets: [1102647]
|
||||
|
||||
- title: "Conversion: Replace all non-ascii characters in CSS class names, as they cause problems with some broken EPUB renderers."
|
||||
tickets: [1102587]
|
||||
|
||||
- title: "Do not choke when reading metadata from MOBI files with incorrectly encoded metadata fields"
|
||||
|
||||
- title: "Conversion: Preserve ToC entries that point nowhere instead of causing them to point to a non-existent file"
|
||||
|
||||
- title: "E-book viewer: Allow entries in the Table of Contents that do not point anywhere, instead of just ignoring them."
|
||||
|
||||
- title: "Content server: Fix the 'Previous' link in the mobile version of the content server webpage skipping an entry"
|
||||
tickets: [1101124]
|
||||
|
||||
improved recipes:
|
||||
- TSN
|
||||
- St. Louis Post Dispatch
|
||||
- Metro UK
|
||||
- Michelle Malkin
|
||||
- Barrons
|
||||
|
||||
new recipes:
|
||||
- title: Contemporary Argentine Writers
|
||||
author: Darko Miletic
|
||||
|
||||
- version: 0.9.15
|
||||
date: 2013-01-18
|
||||
|
||||
|
35
recipes/contemporary_argentine_writers.recipe
Normal file
35
recipes/contemporary_argentine_writers.recipe
Normal file
@ -0,0 +1,35 @@
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2013, Darko Miletic <darko.miletic at gmail.com>'
|
||||
'''
|
||||
contemporaryargentinewriters.wordpress.com
|
||||
'''
|
||||
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
|
||||
class contemporaryargentinewriters(BasicNewsRecipe):
|
||||
title = 'Contemporary Argentine Writers'
|
||||
__author__ = 'Darko Miletic'
|
||||
description = 'Short stories by Argentine writers (and others) translated into English'
|
||||
publisher = 'Dario Bard'
|
||||
category = 'fiction, literature, Argentina, english'
|
||||
oldest_article = 25
|
||||
max_articles_per_feed = 200
|
||||
no_stylesheets = True
|
||||
encoding = 'utf8'
|
||||
use_embedded_content = True
|
||||
language = 'en_AR'
|
||||
remove_empty_feeds = True
|
||||
publication_type = 'blog'
|
||||
extra_css = """
|
||||
body{font-family: Arial,Helvetica,sans-serif }
|
||||
img{margin-bottom: 0.4em; display:block}
|
||||
"""
|
||||
|
||||
conversion_options = {
|
||||
'comment' : description
|
||||
, 'tags' : category
|
||||
, 'publisher' : publisher
|
||||
, 'language' : language
|
||||
}
|
||||
|
||||
feeds = [(u'Posts', u'http://contemporaryargentinewriters.wordpress.com/feed/')]
|
@ -12,14 +12,14 @@ msgstr ""
|
||||
"Report-Msgid-Bugs-To: Debian iso-codes team <pkg-isocodes-"
|
||||
"devel@lists.alioth.debian.org>\n"
|
||||
"POT-Creation-Date: 2011-11-25 14:01+0000\n"
|
||||
"PO-Revision-Date: 2012-12-31 12:50+0000\n"
|
||||
"PO-Revision-Date: 2013-01-19 20:28+0000\n"
|
||||
"Last-Translator: Ferran Rius <frius64@hotmail.com>\n"
|
||||
"Language-Team: Catalan <linux@softcatala.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-01-01 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 16378)\n"
|
||||
"X-Launchpad-Export-Date: 2013-01-20 04:36+0000\n"
|
||||
"X-Generator: Launchpad (build 16430)\n"
|
||||
"Language: ca\n"
|
||||
|
||||
#. name for aaa
|
||||
@ -20216,7 +20216,7 @@ msgstr "Panjabi"
|
||||
|
||||
#. name for pao
|
||||
msgid "Paiute; Northern"
|
||||
msgstr ""
|
||||
msgstr "Paiute Nord"
|
||||
|
||||
#. name for pap
|
||||
msgid "Papiamento"
|
||||
@ -20280,7 +20280,7 @@ msgstr "Popoloca; Coyotepec"
|
||||
|
||||
#. name for pbg
|
||||
msgid "Paraujano"
|
||||
msgstr ""
|
||||
msgstr "Paraujano"
|
||||
|
||||
#. name for pbh
|
||||
msgid "E'ñapa Woromaipu"
|
||||
@ -20308,31 +20308,31 @@ msgstr ""
|
||||
|
||||
#. name for pbr
|
||||
msgid "Pangwa"
|
||||
msgstr ""
|
||||
msgstr "Pangwa"
|
||||
|
||||
#. name for pbs
|
||||
msgid "Pame; Central"
|
||||
msgstr ""
|
||||
msgstr "Pame; Central"
|
||||
|
||||
#. name for pbt
|
||||
msgid "Pashto; Southern"
|
||||
msgstr ""
|
||||
msgstr "Paixtú; Meridional"
|
||||
|
||||
#. name for pbu
|
||||
msgid "Pashto; Northern"
|
||||
msgstr ""
|
||||
msgstr "Paixtú; Septentrional"
|
||||
|
||||
#. name for pbv
|
||||
msgid "Pnar"
|
||||
msgstr ""
|
||||
msgstr "Pnar"
|
||||
|
||||
#. name for pby
|
||||
msgid "Pyu"
|
||||
msgstr ""
|
||||
msgstr "Pyu (Nova Guinea Papua)"
|
||||
|
||||
#. name for pbz
|
||||
msgid "Palu"
|
||||
msgstr ""
|
||||
msgstr "Palu"
|
||||
|
||||
#. name for pca
|
||||
msgid "Popoloca; Santa Inés Ahuatempan"
|
||||
@ -20340,7 +20340,7 @@ msgstr "Popoloca; Ahuatempan"
|
||||
|
||||
#. name for pcb
|
||||
msgid "Pear"
|
||||
msgstr ""
|
||||
msgstr "Pear"
|
||||
|
||||
#. name for pcc
|
||||
msgid "Bouyei"
|
||||
@ -20348,23 +20348,23 @@ msgstr ""
|
||||
|
||||
#. name for pcd
|
||||
msgid "Picard"
|
||||
msgstr ""
|
||||
msgstr "Picard"
|
||||
|
||||
#. name for pce
|
||||
msgid "Palaung; Ruching"
|
||||
msgstr ""
|
||||
msgstr "Palaung; Pale"
|
||||
|
||||
#. name for pcf
|
||||
msgid "Paliyan"
|
||||
msgstr ""
|
||||
msgstr "Paliyà"
|
||||
|
||||
#. name for pcg
|
||||
msgid "Paniya"
|
||||
msgstr ""
|
||||
msgstr "Paniya"
|
||||
|
||||
#. name for pch
|
||||
msgid "Pardhan"
|
||||
msgstr ""
|
||||
msgstr "Pardhan"
|
||||
|
||||
#. name for pci
|
||||
msgid "Duruwa"
|
||||
@ -20372,7 +20372,7 @@ msgstr ""
|
||||
|
||||
#. name for pcj
|
||||
msgid "Parenga"
|
||||
msgstr ""
|
||||
msgstr "Parenga"
|
||||
|
||||
#. name for pck
|
||||
msgid "Chin; Paite"
|
||||
@ -20380,7 +20380,7 @@ msgstr "Chin; Paite"
|
||||
|
||||
#. name for pcl
|
||||
msgid "Pardhi"
|
||||
msgstr ""
|
||||
msgstr "Pardhi"
|
||||
|
||||
#. name for pcm
|
||||
msgid "Pidgin; Nigerian"
|
||||
@ -20388,19 +20388,19 @@ msgstr "Crioll nigerià"
|
||||
|
||||
#. name for pcn
|
||||
msgid "Piti"
|
||||
msgstr ""
|
||||
msgstr "Piti"
|
||||
|
||||
#. name for pcp
|
||||
msgid "Pacahuara"
|
||||
msgstr ""
|
||||
msgstr "Pacahuara"
|
||||
|
||||
#. name for pcr
|
||||
msgid "Panang"
|
||||
msgstr ""
|
||||
msgstr "Panang"
|
||||
|
||||
#. name for pcw
|
||||
msgid "Pyapun"
|
||||
msgstr ""
|
||||
msgstr "Pyapun"
|
||||
|
||||
#. name for pda
|
||||
msgid "Anam"
|
||||
@ -20412,19 +20412,19 @@ msgstr "Alemany; Pensilvàmia"
|
||||
|
||||
#. name for pdi
|
||||
msgid "Pa Di"
|
||||
msgstr ""
|
||||
msgstr "Padi"
|
||||
|
||||
#. name for pdn
|
||||
msgid "Podena"
|
||||
msgstr ""
|
||||
msgstr "Podena"
|
||||
|
||||
#. name for pdo
|
||||
msgid "Padoe"
|
||||
msgstr ""
|
||||
msgstr "Padoe"
|
||||
|
||||
#. name for pdt
|
||||
msgid "Plautdietsch"
|
||||
msgstr ""
|
||||
msgstr "Plautdeitsch"
|
||||
|
||||
#. name for pdu
|
||||
msgid "Kayan"
|
||||
@ -20436,7 +20436,7 @@ msgstr ""
|
||||
|
||||
#. name for peb
|
||||
msgid "Pomo; Eastern"
|
||||
msgstr ""
|
||||
msgstr "Pomo; Oriental"
|
||||
|
||||
#. name for ped
|
||||
msgid "Mala (Papua New Guinea)"
|
||||
@ -20448,11 +20448,11 @@ msgstr ""
|
||||
|
||||
#. name for pef
|
||||
msgid "Pomo; Northeastern"
|
||||
msgstr ""
|
||||
msgstr "Pomo; Nordoriental"
|
||||
|
||||
#. name for peg
|
||||
msgid "Pengo"
|
||||
msgstr ""
|
||||
msgstr "Pengo"
|
||||
|
||||
#. name for peh
|
||||
msgid "Bonan"
|
||||
@ -20464,23 +20464,23 @@ msgstr ""
|
||||
|
||||
#. name for pej
|
||||
msgid "Pomo; Northern"
|
||||
msgstr ""
|
||||
msgstr "Pomo; Septentrional"
|
||||
|
||||
#. name for pek
|
||||
msgid "Penchal"
|
||||
msgstr ""
|
||||
msgstr "Penchal"
|
||||
|
||||
#. name for pel
|
||||
msgid "Pekal"
|
||||
msgstr ""
|
||||
msgstr "Pekal"
|
||||
|
||||
#. name for pem
|
||||
msgid "Phende"
|
||||
msgstr ""
|
||||
msgstr "Phende"
|
||||
|
||||
#. name for peo
|
||||
msgid "Persian; Old (ca. 600-400 B.C.)"
|
||||
msgstr ""
|
||||
msgstr "Persa Antic"
|
||||
|
||||
#. name for pep
|
||||
msgid "Kunja"
|
||||
@ -20488,39 +20488,39 @@ msgstr ""
|
||||
|
||||
#. name for peq
|
||||
msgid "Pomo; Southern"
|
||||
msgstr ""
|
||||
msgstr "Pomo; Meridional"
|
||||
|
||||
#. name for pes
|
||||
msgid "Persian; Iranian"
|
||||
msgstr ""
|
||||
msgstr "Farsi; Occidental"
|
||||
|
||||
#. name for pev
|
||||
msgid "Pémono"
|
||||
msgstr ""
|
||||
msgstr "Pemono"
|
||||
|
||||
#. name for pex
|
||||
msgid "Petats"
|
||||
msgstr ""
|
||||
msgstr "Petats"
|
||||
|
||||
#. name for pey
|
||||
msgid "Petjo"
|
||||
msgstr ""
|
||||
msgstr "Petjo"
|
||||
|
||||
#. name for pez
|
||||
msgid "Penan; Eastern"
|
||||
msgstr ""
|
||||
msgstr "Penan; Oriental"
|
||||
|
||||
#. name for pfa
|
||||
msgid "Pááfang"
|
||||
msgstr ""
|
||||
msgstr "Paafang"
|
||||
|
||||
#. name for pfe
|
||||
msgid "Peere"
|
||||
msgstr ""
|
||||
msgstr "Peere"
|
||||
|
||||
#. name for pfl
|
||||
msgid "Pfaelzisch"
|
||||
msgstr ""
|
||||
msgstr "Pfaelzisch"
|
||||
|
||||
#. name for pga
|
||||
msgid "Creole Arabic; Sudanese"
|
||||
@ -20528,11 +20528,11 @@ msgstr "Àrab crioll; sudanès"
|
||||
|
||||
#. name for pgg
|
||||
msgid "Pangwali"
|
||||
msgstr ""
|
||||
msgstr "Pangwali"
|
||||
|
||||
#. name for pgi
|
||||
msgid "Pagi"
|
||||
msgstr ""
|
||||
msgstr "Pagi"
|
||||
|
||||
#. name for pgk
|
||||
msgid "Rerep"
|
||||
@ -20544,83 +20544,83 @@ msgstr "Irlandès; primitiu"
|
||||
|
||||
#. name for pgn
|
||||
msgid "Paelignian"
|
||||
msgstr ""
|
||||
msgstr "Paelignià"
|
||||
|
||||
#. name for pgs
|
||||
msgid "Pangseng"
|
||||
msgstr ""
|
||||
msgstr "Pangseng"
|
||||
|
||||
#. name for pgu
|
||||
msgid "Pagu"
|
||||
msgstr ""
|
||||
msgstr "Pagu"
|
||||
|
||||
#. name for pgy
|
||||
msgid "Pongyong"
|
||||
msgstr ""
|
||||
msgstr "Pongyong"
|
||||
|
||||
#. name for pha
|
||||
msgid "Pa-Hng"
|
||||
msgstr ""
|
||||
msgstr "Baheng"
|
||||
|
||||
#. name for phd
|
||||
msgid "Phudagi"
|
||||
msgstr ""
|
||||
msgstr "Phudagi"
|
||||
|
||||
#. name for phg
|
||||
msgid "Phuong"
|
||||
msgstr ""
|
||||
msgstr "Phuong"
|
||||
|
||||
#. name for phh
|
||||
msgid "Phukha"
|
||||
msgstr ""
|
||||
msgstr "Phula"
|
||||
|
||||
#. name for phk
|
||||
msgid "Phake"
|
||||
msgstr ""
|
||||
msgstr "Phake"
|
||||
|
||||
#. name for phl
|
||||
msgid "Phalura"
|
||||
msgstr ""
|
||||
msgstr "Phalura"
|
||||
|
||||
#. name for phm
|
||||
msgid "Phimbi"
|
||||
msgstr ""
|
||||
msgstr "Phimbi"
|
||||
|
||||
#. name for phn
|
||||
msgid "Phoenician"
|
||||
msgstr ""
|
||||
msgstr "Fenici"
|
||||
|
||||
#. name for pho
|
||||
msgid "Phunoi"
|
||||
msgstr ""
|
||||
msgstr "Phunoi"
|
||||
|
||||
#. name for phq
|
||||
msgid "Phana'"
|
||||
msgstr ""
|
||||
msgstr "Phana"
|
||||
|
||||
#. name for phr
|
||||
msgid "Pahari-Potwari"
|
||||
msgstr ""
|
||||
msgstr "Pahari; Potwari"
|
||||
|
||||
#. name for pht
|
||||
msgid "Phu Thai"
|
||||
msgstr ""
|
||||
msgstr "Phu Thai"
|
||||
|
||||
#. name for phu
|
||||
msgid "Phuan"
|
||||
msgstr ""
|
||||
msgstr "Phuan"
|
||||
|
||||
#. name for phv
|
||||
msgid "Pahlavani"
|
||||
msgstr ""
|
||||
msgstr "Pahlavani"
|
||||
|
||||
#. name for phw
|
||||
msgid "Phangduwali"
|
||||
msgstr ""
|
||||
msgstr "Phangduwali"
|
||||
|
||||
#. name for pia
|
||||
msgid "Pima Bajo"
|
||||
msgstr ""
|
||||
msgstr "Pima Baix"
|
||||
|
||||
#. name for pib
|
||||
msgid "Yine"
|
||||
@ -20628,35 +20628,35 @@ msgstr ""
|
||||
|
||||
#. name for pic
|
||||
msgid "Pinji"
|
||||
msgstr ""
|
||||
msgstr "Pinji"
|
||||
|
||||
#. name for pid
|
||||
msgid "Piaroa"
|
||||
msgstr ""
|
||||
msgstr "Piaroa"
|
||||
|
||||
#. name for pie
|
||||
msgid "Piro"
|
||||
msgstr ""
|
||||
msgstr "Piro"
|
||||
|
||||
#. name for pif
|
||||
msgid "Pingelapese"
|
||||
msgstr ""
|
||||
msgstr "Pingelapès"
|
||||
|
||||
#. name for pig
|
||||
msgid "Pisabo"
|
||||
msgstr ""
|
||||
msgstr "Pisabo"
|
||||
|
||||
#. name for pih
|
||||
msgid "Pitcairn-Norfolk"
|
||||
msgstr ""
|
||||
msgstr "Pitcairn-Norfolk"
|
||||
|
||||
#. name for pii
|
||||
msgid "Pini"
|
||||
msgstr ""
|
||||
msgstr "Pini"
|
||||
|
||||
#. name for pij
|
||||
msgid "Pijao"
|
||||
msgstr ""
|
||||
msgstr "Pijao"
|
||||
|
||||
#. name for pil
|
||||
msgid "Yom"
|
||||
@ -20664,59 +20664,59 @@ msgstr ""
|
||||
|
||||
#. name for pim
|
||||
msgid "Powhatan"
|
||||
msgstr ""
|
||||
msgstr "Powhatan"
|
||||
|
||||
#. name for pin
|
||||
msgid "Piame"
|
||||
msgstr ""
|
||||
msgstr "Piame"
|
||||
|
||||
#. name for pio
|
||||
msgid "Piapoco"
|
||||
msgstr ""
|
||||
msgstr "Piapoco"
|
||||
|
||||
#. name for pip
|
||||
msgid "Pero"
|
||||
msgstr ""
|
||||
msgstr "Pero"
|
||||
|
||||
#. name for pir
|
||||
msgid "Piratapuyo"
|
||||
msgstr ""
|
||||
msgstr "Piratapuyo"
|
||||
|
||||
#. name for pis
|
||||
msgid "Pijin"
|
||||
msgstr ""
|
||||
msgstr "Pijin"
|
||||
|
||||
#. name for pit
|
||||
msgid "Pitta Pitta"
|
||||
msgstr ""
|
||||
msgstr "Pita Pita"
|
||||
|
||||
#. name for piu
|
||||
msgid "Pintupi-Luritja"
|
||||
msgstr ""
|
||||
msgstr "Pintupi-Luritja"
|
||||
|
||||
#. name for piv
|
||||
msgid "Pileni"
|
||||
msgstr ""
|
||||
msgstr "Pileni"
|
||||
|
||||
#. name for piw
|
||||
msgid "Pimbwe"
|
||||
msgstr ""
|
||||
msgstr "Pimbwe"
|
||||
|
||||
#. name for pix
|
||||
msgid "Piu"
|
||||
msgstr ""
|
||||
msgstr "Piu"
|
||||
|
||||
#. name for piy
|
||||
msgid "Piya-Kwonci"
|
||||
msgstr ""
|
||||
msgstr "Piya-Kwonci"
|
||||
|
||||
#. name for piz
|
||||
msgid "Pije"
|
||||
msgstr ""
|
||||
msgstr "Pije"
|
||||
|
||||
#. name for pjt
|
||||
msgid "Pitjantjatjara"
|
||||
msgstr ""
|
||||
msgstr "Pitjantjatjara"
|
||||
|
||||
#. name for pka
|
||||
msgid "Prākrit; Ardhamāgadhī"
|
||||
@ -20724,31 +20724,31 @@ msgstr ""
|
||||
|
||||
#. name for pkb
|
||||
msgid "Pokomo"
|
||||
msgstr ""
|
||||
msgstr "Pokomo"
|
||||
|
||||
#. name for pkc
|
||||
msgid "Paekche"
|
||||
msgstr ""
|
||||
msgstr "Paekche"
|
||||
|
||||
#. name for pkg
|
||||
msgid "Pak-Tong"
|
||||
msgstr ""
|
||||
msgstr "Pak-Tong"
|
||||
|
||||
#. name for pkh
|
||||
msgid "Pankhu"
|
||||
msgstr ""
|
||||
msgstr "Pankhu"
|
||||
|
||||
#. name for pkn
|
||||
msgid "Pakanha"
|
||||
msgstr ""
|
||||
msgstr "Pakanha"
|
||||
|
||||
#. name for pko
|
||||
msgid "Pökoot"
|
||||
msgstr ""
|
||||
msgstr "Pokoot"
|
||||
|
||||
#. name for pkp
|
||||
msgid "Pukapuka"
|
||||
msgstr ""
|
||||
msgstr "Pukapuka"
|
||||
|
||||
#. name for pkr
|
||||
msgid "Kurumba; Attapady"
|
||||
@ -20764,7 +20764,7 @@ msgstr ""
|
||||
|
||||
#. name for pku
|
||||
msgid "Paku"
|
||||
msgstr ""
|
||||
msgstr "Paku"
|
||||
|
||||
#. name for pla
|
||||
msgid "Miani"
|
||||
@ -20772,7 +20772,7 @@ msgstr ""
|
||||
|
||||
#. name for plb
|
||||
msgid "Polonombauk"
|
||||
msgstr ""
|
||||
msgstr "Polonombauk"
|
||||
|
||||
#. name for plc
|
||||
msgid "Palawano; Central"
|
||||
@ -20808,7 +20808,7 @@ msgstr ""
|
||||
|
||||
#. name for pll
|
||||
msgid "Palaung; Shwe"
|
||||
msgstr ""
|
||||
msgstr "Palaung; Shwe"
|
||||
|
||||
#. name for pln
|
||||
msgid "Palenquero"
|
||||
@ -20900,7 +20900,7 @@ msgstr ""
|
||||
|
||||
#. name for pmm
|
||||
msgid "Pomo"
|
||||
msgstr ""
|
||||
msgstr "Pol"
|
||||
|
||||
#. name for pmn
|
||||
msgid "Pam"
|
||||
@ -20912,7 +20912,7 @@ msgstr ""
|
||||
|
||||
#. name for pmq
|
||||
msgid "Pame; Northern"
|
||||
msgstr ""
|
||||
msgstr "Pame; Septentrional"
|
||||
|
||||
#. name for pmr
|
||||
msgid "Paynamar"
|
||||
@ -20944,7 +20944,7 @@ msgstr "Malai; Papua"
|
||||
|
||||
#. name for pmz
|
||||
msgid "Pame; Southern"
|
||||
msgstr ""
|
||||
msgstr "Pame; Meridional"
|
||||
|
||||
#. name for pna
|
||||
msgid "Punan Bah-Biau"
|
||||
@ -20960,7 +20960,7 @@ msgstr ""
|
||||
|
||||
#. name for pne
|
||||
msgid "Penan; Western"
|
||||
msgstr ""
|
||||
msgstr "Penan; Occidental"
|
||||
|
||||
#. name for png
|
||||
msgid "Pongu"
|
||||
@ -21068,7 +21068,7 @@ msgstr "Polonès"
|
||||
|
||||
#. name for pom
|
||||
msgid "Pomo; Southeastern"
|
||||
msgstr ""
|
||||
msgstr "Pomo; Sudoriental"
|
||||
|
||||
#. name for pon
|
||||
msgid "Pohnpeian"
|
||||
@ -21076,7 +21076,7 @@ msgstr ""
|
||||
|
||||
#. name for poo
|
||||
msgid "Pomo; Central"
|
||||
msgstr ""
|
||||
msgstr "Pomo; Central"
|
||||
|
||||
#. name for pop
|
||||
msgid "Pwapwa"
|
||||
@ -21244,7 +21244,7 @@ msgstr ""
|
||||
|
||||
#. name for prs
|
||||
msgid "Persian; Afghan"
|
||||
msgstr ""
|
||||
msgstr "Farsi; Oriental"
|
||||
|
||||
#. name for prt
|
||||
msgid "Phai"
|
||||
@ -21332,7 +21332,7 @@ msgstr ""
|
||||
|
||||
#. name for pst
|
||||
msgid "Pashto; Central"
|
||||
msgstr ""
|
||||
msgstr "Paixtú; Central"
|
||||
|
||||
#. name for psu
|
||||
msgid "Prākrit; Sauraseni"
|
||||
@ -21884,7 +21884,7 @@ msgstr ""
|
||||
|
||||
#. name for rbb
|
||||
msgid "Palaung; Rumai"
|
||||
msgstr ""
|
||||
msgstr "Palaung; Rumai"
|
||||
|
||||
#. name for rbk
|
||||
msgid "Bontok; Northern"
|
||||
|
@ -18,14 +18,14 @@ msgstr ""
|
||||
"Report-Msgid-Bugs-To: Debian iso-codes team <pkg-isocodes-"
|
||||
"devel@lists.alioth.debian.org>\n"
|
||||
"POT-Creation-Date: 2011-11-25 14:01+0000\n"
|
||||
"PO-Revision-Date: 2012-11-08 15:28+0000\n"
|
||||
"Last-Translator: Elmux <bla.mail@gmx.net>\n"
|
||||
"PO-Revision-Date: 2013-01-19 18:12+0000\n"
|
||||
"Last-Translator: Dennis Baudys <Unknown>\n"
|
||||
"Language-Team: German <debian-l10n-german@lists.debian.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-11-09 04:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16250)\n"
|
||||
"X-Launchpad-Export-Date: 2013-01-20 04:36+0000\n"
|
||||
"X-Generator: Launchpad (build 16430)\n"
|
||||
"Language: de\n"
|
||||
|
||||
#. name for aaa
|
||||
@ -1432,11 +1432,11 @@ msgstr "Arrarnta; Westlich"
|
||||
|
||||
#. name for arg
|
||||
msgid "Aragonese"
|
||||
msgstr "Aragonese"
|
||||
msgstr "Aragonesisch"
|
||||
|
||||
#. name for arh
|
||||
msgid "Arhuaco"
|
||||
msgstr ""
|
||||
msgstr "Arhuaco"
|
||||
|
||||
#. name for ari
|
||||
msgid "Arikara"
|
||||
@ -17702,15 +17702,15 @@ msgstr ""
|
||||
|
||||
#. name for nau
|
||||
msgid "Nauru"
|
||||
msgstr "Nauruanisch"
|
||||
msgstr "Nauruisch"
|
||||
|
||||
#. name for nav
|
||||
msgid "Navajo"
|
||||
msgstr ""
|
||||
msgstr "Navajo"
|
||||
|
||||
#. name for naw
|
||||
msgid "Nawuri"
|
||||
msgstr ""
|
||||
msgstr "Nawuri"
|
||||
|
||||
#. name for nax
|
||||
msgid "Nakwi"
|
||||
@ -29894,7 +29894,7 @@ msgstr ""
|
||||
|
||||
#. name for yor
|
||||
msgid "Yoruba"
|
||||
msgstr "Joruba"
|
||||
msgstr "Yoruba"
|
||||
|
||||
#. name for yos
|
||||
msgid "Yos"
|
||||
|
@ -13,14 +13,14 @@ msgstr ""
|
||||
"Report-Msgid-Bugs-To: Debian iso-codes team <pkg-isocodes-"
|
||||
"devel@lists.alioth.debian.org>\n"
|
||||
"POT-Creation-Date: 2011-11-25 14:01+0000\n"
|
||||
"PO-Revision-Date: 2012-10-20 00:57+0000\n"
|
||||
"Last-Translator: Ida Leter <iatheia@yandex.ru>\n"
|
||||
"PO-Revision-Date: 2013-01-21 14:06+0000\n"
|
||||
"Last-Translator: Don Miguel <bmv@mail.ru>\n"
|
||||
"Language-Team: Russian <debian-l10n-russian@lists.debian.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2012-10-21 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16165)\n"
|
||||
"X-Launchpad-Export-Date: 2013-01-22 04:46+0000\n"
|
||||
"X-Generator: Launchpad (build 16430)\n"
|
||||
"Language: ru\n"
|
||||
|
||||
#. name for aaa
|
||||
@ -181,7 +181,7 @@ msgstr "Айта; Абенлен"
|
||||
|
||||
#. name for abq
|
||||
msgid "Abaza"
|
||||
msgstr ""
|
||||
msgstr "Абазинский"
|
||||
|
||||
#. name for abr
|
||||
msgid "Abron"
|
||||
@ -189,7 +189,7 @@ msgstr "Аброн"
|
||||
|
||||
#. name for abs
|
||||
msgid "Malay; Ambonese"
|
||||
msgstr ""
|
||||
msgstr "Малайский"
|
||||
|
||||
#. name for abt
|
||||
msgid "Ambulas"
|
||||
@ -205,31 +205,31 @@ msgstr ""
|
||||
|
||||
#. name for abw
|
||||
msgid "Pal"
|
||||
msgstr ""
|
||||
msgstr "Палский"
|
||||
|
||||
#. name for abx
|
||||
msgid "Inabaknon"
|
||||
msgstr ""
|
||||
msgstr "Абакнонский"
|
||||
|
||||
#. name for aby
|
||||
msgid "Aneme Wake"
|
||||
msgstr ""
|
||||
msgstr "Анеме Ваке"
|
||||
|
||||
#. name for abz
|
||||
msgid "Abui"
|
||||
msgstr ""
|
||||
msgstr "Абуи"
|
||||
|
||||
#. name for aca
|
||||
msgid "Achagua"
|
||||
msgstr ""
|
||||
msgstr "Ачагуа"
|
||||
|
||||
#. name for acb
|
||||
msgid "Áncá"
|
||||
msgstr ""
|
||||
msgstr "Анка"
|
||||
|
||||
#. name for acd
|
||||
msgid "Gikyode"
|
||||
msgstr ""
|
||||
msgstr "Гикиод"
|
||||
|
||||
#. name for ace
|
||||
msgid "Achinese"
|
||||
@ -261,7 +261,7 @@ msgstr ""
|
||||
|
||||
#. name for acn
|
||||
msgid "Achang"
|
||||
msgstr ""
|
||||
msgstr "Ачанг"
|
||||
|
||||
#. name for acp
|
||||
msgid "Acipa; Eastern"
|
||||
|
@ -4,7 +4,7 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
__appname__ = u'calibre'
|
||||
numeric_version = (0, 9, 15)
|
||||
numeric_version = (0, 9, 16)
|
||||
__version__ = u'.'.join(map(unicode, numeric_version))
|
||||
__author__ = u"Kovid Goyal <kovid@kovidgoyal.net>"
|
||||
|
||||
|
@ -1280,6 +1280,17 @@ class StoreBNStore(StoreBase):
|
||||
headquarters = 'US'
|
||||
formats = ['NOOK']
|
||||
|
||||
class StoreBeamEBooksDEStore(StoreBase):
|
||||
name = 'Beam EBooks DE'
|
||||
author = 'Charles Haley'
|
||||
description = u'Bei uns finden Sie: Tausende deutschsprachige eBooks; Alle eBooks ohne hartes DRM; PDF, ePub und Mobipocket Format; Sofortige Verfügbarkeit - 24 Stunden am Tag; Günstige Preise; eBooks für viele Lesegeräte, PC,Mac und Smartphones; Viele Gratis eBooks'
|
||||
actual_plugin = 'calibre.gui2.store.stores.beam_ebooks_de_plugin:BeamEBooksDEStore'
|
||||
|
||||
drm_free_only = True
|
||||
headquarters = 'DE'
|
||||
formats = ['EPUB', 'MOBI', 'PDF']
|
||||
affiliate = True
|
||||
|
||||
class StoreBeWriteStore(StoreBase):
|
||||
name = 'BeWrite Books'
|
||||
description = u'Publishers of fine books. Highly selective and editorially driven. Does not offer: books for children or exclusively YA, erotica, swords-and-sorcery fantasy and space-opera-style science fiction. All other genres are represented.'
|
||||
@ -1669,6 +1680,7 @@ plugins += [
|
||||
StoreAmazonUKKindleStore,
|
||||
StoreBaenWebScriptionStore,
|
||||
StoreBNStore,
|
||||
StoreBeamEBooksDEStore,
|
||||
StoreBeWriteStore,
|
||||
StoreBiblioStore,
|
||||
StoreBookotekaStore,
|
||||
|
@ -354,6 +354,10 @@ class Cache(object):
|
||||
def pref(self, name, default=None):
|
||||
return self.backend.prefs.get(name, default)
|
||||
|
||||
@write_api
|
||||
def set_pref(self, name, val):
|
||||
self.backend.prefs.set(name, val)
|
||||
|
||||
@api
|
||||
def get_metadata(self, book_id,
|
||||
get_cover=False, get_user_categories=True, cover_as_data=False):
|
||||
|
@ -7,14 +7,17 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import copy
|
||||
from functools import partial
|
||||
from operator import attrgetter
|
||||
from future_builtins import map
|
||||
|
||||
from calibre.library.field_metadata import TagsIcons
|
||||
from calibre.utils.config_base import tweaks
|
||||
from calibre.utils.icu import sort_key
|
||||
from calibre.utils.search_query_parser import saved_searches
|
||||
|
||||
CATEGORY_SORTS = { 'name', 'popularity', 'rating' }
|
||||
CATEGORY_SORTS = ('name', 'popularity', 'rating') # This has to be a tuple not a set
|
||||
|
||||
class Tag(object):
|
||||
|
||||
@ -53,8 +56,7 @@ class Tag(object):
|
||||
|
||||
def find_categories(field_metadata):
|
||||
for category, cat in field_metadata.iteritems():
|
||||
if (cat['is_category'] and cat['kind'] not in {'user', 'search'} and
|
||||
category != 'news'):
|
||||
if (cat['is_category'] and cat['kind'] not in {'user', 'search'}):
|
||||
yield (category, cat['is_multiple'].get('cache_to_list', None), False)
|
||||
elif (cat['datatype'] == 'composite' and
|
||||
cat['display'].get('make_category', False)):
|
||||
@ -88,6 +90,39 @@ def create_tag_class(category, fm, icon_map):
|
||||
tooltip=tooltip, is_editable=is_editable,
|
||||
category=category)
|
||||
|
||||
def clean_user_categories(dbcache):
|
||||
user_cats = dbcache.pref('user_categories', {})
|
||||
new_cats = {}
|
||||
for k in user_cats:
|
||||
comps = [c.strip() for c in k.split('.') if c.strip()]
|
||||
if len(comps) == 0:
|
||||
i = 1
|
||||
while True:
|
||||
if unicode(i) not in user_cats:
|
||||
new_cats[unicode(i)] = user_cats[k]
|
||||
break
|
||||
i += 1
|
||||
else:
|
||||
new_cats['.'.join(comps)] = user_cats[k]
|
||||
try:
|
||||
if new_cats != user_cats:
|
||||
dbcache.set_pref('user_categories', new_cats)
|
||||
except:
|
||||
pass
|
||||
return new_cats
|
||||
|
||||
def sort_categories(items, sort):
|
||||
reverse = True
|
||||
if sort == 'popularity':
|
||||
key=attrgetter('count')
|
||||
elif sort == 'rating':
|
||||
key=attrgetter('avg_rating')
|
||||
else:
|
||||
key=lambda x:sort_key(x.sort or x.name)
|
||||
reverse=False
|
||||
items.sort(key=key, reverse=reverse)
|
||||
return items
|
||||
|
||||
def get_categories(dbcache, sort='name', book_ids=None, icon_map=None):
|
||||
if icon_map is not None and type(icon_map) != TagsIcons:
|
||||
raise TypeError('icon_map passed to get_categories must be of type TagIcons')
|
||||
@ -100,19 +135,98 @@ def get_categories(dbcache, sort='name', book_ids=None, icon_map=None):
|
||||
|
||||
categories = {}
|
||||
book_ids = frozenset(book_ids) if book_ids else book_ids
|
||||
get_metadata = partial(dbcache._get_metadata, get_user_categories=False)
|
||||
bids = None
|
||||
|
||||
for category, is_multiple, is_composite in find_categories(fm):
|
||||
tag_class = create_tag_class(category, fm, icon_map)
|
||||
if is_composite:
|
||||
if bids is None:
|
||||
bids = dbcache._all_book_ids() if book_ids is None else book_ids
|
||||
cats = dbcache.fields[category].get_composite_categories(
|
||||
tag_class, book_rating_map, bids, is_multiple, get_metadata)
|
||||
elif category == 'news':
|
||||
cats = dbcache.fields['tags'].get_news_category(tag_class, book_ids)
|
||||
else:
|
||||
cats = dbcache.fields[category].get_categories(
|
||||
tag_class, book_rating_map, lang_map, book_ids)
|
||||
if sort == 'popularity':
|
||||
key=attrgetter('count')
|
||||
elif sort == 'rating':
|
||||
key=attrgetter('avg_rating')
|
||||
else:
|
||||
key=lambda x:sort_key(x.sort or x.name)
|
||||
cats.sort(key=key)
|
||||
sort_categories(cats, sort)
|
||||
categories[category] = cats
|
||||
|
||||
# Needed for legacy databases that have multiple ratings that
|
||||
# map to n stars
|
||||
for r in categories['rating']:
|
||||
for x in tuple(categories['rating']):
|
||||
if r.name == x.name and r.id != x.id:
|
||||
r.id_set |= x.id_set
|
||||
r.count = r.count + x.count
|
||||
categories['rating'].remove(x)
|
||||
break
|
||||
|
||||
# User categories
|
||||
user_categories = clean_user_categories(dbcache).copy()
|
||||
if user_categories:
|
||||
# We want to use same node in the user category as in the source
|
||||
# category. To do that, we need to find the original Tag node. There is
|
||||
# a time/space tradeoff here. By converting the tags into a map, we can
|
||||
# do the verification in the category loop much faster, at the cost of
|
||||
# temporarily duplicating the categories lists.
|
||||
taglist = {}
|
||||
for c, items in categories.iteritems():
|
||||
taglist[c] = dict(map(lambda t:(icu_lower(t.name), t), items))
|
||||
|
||||
muc = dbcache.pref('grouped_search_make_user_categories', [])
|
||||
gst = dbcache.pref('grouped_search_terms', {})
|
||||
for c in gst:
|
||||
if c not in muc:
|
||||
continue
|
||||
user_categories[c] = []
|
||||
for sc in gst[c]:
|
||||
if sc in categories.keys():
|
||||
for t in categories[sc]:
|
||||
user_categories[c].append([t.name, sc, 0])
|
||||
|
||||
gst_icon = icon_map['gst'] if icon_map else None
|
||||
for user_cat in sorted(user_categories.iterkeys(), key=sort_key):
|
||||
items = []
|
||||
names_seen = {}
|
||||
for name, label, ign in user_categories[user_cat]:
|
||||
n = icu_lower(name)
|
||||
if label in taglist and n in taglist[label]:
|
||||
if user_cat in gst:
|
||||
# for gst items, make copy and consolidate the tags by name.
|
||||
if n in names_seen:
|
||||
t = names_seen[n]
|
||||
t.id_set |= taglist[label][n].id_set
|
||||
t.count += taglist[label][n].count
|
||||
t.tooltip = t.tooltip.replace(')', ', ' + label + ')')
|
||||
else:
|
||||
t = copy.copy(taglist[label][n])
|
||||
t.icon = gst_icon
|
||||
names_seen[t.name] = t
|
||||
items.append(t)
|
||||
else:
|
||||
items.append(taglist[label][n])
|
||||
# else: do nothing, to not include nodes w zero counts
|
||||
cat_name = '@' + user_cat # add the '@' to avoid name collision
|
||||
# Not a problem if we accumulate entries in the icon map
|
||||
if icon_map is not None:
|
||||
icon_map[cat_name] = icon_map['user:']
|
||||
categories[cat_name] = sort_categories(items, sort)
|
||||
|
||||
#### Finally, the saved searches category ####
|
||||
items = []
|
||||
icon = None
|
||||
if icon_map and 'search' in icon_map:
|
||||
icon = icon_map['search']
|
||||
ss = saved_searches()
|
||||
for srch in ss.names():
|
||||
items.append(Tag(srch, tooltip=ss.lookup(srch),
|
||||
sort=srch, icon=icon, category='search',
|
||||
is_editable=False))
|
||||
if len(items):
|
||||
categories['search'] = items
|
||||
|
||||
return categories
|
||||
|
||||
|
||||
|
@ -186,6 +186,25 @@ class CompositeField(OneToOneField):
|
||||
for val, book_ids in val_map.iteritems():
|
||||
yield val, book_ids
|
||||
|
||||
def get_composite_categories(self, tag_class, book_rating_map, book_ids,
|
||||
is_multiple, get_metadata):
|
||||
ans = []
|
||||
id_map = defaultdict(set)
|
||||
for book_id in book_ids:
|
||||
val = self.get_value_with_cache(book_id, get_metadata)
|
||||
vals = [x.strip() for x in val.split(is_multiple)] if is_multiple else [val]
|
||||
for val in vals:
|
||||
if val:
|
||||
id_map[val].add(book_id)
|
||||
for item_id, item_book_ids in id_map.iteritems():
|
||||
ratings = tuple(r for r in (book_rating_map.get(book_id, 0) for
|
||||
book_id in item_book_ids) if r > 0)
|
||||
avg = sum(ratings)/len(ratings) if ratings else 0
|
||||
c = tag_class(item_id, id=item_id, sort=item_id, avg=avg,
|
||||
id_set=item_book_ids, count=len(item_book_ids))
|
||||
ans.append(c)
|
||||
return ans
|
||||
|
||||
class OnDeviceField(OneToOneField):
|
||||
|
||||
def __init__(self, name, table):
|
||||
@ -441,6 +460,34 @@ class SeriesField(ManyToOneField):
|
||||
val = self.table.id_map[item_id]
|
||||
return title_sort(val, order=tss, lang=lang)
|
||||
|
||||
class TagsField(ManyToManyField):
|
||||
|
||||
def get_news_category(self, tag_class, book_ids=None):
|
||||
news_id = None
|
||||
ans = []
|
||||
for item_id, val in self.table.id_map.iteritems():
|
||||
if val == _('News'):
|
||||
news_id = item_id
|
||||
break
|
||||
if news_id is None:
|
||||
return ans
|
||||
|
||||
news_books = self.table.col_book_map[news_id]
|
||||
if book_ids is not None:
|
||||
news_books = news_books.intersection(book_ids)
|
||||
if not news_books:
|
||||
return ans
|
||||
for item_id, item_book_ids in self.table.col_book_map.iteritems():
|
||||
item_book_ids = item_book_ids.intersection(news_books)
|
||||
if item_book_ids:
|
||||
name = self.category_formatter(self.table.id_map[item_id])
|
||||
if name == _('News'):
|
||||
continue
|
||||
c = tag_class(name, id=item_id, sort=name,
|
||||
id_set=item_book_ids, count=len(item_book_ids))
|
||||
ans.append(c)
|
||||
return ans
|
||||
|
||||
def create_field(name, table):
|
||||
cls = {
|
||||
ONE_ONE : OneToOneField,
|
||||
@ -455,6 +502,8 @@ def create_field(name, table):
|
||||
cls = FormatsField
|
||||
elif name == 'identifiers':
|
||||
cls = IdentifiersField
|
||||
elif name == 'tags':
|
||||
cls = TagsField
|
||||
elif table.metadata['datatype'] == 'composite':
|
||||
cls = CompositeField
|
||||
elif table.metadata['datatype'] == 'series':
|
||||
|
@ -17,7 +17,6 @@ from calibre.utils.icu import primary_find
|
||||
from calibre.utils.localization import lang_map, canonicalize_lang
|
||||
from calibre.utils.search_query_parser import SearchQueryParser, ParseException
|
||||
|
||||
# TODO: Thread safety of saved searches
|
||||
CONTAINS_MATCH = 0
|
||||
EQUALS_MATCH = 1
|
||||
REGEXP_MATCH = 2
|
||||
|
@ -98,10 +98,10 @@ class CompositeTable(OneToOneTable):
|
||||
self.book_col_map = {}
|
||||
d = self.metadata['display']
|
||||
self.composite_template = ['composite_template']
|
||||
self.contains_html = d['contains_html']
|
||||
self.make_category = d['make_category']
|
||||
self.composite_sort = d['composite_sort']
|
||||
self.use_decorations = d['use_decorations']
|
||||
self.contains_html = d.get('contains_html', False)
|
||||
self.make_category = d.get('make_category', False)
|
||||
self.composite_sort = d.get('composite_sort', False)
|
||||
self.use_decorations = d.get('use_decorations', False)
|
||||
|
||||
class ManyToOneTable(Table):
|
||||
|
||||
|
Binary file not shown.
@ -95,7 +95,7 @@ class ReadingTest(BaseTest):
|
||||
'series' : 'A Series One',
|
||||
'series_index': 2.0,
|
||||
'rating': 6.0,
|
||||
'tags': ('Tag One',),
|
||||
'tags': ('Tag One', 'News'),
|
||||
'formats':(),
|
||||
'identifiers': {'test':'two'},
|
||||
'timestamp': datetime.datetime(2011, 9, 6, 6, 0,
|
||||
|
@ -93,6 +93,7 @@ class ANDROID(USBMS):
|
||||
# Google
|
||||
0x18d1 : {
|
||||
0x0001 : [0x0223, 0x230, 0x9999],
|
||||
0x0002 : [0x9999],
|
||||
0x0003 : [0x0230, 0x9999],
|
||||
0x4e11 : [0x0100, 0x226, 0x227],
|
||||
0x4e12 : [0x0100, 0x226, 0x227],
|
||||
|
@ -35,7 +35,7 @@ from calibre.library.server import server_config as content_server_config
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
from calibre.utils.ipc import eintr_retry_call
|
||||
from calibre.utils.config import from_json, tweaks
|
||||
from calibre.utils.date import isoformat, now, UNDEFINED_DATE
|
||||
from calibre.utils.date import isoformat, now
|
||||
from calibre.utils.filenames import ascii_filename as sanitize, shorten_components_to
|
||||
from calibre.utils.mdns import (publish as publish_zeroconf, unpublish as
|
||||
unpublish_zeroconf, get_all_ips)
|
||||
|
@ -1430,7 +1430,10 @@ def metadata_to_opf(mi, as_string=True, default_lang=None):
|
||||
elem = metadata.makeelement(tag, attrib=attrib)
|
||||
elem.tail = '\n'+(' '*8)
|
||||
if text:
|
||||
try:
|
||||
elem.text = text.strip()
|
||||
except ValueError:
|
||||
elem.text = clean_ascii_chars(text.strip())
|
||||
metadata.append(elem)
|
||||
|
||||
factory(DC('title'), mi.title)
|
||||
|
@ -87,6 +87,10 @@ class Page(QWebPage): # {{{
|
||||
|
||||
def javaScriptAlert(self, frame, msg):
|
||||
self.log(unicode(msg))
|
||||
|
||||
def shouldInterruptJavaScript(self):
|
||||
return False
|
||||
|
||||
# }}}
|
||||
|
||||
def draw_image_page(page_rect, painter, p, preserve_aspect_ratio=True):
|
||||
|
@ -634,13 +634,12 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
|
||||
def bool_type_decorator(r, idx=-1, bool_cols_are_tristate=True):
|
||||
val = force_to_bool(self.db.data[r][idx])
|
||||
if val is None:
|
||||
if not bool_cols_are_tristate:
|
||||
if val is None or not val:
|
||||
return self.bool_no_icon
|
||||
return NONE
|
||||
if val:
|
||||
return self.bool_yes_icon
|
||||
if val is None:
|
||||
return self.bool_blank_icon
|
||||
return self.bool_no_icon
|
||||
|
||||
def ondevice_decorator(r, idx=-1):
|
||||
|
95
src/calibre/gui2/store/stores/beam_ebooks_de_plugin.py
Normal file
95
src/calibre/gui2/store/stores/beam_ebooks_de_plugin.py
Normal file
@ -0,0 +1,95 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import (unicode_literals, division, absolute_import, print_function)
|
||||
store_version = 1 # Needed for dynamic plugin loading
|
||||
|
||||
__license__ = 'GPL 3'
|
||||
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import urllib2
|
||||
from contextlib import closing
|
||||
|
||||
from lxml import html
|
||||
|
||||
from PyQt4.Qt import QUrl
|
||||
|
||||
from calibre import browser
|
||||
from calibre.gui2 import open_url
|
||||
from calibre.gui2.store import StorePlugin
|
||||
from calibre.gui2.store.basic_config import BasicStoreConfig
|
||||
from calibre.gui2.store.search_result import SearchResult
|
||||
from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
||||
|
||||
class BeamEBooksDEStore(BasicStoreConfig, StorePlugin):
|
||||
|
||||
def open(self, parent=None, detail_item=None, external=False):
|
||||
url = 'http://klick.affiliwelt.net/klick.php?bannerid=10072&pid=32307&prid=908'
|
||||
url_details = ('http://klick.affiliwelt.net/klick.php?'
|
||||
'bannerid=66820&pid=32307&prid=908&feedid=27&prdid={0}')
|
||||
|
||||
if external or self.config.get('open_external', False):
|
||||
if detail_item:
|
||||
url = url_details.format(detail_item)
|
||||
|
||||
open_url(QUrl(url))
|
||||
else:
|
||||
detail_url = None
|
||||
if detail_item:
|
||||
detail_url = url_details.format(detail_item)
|
||||
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
||||
d.setWindowTitle(self.name)
|
||||
d.set_tags(self.config.get('tags', ''))
|
||||
d.exec_()
|
||||
|
||||
def search(self, query, max_results=10, timeout=60):
|
||||
url = 'http://www.beam-ebooks.de/suchergebnis.php?Type=&sw=' + urllib2.quote(query)
|
||||
br = browser()
|
||||
|
||||
counter = max_results
|
||||
with closing(br.open(url, timeout=timeout)) as f:
|
||||
doc = html.fromstring(f.read())
|
||||
for data in doc.xpath('//table[tr/td/div[@class="stil2"]]'):
|
||||
if counter <= 0:
|
||||
break
|
||||
|
||||
id_ = ''.join(data.xpath('./tr/td[1]/a/@href')).strip()
|
||||
if not id_:
|
||||
continue
|
||||
id_ = id_[7:]
|
||||
cover_url = ''.join(data.xpath('./tr/td[1]/a/img/@src'))
|
||||
if cover_url:
|
||||
cover_url = 'http://www.beam-ebooks.de' + cover_url
|
||||
temp = ''.join(data.xpath('./tr/td[1]/a/img/@alt'))
|
||||
colon = temp.find(':')
|
||||
if not temp.startswith('eBook') or colon < 0:
|
||||
continue
|
||||
author = temp[5:colon]
|
||||
title = temp[colon+1:]
|
||||
price = ''.join(data.xpath('./tr/td[3]/text()'))
|
||||
pdf = data.xpath(
|
||||
'boolean(./tr/td[3]/a/img[contains(@alt, "PDF")]/@alt)')
|
||||
epub = data.xpath(
|
||||
'boolean(./tr/td[3]/a/img[contains(@alt, "ePub")]/@alt)')
|
||||
mobi = data.xpath(
|
||||
'boolean(./tr/td[3]/a/img[contains(@alt, "Mobipocket")]/@alt)')
|
||||
counter -= 1
|
||||
|
||||
s = SearchResult()
|
||||
s.cover_url = cover_url
|
||||
s.title = title.strip()
|
||||
s.author = author.strip()
|
||||
s.price = price
|
||||
s.drm = SearchResult.DRM_UNLOCKED
|
||||
s.detail_item = id_
|
||||
formats = []
|
||||
if epub:
|
||||
formats.append('ePub')
|
||||
if pdf:
|
||||
formats.append('PDF')
|
||||
if mobi:
|
||||
formats.append('MOBI')
|
||||
s.formats = ', '.join(formats)
|
||||
|
||||
yield s
|
||||
|
@ -44,7 +44,7 @@ from calibre.utils.recycle_bin import delete_file, delete_tree
|
||||
from calibre.utils.formatter_functions import load_user_template_functions
|
||||
from calibre.db.errors import NoSuchFormat
|
||||
from calibre.db.lazy import FormatMetadata, FormatsList
|
||||
from calibre.db.categories import Tag
|
||||
from calibre.db.categories import Tag, CATEGORY_SORTS
|
||||
from calibre.utils.localization import (canonicalize_lang,
|
||||
calibre_langcode_to_name)
|
||||
|
||||
@ -1644,7 +1644,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
|
||||
########## data structures for get_categories
|
||||
|
||||
CATEGORY_SORTS = ('name', 'popularity', 'rating')
|
||||
CATEGORY_SORTS = CATEGORY_SORTS
|
||||
MATCH_TYPE = ('any', 'all')
|
||||
|
||||
class TCat_Tag(object):
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user