mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
IMplement fetching of ISBN from the web.
This commit is contained in:
parent
4be73c0f49
commit
81c01f4561
@ -62,12 +62,13 @@ class MetaInformation(object):
|
||||
|
||||
def __str__(self):
|
||||
ans = ''
|
||||
ans += 'Title : ' + unicode(self.title) + '\n'
|
||||
ans += 'Author : ' + (', '.join(self.authors) if self.authors is not None else 'None')
|
||||
ans += ((' (' + self.author_sort + ')') if self.author_sort else '') + '\n'
|
||||
ans += 'Category: ' + unicode(self.category) + '\n'
|
||||
ans += 'Comments: ' + unicode(self.comments) + '\n'
|
||||
ans += 'ISBN : ' + unicode(self.isbn) + '\n'
|
||||
ans += 'Title : ' + unicode(self.title) + '\n'
|
||||
ans += 'Author : ' + (', '.join(self.authors) if self.authors is not None else 'None')
|
||||
ans += ((' (' + self.author_sort + ')') if self.author_sort else '') + '\n'
|
||||
ans += 'Publisher: '+ unicode(self.publisher) + '\n'
|
||||
ans += 'Category : ' + unicode(self.category) + '\n'
|
||||
ans += 'Comments : ' + unicode(self.comments) + '\n'
|
||||
ans += 'ISBN : ' + unicode(self.isbn) + '\n'
|
||||
return ans.strip()
|
||||
|
||||
def __nonzero__(self):
|
||||
|
@ -56,14 +56,18 @@ class ISBNDBMetadata(MetaInformation):
|
||||
self.title = book.find('titlelong').string
|
||||
if not self.title:
|
||||
self.title = book.find('title').string
|
||||
self.title = self.title.strip
|
||||
au = book.find('authorstext').string
|
||||
self.title = unicode(self.title).strip()
|
||||
au = unicode(book.find('authorstext').string).strip()
|
||||
temp = au.split(',')
|
||||
self.authors = []
|
||||
for au in temp:
|
||||
if not au: continue
|
||||
self.authors.extend([a.strip() for a in au.split('&')])
|
||||
|
||||
self.author_sort = book.find('authors').find('person').string
|
||||
try:
|
||||
self.author_sort = book.find('authors').find('person').string
|
||||
except:
|
||||
pass
|
||||
self.publisher = book.find('publishertext').string
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
UI = main_ui.py dialogs/metadata_single_ui.py dialogs/metadata_bulk_ui.py dialogs/jobs_ui.py \
|
||||
dialogs/conversion_error_ui.py dialogs/lrf_single_ui.py dialogs/choose_format_ui.py \
|
||||
dialogs/password_ui.py lrf_renderer/main_ui.py lrf_renderer/config_ui.py
|
||||
dialogs/password_ui.py lrf_renderer/main_ui.py lrf_renderer/config_ui.py \
|
||||
dialogs/fetch_metadata_ui.py
|
||||
RC = images_rc.pyc
|
||||
|
||||
PYUIC = $(shell which pyuic4)
|
||||
|
135
src/libprs500/gui2/dialogs/fetch_metadata.py
Normal file
135
src/libprs500/gui2/dialogs/fetch_metadata.py
Normal file
@ -0,0 +1,135 @@
|
||||
## Copyright (C) 2007 Kovid Goyal kovid@kovidgoyal.net
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License along
|
||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
'''
|
||||
GUI for fetching metadata from servers.
|
||||
'''
|
||||
|
||||
from PyQt4.QtCore import Qt, QObject, SIGNAL, QSettings, QVariant, \
|
||||
QAbstractTableModel, QCoreApplication
|
||||
from PyQt4.QtGui import QDialog, QItemSelectionModel
|
||||
|
||||
from libprs500.gui2.dialogs.fetch_metadata_ui import Ui_FetchMetadata
|
||||
from libprs500.gui2 import error_dialog, NONE
|
||||
from libprs500.ebooks.metadata.isbndb import create_books, option_parser
|
||||
|
||||
class Matches(QAbstractTableModel):
|
||||
|
||||
def __init__(self, matches):
|
||||
self.matches = matches
|
||||
QAbstractTableModel.__init__(self)
|
||||
|
||||
def rowCount(self, *args):
|
||||
return len(self.matches)
|
||||
|
||||
def columnCount(self, *args):
|
||||
return 5
|
||||
|
||||
def headerData(self, section, orientation, role):
|
||||
if role != Qt.DisplayRole:
|
||||
return NONE
|
||||
text = ""
|
||||
if orientation == Qt.Horizontal:
|
||||
if section == 0: text = "Title"
|
||||
elif section == 1: text = "Author(s)"
|
||||
elif section == 2: text = "Author Sort"
|
||||
elif section == 3: text = "Publisher"
|
||||
elif section == 4: text = "ISBN"
|
||||
|
||||
return QVariant(self.trUtf8(text))
|
||||
else:
|
||||
return QVariant(section+1)
|
||||
|
||||
def data(self, index, role):
|
||||
row, col = index.row(), index.column()
|
||||
if role == Qt.DisplayRole:
|
||||
book = self.matches[row]
|
||||
res = None
|
||||
if col == 0:
|
||||
res = book.title
|
||||
elif col == 1:
|
||||
res = ', '.join(book.authors)
|
||||
elif col == 2:
|
||||
res = book.author_sort
|
||||
elif col == 3:
|
||||
res = book.publisher
|
||||
elif col == 4:
|
||||
res = book.isbn
|
||||
if not res:
|
||||
return NONE
|
||||
return QVariant(res)
|
||||
return NONE
|
||||
|
||||
class FetchMetadata(QDialog, Ui_FetchMetadata):
|
||||
|
||||
def __init__(self, parent, isbn, title, author, publisher):
|
||||
QDialog.__init__(self, parent)
|
||||
Ui_FetchMetadata.__init__(self)
|
||||
self.setupUi(self)
|
||||
|
||||
QObject.connect(self.fetch, SIGNAL('clicked()'), self.fetch_metadata)
|
||||
|
||||
self.key.setText(QSettings().value('isbndb.com key', QVariant('')).toString())
|
||||
|
||||
self.setWindowTitle(title if title else 'Unknown')
|
||||
self.tlabel.setText(self.tlabel.text().arg(title if title else 'Unknown'))
|
||||
self.isbn = isbn
|
||||
self.title = title
|
||||
self.author = author
|
||||
self.publisher = publisher
|
||||
|
||||
def fetch_metadata(self):
|
||||
key = str(self.key.text())
|
||||
if not key:
|
||||
error_dialog(self, 'Cannot connect',
|
||||
'You must specify a valid access key for isndb.com')
|
||||
return
|
||||
else:
|
||||
QSettings().setValue('isbndb.com key', QVariant(self.key.text()))
|
||||
|
||||
args = ['isbndb']
|
||||
if self.isbn:
|
||||
args.extend(('--isbn', self.isbn))
|
||||
if self.title:
|
||||
args.extend(('--title', self.title))
|
||||
if self.author:
|
||||
args.extend(('--author', self.author))
|
||||
#if self.publisher:
|
||||
# args.extend(('--publisher', self.publisher))
|
||||
|
||||
self.fetch.setEnabled(False)
|
||||
|
||||
QCoreApplication.instance().processEvents()
|
||||
|
||||
args.append(key)
|
||||
parser = option_parser()
|
||||
opts, args = parser.parse_args(args)
|
||||
|
||||
books = create_books(opts, args)
|
||||
|
||||
self.model = Matches(books)
|
||||
|
||||
self.matches.setModel(self.model)
|
||||
self.model.reset()
|
||||
self.matches.selectionModel().select(self.model.index(0, 0),
|
||||
QItemSelectionModel.Select | QItemSelectionModel.Rows)
|
||||
self.fetch.setEnabled(True)
|
||||
|
||||
|
||||
|
||||
def selected_book(self):
|
||||
try:
|
||||
return self.matches.model().matches[self.matches.currentIndex().row()]
|
||||
except:
|
||||
return None
|
144
src/libprs500/gui2/dialogs/fetch_metadata.ui
Normal file
144
src/libprs500/gui2/dialogs/fetch_metadata.ui
Normal file
@ -0,0 +1,144 @@
|
||||
<ui version="4.0" >
|
||||
<class>FetchMetadata</class>
|
||||
<widget class="QDialog" name="FetchMetadata" >
|
||||
<property name="windowModality" >
|
||||
<enum>Qt::WindowModal</enum>
|
||||
</property>
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>830</width>
|
||||
<height>622</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>Fetch metadata</string>
|
||||
</property>
|
||||
<property name="windowIcon" >
|
||||
<iconset resource="../images.qrc" >:/images/metadata.svg</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="tlabel" >
|
||||
<property name="text" >
|
||||
<string>Fetching metadata for <b>%1</b></string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<string>Sign up for a free account from <a href="http://www.isndb.com">isndb.com</a> to get an access key.</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="openExternalLinks" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>&Access Key;</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>key</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="key" />
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fetch" >
|
||||
<property name="text" >
|
||||
<string>Fetch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox" >
|
||||
<property name="title" >
|
||||
<string>Matches</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Select the book that most closely matches your copy from the list below</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="matches" >
|
||||
<property name="alternatingRowColors" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode" >
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior" >
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../images.qrc" />
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>FetchMetadata</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>460</x>
|
||||
<y>599</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>657</x>
|
||||
<y>530</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>FetchMetadata</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>417</x>
|
||||
<y>599</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>0</x>
|
||||
<y>491</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@ -73,7 +73,8 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
|
||||
except ValueError:
|
||||
pass
|
||||
if not formats:
|
||||
d = error_dialog(window, 'No available formats', 'Cannot convert %s as this book has no supported formats'%(self.gui_title.text()))
|
||||
d = error_dialog(window, 'No available formats',
|
||||
'Cannot convert %s as this book has no supported formats'%(self.gui_title.text()))
|
||||
d.exec_()
|
||||
|
||||
if len(formats) > 1:
|
||||
|
@ -12,6 +12,7 @@
|
||||
## You should have received a copy of the GNU General Public License along
|
||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
from libprs500.gui2.dialogs.fetch_metadata import FetchMetadata
|
||||
'''
|
||||
The dialog used to edit meta information for a book as well as
|
||||
add/remove formats
|
||||
@ -137,8 +138,14 @@ class MetadataSingleDialog(QDialog, Ui_MetadataSingleDialog):
|
||||
self.add_format)
|
||||
QObject.connect(self.remove_format_button, SIGNAL("clicked(bool)"), \
|
||||
self.remove_format)
|
||||
QObject.connect(self.fetch_metadata_button, SIGNAL('clicked()'),
|
||||
self.fetch_metadata)
|
||||
|
||||
self.title.setText(db.title(row))
|
||||
isbn = db.isbn(self.id)
|
||||
if not isbn:
|
||||
isbn = ''
|
||||
self.isbn.setText(isbn)
|
||||
au = self.db.authors(row)
|
||||
self.authors.setText(au if au else '')
|
||||
aus = self.db.author_sort(row)
|
||||
@ -188,6 +195,25 @@ class MetadataSingleDialog(QDialog, Ui_MetadataSingleDialog):
|
||||
|
||||
self.exec_()
|
||||
|
||||
def fetch_metadata(self):
|
||||
isbn = qstring_to_unicode(self.isbn.text())
|
||||
title = qstring_to_unicode(self.title.text())
|
||||
author = qstring_to_unicode(self.authors.text()).split(',')[0]
|
||||
publisher = qstring_to_unicode(self.publisher.text())
|
||||
if isbn or title or author or publisher:
|
||||
d = FetchMetadata(self, isbn, title, author, publisher)
|
||||
d.exec_()
|
||||
if d.result() == QDialog.Accepted:
|
||||
book = d.selected_book()
|
||||
if book:
|
||||
self.title.setText(book.title)
|
||||
self.authors.setText(', '.join(book.authors))
|
||||
if book.author_sort: self.author_sort.setText(book.author_sort)
|
||||
self.publisher.setText(book.publisher)
|
||||
self.isbn.setText(book.isbn)
|
||||
else:
|
||||
error_dialog(self, 'Cannot fetch metadata', 'You must specify at least one of ISBN, Title, Authors or Publisher')
|
||||
|
||||
def enable_series_index(self, *args):
|
||||
self.series_index.setEnabled(True)
|
||||
|
||||
@ -201,6 +227,7 @@ class MetadataSingleDialog(QDialog, Ui_MetadataSingleDialog):
|
||||
aus = qstring_to_unicode(self.author_sort.text())
|
||||
if aus:
|
||||
self.db.set_author_sort(self.id, aus)
|
||||
self.db.set_isbn(self.id, qstring_to_unicode(self.isbn.text()))
|
||||
self.db.set_rating(self.id, 2*self.rating.value())
|
||||
self.db.set_publisher(self.id, qstring_to_unicode(self.publisher.text()))
|
||||
self.db.set_tags(self.id, qstring_to_unicode(self.tags.text()).split(','))
|
||||
|
@ -218,6 +218,22 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1" >
|
||||
<widget class="QLineEdit" name="isbn" />
|
||||
</item>
|
||||
<item row="8" column="0" >
|
||||
<widget class="QLabel" name="label_9" >
|
||||
<property name="text" >
|
||||
<string>IS&BN:</string>
|
||||
</property>
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>isbn</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -233,6 +249,13 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="fetch_metadata_button" >
|
||||
<property name="text" >
|
||||
<string>Fetch metadata from server</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupBox_3" >
|
||||
@ -503,8 +526,8 @@
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
<x>257</x>
|
||||
<y>646</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>157</x>
|
||||
@ -519,8 +542,8 @@
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
<x>325</x>
|
||||
<y>646</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>286</x>
|
||||
|
@ -653,7 +653,17 @@ class LibraryDatabase(object):
|
||||
)
|
||||
conn.execute('pragma user_version=2')
|
||||
conn.commit()
|
||||
|
||||
|
||||
@staticmethod
|
||||
def upgrade_version2(conn):
|
||||
conn.executescript(
|
||||
'''
|
||||
/***** Add ISBN column ******/
|
||||
ALTER TABLE books ADD COLUMN isbn TEXT DEFAULT "" COLLATE NOCASE;
|
||||
''')
|
||||
conn.execute('pragma user_version=3')
|
||||
conn.commit()
|
||||
|
||||
def __del__(self):
|
||||
global _lock_file
|
||||
import os
|
||||
@ -669,6 +679,8 @@ class LibraryDatabase(object):
|
||||
LibraryDatabase.create_version1(self.conn)
|
||||
if self.user_version == 1: # Upgrade to 2
|
||||
LibraryDatabase.upgrade_version1(self.conn)
|
||||
if self.user_version == 2: # Upgrade to 3
|
||||
LibraryDatabase.upgrade_version2(self.conn)
|
||||
|
||||
@apply
|
||||
def user_version():
|
||||
@ -740,6 +752,9 @@ class LibraryDatabase(object):
|
||||
return self.data[index][2]
|
||||
return self.conn.execute('SELECT authors FROM meta WHERE id=?',(index,)).fetchone()[0]
|
||||
|
||||
def isbn(self, id):
|
||||
return self.conn.execute('SELECT isbn FROM books WHERE id=?',(id,)).fetchone()[0]
|
||||
|
||||
def author_sort(self, index):
|
||||
id = self.id(index)
|
||||
return self.conn.execute('SELECT author_sort FROM books WHERE id=?', (id,)).fetchone()[0]
|
||||
@ -909,6 +924,10 @@ class LibraryDatabase(object):
|
||||
self.conn.execute('UPDATE books SET title=? WHERE id=?', (title, id))
|
||||
self.conn.commit()
|
||||
|
||||
def set_isbn(self, id, isbn):
|
||||
self.conn.execute('UPDATE books SET isbn=? WHERE id=?', (isbn, id))
|
||||
self.conn.commit()
|
||||
|
||||
def set_publisher(self, id, publisher):
|
||||
self.conn.execute('DELETE FROM books_publishers_link WHERE book=?',(id,))
|
||||
if publisher:
|
||||
|
Loading…
x
Reference in New Issue
Block a user