mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
KG updates
This commit is contained in:
commit
2fa95e4804
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2008-2010, Darko Miletic <darko.miletic at gmail.com>'
|
__copyright__ = '2008-2011, Darko Miletic <darko.miletic at gmail.com>'
|
||||||
'''
|
'''
|
||||||
blic.rs
|
blic.rs
|
||||||
'''
|
'''
|
||||||
@ -21,21 +21,53 @@ class Blic(BasicNewsRecipe):
|
|||||||
masthead_url = 'http://www.blic.rs/resources/images/header/header_back.png'
|
masthead_url = 'http://www.blic.rs/resources/images/header/header_back.png'
|
||||||
language = 'sr'
|
language = 'sr'
|
||||||
publication_type = 'newspaper'
|
publication_type = 'newspaper'
|
||||||
extra_css = '@font-face {font-family: "serif1";src:url(res:///opt/sony/ebook/FONT/tt0011m_.ttf)} @font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)} body{font-family: Georgia, serif1, serif} .article_description{font-family: Arial, sans1, sans-serif} .img_full{float: none} img{margin-bottom: 0.8em} '
|
extra_css = """
|
||||||
|
@font-face {font-family: "serif1";src:url(res:///opt/sony/ebook/FONT/tt0011m_.ttf)}
|
||||||
|
@font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)}
|
||||||
|
body{font-family: Georgia, serif1, serif}
|
||||||
|
.articledescription,#nadnaslov,.article_info{font-family: Arial, sans1, sans-serif}
|
||||||
|
.img_full{float: none}
|
||||||
|
#nadnaslov{font-size: small}
|
||||||
|
#article_lead{font-size: 1.5em}
|
||||||
|
h1{color: red}
|
||||||
|
.potpis{font-size: x-small; color: gray}
|
||||||
|
.article_info{font-size: small}
|
||||||
|
img{margin-bottom: 0.8em; margin-top: 0.8em; display: block}
|
||||||
|
"""
|
||||||
|
|
||||||
conversion_options = {
|
conversion_options = {
|
||||||
'comment' : description
|
'comment' : description
|
||||||
, 'tags' : category
|
, 'tags' : category
|
||||||
, 'publisher': publisher
|
, 'publisher': publisher
|
||||||
, 'language' : language
|
, 'language' : language
|
||||||
|
, 'linearize_tables' : True
|
||||||
}
|
}
|
||||||
|
|
||||||
preprocess_regexps = [(re.compile(u'\u0110'), lambda match: u'\u00D0')]
|
preprocess_regexps = [(re.compile(u'\u0110'), lambda match: u'\u00D0')]
|
||||||
remove_tags_before = dict(name='div', attrs={'id':'article_info'})
|
remove_tags_before = dict(name='div', attrs={'id':'article_info'})
|
||||||
remove_tags = [dict(name=['object','link'])]
|
remove_tags = [dict(name=['object','link','meta','base','object','embed'])]
|
||||||
remove_attributes = ['width','height']
|
remove_attributes = ['width','height','m_id','m_ext','mlg_id','poll_id','v_id']
|
||||||
|
|
||||||
feeds = [(u'Danasnje Vesti', u'http://www.blic.rs/rss/danasnje-vesti')]
|
feeds = [
|
||||||
|
(u'Politika' , u'http://www.blic.rs/rss/Vesti/Politika')
|
||||||
|
,(u'Tema Dana' , u'http://www.blic.rs/rss/Vesti/Tema-Dana')
|
||||||
|
,(u'Svet' , u'http://www.blic.rs/rss/Vesti/Svet')
|
||||||
|
,(u'Drustvo' , u'http://www.blic.rs/rss/Vesti/Drustvo')
|
||||||
|
,(u'Ekonomija' , u'http://www.blic.rs/rss/Vesti/Ekonomija')
|
||||||
|
,(u'Hronika' , u'http://www.blic.rs/rss/Vesti/Hronika')
|
||||||
|
,(u'Beograd' , u'http://www.blic.rs/rss/Vesti/Beograd')
|
||||||
|
,(u'Srbija' , u'http://www.blic.rs/rss/Vesti/Srbija')
|
||||||
|
,(u'Vojvodina' , u'http://www.blic.rs/rss/Vesti/Vojvodina')
|
||||||
|
,(u'Republika Srpska' , u'http://www.blic.rs/rss/Vesti/Republika-Srpska')
|
||||||
|
,(u'Reportaza' , u'http://www.blic.rs/rss/Vesti/Reportaza')
|
||||||
|
,(u'Dodatak' , u'http://www.blic.rs/rss/Vesti/Dodatak')
|
||||||
|
,(u'Zabava' , u'http://www.blic.rs/rss/Zabava')
|
||||||
|
,(u'Kultura' , u'http://www.blic.rs/rss/Kultura')
|
||||||
|
,(u'Slobodno Vreme' , u'http://www.blic.rs/rss/Slobodno-vreme')
|
||||||
|
,(u'IT' , u'http://www.blic.rs/rss/IT')
|
||||||
|
,(u'Komentar' , u'http://www.blic.rs/rss/Komentar')
|
||||||
|
,(u'Intervju' , u'http://www.blic.rs/rss/Intervju')
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def print_version(self, url):
|
def print_version(self, url):
|
||||||
@ -44,4 +76,4 @@ class Blic(BasicNewsRecipe):
|
|||||||
def preprocess_html(self, soup):
|
def preprocess_html(self, soup):
|
||||||
for item in soup.findAll(style=True):
|
for item in soup.findAll(style=True):
|
||||||
del item['style']
|
del item['style']
|
||||||
return self.adeify_images(soup)
|
return soup
|
||||||
|
@ -241,7 +241,7 @@ def get_parsed_proxy(typ='http', debug=True):
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
def browser(honor_time=True, max_time=2, mobile_browser=False):
|
def browser(honor_time=True, max_time=2, mobile_browser=False, user_agent=None):
|
||||||
'''
|
'''
|
||||||
Create a mechanize browser for web scraping. The browser handles cookies,
|
Create a mechanize browser for web scraping. The browser handles cookies,
|
||||||
refresh requests and ignores robots.txt. Also uses proxy if avaialable.
|
refresh requests and ignores robots.txt. Also uses proxy if avaialable.
|
||||||
@ -253,8 +253,10 @@ def browser(honor_time=True, max_time=2, mobile_browser=False):
|
|||||||
opener = Browser()
|
opener = Browser()
|
||||||
opener.set_handle_refresh(True, max_time=max_time, honor_time=honor_time)
|
opener.set_handle_refresh(True, max_time=max_time, honor_time=honor_time)
|
||||||
opener.set_handle_robots(False)
|
opener.set_handle_robots(False)
|
||||||
opener.addheaders = [('User-agent', ' Mozilla/5.0 (Windows; U; Windows CE 5.1; rv:1.8.1a3) Gecko/20060610 Minimo/0.016' if mobile_browser else \
|
if user_agent is None:
|
||||||
'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101210 Gentoo Firefox/3.6.13')]
|
user_agent = ' Mozilla/5.0 (Windows; U; Windows CE 5.1; rv:1.8.1a3) Gecko/20060610 Minimo/0.016' if mobile_browser else \
|
||||||
|
'Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101210 Gentoo Firefox/3.6.13'
|
||||||
|
opener.addheaders = [('User-agent', user_agent)]
|
||||||
http_proxy = get_proxies().get('http', None)
|
http_proxy = get_proxies().get('http', None)
|
||||||
if http_proxy:
|
if http_proxy:
|
||||||
opener.set_proxies({'http':http_proxy})
|
opener.set_proxies({'http':http_proxy})
|
||||||
|
@ -21,7 +21,7 @@ class ANDROID(USBMS):
|
|||||||
# HTC
|
# HTC
|
||||||
0x0bb4 : { 0x0c02 : [0x100, 0x0227, 0x0226], 0x0c01 : [0x100, 0x0227], 0x0ff9
|
0x0bb4 : { 0x0c02 : [0x100, 0x0227, 0x0226], 0x0c01 : [0x100, 0x0227], 0x0ff9
|
||||||
: [0x0100, 0x0227, 0x0226], 0x0c87: [0x0100, 0x0227, 0x0226],
|
: [0x0100, 0x0227, 0x0226], 0x0c87: [0x0100, 0x0227, 0x0226],
|
||||||
0xc92 : [0x100], 0xc97: [0x226]},
|
0xc92 : [0x100], 0xc97: [0x226], 0xc99 : [0x0100]},
|
||||||
|
|
||||||
# Eken
|
# Eken
|
||||||
0x040d : { 0x8510 : [0x0001], 0x0851 : [0x1] },
|
0x040d : { 0x8510 : [0x0001], 0x0851 : [0x1] },
|
||||||
@ -54,7 +54,7 @@ class ANDROID(USBMS):
|
|||||||
0x1004 : { 0x61cc : [0x100] },
|
0x1004 : { 0x61cc : [0x100] },
|
||||||
|
|
||||||
# Archos
|
# Archos
|
||||||
0x0e79 : { 0x1420 : [0x0216]},
|
0x0e79 : { 0x1419: [0x0216], 0x1420 : [0x0216]},
|
||||||
|
|
||||||
}
|
}
|
||||||
EBOOK_DIR_MAIN = ['eBooks/import', 'wordplayer/calibretransfer', 'Books']
|
EBOOK_DIR_MAIN = ['eBooks/import', 'wordplayer/calibretransfer', 'Books']
|
||||||
@ -70,10 +70,10 @@ class ANDROID(USBMS):
|
|||||||
'__UMS_COMPOSITE', '_MB200', 'MASS_STORAGE', '_-_CARD', 'SGH-I897',
|
'__UMS_COMPOSITE', '_MB200', 'MASS_STORAGE', '_-_CARD', 'SGH-I897',
|
||||||
'GT-I9000', 'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID',
|
'GT-I9000', 'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID',
|
||||||
'SCH-I500_CARD', 'SPH-D700_CARD', 'MB810', 'GT-P1000', 'DESIRE',
|
'SCH-I500_CARD', 'SPH-D700_CARD', 'MB810', 'GT-P1000', 'DESIRE',
|
||||||
'SGH-T849', '_MB300', 'A70S', 'S_ANDROID']
|
'SGH-T849', '_MB300', 'A70S', 'S_ANDROID', 'A101IT']
|
||||||
WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897',
|
WINDOWS_CARD_A_MEM = ['ANDROID_PHONE', 'GT-I9000_CARD', 'SGH-I897',
|
||||||
'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD',
|
'FILE-STOR_GADGET', 'SGH-T959', 'SAMSUNG_ANDROID', 'GT-P1000_CARD',
|
||||||
'A70S']
|
'A70S', 'A101IT']
|
||||||
|
|
||||||
OSX_MAIN_MEM = 'Android Device Main Memory'
|
OSX_MAIN_MEM = 'Android Device Main Memory'
|
||||||
|
|
||||||
|
@ -224,6 +224,10 @@ class Dehyphenator(object):
|
|||||||
return firsthalf+u'\u2014'+wraptags+secondhalf
|
return firsthalf+u'\u2014'+wraptags+secondhalf
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
if self.format == 'individual_words' and len(firsthalf) + len(secondhalf) <= 6:
|
||||||
|
if self.verbose > 2:
|
||||||
|
self.log("too short, returned hyphenated word: " + str(hyphenated))
|
||||||
|
return hyphenated
|
||||||
if len(firsthalf) <= 2 and len(secondhalf) <= 2:
|
if len(firsthalf) <= 2 and len(secondhalf) <= 2:
|
||||||
if self.verbose > 2:
|
if self.verbose > 2:
|
||||||
self.log("too short, returned hyphenated word: " + str(hyphenated))
|
self.log("too short, returned hyphenated word: " + str(hyphenated))
|
||||||
|
@ -4,7 +4,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
Fetch cover from LibraryThing.com based on ISBN number.
|
Fetch cover from LibraryThing.com based on ISBN number.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import sys, socket, os, re
|
import sys, socket, os, re, random
|
||||||
|
|
||||||
from lxml import html
|
from lxml import html
|
||||||
import mechanize
|
import mechanize
|
||||||
@ -16,13 +16,26 @@ from calibre.ebooks.chardet import strip_encoding_declarations
|
|||||||
|
|
||||||
OPENLIBRARY = 'http://covers.openlibrary.org/b/isbn/%s-L.jpg?default=false'
|
OPENLIBRARY = 'http://covers.openlibrary.org/b/isbn/%s-L.jpg?default=false'
|
||||||
|
|
||||||
|
def get_ua():
|
||||||
|
choices = [
|
||||||
|
'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.11) Gecko/20101012 Firefox/3.6.11'
|
||||||
|
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)'
|
||||||
|
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)'
|
||||||
|
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)'
|
||||||
|
'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16'
|
||||||
|
'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) Chrome/0.2.153.1 Safari/525.19'
|
||||||
|
'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.11) Gecko/20101012 Firefox/3.6.11'
|
||||||
|
]
|
||||||
|
return choices[random.randint(0, len(choices)-1)]
|
||||||
|
|
||||||
|
|
||||||
class HeadRequest(mechanize.Request):
|
class HeadRequest(mechanize.Request):
|
||||||
|
|
||||||
def get_method(self):
|
def get_method(self):
|
||||||
return 'HEAD'
|
return 'HEAD'
|
||||||
|
|
||||||
def check_for_cover(isbn, timeout=5.):
|
def check_for_cover(isbn, timeout=5.):
|
||||||
br = browser()
|
br = browser(user_agent=get_ua())
|
||||||
br.set_handle_redirect(False)
|
br.set_handle_redirect(False)
|
||||||
try:
|
try:
|
||||||
br.open_novisit(HeadRequest(OPENLIBRARY%isbn), timeout=timeout)
|
br.open_novisit(HeadRequest(OPENLIBRARY%isbn), timeout=timeout)
|
||||||
@ -51,7 +64,7 @@ def login(br, username, password, force=True):
|
|||||||
|
|
||||||
def cover_from_isbn(isbn, timeout=5., username=None, password=None):
|
def cover_from_isbn(isbn, timeout=5., username=None, password=None):
|
||||||
src = None
|
src = None
|
||||||
br = browser()
|
br = browser(user_agent=get_ua())
|
||||||
try:
|
try:
|
||||||
return br.open(OPENLIBRARY%isbn, timeout=timeout).read(), 'jpg'
|
return br.open(OPENLIBRARY%isbn, timeout=timeout).read(), 'jpg'
|
||||||
except:
|
except:
|
||||||
@ -100,7 +113,7 @@ def get_social_metadata(title, authors, publisher, isbn, username=None,
|
|||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
mi = MetaInformation(title, authors)
|
mi = MetaInformation(title, authors)
|
||||||
if isbn:
|
if isbn:
|
||||||
br = browser()
|
br = browser(user_agent=get_ua())
|
||||||
if username and password:
|
if username and password:
|
||||||
try:
|
try:
|
||||||
login(br, username, password, force=False)
|
login(br, username, password, force=False)
|
||||||
|
@ -262,7 +262,7 @@ class RTFMLizer(object):
|
|||||||
|
|
||||||
if hasattr(elem, 'tail') and elem.tail != None and elem.tail.strip() != '':
|
if hasattr(elem, 'tail') and elem.tail != None and elem.tail.strip() != '':
|
||||||
if 'block' in tag_stack:
|
if 'block' in tag_stack:
|
||||||
text += '%s ' % txt2rtf(elem.tail)
|
text += '%s' % txt2rtf(elem.tail)
|
||||||
else:
|
else:
|
||||||
text += '{\\par \\pard \\hyphpar %s}' % txt2rtf(elem.tail)
|
text += '{\\par \\pard \\hyphpar %s}' % txt2rtf(elem.tail)
|
||||||
|
|
||||||
|
@ -175,9 +175,9 @@ def detect_formatting_type(txt):
|
|||||||
# Block quote.
|
# Block quote.
|
||||||
textile_count += len(re.findall(r'(?mu)^bq\.', txt))
|
textile_count += len(re.findall(r'(?mu)^bq\.', txt))
|
||||||
# Images
|
# Images
|
||||||
textile_count += len(re.findall(r'\![^\s]+(:[^\s]+)*', txt))
|
textile_count += len(re.findall(r'\![^\s]+(?=.*?/)(:[^\s]+)*', txt))
|
||||||
# Links
|
# Links
|
||||||
textile_count += len(re.findall(r'"(\(.+?\))*[^\(]+?(\(.+?\))*":[^\s]+', txt))
|
textile_count += len(re.findall(r'"(?=".*?\()(\(.+?\))*[^\(]+?(\(.+?\))*":[^\s]+', txt))
|
||||||
|
|
||||||
if markdown_count > 5 or textile_count > 5:
|
if markdown_count > 5 or textile_count > 5:
|
||||||
if markdown_count > textile_count:
|
if markdown_count > textile_count:
|
||||||
|
@ -8,11 +8,12 @@ __docformat__ = 'restructuredtext en'
|
|||||||
import os
|
import os
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from PyQt4.Qt import QInputDialog, QPixmap, QMenu
|
from PyQt4.Qt import QPixmap, QMenu
|
||||||
|
|
||||||
|
|
||||||
from calibre.gui2 import error_dialog, choose_files, \
|
from calibre.gui2 import error_dialog, choose_files, \
|
||||||
choose_dir, warning_dialog, info_dialog
|
choose_dir, warning_dialog, info_dialog
|
||||||
|
from calibre.gui2.dialogs.add_empty_book import AddEmptyBookDialog
|
||||||
from calibre.gui2.widgets import IMAGE_EXTENSIONS
|
from calibre.gui2.widgets import IMAGE_EXTENSIONS
|
||||||
from calibre.ebooks import BOOK_EXTENSIONS
|
from calibre.ebooks import BOOK_EXTENSIONS
|
||||||
from calibre.utils.filenames import ascii_filename
|
from calibre.utils.filenames import ascii_filename
|
||||||
@ -42,7 +43,7 @@ class AddAction(InterfaceAction):
|
|||||||
'ebook file is a different book)'), self.add_recursive_multiple)
|
'ebook file is a different book)'), self.add_recursive_multiple)
|
||||||
self.add_menu.addSeparator()
|
self.add_menu.addSeparator()
|
||||||
self.add_menu.addAction(_('Add Empty book. (Book entry with no '
|
self.add_menu.addAction(_('Add Empty book. (Book entry with no '
|
||||||
'formats)'), self.add_empty)
|
'formats)'), self.add_empty, _('Shift+Ctrl+E'))
|
||||||
self.add_menu.addAction(_('Add from ISBN'), self.add_from_isbn)
|
self.add_menu.addAction(_('Add from ISBN'), self.add_from_isbn)
|
||||||
self.qaction.setMenu(self.add_menu)
|
self.qaction.setMenu(self.add_menu)
|
||||||
self.qaction.triggered.connect(self.add_books)
|
self.qaction.triggered.connect(self.add_books)
|
||||||
@ -83,12 +84,21 @@ class AddAction(InterfaceAction):
|
|||||||
Add an empty book item to the library. This does not import any formats
|
Add an empty book item to the library. This does not import any formats
|
||||||
from a book file.
|
from a book file.
|
||||||
'''
|
'''
|
||||||
num, ok = QInputDialog.getInt(self.gui, _('How many empty books?'),
|
author = None
|
||||||
_('How many empty books should be added?'), 1, 1, 100)
|
index = self.gui.library_view.currentIndex()
|
||||||
if ok:
|
if index.isValid():
|
||||||
|
raw = index.model().db.authors(index.row())
|
||||||
|
if raw:
|
||||||
|
authors = [a.strip().replace('|', ',') for a in raw.split(',')]
|
||||||
|
if authors:
|
||||||
|
author = authors[0]
|
||||||
|
dlg = AddEmptyBookDialog(self.gui, self.gui.library_view.model().db, author)
|
||||||
|
if dlg.exec_() == dlg.Accepted:
|
||||||
|
num = dlg.qty_to_add
|
||||||
from calibre.ebooks.metadata import MetaInformation
|
from calibre.ebooks.metadata import MetaInformation
|
||||||
for x in xrange(num):
|
for x in xrange(num):
|
||||||
self.gui.library_view.model().db.import_book(MetaInformation(None), [])
|
mi = MetaInformation(_('Unknown'), dlg.selected_authors)
|
||||||
|
self.gui.library_view.model().db.import_book(mi, [])
|
||||||
self.gui.library_view.model().books_added(num)
|
self.gui.library_view.model().books_added(num)
|
||||||
|
|
||||||
def add_isbns(self, books, add_tags=[]):
|
def add_isbns(self, books, add_tags=[]):
|
||||||
|
@ -32,7 +32,7 @@ class LibraryUsageStats(object): # {{{
|
|||||||
locs = list(self.stats.keys())
|
locs = list(self.stats.keys())
|
||||||
locs.sort(cmp=lambda x, y: cmp(self.stats[x], self.stats[y]),
|
locs.sort(cmp=lambda x, y: cmp(self.stats[x], self.stats[y]),
|
||||||
reverse=True)
|
reverse=True)
|
||||||
for key in locs[15:]:
|
for key in locs[25:]:
|
||||||
self.stats.pop(key)
|
self.stats.pop(key)
|
||||||
gprefs.set('library_usage_stats', self.stats)
|
gprefs.set('library_usage_stats', self.stats)
|
||||||
|
|
||||||
@ -384,7 +384,14 @@ class ChooseLibraryAction(InterfaceAction):
|
|||||||
return
|
return
|
||||||
|
|
||||||
prefs['library_path'] = loc
|
prefs['library_path'] = loc
|
||||||
|
#from calibre.utils.mem import memory
|
||||||
|
#import weakref, gc
|
||||||
|
#ref = weakref.ref(self.gui.library_view.model().db)
|
||||||
|
#before = memory()/1024**2
|
||||||
self.gui.library_moved(loc)
|
self.gui.library_moved(loc)
|
||||||
|
#print gc.get_referrers(ref)[0]
|
||||||
|
#for i in xrange(3): gc.collect()
|
||||||
|
#print 'leaked:', memory()/1024**2 - before
|
||||||
|
|
||||||
def qs_requested(self, idx, *args):
|
def qs_requested(self, idx, *args):
|
||||||
self.switch_requested(self.qs_locations[idx])
|
self.switch_requested(self.qs_locations[idx])
|
||||||
|
@ -47,6 +47,8 @@ class RegexBuilder(QDialog, Ui_RegexBuilder):
|
|||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
self.regex.setStyleSheet('QLineEdit { color: black; background-color: white; }')
|
self.regex.setStyleSheet('QLineEdit { color: black; background-color: white; }')
|
||||||
|
self.preview.setExtraSelections([])
|
||||||
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def do_test(self):
|
def do_test(self):
|
||||||
|
@ -379,7 +379,8 @@ def populate_metadata_page(layout, db, book_id, bulk=False, two_column=False, pa
|
|||||||
w = bulk_widgets[type](db, col, parent)
|
w = bulk_widgets[type](db, col, parent)
|
||||||
else:
|
else:
|
||||||
w = widgets[type](db, col, parent)
|
w = widgets[type](db, col, parent)
|
||||||
w.initialize(book_id)
|
if book_id is not None:
|
||||||
|
w.initialize(book_id)
|
||||||
return w
|
return w
|
||||||
x = db.custom_column_num_map
|
x = db.custom_column_num_map
|
||||||
cols = list(x)
|
cols = list(x)
|
||||||
|
85
src/calibre/gui2/dialogs/add_empty_book.py
Normal file
85
src/calibre/gui2/dialogs/add_empty_book.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
|
||||||
|
|
||||||
|
from PyQt4.Qt import QDialog, QGridLayout, QLabel, QDialogButtonBox, \
|
||||||
|
QApplication, QSpinBox, QToolButton, QIcon
|
||||||
|
from calibre.ebooks.metadata import authors_to_string, string_to_authors
|
||||||
|
from calibre.gui2.widgets import CompleteComboBox
|
||||||
|
from calibre.utils.icu import sort_key
|
||||||
|
|
||||||
|
class AddEmptyBookDialog(QDialog):
|
||||||
|
|
||||||
|
def __init__(self, parent, db, author):
|
||||||
|
QDialog.__init__(self, parent)
|
||||||
|
self.db = db
|
||||||
|
|
||||||
|
self.setWindowTitle(_('How many empty books?'))
|
||||||
|
|
||||||
|
self._layout = QGridLayout(self)
|
||||||
|
self.setLayout(self._layout)
|
||||||
|
|
||||||
|
self.qty_label = QLabel(_('How many empty books should be added?'))
|
||||||
|
self._layout.addWidget(self.qty_label, 0, 0, 1, 2)
|
||||||
|
|
||||||
|
self.qty_spinbox = QSpinBox(self)
|
||||||
|
self.qty_spinbox.setRange(1, 10000)
|
||||||
|
self.qty_spinbox.setValue(1)
|
||||||
|
self._layout.addWidget(self.qty_spinbox, 1, 0, 1, 2)
|
||||||
|
|
||||||
|
self.author_label = QLabel(_('Set the author of the new books to:'))
|
||||||
|
self._layout.addWidget(self.author_label, 2, 0, 1, 2)
|
||||||
|
|
||||||
|
self.authors_combo = CompleteComboBox(self)
|
||||||
|
self.authors_combo.setSizeAdjustPolicy(
|
||||||
|
self.authors_combo.AdjustToMinimumContentsLengthWithIcon)
|
||||||
|
self.authors_combo.setEditable(True)
|
||||||
|
self._layout.addWidget(self.authors_combo, 3, 0, 1, 1)
|
||||||
|
self.initialize_authors(db, author)
|
||||||
|
|
||||||
|
self.clear_button = QToolButton(self)
|
||||||
|
self.clear_button.setIcon(QIcon(I('trash.png')))
|
||||||
|
self.clear_button.setToolTip(_('Reset author to Unknown'))
|
||||||
|
self.clear_button.clicked.connect(self.reset_author)
|
||||||
|
self._layout.addWidget(self.clear_button, 3, 1, 1, 1)
|
||||||
|
|
||||||
|
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
||||||
|
button_box.accepted.connect(self.accept)
|
||||||
|
button_box.rejected.connect(self.reject)
|
||||||
|
self._layout.addWidget(button_box)
|
||||||
|
self.resize(self.sizeHint())
|
||||||
|
|
||||||
|
def reset_author(self, *args):
|
||||||
|
self.authors_combo.setEditText(_('Unknown'))
|
||||||
|
|
||||||
|
def initialize_authors(self, db, author):
|
||||||
|
all_authors = db.all_authors()
|
||||||
|
all_authors.sort(key=lambda x : sort_key(x[1]))
|
||||||
|
for i in all_authors:
|
||||||
|
id, name = i
|
||||||
|
name = [name.strip().replace('|', ',') for n in name.split(',')]
|
||||||
|
self.authors_combo.addItem(authors_to_string(name))
|
||||||
|
|
||||||
|
au = author
|
||||||
|
if not au:
|
||||||
|
au = _('Unknown')
|
||||||
|
self.authors_combo.setEditText(au.replace('|', ','))
|
||||||
|
|
||||||
|
self.authors_combo.set_separator('&')
|
||||||
|
self.authors_combo.set_space_before_sep(True)
|
||||||
|
self.authors_combo.update_items_cache(db.all_author_names())
|
||||||
|
|
||||||
|
@property
|
||||||
|
def qty_to_add(self):
|
||||||
|
return self.qty_spinbox.value()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def selected_authors(self):
|
||||||
|
return string_to_authors(unicode(self.authors_combo.text()))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = QApplication([])
|
||||||
|
d = AddEmptyBookDialog()
|
||||||
|
d.exec_()
|
@ -775,7 +775,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
|
|||||||
self.original_tags = unicode(self.tags.text())
|
self.original_tags = unicode(self.tags.text())
|
||||||
else:
|
else:
|
||||||
self.tags.setText(self.original_tags)
|
self.tags.setText(self.original_tags)
|
||||||
d = TagEditor(self, self.db, self.row)
|
d = TagEditor(self, self.db, self.id)
|
||||||
d.exec_()
|
d.exec_()
|
||||||
if d.result() == QDialog.Accepted:
|
if d.result() == QDialog.Accepted:
|
||||||
tag_string = ', '.join(d.tags)
|
tag_string = ', '.join(d.tags)
|
||||||
|
@ -10,13 +10,13 @@ from calibre.utils.icu import sort_key
|
|||||||
|
|
||||||
class TagEditor(QDialog, Ui_TagEditor):
|
class TagEditor(QDialog, Ui_TagEditor):
|
||||||
|
|
||||||
def __init__(self, window, db, index=None):
|
def __init__(self, window, db, id_=None):
|
||||||
QDialog.__init__(self, window)
|
QDialog.__init__(self, window)
|
||||||
Ui_TagEditor.__init__(self)
|
Ui_TagEditor.__init__(self)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
self.db = db
|
self.db = db
|
||||||
self.index = index
|
self.index = db.row(id_)
|
||||||
if self.index is not None:
|
if self.index is not None:
|
||||||
tags = self.db.tags(self.index)
|
tags = self.db.tags(self.index)
|
||||||
else:
|
else:
|
||||||
|
@ -356,6 +356,13 @@ class %(classname)s(%(base_class)s):
|
|||||||
self.populate_options(AutomaticNewsRecipe)
|
self.populate_options(AutomaticNewsRecipe)
|
||||||
self.source_code.setText('')
|
self.source_code.setText('')
|
||||||
|
|
||||||
|
def reject(self):
|
||||||
|
if question_dialog(self, _('Are you sure?'),
|
||||||
|
_('You will lose any unsaved changes. To save your'
|
||||||
|
' changes, click the Add/Update recipe button.'
|
||||||
|
' Continue?'), show_copy_button=False):
|
||||||
|
ResizableDialog.reject(self)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
from calibre.gui2 import is_ok_to_use_qt
|
from calibre.gui2 import is_ok_to_use_qt
|
||||||
is_ok_to_use_qt()
|
is_ok_to_use_qt()
|
||||||
|
1014
src/calibre/gui2/metadata/basic_widgets.py
Normal file
1014
src/calibre/gui2/metadata/basic_widgets.py
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -440,6 +440,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
except:
|
except:
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
olddb.break_cycles()
|
||||||
if self.device_connected:
|
if self.device_connected:
|
||||||
self.set_books_in_library(self.booklists(), reset=True)
|
self.set_books_in_library(self.booklists(), reset=True)
|
||||||
self.refresh_ondevice()
|
self.refresh_ondevice()
|
||||||
|
@ -361,6 +361,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
self.refresh()
|
self.refresh()
|
||||||
self.last_update_check = self.last_modified()
|
self.last_update_check = self.last_modified()
|
||||||
|
|
||||||
|
def break_cycles(self):
|
||||||
|
self.data = self.field_metadata = self.prefs = self.listeners = None
|
||||||
|
|
||||||
def initialize_database(self):
|
def initialize_database(self):
|
||||||
metadata_sqlite = open(P('metadata_sqlite.sql'), 'rb').read()
|
metadata_sqlite = open(P('metadata_sqlite.sql'), 'rb').read()
|
||||||
|
@ -441,7 +441,7 @@ menu, choose "Validate fonts".
|
|||||||
I downloaded the installer, but it is not working?
|
I downloaded the installer, but it is not working?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Downloading from the internet can sometimes result in a corrupted download. If the |app| installer you downloaded is not opening, try downloading it again. If re-downloading it does not work, download it from `an alternate location <http://sourceforge.net/projects/calibre/files/>`_. If the installer still doesn't work, then something on your computer is preventing it from running. Best place to ask for more help is in the `forums <http://www.mobileread.com/forums/usercp.php>`_.
|
Downloading from the internet can sometimes result in a corrupted download. If the |app| installer you downloaded is not opening, try downloading it again. If re-downloading it does not work, download it from `an alternate location <http://sourceforge.net/projects/calibre/files/>`_. If the installer still doesn't work, then something on your computer is preventing it from running. Try rebooting your computer and running a registry cleaner like `Wise registry cleaner <http://www.wisecleaner.com>`_. Best place to ask for more help is in the `forums <http://www.mobileread.com/forums/usercp.php>`_.
|
||||||
|
|
||||||
My antivirus program claims |app| is a virus/trojan?
|
My antivirus program claims |app| is a virus/trojan?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -104,12 +104,12 @@ class cmd_commit(_cmd_commit):
|
|||||||
|
|
||||||
def close_bug(self, bug, action, url, config):
|
def close_bug(self, bug, action, url, config):
|
||||||
print 'Closing bug #%s'% bug
|
print 'Closing bug #%s'% bug
|
||||||
nick = config.get_nickname()
|
#nick = config.get_nickname()
|
||||||
suffix = config.get_user_option('bug_close_comment')
|
suffix = config.get_user_option('bug_close_comment')
|
||||||
if suffix is None:
|
if suffix is None:
|
||||||
suffix = 'The fix will be in the next release.'
|
suffix = 'The fix will be in the next release.'
|
||||||
action = action+'ed'
|
action = action+'ed'
|
||||||
msg = '%s in branch %s. %s'%(action, nick, suffix)
|
msg = '%s in branch %s. %s'%(action, 'lp:calibre', suffix)
|
||||||
msg = msg.replace('Fixesed', 'Fixed')
|
msg = msg.replace('Fixesed', 'Fixed')
|
||||||
server = xmlrpclib.ServerProxy(url)
|
server = xmlrpclib.ServerProxy(url)
|
||||||
server.ticket.update(int(bug), msg,
|
server.ticket.update(int(bug), msg,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user