mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Pull from trunk
This commit is contained in:
commit
d0c6124938
@ -6,7 +6,7 @@ __docformat__ = 'restructuredtext en'
|
||||
|
||||
'''
|
||||
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.
|
||||
'''
|
||||
|
||||
|
@ -6,7 +6,6 @@ nspm.rs
|
||||
|
||||
import re
|
||||
from calibre.web.feeds.news import BasicNewsRecipe
|
||||
from calibre.ebooks.BeautifulSoup import Tag
|
||||
|
||||
class Nspm(BasicNewsRecipe):
|
||||
title = 'Nova srpska politicka misao'
|
||||
@ -22,14 +21,14 @@ class Nspm(BasicNewsRecipe):
|
||||
encoding = 'utf-8'
|
||||
language = 'sr'
|
||||
delay = 2
|
||||
publication_type = 'magazine'
|
||||
publication_type = 'magazine'
|
||||
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)}
|
||||
@font-face {font-family: "sans1";src:url(res:///opt/sony/ebook/FONT/tt0003m_.ttf)}
|
||||
body{font-family: "Times New Roman", serif1, serif}
|
||||
.article_description{font-family: Arial, sans1, sans-serif}
|
||||
img{margin-top:0.5em; margin-bottom: 0.7em}
|
||||
.author{color: #990000; font-weight: bold}
|
||||
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: "Times New Roman", serif1, serif}
|
||||
.article_description{font-family: Arial, sans1, sans-serif}
|
||||
img{margin-top:0.5em; margin-bottom: 0.7em}
|
||||
.author{color: #990000; font-weight: bold}
|
||||
.author,.createdate{font-size: 0.9em} """
|
||||
|
||||
conversion_options = {
|
||||
@ -68,4 +67,4 @@ class Nspm(BasicNewsRecipe):
|
||||
def preprocess_html(self, soup):
|
||||
for item in soup.body.findAll(style=True):
|
||||
del item['style']
|
||||
return self.adeify_images(soup)
|
||||
return self.adeify_images(soup)
|
||||
|
@ -9,6 +9,7 @@ from threading import Thread
|
||||
from calibre import prints
|
||||
from calibre.utils.config import OptionParser
|
||||
from calibre.utils.logging import default_log
|
||||
from calibre.utils.titlecase import titlecase
|
||||
from calibre.customize import Plugin
|
||||
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:
|
||||
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]
|
||||
|
||||
def get_social_metadata(mi, verbose=0):
|
||||
|
@ -296,6 +296,17 @@ class AddAction(object): # {{{
|
||||
self.library_view.model().db.import_book(MetaInformation(None), [])
|
||||
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):
|
||||
to_device = self.stack.currentIndex() != 0
|
||||
self._add_books(paths, to_device)
|
||||
@ -342,6 +353,12 @@ class AddAction(object): # {{{
|
||||
def add_filesystem_book(self, paths, allow_device=True):
|
||||
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):
|
||||
'''
|
||||
Add books from the local filesystem to either the library or the device.
|
||||
@ -625,6 +642,13 @@ class EditMetadataAction(object): # {{{
|
||||
return
|
||||
db = self.library_view.model().db
|
||||
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:
|
||||
get_social_metadata = config['get_social_metadata']
|
||||
else:
|
||||
|
@ -63,7 +63,7 @@
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="opt_force_max_line_length">
|
||||
<property name="text">
|
||||
<string>Force maximum line lenght</string>
|
||||
<string>Force maximum line length</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
40
src/calibre/gui2/dialogs/add_from_isbn.py
Normal file
40
src/calibre/gui2/dialogs/add_from_isbn.py
Normal 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)
|
||||
|
90
src/calibre/gui2/dialogs/add_from_isbn.ui
Normal file
90
src/calibre/gui2/dialogs/add_from_isbn.ui
Normal 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><p>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.<p>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>&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>
|
@ -538,8 +538,10 @@ class MainWindowMixin(object):
|
||||
self.add_menu.addAction(_('Add books from directories, including '
|
||||
'sub directories (Multiple books per directory, assumes every '
|
||||
'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 '
|
||||
'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.triggered.connect(self.add_books)
|
||||
self.action_del.triggered.connect(self.delete_books)
|
||||
|
@ -146,7 +146,8 @@ class SearchBox2(QComboBox):
|
||||
self._in_a_search = False
|
||||
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
|
||||
self.do_search()
|
||||
self.timer.start(1500)
|
||||
if self.as_you_type:
|
||||
self.timer.start(1500)
|
||||
|
||||
def mouse_released(self, event):
|
||||
self.normalize_state()
|
||||
|
@ -1673,6 +1673,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
self.data.refresh_ids(self, [id]) # Needed to update format list and size
|
||||
if notify:
|
||||
self.notify('add', [id])
|
||||
return id
|
||||
|
||||
def get_top_level_move_items(self):
|
||||
items = set(os.listdir(self.library_path))
|
||||
|
@ -12,7 +12,7 @@ from ctypes import Structure as _Structure, c_char_p, c_uint, c_void_p, POINTER,
|
||||
from tempfile import NamedTemporaryFile
|
||||
from StringIO import StringIO
|
||||
|
||||
from calibre import iswindows, load_library, CurrentDir, prints
|
||||
from calibre import iswindows, load_library, CurrentDir
|
||||
from calibre.ptempfile import TemporaryDirectory
|
||||
|
||||
_librar_name = 'libunrar'
|
||||
|
@ -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
|
||||
series:true will give you all books that belong to a series
|
||||
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
|
||||
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
Loading…
x
Reference in New Issue
Block a user