mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Move from gprefs to a store specific JSON config that each store automatically has access to use.
This commit is contained in:
commit
4ff0747da0
@ -25,6 +25,7 @@ msprefs.defaults['max_tags'] = 20
|
|||||||
msprefs.defaults['wait_after_first_identify_result'] = 30 # seconds
|
msprefs.defaults['wait_after_first_identify_result'] = 30 # seconds
|
||||||
msprefs.defaults['wait_after_first_cover_result'] = 60 # seconds
|
msprefs.defaults['wait_after_first_cover_result'] = 60 # seconds
|
||||||
msprefs.defaults['swap_author_names'] = False
|
msprefs.defaults['swap_author_names'] = False
|
||||||
|
msprefs.defaults['fewer_tags'] = True
|
||||||
|
|
||||||
# Google covers are often poor quality (scans/errors) but they have high
|
# Google covers are often poor quality (scans/errors) but they have high
|
||||||
# resolution, so they trump covers from better sources. So make sure they
|
# resolution, so they trump covers from better sources. So make sure they
|
||||||
|
@ -216,7 +216,7 @@ class ISBNMerge(object):
|
|||||||
|
|
||||||
# We assume the smallest set of tags has the least cruft in it
|
# We assume the smallest set of tags has the least cruft in it
|
||||||
ans.tags = self.length_merge('tags', results,
|
ans.tags = self.length_merge('tags', results,
|
||||||
null_value=ans.tags)
|
null_value=ans.tags, shortest=msprefs['fewer_tags'])
|
||||||
|
|
||||||
# We assume the longest series has the most info in it
|
# We assume the longest series has the most info in it
|
||||||
ans.series = self.length_merge('series', results,
|
ans.series = self.length_merge('series', results,
|
||||||
|
@ -3,7 +3,7 @@ from __future__ import (unicode_literals, division, absolute_import,
|
|||||||
print_function)
|
print_function)
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
__copyright__ = '2011, Kovid Goyal kovid@kovidgoyal.net'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
'''
|
'''
|
||||||
@ -17,7 +17,7 @@ from lxml import html
|
|||||||
from lxml.html import soupparser
|
from lxml.html import soupparser
|
||||||
|
|
||||||
from calibre.ebooks.metadata import check_isbn
|
from calibre.ebooks.metadata import check_isbn
|
||||||
from calibre.ebooks.metadata.sources.base import Source
|
from calibre.ebooks.metadata.sources.base import Source, Option
|
||||||
from calibre.ebooks.metadata.book.base import Metadata
|
from calibre.ebooks.metadata.book.base import Metadata
|
||||||
from calibre.ebooks.chardet import xml_to_unicode
|
from calibre.ebooks.chardet import xml_to_unicode
|
||||||
from calibre.library.comments import sanitize_comments_html
|
from calibre.library.comments import sanitize_comments_html
|
||||||
@ -40,6 +40,18 @@ class OverDrive(Source):
|
|||||||
supports_gzip_transfer_encoding = False
|
supports_gzip_transfer_encoding = False
|
||||||
cached_cover_url_is_reliable = True
|
cached_cover_url_is_reliable = True
|
||||||
|
|
||||||
|
options = (
|
||||||
|
Option('get_full_metadata', 'bool', False,
|
||||||
|
_('Download all metadata (slow)'),
|
||||||
|
_('Enable this option to gather all metadata available from Overdrive.')),
|
||||||
|
)
|
||||||
|
|
||||||
|
config_help_message = '<p>'+_('Additional metadata can be taken from Overdrive\'s book detail'
|
||||||
|
' page. This includes a limited set of tags used by libraries, comments, language,'
|
||||||
|
' and the ebook ISBN. Collecting this data is disabled by default due to the extra'
|
||||||
|
' time required. Check the download all metadata option below to'
|
||||||
|
' enable downloading this data.')
|
||||||
|
|
||||||
def identify(self, log, result_queue, abort, title=None, authors=None, # {{{
|
def identify(self, log, result_queue, abort, title=None, authors=None, # {{{
|
||||||
identifiers={}, timeout=30):
|
identifiers={}, timeout=30):
|
||||||
ovrdrv_id = identifiers.get('overdrive', None)
|
ovrdrv_id = identifiers.get('overdrive', None)
|
||||||
@ -54,11 +66,13 @@ class OverDrive(Source):
|
|||||||
self.parse_search_results(ovrdrv_data, mi)
|
self.parse_search_results(ovrdrv_data, mi)
|
||||||
if ovrdrv_id is None:
|
if ovrdrv_id is None:
|
||||||
ovrdrv_id = ovrdrv_data[7]
|
ovrdrv_id = ovrdrv_data[7]
|
||||||
|
|
||||||
|
if self.prefs['get_full_metadata']:
|
||||||
|
self.get_book_detail(br, ovrdrv_data[1], mi, ovrdrv_id, log)
|
||||||
|
|
||||||
if isbn is not None:
|
if isbn is not None:
|
||||||
self.cache_isbn_to_identifier(isbn, ovrdrv_id)
|
self.cache_isbn_to_identifier(isbn, ovrdrv_id)
|
||||||
|
|
||||||
self.get_book_detail(br, ovrdrv_data[1], mi, ovrdrv_id, log)
|
|
||||||
|
|
||||||
result_queue.put(mi)
|
result_queue.put(mi)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
@ -438,4 +452,3 @@ if __name__ == '__main__':
|
|||||||
authors_test(['Agatha Christie'])]
|
authors_test(['Agatha Christie'])]
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ from functools import partial
|
|||||||
|
|
||||||
from PyQt4.Qt import QMenu
|
from PyQt4.Qt import QMenu
|
||||||
|
|
||||||
from calibre.gui2 import JSONConfig
|
|
||||||
from calibre.gui2.actions import InterfaceAction
|
from calibre.gui2.actions import InterfaceAction
|
||||||
|
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||||
|
|
||||||
class StoreAction(InterfaceAction):
|
class StoreAction(InterfaceAction):
|
||||||
|
|
||||||
@ -19,8 +19,6 @@ class StoreAction(InterfaceAction):
|
|||||||
action_spec = (_('Get books'), 'store.png', None, None)
|
action_spec = (_('Get books'), 'store.png', None, None)
|
||||||
|
|
||||||
def genesis(self):
|
def genesis(self):
|
||||||
self.config = JSONConfig('store/action')
|
|
||||||
|
|
||||||
self.qaction.triggered.connect(self.search)
|
self.qaction.triggered.connect(self.search)
|
||||||
self.store_menu = QMenu()
|
self.store_menu = QMenu()
|
||||||
self.load_menu()
|
self.load_menu()
|
||||||
@ -34,34 +32,35 @@ class StoreAction(InterfaceAction):
|
|||||||
self.qaction.setMenu(self.store_menu)
|
self.qaction.setMenu(self.store_menu)
|
||||||
|
|
||||||
def search(self):
|
def search(self):
|
||||||
self.first_run_check()
|
self.show_disclaimer()
|
||||||
from calibre.gui2.store.search import SearchDialog
|
from calibre.gui2.store.search import SearchDialog
|
||||||
sd = SearchDialog(self.gui.istores, self.gui)
|
sd = SearchDialog(self.gui.istores, self.gui)
|
||||||
sd.exec_()
|
sd.exec_()
|
||||||
|
|
||||||
def open_store(self, store_plugin):
|
def open_store(self, store_plugin):
|
||||||
self.first_run_check()
|
self.show_disclaimer()
|
||||||
store_plugin.open(self.gui)
|
store_plugin.open(self.gui)
|
||||||
|
|
||||||
def first_run_check(self):
|
def show_disclaimer(self):
|
||||||
if self.config.get('first_run', True):
|
confirm(('<p>' +
|
||||||
self.config['first_run'] = False
|
|
||||||
from calibre.gui2 import info_dialog
|
|
||||||
info_dialog(self.gui, _('About Get Books'), '<p>' +
|
|
||||||
_('Calibre helps you find the ebooks you want by searching '
|
_('Calibre helps you find the ebooks you want by searching '
|
||||||
'the websites of a variety of commercial and public domain '
|
'the websites of various commercial and public domain '
|
||||||
'book sources for you.') +
|
'book sources for you.') +
|
||||||
'<p>' +
|
'<p>' +
|
||||||
_('Using the integrated search you can easily find which '
|
_('Using the integrated search you can easily find which '
|
||||||
'store has the book you are looking for, at the best price. '
|
'store has the book you are looking for, at the best price. '
|
||||||
'You will also get DRM status and other useful information.')
|
'You also get DRM status and other useful information.')
|
||||||
+ '<p>' +
|
+ '<p>' +
|
||||||
_('All transactions (paid or otherwise) are handled between '
|
_('All transactions (paid or otherwise) are handled between '
|
||||||
'you and the particular website. '
|
'you and the book seller. '
|
||||||
'Calibre is not part of this process and any issues related '
|
'Calibre is not part of this process and any issues related '
|
||||||
'to a purchase should be directed to the website you are '
|
'to a purchase should be directed to the website you are '
|
||||||
'buying from. Be sure to double check that any books you get '
|
'buying from. Be sure to double check that any books you get '
|
||||||
'will work with your e-book reader, especially if the book you '
|
'will work with your e-book reader, especially if the book you '
|
||||||
'are buying has '
|
'are buying has '
|
||||||
'<a href="http://drmfree.calibre-ebook.com/about#drm">DRM</a>.'
|
'<a href="http://drmfree.calibre-ebook.com/about#drm">DRM</a>.'
|
||||||
), show=True, show_copy_button=False)
|
)), 'about_get_books_msg',
|
||||||
|
parent=self.gui, show_cancel_button=False,
|
||||||
|
confirm_msg=_('Show this message again'),
|
||||||
|
pixmap='dialog_information.png', title=_('About Get Books'))
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ class Dialog(QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
|
|
||||||
def confirm(msg, name, parent=None, pixmap='dialog_warning.png', title=None,
|
def confirm(msg, name, parent=None, pixmap='dialog_warning.png', title=None,
|
||||||
show_cancel_button=True):
|
show_cancel_button=True, confirm_msg=None):
|
||||||
if not dynamic.get(confirm_config_name(name), True):
|
if not dynamic.get(confirm_config_name(name), True):
|
||||||
return True
|
return True
|
||||||
d = Dialog(msg, name, parent)
|
d = Dialog(msg, name, parent)
|
||||||
@ -35,5 +35,7 @@ def confirm(msg, name, parent=None, pixmap='dialog_warning.png', title=None,
|
|||||||
d.setWindowTitle(title)
|
d.setWindowTitle(title)
|
||||||
if not show_cancel_button:
|
if not show_cancel_button:
|
||||||
d.buttonBox.button(d.buttonBox.Cancel).setVisible(False)
|
d.buttonBox.button(d.buttonBox.Cancel).setVisible(False)
|
||||||
|
if confirm_msg is not None:
|
||||||
|
d.again.setText(confirm_msg)
|
||||||
d.resize(d.sizeHint())
|
d.resize(d.sizeHint())
|
||||||
return d.exec_() == d.Accepted
|
return d.exec_() == d.Accepted
|
||||||
|
@ -259,6 +259,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
r('wait_after_first_identify_result', msprefs)
|
r('wait_after_first_identify_result', msprefs)
|
||||||
r('wait_after_first_cover_result', msprefs)
|
r('wait_after_first_cover_result', msprefs)
|
||||||
r('swap_author_names', msprefs)
|
r('swap_author_names', msprefs)
|
||||||
|
r('fewer_tags', msprefs)
|
||||||
|
|
||||||
self.configure_plugin_button.clicked.connect(self.configure_plugin)
|
self.configure_plugin_button.clicked.connect(self.configure_plugin)
|
||||||
self.sources_model = SourcesModel(self)
|
self.sources_model = SourcesModel(self)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>781</width>
|
<width>781</width>
|
||||||
<height>300</height>
|
<height>394</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -21,7 +21,7 @@
|
|||||||
<widget class="QStackedWidget" name="stack">
|
<widget class="QStackedWidget" name="stack">
|
||||||
<widget class="QWidget" name="page">
|
<widget class="QWidget" name="page">
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0" rowspan="6">
|
<item row="0" column="0" rowspan="7">
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Metadata sources</string>
|
<string>Metadata sources</string>
|
||||||
@ -105,7 +105,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Max. number of &tags to download:</string>
|
<string>Max. number of &tags to download:</string>
|
||||||
@ -115,10 +115,10 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="2">
|
<item row="4" column="2">
|
||||||
<widget class="QSpinBox" name="opt_max_tags"/>
|
<widget class="QSpinBox" name="opt_max_tags"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="5" column="1">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Max. &time to wait after first match is found:</string>
|
<string>Max. &time to wait after first match is found:</string>
|
||||||
@ -128,14 +128,14 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="2">
|
<item row="5" column="2">
|
||||||
<widget class="QSpinBox" name="opt_wait_after_first_identify_result">
|
<widget class="QSpinBox" name="opt_wait_after_first_identify_result">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> secs</string>
|
<string> secs</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1">
|
<item row="6" column="1">
|
||||||
<widget class="QLabel" name="label_4">
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Max. time to wait after first &cover is found:</string>
|
<string>Max. time to wait after first &cover is found:</string>
|
||||||
@ -145,13 +145,24 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="2">
|
<item row="6" column="2">
|
||||||
<widget class="QSpinBox" name="opt_wait_after_first_cover_result">
|
<widget class="QSpinBox" name="opt_wait_after_first_cover_result">
|
||||||
<property name="suffix">
|
<property name="suffix">
|
||||||
<string> secs</string>
|
<string> secs</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="1" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="opt_fewer_tags">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><p>Different metadata sources have different sets of tags for the same book. If this option is checked, then calibre will use the smaller tag sets. These tend to be more like genres, while the larger tag sets tend to describe the books content.
|
||||||
|
<p>Note that this option will only make a practical difference if one of the metadata sources has a genre like tag set for the book you are searching for. Most often, they all have large tag sets.</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Prefer &fewer tags</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="page_2"/>
|
<widget class="QWidget" name="page_2"/>
|
||||||
|
@ -46,9 +46,12 @@ class StorePlugin(object): # {{{
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, gui, name):
|
def __init__(self, gui, name):
|
||||||
|
from calibre.gui2 import JSONConfig
|
||||||
|
|
||||||
self.gui = gui
|
self.gui = gui
|
||||||
self.name = name
|
self.name = name
|
||||||
self.base_plugin = None
|
self.base_plugin = None
|
||||||
|
self.config = JSONConfig('store/stores/' + self.name)
|
||||||
|
|
||||||
def open(self, gui, parent=None, detail_item=None, external=False):
|
def open(self, gui, parent=None, detail_item=None, external=False):
|
||||||
'''
|
'''
|
||||||
|
@ -8,14 +8,8 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
from PyQt4.Qt import QWidget
|
from PyQt4.Qt import QWidget
|
||||||
|
|
||||||
from calibre.gui2 import gprefs
|
|
||||||
from calibre.gui2.store.basic_config_widget_ui import Ui_Form
|
from calibre.gui2.store.basic_config_widget_ui import Ui_Form
|
||||||
|
|
||||||
def save_settings(config_widget):
|
|
||||||
gprefs[config_widget.store.name + '_open_external'] = config_widget.open_external.isChecked()
|
|
||||||
tags = unicode(config_widget.tags.text())
|
|
||||||
gprefs[config_widget.store.name + '_tags'] = tags
|
|
||||||
|
|
||||||
class BasicStoreConfigWidget(QWidget, Ui_Form):
|
class BasicStoreConfigWidget(QWidget, Ui_Form):
|
||||||
|
|
||||||
def __init__(self, store):
|
def __init__(self, store):
|
||||||
@ -27,10 +21,10 @@ class BasicStoreConfigWidget(QWidget, Ui_Form):
|
|||||||
self.load_setings()
|
self.load_setings()
|
||||||
|
|
||||||
def load_setings(self):
|
def load_setings(self):
|
||||||
settings = self.store.get_settings()
|
config = self.store.config
|
||||||
|
|
||||||
self.open_external.setChecked(settings.get(self.store.name + '_open_external'))
|
self.open_external.setChecked(config.get('open_external', False))
|
||||||
self.tags.setText(settings.get(self.store.name + '_tags', ''))
|
self.tags.setText(config.get('tags', ''))
|
||||||
|
|
||||||
class BasicStoreConfig(object):
|
class BasicStoreConfig(object):
|
||||||
|
|
||||||
@ -41,12 +35,6 @@ class BasicStoreConfig(object):
|
|||||||
return BasicStoreConfigWidget(self)
|
return BasicStoreConfigWidget(self)
|
||||||
|
|
||||||
def save_settings(self, config_widget):
|
def save_settings(self, config_widget):
|
||||||
save_settings(config_widget)
|
self.config['open_external'] = config_widget.open_external.isChecked()
|
||||||
|
tags = unicode(config_widget.tags.text())
|
||||||
def get_settings(self):
|
self.config['tags'] = tags
|
||||||
settings = {}
|
|
||||||
|
|
||||||
settings[self.name + '_open_external'] = gprefs.get(self.name + '_open_external', False)
|
|
||||||
settings[self.name + '_tags'] = gprefs.get(self.name + '_tags', self.name + ', store, download')
|
|
||||||
|
|
||||||
return settings
|
|
||||||
|
@ -23,10 +23,9 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
|||||||
class BeWriteStore(BasicStoreConfig, StorePlugin):
|
class BeWriteStore(BasicStoreConfig, StorePlugin):
|
||||||
|
|
||||||
def open(self, parent=None, detail_item=None, external=False):
|
def open(self, parent=None, detail_item=None, external=False):
|
||||||
settings = self.get_settings()
|
|
||||||
url = 'http://www.bewrite.net/mm5/merchant.mvc?Screen=SFNT'
|
url = 'http://www.bewrite.net/mm5/merchant.mvc?Screen=SFNT'
|
||||||
|
|
||||||
if external or settings.get(self.name + '_open_external', False):
|
if external or self.config.get('open_external', False):
|
||||||
if detail_item:
|
if detail_item:
|
||||||
url = url + detail_item
|
url = url + detail_item
|
||||||
open_url(QUrl(url_slash_cleaner(url)))
|
open_url(QUrl(url_slash_cleaner(url)))
|
||||||
@ -36,7 +35,7 @@ class BeWriteStore(BasicStoreConfig, StorePlugin):
|
|||||||
detail_url = url + detail_item
|
detail_url = url + detail_item
|
||||||
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
||||||
d.setWindowTitle(self.name)
|
d.setWindowTitle(self.name)
|
||||||
d.set_tags(settings.get(self.name + '_tags', ''))
|
d.set_tags(self.config.get('tags', ''))
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
def search(self, query, max_results=10, timeout=60):
|
def search(self, query, max_results=10, timeout=60):
|
||||||
|
@ -25,8 +25,6 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
|||||||
class BNStore(BasicStoreConfig, StorePlugin):
|
class BNStore(BasicStoreConfig, StorePlugin):
|
||||||
|
|
||||||
def open(self, parent=None, detail_item=None, external=False):
|
def open(self, parent=None, detail_item=None, external=False):
|
||||||
settings = self.get_settings()
|
|
||||||
|
|
||||||
pub_id = '21000000000352219'
|
pub_id = '21000000000352219'
|
||||||
# Use Kovid's affiliate id 30% of the time.
|
# Use Kovid's affiliate id 30% of the time.
|
||||||
if random.randint(1, 10) in (1, 2, 3):
|
if random.randint(1, 10) in (1, 2, 3):
|
||||||
@ -40,12 +38,12 @@ class BNStore(BasicStoreConfig, StorePlugin):
|
|||||||
isbn = mo.group('isbn')
|
isbn = mo.group('isbn')
|
||||||
detail_item = 'http://gan.doubleclick.net/gan_click?lid=41000000012871747&pid=' + isbn + '&adurl=' + detail_item + '&pubid=' + pub_id
|
detail_item = 'http://gan.doubleclick.net/gan_click?lid=41000000012871747&pid=' + isbn + '&adurl=' + detail_item + '&pubid=' + pub_id
|
||||||
|
|
||||||
if external or settings.get(self.name + '_open_external', False):
|
if external or self.config.get('open_external', False):
|
||||||
open_url(QUrl(url_slash_cleaner(detail_item if detail_item else url)))
|
open_url(QUrl(url_slash_cleaner(detail_item if detail_item else url)))
|
||||||
else:
|
else:
|
||||||
d = WebStoreDialog(self.gui, url, parent, detail_item)
|
d = WebStoreDialog(self.gui, url, parent, detail_item)
|
||||||
d.setWindowTitle(self.name)
|
d.setWindowTitle(self.name)
|
||||||
d.set_tags(settings.get(self.name + '_tags', ''))
|
d.set_tags(self.config.get('tags', ''))
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
def search(self, query, max_results=10, timeout=60):
|
def search(self, query, max_results=10, timeout=60):
|
||||||
|
@ -24,7 +24,6 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
|||||||
class DieselEbooksStore(BasicStoreConfig, StorePlugin):
|
class DieselEbooksStore(BasicStoreConfig, StorePlugin):
|
||||||
|
|
||||||
def open(self, parent=None, detail_item=None, external=False):
|
def open(self, parent=None, detail_item=None, external=False):
|
||||||
settings = self.get_settings()
|
|
||||||
url = 'http://www.diesel-ebooks.com/'
|
url = 'http://www.diesel-ebooks.com/'
|
||||||
|
|
||||||
aff_id = '?aid=2049'
|
aff_id = '?aid=2049'
|
||||||
@ -37,12 +36,12 @@ class DieselEbooksStore(BasicStoreConfig, StorePlugin):
|
|||||||
detail_url = url + detail_item + aff_id
|
detail_url = url + detail_item + aff_id
|
||||||
url = url + aff_id
|
url = url + aff_id
|
||||||
|
|
||||||
if external or settings.get(self.name + '_open_external', False):
|
if external or self.config.get('open_external', False):
|
||||||
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
|
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
|
||||||
else:
|
else:
|
||||||
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
||||||
d.setWindowTitle(self.name)
|
d.setWindowTitle(self.name)
|
||||||
d.set_tags(settings.get(self.name + '_tags', ''))
|
d.set_tags(self.config.get('tags', ''))
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
def search(self, query, max_results=10, timeout=60):
|
def search(self, query, max_results=10, timeout=60):
|
||||||
|
@ -25,8 +25,6 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
|||||||
class EbookscomStore(BasicStoreConfig, StorePlugin):
|
class EbookscomStore(BasicStoreConfig, StorePlugin):
|
||||||
|
|
||||||
def open(self, parent=None, detail_item=None, external=False):
|
def open(self, parent=None, detail_item=None, external=False):
|
||||||
settings = self.get_settings()
|
|
||||||
|
|
||||||
m_url = 'http://www.dpbolvw.net/'
|
m_url = 'http://www.dpbolvw.net/'
|
||||||
h_click = 'click-4879827-10364500'
|
h_click = 'click-4879827-10364500'
|
||||||
d_click = 'click-4879827-10281551'
|
d_click = 'click-4879827-10281551'
|
||||||
@ -40,12 +38,12 @@ class EbookscomStore(BasicStoreConfig, StorePlugin):
|
|||||||
if detail_item:
|
if detail_item:
|
||||||
detail_url = m_url + d_click + detail_item
|
detail_url = m_url + d_click + detail_item
|
||||||
|
|
||||||
if external or settings.get(self.name + '_open_external', False):
|
if external or self.config.get('open_external', False):
|
||||||
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
|
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
|
||||||
else:
|
else:
|
||||||
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
||||||
d.setWindowTitle(self.name)
|
d.setWindowTitle(self.name)
|
||||||
d.set_tags(settings.get(self.name + '_tags', ''))
|
d.set_tags(self.config.get('tags', ''))
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
def search(self, query, max_results=10, timeout=60):
|
def search(self, query, max_results=10, timeout=60):
|
||||||
|
@ -25,8 +25,6 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
|||||||
class EHarlequinStore(BasicStoreConfig, StorePlugin):
|
class EHarlequinStore(BasicStoreConfig, StorePlugin):
|
||||||
|
|
||||||
def open(self, parent=None, detail_item=None, external=False):
|
def open(self, parent=None, detail_item=None, external=False):
|
||||||
settings = self.get_settings()
|
|
||||||
|
|
||||||
m_url = 'http://www.dpbolvw.net/'
|
m_url = 'http://www.dpbolvw.net/'
|
||||||
h_click = 'click-4879827-534091'
|
h_click = 'click-4879827-534091'
|
||||||
d_click = 'click-4879827-10375439'
|
d_click = 'click-4879827-10375439'
|
||||||
@ -40,12 +38,12 @@ class EHarlequinStore(BasicStoreConfig, StorePlugin):
|
|||||||
if detail_item:
|
if detail_item:
|
||||||
detail_url = m_url + d_click + detail_item
|
detail_url = m_url + d_click + detail_item
|
||||||
|
|
||||||
if external or settings.get(self.name + '_open_external', False):
|
if external or self.config.get('open_external', False):
|
||||||
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
|
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
|
||||||
else:
|
else:
|
||||||
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
||||||
d.setWindowTitle(self.name)
|
d.setWindowTitle(self.name)
|
||||||
d.set_tags(settings.get(self.name + '_tags', ''))
|
d.set_tags(self.config.get('tags', ''))
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
def search(self, query, max_results=10, timeout=60):
|
def search(self, query, max_results=10, timeout=60):
|
||||||
|
@ -23,11 +23,10 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
|||||||
class FeedbooksStore(BasicStoreConfig, StorePlugin):
|
class FeedbooksStore(BasicStoreConfig, StorePlugin):
|
||||||
|
|
||||||
def open(self, parent=None, detail_item=None, external=False):
|
def open(self, parent=None, detail_item=None, external=False):
|
||||||
settings = self.get_settings()
|
|
||||||
url = 'http://m.feedbooks.com/'
|
url = 'http://m.feedbooks.com/'
|
||||||
ext_url = 'http://feedbooks.com/'
|
ext_url = 'http://feedbooks.com/'
|
||||||
|
|
||||||
if external or settings.get(self.name + '_open_external', False):
|
if external or self.config.get('open_external', False):
|
||||||
if detail_item:
|
if detail_item:
|
||||||
ext_url = ext_url + detail_item
|
ext_url = ext_url + detail_item
|
||||||
open_url(QUrl(url_slash_cleaner(ext_url)))
|
open_url(QUrl(url_slash_cleaner(ext_url)))
|
||||||
@ -37,7 +36,7 @@ class FeedbooksStore(BasicStoreConfig, StorePlugin):
|
|||||||
detail_url = url + detail_item
|
detail_url = url + detail_item
|
||||||
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
||||||
d.setWindowTitle(self.name)
|
d.setWindowTitle(self.name)
|
||||||
d.set_tags(settings.get(self.name + '_tags', ''))
|
d.set_tags(self.config.get('tags', ''))
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
def search(self, query, max_results=10, timeout=60):
|
def search(self, query, max_results=10, timeout=60):
|
||||||
|
@ -23,11 +23,10 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
|||||||
class GutenbergStore(BasicStoreConfig, StorePlugin):
|
class GutenbergStore(BasicStoreConfig, StorePlugin):
|
||||||
|
|
||||||
def open(self, parent=None, detail_item=None, external=False):
|
def open(self, parent=None, detail_item=None, external=False):
|
||||||
settings = self.get_settings()
|
|
||||||
url = 'http://m.gutenberg.org/'
|
url = 'http://m.gutenberg.org/'
|
||||||
ext_url = 'http://gutenberg.org/'
|
ext_url = 'http://gutenberg.org/'
|
||||||
|
|
||||||
if external or settings.get(self.name + '_open_external', False):
|
if external or self.config.get('open_external', False):
|
||||||
if detail_item:
|
if detail_item:
|
||||||
ext_url = ext_url + detail_item
|
ext_url = ext_url + detail_item
|
||||||
open_url(QUrl(url_slash_cleaner(ext_url)))
|
open_url(QUrl(url_slash_cleaner(ext_url)))
|
||||||
@ -37,7 +36,7 @@ class GutenbergStore(BasicStoreConfig, StorePlugin):
|
|||||||
detail_url = url + detail_item
|
detail_url = url + detail_item
|
||||||
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
||||||
d.setWindowTitle(self.name)
|
d.setWindowTitle(self.name)
|
||||||
d.set_tags(settings.get(self.name + '_tags', ''))
|
d.set_tags(self.config.get('tags', ''))
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
def search(self, query, max_results=10, timeout=60):
|
def search(self, query, max_results=10, timeout=60):
|
||||||
|
@ -24,8 +24,6 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
|||||||
class KoboStore(BasicStoreConfig, StorePlugin):
|
class KoboStore(BasicStoreConfig, StorePlugin):
|
||||||
|
|
||||||
def open(self, parent=None, detail_item=None, external=False):
|
def open(self, parent=None, detail_item=None, external=False):
|
||||||
settings = self.get_settings()
|
|
||||||
|
|
||||||
m_url = 'http://www.dpbolvw.net/'
|
m_url = 'http://www.dpbolvw.net/'
|
||||||
h_click = 'click-4879827-10762497'
|
h_click = 'click-4879827-10762497'
|
||||||
d_click = 'click-4879827-10772898'
|
d_click = 'click-4879827-10772898'
|
||||||
@ -39,12 +37,12 @@ class KoboStore(BasicStoreConfig, StorePlugin):
|
|||||||
if detail_item:
|
if detail_item:
|
||||||
detail_url = m_url + d_click + detail_item
|
detail_url = m_url + d_click + detail_item
|
||||||
|
|
||||||
if external or settings.get(self.name + '_open_external', False):
|
if external or self.config.get('open_external', False):
|
||||||
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
|
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
|
||||||
else:
|
else:
|
||||||
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
||||||
d.setWindowTitle(self.name)
|
d.setWindowTitle(self.name)
|
||||||
d.set_tags(settings.get(self.name + '_tags', ''))
|
d.set_tags(self.config.get('tags', ''))
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
def search(self, query, max_results=10, timeout=60):
|
def search(self, query, max_results=10, timeout=60):
|
||||||
|
@ -24,19 +24,18 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
|||||||
class ManyBooksStore(BasicStoreConfig, StorePlugin):
|
class ManyBooksStore(BasicStoreConfig, StorePlugin):
|
||||||
|
|
||||||
def open(self, parent=None, detail_item=None, external=False):
|
def open(self, parent=None, detail_item=None, external=False):
|
||||||
settings = self.get_settings()
|
|
||||||
url = 'http://manybooks.net/'
|
url = 'http://manybooks.net/'
|
||||||
|
|
||||||
detail_url = None
|
detail_url = None
|
||||||
if detail_item:
|
if detail_item:
|
||||||
detail_url = url + detail_item
|
detail_url = url + detail_item
|
||||||
|
|
||||||
if external or settings.get(self.name + '_open_external', False):
|
if external or self.config.get('open_external', False):
|
||||||
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
|
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
|
||||||
else:
|
else:
|
||||||
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
||||||
d.setWindowTitle(self.name)
|
d.setWindowTitle(self.name)
|
||||||
d.set_tags(settings.get(self.name + '_tags', ''))
|
d.set_tags(self.config.get('tags', ''))
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
def search(self, query, max_results=10, timeout=60):
|
def search(self, query, max_results=10, timeout=60):
|
||||||
|
@ -18,7 +18,7 @@ from PyQt4.Qt import Qt, QUrl, QDialog, QAbstractItemModel, QModelIndex, QVarian
|
|||||||
pyqtSignal
|
pyqtSignal
|
||||||
|
|
||||||
from calibre import browser
|
from calibre import browser
|
||||||
from calibre.gui2 import open_url, NONE, JSONConfig
|
from calibre.gui2 import open_url, NONE
|
||||||
from calibre.gui2.store import StorePlugin
|
from calibre.gui2.store import StorePlugin
|
||||||
from calibre.gui2.store.basic_config import BasicStoreConfig
|
from calibre.gui2.store.basic_config import BasicStoreConfig
|
||||||
from calibre.gui2.store.mobileread_store_dialog_ui import Ui_Dialog
|
from calibre.gui2.store.mobileread_store_dialog_ui import Ui_Dialog
|
||||||
@ -29,20 +29,18 @@ from calibre.utils.icu import sort_key
|
|||||||
class MobileReadStore(BasicStoreConfig, StorePlugin):
|
class MobileReadStore(BasicStoreConfig, StorePlugin):
|
||||||
|
|
||||||
def genesis(self):
|
def genesis(self):
|
||||||
self.config = JSONConfig('store/store/' + self.name)
|
|
||||||
self.rlock = RLock()
|
self.rlock = RLock()
|
||||||
|
|
||||||
def open(self, parent=None, detail_item=None, external=False):
|
def open(self, parent=None, detail_item=None, external=False):
|
||||||
settings = self.get_settings()
|
|
||||||
url = 'http://www.mobileread.com/'
|
url = 'http://www.mobileread.com/'
|
||||||
|
|
||||||
if external or settings.get(self.name + '_open_external', False):
|
if external or self.config.get('open_external', False):
|
||||||
open_url(QUrl(detail_item if detail_item else url))
|
open_url(QUrl(detail_item if detail_item else url))
|
||||||
else:
|
else:
|
||||||
if detail_item:
|
if detail_item:
|
||||||
d = WebStoreDialog(self.gui, url, parent, detail_item)
|
d = WebStoreDialog(self.gui, url, parent, detail_item)
|
||||||
d.setWindowTitle(self.name)
|
d.setWindowTitle(self.name)
|
||||||
d.set_tags(settings.get(self.name + '_tags', ''))
|
d.set_tags(self.config.get('tags', ''))
|
||||||
d.exec_()
|
d.exec_()
|
||||||
else:
|
else:
|
||||||
d = MobeReadStoreDialog(self, parent)
|
d = MobeReadStoreDialog(self, parent)
|
||||||
|
@ -23,10 +23,9 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
|||||||
class OpenLibraryStore(BasicStoreConfig, StorePlugin):
|
class OpenLibraryStore(BasicStoreConfig, StorePlugin):
|
||||||
|
|
||||||
def open(self, parent=None, detail_item=None, external=False):
|
def open(self, parent=None, detail_item=None, external=False):
|
||||||
settings = self.get_settings()
|
|
||||||
url = 'http://openlibrary.org/'
|
url = 'http://openlibrary.org/'
|
||||||
|
|
||||||
if external or settings.get(self.name + '_open_external', False):
|
if external or self.config.get('open_external', False):
|
||||||
if detail_item:
|
if detail_item:
|
||||||
url = url + detail_item
|
url = url + detail_item
|
||||||
open_url(QUrl(url_slash_cleaner(url)))
|
open_url(QUrl(url_slash_cleaner(url)))
|
||||||
@ -36,7 +35,7 @@ class OpenLibraryStore(BasicStoreConfig, StorePlugin):
|
|||||||
detail_url = url + detail_item
|
detail_url = url + detail_item
|
||||||
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
||||||
d.setWindowTitle(self.name)
|
d.setWindowTitle(self.name)
|
||||||
d.set_tags(settings.get(self.name + '_tags', ''))
|
d.set_tags(self.config.get('tags', ''))
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
def search(self, query, max_results=10, timeout=60):
|
def search(self, query, max_results=10, timeout=60):
|
||||||
|
@ -396,7 +396,7 @@ class DetailsThreadPool(GenericDownloadThreadPool):
|
|||||||
|
|
||||||
|
|
||||||
class DetailsThread(Thread):
|
class DetailsThread(Thread):
|
||||||
|
|
||||||
def __init__(self, tasks, results):
|
def __init__(self, tasks, results):
|
||||||
Thread.__init__(self)
|
Thread.__init__(self)
|
||||||
self.daemon = True
|
self.daemon = True
|
||||||
@ -428,11 +428,14 @@ class Matches(QAbstractItemModel):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
QAbstractItemModel.__init__(self)
|
QAbstractItemModel.__init__(self)
|
||||||
|
|
||||||
self.DRM_LOCKED_ICON = QPixmap(I('drm-locked.png')).scaledToHeight(64)
|
self.DRM_LOCKED_ICON = QPixmap(I('drm-locked.png')).scaledToHeight(64,
|
||||||
self.DRM_UNLOCKED_ICON = QPixmap(I('drm-unlocked.png')).scaledToHeight(64)
|
Qt.SmoothTransformation)
|
||||||
self.DRM_UNKNOWN_ICON = QPixmap(I('dialog_warning.png')).scaledToHeight(64)
|
self.DRM_UNLOCKED_ICON = QPixmap(I('drm-unlocked.png')).scaledToHeight(64,
|
||||||
|
Qt.SmoothTransformation)
|
||||||
|
self.DRM_UNKNOWN_ICON = QPixmap(I('dialog_question.png')).scaledToHeight(64,
|
||||||
|
Qt.SmoothTransformation)
|
||||||
|
|
||||||
# All matches. Used to determine the order to display
|
# All matches. Used to determine the order to display
|
||||||
# self.matches because the SearchFilter returns
|
# self.matches because the SearchFilter returns
|
||||||
# matches unordered.
|
# matches unordered.
|
||||||
@ -482,7 +485,7 @@ class Matches(QAbstractItemModel):
|
|||||||
return self.matches[row]
|
return self.matches[row]
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def filter_results(self):
|
def filter_results(self):
|
||||||
self.layoutAboutToBeChanged.emit()
|
self.layoutAboutToBeChanged.emit()
|
||||||
if self.query:
|
if self.query:
|
||||||
@ -611,13 +614,13 @@ class Matches(QAbstractItemModel):
|
|||||||
self.reorder_matches()
|
self.reorder_matches()
|
||||||
if reset:
|
if reset:
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
def reorder_matches(self):
|
def reorder_matches(self):
|
||||||
self.matches = sorted(self.matches, key=lambda x: self.all_matches.index(x))
|
self.matches = sorted(self.matches, key=lambda x: self.all_matches.index(x))
|
||||||
|
|
||||||
|
|
||||||
class SearchFilter(SearchQueryParser):
|
class SearchFilter(SearchQueryParser):
|
||||||
|
|
||||||
USABLE_LOCATIONS = [
|
USABLE_LOCATIONS = [
|
||||||
'all',
|
'all',
|
||||||
'author',
|
'author',
|
||||||
@ -637,7 +640,7 @@ class SearchFilter(SearchQueryParser):
|
|||||||
|
|
||||||
def add_search_result(self, search_result):
|
def add_search_result(self, search_result):
|
||||||
self.srs.add(search_result)
|
self.srs.add(search_result)
|
||||||
|
|
||||||
def clear_search_results(self):
|
def clear_search_results(self):
|
||||||
self.srs = set([])
|
self.srs = set([])
|
||||||
|
|
||||||
@ -710,7 +713,7 @@ class SearchFilter(SearchQueryParser):
|
|||||||
m = CONTAINS_MATCH
|
m = CONTAINS_MATCH
|
||||||
else:
|
else:
|
||||||
m = matchkind
|
m = matchkind
|
||||||
|
|
||||||
if locvalue == 'format':
|
if locvalue == 'format':
|
||||||
vals = accessor(sr).split(',')
|
vals = accessor(sr).split(',')
|
||||||
else:
|
else:
|
||||||
|
@ -25,7 +25,6 @@ from calibre.gui2.store.web_store_dialog import WebStoreDialog
|
|||||||
class SmashwordsStore(BasicStoreConfig, StorePlugin):
|
class SmashwordsStore(BasicStoreConfig, StorePlugin):
|
||||||
|
|
||||||
def open(self, parent=None, detail_item=None, external=False):
|
def open(self, parent=None, detail_item=None, external=False):
|
||||||
settings = self.get_settings()
|
|
||||||
url = 'http://www.smashwords.com/'
|
url = 'http://www.smashwords.com/'
|
||||||
|
|
||||||
aff_id = '?ref=usernone'
|
aff_id = '?ref=usernone'
|
||||||
@ -38,12 +37,12 @@ class SmashwordsStore(BasicStoreConfig, StorePlugin):
|
|||||||
detail_url = url + detail_item + aff_id
|
detail_url = url + detail_item + aff_id
|
||||||
url = url + aff_id
|
url = url + aff_id
|
||||||
|
|
||||||
if external or settings.get(self.name + '_open_external', False):
|
if external or self.config.get('open_external', False):
|
||||||
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
|
open_url(QUrl(url_slash_cleaner(detail_url if detail_url else url)))
|
||||||
else:
|
else:
|
||||||
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
d = WebStoreDialog(self.gui, url, parent, detail_url)
|
||||||
d.setWindowTitle(self.name)
|
d.setWindowTitle(self.name)
|
||||||
d.set_tags(settings.get(self.name + '_tags', ''))
|
d.set_tags(self.config.get('tags', ''))
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
def search(self, query, max_results=10, timeout=60):
|
def search(self, query, max_results=10, timeout=60):
|
||||||
|
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
63
src/calibre/utils/text2int.py
Executable file
63
src/calibre/utils/text2int.py
Executable file
@ -0,0 +1,63 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
__author__ = "stackoverflow community"
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
"""
|
||||||
|
Takes english numeric words and converts them to integers.
|
||||||
|
Returns False if the word isn't a number.
|
||||||
|
|
||||||
|
implementation courtesy of the stackoverflow community:
|
||||||
|
http://stackoverflow.com/questions/493174/is-there-a-way-to-convert-number-words-to-integers-python
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
numwords = {}
|
||||||
|
|
||||||
|
def text2int(textnum):
|
||||||
|
if not numwords:
|
||||||
|
|
||||||
|
units = [ "zero", "one", "two", "three", "four", "five", "six",
|
||||||
|
"seven", "eight", "nine", "ten", "eleven", "twelve",
|
||||||
|
"thirteen", "fourteen", "fifteen", "sixteen", "seventeen",
|
||||||
|
"eighteen", "nineteen"]
|
||||||
|
|
||||||
|
tens = ["", "", "twenty", "thirty", "forty", "fifty", "sixty",
|
||||||
|
"seventy", "eighty", "ninety"]
|
||||||
|
|
||||||
|
scales = ["hundred", "thousand", "million", "billion", "trillion",
|
||||||
|
'quadrillion', 'quintillion', 'sexillion', 'septillion',
|
||||||
|
'octillion', 'nonillion', 'decillion' ]
|
||||||
|
|
||||||
|
numwords["and"] = (1, 0)
|
||||||
|
for idx, word in enumerate(units): numwords[word] = (1, idx)
|
||||||
|
for idx, word in enumerate(tens): numwords[word] = (1, idx * 10)
|
||||||
|
for idx, word in enumerate(scales): numwords[word] = (10 ** (idx * 3 or 2), 0)
|
||||||
|
|
||||||
|
ordinal_words = {'first':1, 'second':2, 'third':3, 'fifth':5,
|
||||||
|
'eighth':8, 'ninth':9, 'twelfth':12}
|
||||||
|
ordinal_endings = [('ieth', 'y'), ('th', '')]
|
||||||
|
current = result = 0
|
||||||
|
tokens = re.split(r"[\s-]+", textnum)
|
||||||
|
for word in tokens:
|
||||||
|
if word in ordinal_words:
|
||||||
|
scale, increment = (1, ordinal_words[word])
|
||||||
|
else:
|
||||||
|
for ending, replacement in ordinal_endings:
|
||||||
|
if word.endswith(ending):
|
||||||
|
word = "%s%s" % (word[:-len(ending)], replacement)
|
||||||
|
|
||||||
|
if word not in numwords:
|
||||||
|
#raise Exception("Illegal word: " + word)
|
||||||
|
return False
|
||||||
|
|
||||||
|
scale, increment = numwords[word]
|
||||||
|
|
||||||
|
if scale > 1:
|
||||||
|
current = max(1, current)
|
||||||
|
|
||||||
|
current = current * scale + increment
|
||||||
|
if scale > 100:
|
||||||
|
result += current
|
||||||
|
current = 0
|
||||||
|
|
||||||
|
return result + current
|
Loading…
x
Reference in New Issue
Block a user