mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk
This commit is contained in:
commit
ad23762ae6
@ -131,7 +131,7 @@ class ZeitEPUBAbo(BasicNewsRecipe):
|
||||
browser.form['pass']=self.password
|
||||
browser.submit()
|
||||
# now find the correct file, we will still use the ePub file
|
||||
epublink = browser.find_link(text_regex=re.compile('.*Ausgabe als Datei im ePub-Format.*'))
|
||||
epublink = browser.find_link(text_regex=re.compile('.*Download als Datei im ePub-Format für eReader.*'))
|
||||
response = browser.follow_link(epublink)
|
||||
self.report_progress(1,_('next step'))
|
||||
|
||||
|
@ -224,7 +224,7 @@ class TREKSTOR(USBMS):
|
||||
FORMATS = ['epub', 'txt', 'pdf']
|
||||
|
||||
VENDOR_ID = [0x1e68]
|
||||
PRODUCT_ID = [0x0041, 0x0042, 0x0052,
|
||||
PRODUCT_ID = [0x0041, 0x0042, 0x0052, 0x004e,
|
||||
0x003e # This is for the EBOOK_PLAYER_5M https://bugs.launchpad.net/bugs/792091
|
||||
]
|
||||
BCD = [0x0002]
|
||||
|
@ -30,6 +30,8 @@ CONTENT_TAGS = set(['img', 'hr', 'br'])
|
||||
|
||||
NOT_VTAGS = HEADER_TAGS | NESTABLE_TAGS | TABLE_TAGS | SPECIAL_TAGS | \
|
||||
CONTENT_TAGS
|
||||
LEAF_TAGS = set(['base', 'basefont', 'frame', 'link', 'meta', 'area', 'br',
|
||||
'col', 'hr', 'img', 'input', 'param'])
|
||||
PAGE_BREAKS = set(['always', 'left', 'right'])
|
||||
|
||||
COLLAPSE = re.compile(r'[ \t\r\n\v]+')
|
||||
@ -246,7 +248,17 @@ class MobiMLizer(object):
|
||||
last.text = None
|
||||
else:
|
||||
last = bstate.body[-1]
|
||||
last.addprevious(anchor)
|
||||
# We use append instead of addprevious so that inline
|
||||
# anchors in large blocks point to the correct place. See
|
||||
# https://bugs.launchpad.net/calibre/+bug/899831
|
||||
# This could potentially break if inserting an anchor at
|
||||
# this point in the markup is illegal, but I cannot think
|
||||
# of such a case offhand.
|
||||
if barename(last.tag) in LEAF_TAGS:
|
||||
last.addprevious(anchor)
|
||||
else:
|
||||
last.append(anchor)
|
||||
|
||||
istate.ids.clear()
|
||||
if not text:
|
||||
return
|
||||
@ -528,7 +540,11 @@ class MobiMLizer(object):
|
||||
old_mim = self.opts.mobi_ignore_margins
|
||||
self.opts.mobi_ignore_margins = False
|
||||
|
||||
if text or tag in CONTENT_TAGS or tag in NESTABLE_TAGS:
|
||||
if (text or tag in CONTENT_TAGS or tag in NESTABLE_TAGS or (
|
||||
# We have an id but no text and no children, the id should still
|
||||
# be added.
|
||||
istate.ids and tag in ('a', 'span', 'i', 'b', 'u') and
|
||||
len(elem)==0)):
|
||||
self.mobimlize_content(tag, text, bstate, istates)
|
||||
for child in elem:
|
||||
self.mobimlize_elem(child, stylizer, bstate, istates)
|
||||
|
@ -18,7 +18,8 @@ from calibre.ebooks.chardet import xml_to_unicode
|
||||
from calibre.utils.zipfile import safe_replace
|
||||
from calibre.utils.config import DynamicConfig
|
||||
from calibre.utils.logging import Log
|
||||
from calibre import guess_type, prints, prepare_string_for_xml
|
||||
from calibre import (guess_type, prints, prepare_string_for_xml,
|
||||
xml_replace_entities)
|
||||
from calibre.ebooks.oeb.transforms.cover import CoverManager
|
||||
from calibre.constants import filesystem_encoding
|
||||
|
||||
@ -96,13 +97,19 @@ class EbookIterator(object):
|
||||
self.ebook_ext = ext.replace('original_', '')
|
||||
|
||||
def search(self, text, index, backwards=False):
|
||||
text = text.lower()
|
||||
text = prepare_string_for_xml(text.lower())
|
||||
pmap = [(i, path) for i, path in enumerate(self.spine)]
|
||||
if backwards:
|
||||
pmap.reverse()
|
||||
for i, path in pmap:
|
||||
if (backwards and i < index) or (not backwards and i > index):
|
||||
if text in open(path, 'rb').read().decode(path.encoding).lower():
|
||||
with open(path, 'rb') as f:
|
||||
raw = f.read().decode(path.encoding)
|
||||
try:
|
||||
raw = xml_replace_entities(raw)
|
||||
except:
|
||||
pass
|
||||
if text in raw.lower():
|
||||
return i
|
||||
|
||||
def find_missing_css_files(self):
|
||||
|
@ -9,7 +9,7 @@ from PyQt4.Qt import QThread, QObject, Qt, QProgressDialog, pyqtSignal, QTimer
|
||||
|
||||
from calibre.gui2.dialogs.progress import ProgressDialog
|
||||
from calibre.gui2 import (question_dialog, error_dialog, info_dialog, gprefs,
|
||||
warning_dialog)
|
||||
warning_dialog, available_width)
|
||||
from calibre.ebooks.metadata.opf2 import OPF
|
||||
from calibre.ebooks.metadata import MetaInformation
|
||||
from calibre.constants import preferred_encoding, filesystem_encoding, DEBUG
|
||||
@ -244,6 +244,7 @@ class Adder(QObject): # {{{
|
||||
def __init__(self, parent, db, callback, spare_server=None):
|
||||
QObject.__init__(self, parent)
|
||||
self.pd = ProgressDialog(_('Adding...'), parent=parent)
|
||||
self.pd.setMaximumWidth(min(600, int(available_width()*0.75)))
|
||||
self.spare_server = spare_server
|
||||
self.db = db
|
||||
self.pd.setModal(True)
|
||||
|
@ -25,7 +25,8 @@ from calibre.utils.logging import Log
|
||||
|
||||
class BulkConfig(Config):
|
||||
|
||||
def __init__(self, parent, db, preferred_output_format=None):
|
||||
def __init__(self, parent, db, preferred_output_format=None,
|
||||
has_saved_settings=True):
|
||||
ResizableDialog.__init__(self, parent)
|
||||
|
||||
self.setup_output_formats(db, preferred_output_format)
|
||||
@ -54,6 +55,12 @@ class BulkConfig(Config):
|
||||
rb = self.buttonBox.button(self.buttonBox.RestoreDefaults)
|
||||
rb.setVisible(False)
|
||||
self.groups.setMouseTracking(True)
|
||||
if not has_saved_settings:
|
||||
o = self.opt_individual_saved_settings
|
||||
o.setEnabled(False)
|
||||
o.setToolTip(_('None of the selected books have saved conversion '
|
||||
'settings.'))
|
||||
o.setChecked(False)
|
||||
|
||||
|
||||
def setup_pipeline(self, *args):
|
||||
|
@ -70,7 +70,7 @@ if pictureflow is not None:
|
||||
ans = ''
|
||||
except:
|
||||
ans = ''
|
||||
return ans
|
||||
return ans.replace('&', '&&')
|
||||
|
||||
def subtitle(self, index):
|
||||
try:
|
||||
|
@ -5,8 +5,9 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
import os, itertools, operator
|
||||
from functools import partial
|
||||
from future_builtins import map
|
||||
|
||||
from PyQt4.Qt import (QTableView, Qt, QAbstractItemView, QMenu, pyqtSignal,
|
||||
QModelIndex, QIcon, QItemSelection, QMimeData, QDrag, QApplication,
|
||||
@ -793,8 +794,13 @@ class BooksView(QTableView): # {{{
|
||||
sel = QItemSelection()
|
||||
m = self.model()
|
||||
max_col = m.columnCount(QModelIndex()) - 1
|
||||
for row in rows:
|
||||
sel.select(m.index(row, 0), m.index(row, max_col))
|
||||
# Create a range based selector for each set of contiguous rows
|
||||
# as supplying selectors for each individual row causes very poor
|
||||
# performance if a large number of rows has to be selected.
|
||||
for k, g in itertools.groupby(enumerate(rows), lambda (i,x):i-x):
|
||||
group = list(map(operator.itemgetter(1), g))
|
||||
sel.merge(QItemSelection(m.index(min(group), 0),
|
||||
m.index(max(group), max_col)), sm.Select)
|
||||
sm.select(sel, sm.ClearAndSelect)
|
||||
|
||||
def get_selected_ids(self):
|
||||
|
@ -252,7 +252,7 @@ class SearchDialog(QDialog, Ui_Dialog):
|
||||
# Milliseconds
|
||||
self.hang_time = self.config.get('hang_time', 75) * 1000
|
||||
|
||||
self.max_results = self.config.get('max_results', 10)
|
||||
self.max_results = self.config.get('max_results', 15)
|
||||
self.should_open_external = self.config.get('open_external', True)
|
||||
|
||||
# Number of threads to run for each type of operation
|
||||
|
@ -14,7 +14,7 @@
|
||||
<string>Get Books</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../../../../resources/images.qrc">
|
||||
<iconset>
|
||||
<normaloff>:/images/store.png</normaloff>:/images/store.png</iconset>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
@ -82,8 +82,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>173</width>
|
||||
<height>106</height>
|
||||
<width>193</width>
|
||||
<height>127</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
@ -254,6 +254,19 @@
|
||||
<header>widgets.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>search_edit</tabstop>
|
||||
<tabstop>search</tabstop>
|
||||
<tabstop>results_view</tabstop>
|
||||
<tabstop>store_list</tabstop>
|
||||
<tabstop>select_all_stores</tabstop>
|
||||
<tabstop>select_invert_stores</tabstop>
|
||||
<tabstop>select_none_stores</tabstop>
|
||||
<tabstop>configure</tabstop>
|
||||
<tabstop>open_external</tabstop>
|
||||
<tabstop>close</tabstop>
|
||||
<tabstop>adv_search_button</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../../../../resources/images.qrc"/>
|
||||
</resources>
|
||||
|
@ -40,9 +40,9 @@ class ChitankaStore(BasicStoreConfig, StorePlugin):
|
||||
d.exec_()
|
||||
|
||||
def search(self, query, max_results=10, timeout=60):
|
||||
# check for cyrilic symbols before performing search
|
||||
# check for cyrillic symbols before performing search
|
||||
uquery = unicode(query.strip(), 'utf-8')
|
||||
reObj = re.search(u'^[а-яА-Я\\d]{4,}[а-яА-Я\\d\\s]*$', uquery)
|
||||
reObj = re.search(u'^[а-яА-Я\\d\\s]{3,}$', uquery)
|
||||
if not reObj:
|
||||
return
|
||||
|
||||
|
@ -46,9 +46,9 @@ class eKnigiStore(BasicStoreConfig, StorePlugin):
|
||||
d.exec_()
|
||||
|
||||
def search(self, query, max_results=10, timeout=60):
|
||||
# check for cyrilic symbols before performing search
|
||||
# check for cyrillic symbols before performing search
|
||||
uquery = unicode(query.strip(), 'utf-8')
|
||||
reObj = re.search(u'^[а-яА-Я\\d]{2,}[а-яА-Я\\d\\s]*$', uquery)
|
||||
reObj = re.search(u'^[а-яА-Я\\d\\s]{2,}$', uquery)
|
||||
if not reObj:
|
||||
return
|
||||
|
||||
|
@ -112,7 +112,10 @@ def convert_bulk_ebook(parent, queue, db, book_ids, out_format=None, args=[]):
|
||||
if total == 0:
|
||||
return None, None, None
|
||||
|
||||
d = BulkConfig(parent, db, out_format)
|
||||
has_saved_settings = db.has_conversion_options(book_ids)
|
||||
|
||||
d = BulkConfig(parent, db, out_format,
|
||||
has_saved_settings=has_saved_settings)
|
||||
if d.exec_() != QDialog.Accepted:
|
||||
return None
|
||||
|
||||
|
@ -359,7 +359,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
||||
'log will be displayed automatically.')%self.gui_debug, show=True)
|
||||
|
||||
def esc(self, *args):
|
||||
self.search.clear()
|
||||
self.clear_button.click()
|
||||
|
||||
def start_content_server(self, check_started=True):
|
||||
from calibre.library.server.main import start_threaded_server
|
||||
|
@ -1085,6 +1085,14 @@ ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
||||
return cPickle.loads(str(data))
|
||||
return None
|
||||
|
||||
def has_conversion_options(self, ids, format='PIPE'):
|
||||
ids = tuple(ids)
|
||||
if len(ids) > 50000:
|
||||
return True
|
||||
return self.conn.get('''
|
||||
SELECT data FROM conversion_options WHERE book IN %r AND
|
||||
format=? LIMIT 1'''%(ids,), (format,), all=False) is not None
|
||||
|
||||
def delete_conversion_options(self, id, format, commit=True):
|
||||
self.conn.execute('DELETE FROM conversion_options WHERE book=? AND format=?',
|
||||
(id, format.upper()))
|
||||
|
Loading…
x
Reference in New Issue
Block a user