Merge from trunk and fix case change in edit metadata single.

This commit is contained in:
Charles Haley 2011-05-05 20:05:05 +01:00
commit ec776e3052
7 changed files with 64 additions and 48 deletions

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
__license__ = 'GPL v3'
__copyright__ = u'2010, Tomasz Dlugosz <tomek3d@gmail.com>'
__copyright__ = u'2010-2011, Tomasz Dlugosz <tomek3d@gmail.com>'
'''
frazpc.pl
'''
@ -19,17 +19,20 @@ class FrazPC(BasicNewsRecipe):
use_embedded_content = False
no_stylesheets = True
feeds = [(u'Aktualno\u015bci', u'http://www.frazpc.pl/feed'), (u'Recenzje', u'http://www.frazpc.pl/kat/recenzje-2/feed') ]
keep_only_tags = [dict(name='div', attrs={'id':'FRAZ_CONTENT'})]
remove_tags = [dict(name='p', attrs={'class':'gray tagsP fs11'})]
preprocess_regexps = [
(re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in
[(r'<div id="post-[0-9]*"', lambda match: '<div id="FRAZ_CONTENT"'),
(r'href="/f/news/', lambda match: 'href="http://www.frazpc.pl/f/news/'),
(r' &nbsp; <a href="http://www.frazpc.pl/[^>]*?">(Skomentuj|Komentarz(e)?\([0-9]*\))</a>&nbsp; \|', lambda match: '')]
feeds = [
(u'Aktualno\u015bci', u'http://www.frazpc.pl/feed/aktualnosci'),
(u'Artyku\u0142y', u'http://www.frazpc.pl/feed/artykuly')
]
keep_only_tags = [dict(name='div', attrs={'class':'article'})]
remove_tags = [
dict(name='div', attrs={'class':'title-wrapper'}),
dict(name='p', attrs={'class':'tags'}),
dict(name='p', attrs={'class':'article-links'}),
dict(name='div', attrs={'class':'comments_box'})
]
preprocess_regexps = [(re.compile(r'\| <a href="#comments">Komentarze \([0-9]*\)</a>'), lambda match: '')]
remove_attributes = [ 'width', 'height' ]

View File

@ -607,6 +607,7 @@ class StoreBase(Plugin): # {{{
supported_platforms = ['windows', 'osx', 'linux']
author = 'John Schember'
type = _('Store')
minimum_calibre_version = (0, 7, 59)
actual_plugin = None

View File

@ -6,7 +6,6 @@ __docformat__ = 'restructuredtext en'
Device driver for BOEYE serial readers
'''
import re
from calibre.devices.usbms.driver import USBMS
class BOEYE_BEX(USBMS):

View File

@ -298,11 +298,12 @@ class AuthorSortEdit(EnLineEdit):
self.current_val = self.db.author_sort_from_authors(authors)
def initialize(self, db, id_):
self.current_val = db.author_sort(id_, index_is_id=True)
self.current_val = self.original_val = db.author_sort(id_, index_is_id=True)
def commit(self, db, id_):
aus = self.current_val
db.set_author_sort(id_, aus, notify=False, commit=False)
if aus != self.original_val:
db.set_author_sort(id_, aus, notify=False, commit=False)
return True
# }}}

View File

@ -13,7 +13,7 @@ from functools import partial
from PyQt4.Qt import (Qt, QVBoxLayout, QHBoxLayout, QWidget, QPushButton,
QGridLayout, pyqtSignal, QDialogButtonBox, QScrollArea, QFont,
QTabWidget, QIcon, QToolButton, QSplitter, QGroupBox, QSpacerItem,
QSizePolicy, QPalette, QFrame, QSize, QKeySequence, QMenu, QLabel)
QSizePolicy, QPalette, QFrame, QSize, QKeySequence, QMenu)
from calibre.ebooks.metadata import authors_to_string, string_to_authors
from calibre.gui2 import ResizableDialog, error_dialog, gprefs, pixmap_to_data

View File

@ -47,7 +47,7 @@ class StorePlugin(object): # {{{
def __init__(self, gui, name):
from calibre.gui2 import JSONConfig
self.gui = gui
self.name = name
self.base_plugin = None
@ -79,14 +79,14 @@ class StorePlugin(object): # {{{
return items as a generator.
Don't be lazy with the search! Load as much data as possible in the
:class:`calibre.gui2.store.search_result.SearchResult` object.
:class:`calibre.gui2.store.search_result.SearchResult` object.
However, if data (such as cover_url)
isn't available because the store does not display cover images then it's okay to
ignore it.
At the very least a :class:`calibre.gui2.store.search_result.SearchResult`
returned by this function must have the title, author and id.
If you have to parse multiple pages to get all of the data then implement
:meth:`get_deatils` for retrieving additional information.
@ -105,24 +105,24 @@ class StorePlugin(object): # {{{
item_data is plugin specific and is used in :meth:`open` to open to a specifc place in the store.
'''
raise NotImplementedError()
def get_details(self, search_result, timeout=60):
'''
Delayed search for information about specific search items.
Typically, this will be used when certain information such as
formats, drm status, cover url are not part of the main search
results and the information is on another web page.
Using this function allows for the main information (title, author)
to be displayed in the search results while other information can
take extra time to load. Splitting retrieving data that takes longer
to load into a separate function will give the illusion of the search
being faster.
:param search_result: A search result that need details set.
:param timeout: The maximum amount of time in seconds to spend downloading details.
:return: True if the search_result was modified otherwise False
'''
return False
@ -133,30 +133,30 @@ class StorePlugin(object): # {{{
is called to update the caches. It is recommended to call this function
from :meth:`open`. Especially if :meth:`open` does anything other than
open a web page.
This function can be called at any time. It is up to the plugin to determine
if the cache really does need updating. Unless :param:`force` is True, then
the plugin must update the cache. The only time force should be True is if
this function is called by the plugin's configuration dialog.
if :param:`suppress_progress` is False it is safe to assume that this function
is being called from the main GUI thread so it is safe and recommended to use
a QProgressDialog to display what is happening and allow the user to cancel
the operation. if :param:`suppress_progress` is True then run the update
silently. In this case there is no guarantee what thread is calling this
function so no Qt related functionality that requires being run in the main
GUI thread should be run. E.G. Open a QProgressDialog.
GUI thread should be run. E.G. Open a QProgressDialog.
:param parent: The parent object to be used by an GUI dialogs.
:param timeout: The maximum amount of time that should be spent in
any given network connection.
:param force: Force updating the cache even if the plugin has determined
it is not necessary.
:param suppress_progress: Should a progress indicator be shown.
:return: True if the cache was updated, False otherwise.
'''
return False

View File

@ -33,7 +33,7 @@ from calibre import isbytestring
from calibre.utils.filenames import ascii_filename
from calibre.utils.date import utcnow, now as nowf, utcfromtimestamp
from calibre.utils.config import prefs, tweaks, from_json, to_json
from calibre.utils.icu import sort_key
from calibre.utils.icu import sort_key, strcmp
from calibre.utils.search_query_parser import saved_searches, set_saved_searches
from calibre.ebooks import BOOK_EXTENSIONS, check_ebook_format
from calibre.utils.magick.draw import save_cover_data_to
@ -1920,6 +1920,18 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
result.append(r)
return ' & '.join(result).replace('|', ',')
def _update_author_in_cache(self, id_, ss, final_authors):
self.conn.execute('UPDATE books SET author_sort=? WHERE id=?', (ss, id_))
self.data.set(id_, self.FIELD_MAP['authors'],
','.join([a.replace(',', '|') for a in final_authors]),
row_is_id=True)
self.data.set(id_, self.FIELD_MAP['author_sort'], ss, row_is_id=True)
aum = self.authors_with_sort_strings(id_, index_is_id=True)
self.data.set(id_, self.FIELD_MAP['au_map'],
':#:'.join([':::'.join((au.replace(',', '|'), aus)) for (au, aus) in aum]),
row_is_id=True)
def _set_authors(self, id, authors, allow_case_change=False):
if not authors:
authors = [_('Unknown')]
@ -1933,14 +1945,17 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
a = a.strip().replace(',', '|')
if not isinstance(a, unicode):
a = a.decode(preferred_encoding, 'replace')
aus = self.conn.get('SELECT id, name FROM authors WHERE name=?', (a,))
aus = self.conn.get('SELECT id, name, sort FROM authors WHERE name=?', (a,))
if aus:
aid, name = aus[0]
aid, name, sort = aus[0]
# Handle change of case
if name != a:
if allow_case_change:
self.conn.execute('''UPDATE authors
SET name=? WHERE id=?''', (a, aid))
ns = author_to_author_sort(a.replace('|', ','))
if strcmp(sort, ns) == 0:
sort = ns
self.conn.execute('''UPDATE authors SET name=?, sort=?
WHERE id=?''', (a, sort, aid))
case_change = True
else:
a = name
@ -1957,17 +1972,14 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
bks = self.conn.get('''SELECT book FROM books_authors_link
WHERE author=?''', (aid,))
books_to_refresh |= set([bk[0] for bk in bks])
for bk in books_to_refresh:
ss = self.author_sort_from_book(id, index_is_id=True)
aus = self.author_sort(bk, index_is_id=True)
if strcmp(aus, ss) == 0:
self._update_author_in_cache(bk, ss, final_authors)
# This can repeat what was done above in rare cases. Let it.
ss = self.author_sort_from_book(id, index_is_id=True)
self.conn.execute('UPDATE books SET author_sort=? WHERE id=?',
(ss, id))
self.data.set(id, self.FIELD_MAP['authors'],
','.join([a.replace(',', '|') for a in final_authors]),
row_is_id=True)
self.data.set(id, self.FIELD_MAP['author_sort'], ss, row_is_id=True)
aum = self.authors_with_sort_strings(id, index_is_id=True)
self.data.set(id, self.FIELD_MAP['au_map'],
':#:'.join([':::'.join((au.replace(',', '|'), aus)) for (au, aus) in aum]),
row_is_id=True)
self._update_author_in_cache(id, ss, final_authors)
return books_to_refresh
def set_authors(self, id, authors, notify=True, commit=True,