Pull from trunk

This commit is contained in:
Kovid Goyal 2010-08-11 13:50:26 -06:00
commit d0c6124938
13 changed files with 464 additions and 253 deletions

View File

@ -6,7 +6,7 @@ __docformat__ = 'restructuredtext en'
''' '''
Contains various tweaks that affect calibre behavior. Only edit this file if Contains various tweaks that affect calibre behavior. Only edit this file if
you know what you are dong. If you delete this file, it will be recreated from you know what you are doing. If you delete this file, it will be recreated from
defaults. defaults.
''' '''

View File

@ -6,7 +6,6 @@ nspm.rs
import re import re
from calibre.web.feeds.news import BasicNewsRecipe from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import Tag
class Nspm(BasicNewsRecipe): class Nspm(BasicNewsRecipe):
title = 'Nova srpska politicka misao' title = 'Nova srpska politicka misao'
@ -22,14 +21,14 @@ class Nspm(BasicNewsRecipe):
encoding = 'utf-8' encoding = 'utf-8'
language = 'sr' language = 'sr'
delay = 2 delay = 2
publication_type = 'magazine' publication_type = 'magazine'
masthead_url = 'http://www.nspm.rs/templates/jsn_epic_pro/images/logol.jpg' masthead_url = 'http://www.nspm.rs/templates/jsn_epic_pro/images/logol.jpg'
extra_css = """ @font-face {font-family: "serif1";src:url(res:///opt/sony/ebook/FONT/tt0011m_.ttf)} 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)} @font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)}
body{font-family: "Times New Roman", serif1, serif} body{font-family: "Times New Roman", serif1, serif}
.article_description{font-family: Arial, sans1, sans-serif} .article_description{font-family: Arial, sans1, sans-serif}
img{margin-top:0.5em; margin-bottom: 0.7em} img{margin-top:0.5em; margin-bottom: 0.7em}
.author{color: #990000; font-weight: bold} .author{color: #990000; font-weight: bold}
.author,.createdate{font-size: 0.9em} """ .author,.createdate{font-size: 0.9em} """
conversion_options = { conversion_options = {
@ -68,4 +67,4 @@ class Nspm(BasicNewsRecipe):
def preprocess_html(self, soup): def preprocess_html(self, soup):
for item in soup.body.findAll(style=True): for item in soup.body.findAll(style=True):
del item['style'] del item['style']
return self.adeify_images(soup) return self.adeify_images(soup)

View File

@ -9,6 +9,7 @@ from threading import Thread
from calibre import prints from calibre import prints
from calibre.utils.config import OptionParser from calibre.utils.config import OptionParser
from calibre.utils.logging import default_log from calibre.utils.logging import default_log
from calibre.utils.titlecase import titlecase
from calibre.customize import Plugin from calibre.customize import Plugin
from calibre.ebooks.metadata.covers import check_for_cover from calibre.ebooks.metadata.covers import check_for_cover
@ -384,6 +385,16 @@ def search(title=None, author=None, publisher=None, isbn=None, isbndb_key=None,
if r.pubdate is None: if r.pubdate is None:
r.pubdate = pubdate r.pubdate = pubdate
def fix_case(x):
if x and x.isupper():
x = titlecase(x)
return x
for r in results:
r.title = fix_case(r.title)
if r.authors:
r.authors = list(map(fix_case, r.authors))
return results, [(x.name, x.exception, x.tb) for x in fetchers] return results, [(x.name, x.exception, x.tb) for x in fetchers]
def get_social_metadata(mi, verbose=0): def get_social_metadata(mi, verbose=0):

View File

@ -296,6 +296,17 @@ class AddAction(object): # {{{
self.library_view.model().db.import_book(MetaInformation(None), []) self.library_view.model().db.import_book(MetaInformation(None), [])
self.library_view.model().books_added(num) self.library_view.model().books_added(num)
def add_isbns(self, isbns):
from calibre.ebooks.metadata import MetaInformation
ids = set([])
for x in isbns:
mi = MetaInformation(None)
mi.isbn = x
ids.add(self.library_view.model().db.import_book(mi, []))
self.library_view.model().books_added(len(isbns))
self.do_download_metadata(ids)
def files_dropped(self, paths): def files_dropped(self, paths):
to_device = self.stack.currentIndex() != 0 to_device = self.stack.currentIndex() != 0
self._add_books(paths, to_device) self._add_books(paths, to_device)
@ -342,6 +353,12 @@ class AddAction(object): # {{{
def add_filesystem_book(self, paths, allow_device=True): def add_filesystem_book(self, paths, allow_device=True):
self._add_filesystem_book(paths, allow_device=allow_device) self._add_filesystem_book(paths, allow_device=allow_device)
def add_from_isbn(self, *args):
from calibre.gui2.dialogs.add_from_isbn import AddFromISBN
d = AddFromISBN(self)
if d.exec_() == d.Accepted:
self.add_isbns(d.isbns)
def add_books(self, *args): def add_books(self, *args):
''' '''
Add books from the local filesystem to either the library or the device. Add books from the local filesystem to either the library or the device.
@ -625,6 +642,13 @@ class EditMetadataAction(object): # {{{
return return
db = self.library_view.model().db db = self.library_view.model().db
ids = [db.id(row.row()) for row in rows] ids = [db.id(row.row()) for row in rows]
self.do_download_metadata(ids, covers=covers,
set_metadata=set_metadata,
set_social_metadata=set_social_metadata)
def do_download_metadata(self, ids, covers=True, set_metadata=True,
set_social_metadata=None):
db = self.library_view.model().db
if set_social_metadata is None: if set_social_metadata is None:
get_social_metadata = config['get_social_metadata'] get_social_metadata = config['get_social_metadata']
else: else:

View File

@ -63,7 +63,7 @@
<item row="2" column="0" colspan="2"> <item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="opt_force_max_line_length"> <widget class="QCheckBox" name="opt_force_max_line_length">
<property name="text"> <property name="text">
<string>Force maximum line lenght</string> <string>Force maximum line length</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -0,0 +1,40 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from PyQt4.Qt import QDialog, QApplication
from calibre.gui2.dialogs.add_from_isbn_ui import Ui_Dialog
from calibre.ebooks.metadata import check_isbn
class AddFromISBN(QDialog, Ui_Dialog):
def __init__(self, parent=None):
QDialog.__init__(self, parent)
self.setupUi(self)
self.isbns = []
self.paste_button.clicked.connect(self.paste)
def paste(self, *args):
app = QApplication.instance()
c = app.clipboard()
txt = unicode(c.text()).strip()
if txt:
old = unicode(self.isbn_box.toPlainText()).strip()
new = old + '\n' + txt
self.isbn_box.setPlainText(new)
def accept(self, *args):
for line in unicode(self.isbn_box.toPlainText()).strip().splitlines():
if line:
isbn = check_isbn(line)
if isbn is not None:
isbn = isbn.upper()
if isbn not in self.isbns:
self.isbns.append(isbn)
QDialog.accept(self, *args)

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>678</width>
<height>430</height>
</rect>
</property>
<property name="windowTitle">
<string>Add books by ISBN</string>
</property>
<property name="windowIcon">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/add_book.svg</normaloff>:/images/add_book.svg</iconset>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPlainTextEdit" name="isbn_box"/>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;p&gt;Enter a list of ISBNs in the box to the left, one per line. calibre will automatically create entries for books based on the ISBN and download metadata and covers for them.&lt;p&gt;Any invalid ISBNs in the list will be ignored.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="paste_button">
<property name="text">
<string>&amp;Paste from clipboard</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../../../resources/images.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -538,8 +538,10 @@ class MainWindowMixin(object):
self.add_menu.addAction(_('Add books from directories, including ' self.add_menu.addAction(_('Add books from directories, including '
'sub directories (Multiple books per directory, assumes every ' 'sub directories (Multiple books per directory, assumes every '
'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.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)
self.add_menu.addAction(_('Add from ISBN'), self.add_from_isbn)
self.action_add.setMenu(self.add_menu) self.action_add.setMenu(self.add_menu)
self.action_add.triggered.connect(self.add_books) self.action_add.triggered.connect(self.add_books)
self.action_del.triggered.connect(self.delete_books) self.action_del.triggered.connect(self.delete_books)

View File

@ -146,7 +146,8 @@ class SearchBox2(QComboBox):
self._in_a_search = False self._in_a_search = False
if event.key() in (Qt.Key_Return, Qt.Key_Enter): if event.key() in (Qt.Key_Return, Qt.Key_Enter):
self.do_search() self.do_search()
self.timer.start(1500) if self.as_you_type:
self.timer.start(1500)
def mouse_released(self, event): def mouse_released(self, event):
self.normalize_state() self.normalize_state()

View File

@ -1673,6 +1673,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
self.data.refresh_ids(self, [id]) # Needed to update format list and size self.data.refresh_ids(self, [id]) # Needed to update format list and size
if notify: if notify:
self.notify('add', [id]) self.notify('add', [id])
return id
def get_top_level_move_items(self): def get_top_level_move_items(self):
items = set(os.listdir(self.library_path)) items = set(os.listdir(self.library_path))

View File

@ -12,7 +12,7 @@ from ctypes import Structure as _Structure, c_char_p, c_uint, c_void_p, POINTER,
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
from StringIO import StringIO from StringIO import StringIO
from calibre import iswindows, load_library, CurrentDir, prints from calibre import iswindows, load_library, CurrentDir
from calibre.ptempfile import TemporaryDirectory from calibre.ptempfile import TemporaryDirectory
_librar_name = 'libunrar' _librar_name = 'libunrar'

View File

@ -247,6 +247,7 @@ You can search for the absence or presence of a field using the special "true" a
cover:false will give you all books without a cover cover:false will give you all books without a cover
series:true will give you all books that belong to a series series:true will give you all books that belong to a series
comments:false will give you all books with an empty comment comments:false will give you all books with an empty comment
format:false will give you all books with no actual files (empty records)
Yes/no custom columns are searchable. Searching for ``false``, ``empty``, or ``blank`` will find all books Yes/no custom columns are searchable. Searching for ``false``, ``empty``, or ``blank`` will find all books
with undefined values in the column. Searching for ``true`` will find all books that do not have undefined with undefined values in the column. Searching for ``true`` will find all books that do not have undefined

File diff suppressed because it is too large Load Diff