IMplement fetching of ISBN from the web.

This commit is contained in:
Kovid Goyal 2007-10-25 05:27:34 +00:00
parent 4be73c0f49
commit 81c01f4561
9 changed files with 371 additions and 16 deletions

View File

@ -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):

View File

@ -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

View File

@ -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)

View 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

View 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 &lt;b>%1&lt;/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 &lt;a href="http://www.isndb.com">isndb.com&lt;/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>&amp;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>

View File

@ -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:

View File

@ -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(','))

View File

@ -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&amp;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>

View File

@ -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: