diff --git a/src/libprs500/ebooks/metadata/__init__.py b/src/libprs500/ebooks/metadata/__init__.py
index 337a0facf6..3f1d8a86eb 100644
--- a/src/libprs500/ebooks/metadata/__init__.py
+++ b/src/libprs500/ebooks/metadata/__init__.py
@@ -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):
diff --git a/src/libprs500/ebooks/metadata/isbndb.py b/src/libprs500/ebooks/metadata/isbndb.py
index be905ee139..59a6132ca1 100644
--- a/src/libprs500/ebooks/metadata/isbndb.py
+++ b/src/libprs500/ebooks/metadata/isbndb.py
@@ -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
diff --git a/src/libprs500/gui2/Makefile b/src/libprs500/gui2/Makefile
index fddb1cdd7c..fde86b6f73 100644
--- a/src/libprs500/gui2/Makefile
+++ b/src/libprs500/gui2/Makefile
@@ -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)
diff --git a/src/libprs500/gui2/dialogs/fetch_metadata.py b/src/libprs500/gui2/dialogs/fetch_metadata.py
new file mode 100644
index 0000000000..6bd4cf86c6
--- /dev/null
+++ b/src/libprs500/gui2/dialogs/fetch_metadata.py
@@ -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
diff --git a/src/libprs500/gui2/dialogs/fetch_metadata.ui b/src/libprs500/gui2/dialogs/fetch_metadata.ui
new file mode 100644
index 0000000000..259c77b657
--- /dev/null
+++ b/src/libprs500/gui2/dialogs/fetch_metadata.ui
@@ -0,0 +1,144 @@
+
+ FetchMetadata
+
+
+ Qt::WindowModal
+
+
+
+ 0
+ 0
+ 830
+ 622
+
+
+
+ Fetch metadata
+
+
+ :/images/metadata.svg
+
+
+ -
+
+
+ Fetching metadata for <b>%1</b>
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Sign up for a free account from <a href="http://www.isndb.com">isndb.com</a> to get an access key.
+
+
+ Qt::AlignCenter
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+ &Access Key;
+
+
+ key
+
+
+
+ -
+
+
+ -
+
+
+ Fetch
+
+
+
+
+
+ -
+
+
+ Matches
+
+
+
-
+
+
+ Select the book that most closely matches your copy from the list below
+
+
+
+ -
+
+
+ true
+
+
+ QAbstractItemView::SingleSelection
+
+
+ QAbstractItemView::SelectRows
+
+
+
+
+
+
+ -
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ FetchMetadata
+ accept()
+
+
+ 460
+ 599
+
+
+ 657
+ 530
+
+
+
+
+ buttonBox
+ rejected()
+ FetchMetadata
+ reject()
+
+
+ 417
+ 599
+
+
+ 0
+ 491
+
+
+
+
+
diff --git a/src/libprs500/gui2/dialogs/lrf_single.py b/src/libprs500/gui2/dialogs/lrf_single.py
index 456fdc942c..7c29e501bc 100644
--- a/src/libprs500/gui2/dialogs/lrf_single.py
+++ b/src/libprs500/gui2/dialogs/lrf_single.py
@@ -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:
diff --git a/src/libprs500/gui2/dialogs/metadata_single.py b/src/libprs500/gui2/dialogs/metadata_single.py
index cd76934cf6..d114d8da43 100644
--- a/src/libprs500/gui2/dialogs/metadata_single.py
+++ b/src/libprs500/gui2/dialogs/metadata_single.py
@@ -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(','))
diff --git a/src/libprs500/gui2/dialogs/metadata_single.ui b/src/libprs500/gui2/dialogs/metadata_single.ui
index c175d65b8c..f016381223 100644
--- a/src/libprs500/gui2/dialogs/metadata_single.ui
+++ b/src/libprs500/gui2/dialogs/metadata_single.ui
@@ -218,6 +218,22 @@
+ -
+
+
+ -
+
+
+ IS&BN:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ isbn
+
+
+
@@ -233,6 +249,13 @@
+ -
+
+
+ Fetch metadata from server
+
+
+
@@ -503,8 +526,8 @@
accept()
- 248
- 254
+ 257
+ 646
157
@@ -519,8 +542,8 @@
reject()
- 316
- 260
+ 325
+ 646
286
diff --git a/src/libprs500/library/database.py b/src/libprs500/library/database.py
index 374b0e0cd5..4568b7ee49 100644
--- a/src/libprs500/library/database.py
+++ b/src/libprs500/library/database.py
@@ -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: