mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
GUI conversion implemented. version 0.3.102
This commit is contained in:
parent
165859c6c7
commit
0104da8351
@ -13,7 +13,7 @@
|
|||||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
''' E-book management software'''
|
''' E-book management software'''
|
||||||
__version__ = "0.3.101"
|
__version__ = "0.3.102"
|
||||||
__docformat__ = "epytext"
|
__docformat__ = "epytext"
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
__appname__ = 'libprs500'
|
__appname__ = 'libprs500'
|
||||||
|
@ -35,12 +35,17 @@ def largest_file(files):
|
|||||||
return file
|
return file
|
||||||
|
|
||||||
def find_htmlfile(dir):
|
def find_htmlfile(dir):
|
||||||
for pair in (('*toc*.htm*', '*toc*.xhtm*'), ('*.htm*', '*.xhtm*')):
|
cwd = os.getcwd()
|
||||||
files = glob.glob(os.path.join(dir, pair[0]))
|
try:
|
||||||
files += glob.glob(os.path.join(dir, pair[1]))
|
os.chdir(dir)
|
||||||
file = largest_file(files)
|
for pair in (('*toc*.htm*', '*toc*.xhtm*'), ('*.htm*', '*.xhtm*')):
|
||||||
if file:
|
files = glob.glob(pair[0])
|
||||||
return file
|
files += glob.glob(pair[1])
|
||||||
|
file = largest_file(files)
|
||||||
|
if file:
|
||||||
|
return os.path.join(dir, file)
|
||||||
|
finally:
|
||||||
|
os.chdir(cwd)
|
||||||
|
|
||||||
|
|
||||||
def handle_archive(path):
|
def handle_archive(path):
|
||||||
|
@ -33,6 +33,6 @@ class ChooseFormatDialog(QDialog, Ui_ChooseFormatDialog):
|
|||||||
self.formats.setCurrentRow(0)
|
self.formats.setCurrentRow(0)
|
||||||
|
|
||||||
def format(self):
|
def format(self):
|
||||||
self._formats[self.formats.currentRow()]
|
return self._formats[self.formats.currentRow()]
|
||||||
|
|
||||||
|
|
@ -22,6 +22,8 @@ from libprs500.gui2.dialogs.choose_format import ChooseFormatDialog
|
|||||||
from libprs500.gui2 import qstring_to_unicode, error_dialog, \
|
from libprs500.gui2 import qstring_to_unicode, error_dialog, \
|
||||||
pixmap_to_data, choose_images
|
pixmap_to_data, choose_images
|
||||||
from libprs500.ebooks.lrf import option_parser
|
from libprs500.ebooks.lrf import option_parser
|
||||||
|
from libprs500.ptempfile import PersistentTemporaryFile
|
||||||
|
from libprs500 import __appname__
|
||||||
|
|
||||||
class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
|
class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
|
||||||
|
|
||||||
@ -51,6 +53,8 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
|
|||||||
QObject.connect(self.cover_button, SIGNAL("clicked(bool)"), self.select_cover)
|
QObject.connect(self.cover_button, SIGNAL("clicked(bool)"), self.select_cover)
|
||||||
self.categoryList.leaveEvent = self.reset_help
|
self.categoryList.leaveEvent = self.reset_help
|
||||||
self.reset_help()
|
self.reset_help()
|
||||||
|
self.output_format = 'LRF'
|
||||||
|
self.selected_format = None
|
||||||
self.setup_tooltips()
|
self.setup_tooltips()
|
||||||
self.initialize_options()
|
self.initialize_options()
|
||||||
self.db = db
|
self.db = db
|
||||||
@ -61,34 +65,31 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
|
|||||||
self.changed = False
|
self.changed = False
|
||||||
self.read_saved_options()
|
self.read_saved_options()
|
||||||
self.initialize_metadata()
|
self.initialize_metadata()
|
||||||
formats = self.db.formats(self.row)
|
formats = [i.upper() for i in self.db.formats(self.row).split(',')]
|
||||||
|
try:
|
||||||
|
formats.remove(self.output_format)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
if not formats:
|
if not formats:
|
||||||
d = error_dialog(window, 'No available formats', 'Cannot convert as this book has no available formats')
|
d = error_dialog(window, 'No available formats', 'Cannot convert as this book has no available formats')
|
||||||
d.exec_()
|
d.exec_()
|
||||||
formats = [i.upper() for i in formats.split(',')]
|
|
||||||
self.selected_format = None
|
|
||||||
try:
|
|
||||||
formats.remove('LRF')
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
if len(formats) > 1:
|
if len(formats) > 1:
|
||||||
d = ChooseFormatDialog(window, 'Choose the format to convert into LRF', formats)
|
d = ChooseFormatDialog(window, 'Choose the format to convert into LRF', formats)
|
||||||
d.exec_()
|
d.exec_()
|
||||||
if d.result() == QDialog.Accepted:
|
if d.result() == QDialog.Accepted:
|
||||||
self.selected_format = d.format()
|
self.selected_format = d.format()
|
||||||
else:
|
else:
|
||||||
if len(formats):
|
self.selected_format = formats[0]
|
||||||
self.selected_format = formats[0]
|
|
||||||
else:
|
|
||||||
d = error_dialog(window, 'No suitable formats', 'Cannot convert as this book has no suitable formats.')
|
|
||||||
d.exec_()
|
|
||||||
if self.selected_format:
|
if self.selected_format:
|
||||||
self.setWindowTitle('Convert %s to LRF'%(self.selected_format,))
|
self.setWindowTitle('Convert %s to LRF'%(self.selected_format,))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def read_saved_options(self):
|
def read_saved_options(self):
|
||||||
cmdline = self.db.conversion_options(self.id, 'lrf')
|
cmdline = self.db.conversion_options(self.id, self.output_format.lower())
|
||||||
print 1, cmdline
|
|
||||||
if cmdline:
|
if cmdline:
|
||||||
for opt in self.options():
|
for opt in self.options():
|
||||||
try:
|
try:
|
||||||
@ -236,7 +237,7 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
|
|||||||
args[0].accept()
|
args[0].accept()
|
||||||
|
|
||||||
def build_commandline(self):
|
def build_commandline(self):
|
||||||
cmd = []
|
cmd = [__appname__]
|
||||||
for name in self.option_map.keys():
|
for name in self.option_map.keys():
|
||||||
opt = self.option_map[name].get_opt_string()
|
opt = self.option_map[name].get_opt_string()
|
||||||
obj = getattr(self, name)
|
obj = getattr(self, name)
|
||||||
@ -256,6 +257,9 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
|
|||||||
cmd.extend(['--profile', qstring_to_unicode(self.gui_profile.currentText())])
|
cmd.extend(['--profile', qstring_to_unicode(self.gui_profile.currentText())])
|
||||||
return cmd
|
return cmd
|
||||||
|
|
||||||
|
def title(self):
|
||||||
|
return qstring_to_unicode(self.gui_title.text())
|
||||||
|
|
||||||
def write_metadata(self):
|
def write_metadata(self):
|
||||||
title = qstring_to_unicode(self.gui_title.text())
|
title = qstring_to_unicode(self.gui_title.text())
|
||||||
self.db.set_title(self.id, title)
|
self.db.set_title(self.id, title)
|
||||||
@ -263,7 +267,6 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
|
|||||||
if au: self.db.set_authors(self.id, au)
|
if au: self.db.set_authors(self.id, au)
|
||||||
aus = qstring_to_unicode(self.gui_author_sort.text())
|
aus = qstring_to_unicode(self.gui_author_sort.text())
|
||||||
if aus: self.db.set_author_sort(self.id, aus)
|
if aus: self.db.set_author_sort(self.id, aus)
|
||||||
print self.db.author_sort(self.row)
|
|
||||||
self.db.set_publisher(self.id, qstring_to_unicode(self.gui_publisher.text()))
|
self.db.set_publisher(self.id, qstring_to_unicode(self.gui_publisher.text()))
|
||||||
self.db.set_tags(self.id, qstring_to_unicode(self.tags.text()).split(','))
|
self.db.set_tags(self.id, qstring_to_unicode(self.tags.text()).split(','))
|
||||||
self.db.set_series(self.id, qstring_to_unicode(self.series.currentText()))
|
self.db.set_series(self.id, qstring_to_unicode(self.series.currentText()))
|
||||||
@ -274,8 +277,16 @@ class LRFSingleDialog(QDialog, Ui_LRFSingleDialog):
|
|||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
cmdline = self.build_commandline()
|
cmdline = self.build_commandline()
|
||||||
# TODO: put cover into tempfile
|
self.cover_file = None
|
||||||
self.write_metadata()
|
self.write_metadata()
|
||||||
self.db.set_conversion_options(self.id, 'lrf', cmdline)
|
cover = self.db.cover(self.row)
|
||||||
|
if cover:
|
||||||
|
self.cover_file = PersistentTemporaryFile(suffix='.jpeg')
|
||||||
|
self.cover_file.write(cover)
|
||||||
|
self.cover_file.close()
|
||||||
|
self.db.set_conversion_options(self.id, self.output_format.lower(), cmdline)
|
||||||
|
if self.cover_file:
|
||||||
|
cmdline.extend(['--cover', self.cover_file.name])
|
||||||
|
self.cmdline = [str(i) for i in cmdline]
|
||||||
QDialog.accept(self)
|
QDialog.accept(self)
|
||||||
|
|
@ -25,6 +25,7 @@ from libprs500 import __version__, __appname__
|
|||||||
from libprs500.ptempfile import PersistentTemporaryFile
|
from libprs500.ptempfile import PersistentTemporaryFile
|
||||||
from libprs500.ebooks.metadata.meta import get_metadata
|
from libprs500.ebooks.metadata.meta import get_metadata
|
||||||
from libprs500.ebooks.lrf.web.convert_from import main as web2lrf
|
from libprs500.ebooks.lrf.web.convert_from import main as web2lrf
|
||||||
|
from libprs500.ebooks.lrf.any.convert_from import main as any2lrf
|
||||||
from libprs500.devices.errors import FreeSpaceError
|
from libprs500.devices.errors import FreeSpaceError
|
||||||
from libprs500.devices.interface import Device
|
from libprs500.devices.interface import Device
|
||||||
from libprs500.gui2 import APP_TITLE, warning_dialog, choose_files, error_dialog, \
|
from libprs500.gui2 import APP_TITLE, warning_dialog, choose_files, error_dialog, \
|
||||||
@ -471,7 +472,7 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
self.current_view().model().save_to_disk(rows, dir)
|
self.current_view().model().save_to_disk(rows, dir)
|
||||||
else:
|
else:
|
||||||
paths = self.current_view().model().paths(rows)
|
paths = self.current_view().model().paths(rows)
|
||||||
self.job_manager.run_device_job(self.books_saved,
|
self.job_manager.run_device_job(self.books_saved,
|
||||||
self.device_manager.save_books_func(), paths, dir)
|
self.device_manager.save_books_func(), paths, dir)
|
||||||
|
|
||||||
def books_saved(self, id, description, result, exception, formatted_traceback):
|
def books_saved(self, id, description, result, exception, formatted_traceback):
|
||||||
@ -525,7 +526,8 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
|
|
||||||
############################### Convert ####################################
|
############################### Convert ####################################
|
||||||
def convert_bulk(self, checked):
|
def convert_bulk(self, checked):
|
||||||
pass
|
d = error_dialog(self.window, 'Cannot convert', 'Not yet implemented.')
|
||||||
|
d.exec_()
|
||||||
|
|
||||||
def convert_single(self, checked):
|
def convert_single(self, checked):
|
||||||
rows = self.library_view.selectionModel().selectedRows()
|
rows = self.library_view.selectionModel().selectedRows()
|
||||||
@ -533,10 +535,42 @@ class Main(QObject, Ui_MainWindow):
|
|||||||
d = error_dialog(self.window, 'Cannot convert', 'No books selected')
|
d = error_dialog(self.window, 'Cannot convert', 'No books selected')
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
|
changed = False
|
||||||
for row in rows:
|
for row in rows:
|
||||||
d = LRFSingleDialog(self.window, self.library_view.model().db, row)
|
d = LRFSingleDialog(self.window, self.library_view.model().db, row)
|
||||||
if d.selected_format:
|
if d.selected_format:
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
if d.result() == QDialog.Accepted:
|
||||||
|
changed = True
|
||||||
|
cmdline = d.cmdline
|
||||||
|
data = self.library_view.model().db.format(row.row(), d.selected_format)
|
||||||
|
pt = PersistentTemporaryFile('.'+d.selected_format.lower())
|
||||||
|
pt.write(data)
|
||||||
|
pt.close()
|
||||||
|
of = PersistentTemporaryFile('.lrf')
|
||||||
|
of.close()
|
||||||
|
cmdline.extend(['-o', of.name])
|
||||||
|
cmdline.append(pt.name)
|
||||||
|
id = self.job_manager.run_conversion_job(self.book_converted,
|
||||||
|
any2lrf, args=cmdline,
|
||||||
|
job_description='Convert book:'+d.title())
|
||||||
|
|
||||||
|
|
||||||
|
self.conversion_jobs[id] = (d.cover_file, pt, of, d.output_format, d.id)
|
||||||
|
if changed:
|
||||||
|
self.library_view.model().resort(reset=False)
|
||||||
|
self.library_view.model().research()
|
||||||
|
|
||||||
|
|
||||||
|
def book_converted(self, id, description, result, exception, formatted_traceback, log):
|
||||||
|
of, fmt, book_id = self.conversion_jobs.pop(id)[2:]
|
||||||
|
if exception:
|
||||||
|
self.conversion_job_exception(id, description, exception, formatted_traceback, log)
|
||||||
|
return
|
||||||
|
data = open(of.name, 'rb')
|
||||||
|
self.library_view.model().db.add_format(book_id, fmt, data, index_is_id=True)
|
||||||
|
data.close()
|
||||||
|
self.status_bar.showMessage(description + ' completed', 2000)
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
def location_selected(self, location):
|
def location_selected(self, location):
|
||||||
|
@ -754,9 +754,9 @@ class LibraryDatabase(object):
|
|||||||
return None
|
return None
|
||||||
return matches[0][0]
|
return matches[0][0]
|
||||||
|
|
||||||
def formats(self, index):
|
def formats(self, index, index_is_id=False):
|
||||||
''' Return available formats as a comma separated list '''
|
''' Return available formats as a comma separated list '''
|
||||||
id = self.id(index)
|
id = index if index_is_id else self.id(index)
|
||||||
matches = self.conn.execute('SELECT concat(format) FROM data WHERE data.book=?', (id,)).fetchall()
|
matches = self.conn.execute('SELECT concat(format) FROM data WHERE data.book=?', (id,)).fetchall()
|
||||||
if not matches:
|
if not matches:
|
||||||
return None
|
return None
|
||||||
@ -777,18 +777,21 @@ class LibraryDatabase(object):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def add_format(self, index, ext, stream):
|
def add_format(self, index, ext, stream, index_is_id=False):
|
||||||
'''
|
'''
|
||||||
Add the format specified by ext. If it already exists it is replaced.
|
Add the format specified by ext. If it already exists it is replaced.
|
||||||
'''
|
'''
|
||||||
id = self.id(index)
|
id = index if index_is_id else self.id(index)
|
||||||
stream.seek(0, 2)
|
stream.seek(0, 2)
|
||||||
usize = stream.tell()
|
usize = stream.tell()
|
||||||
stream.seek(0)
|
stream.seek(0)
|
||||||
data = sqlite.Binary(compress(stream.read()))
|
data = sqlite.Binary(compress(stream.read()))
|
||||||
exts = self.formats(index)
|
exts = self.formats(index, index_is_id=index_is_id)
|
||||||
if not exts:
|
if not exts:
|
||||||
exts = []
|
exts = []
|
||||||
|
if not ext:
|
||||||
|
ext = ''
|
||||||
|
ext = ext.lower()
|
||||||
if ext in exts:
|
if ext in exts:
|
||||||
self.conn.execute('UPDATE data SET data=? WHERE format=? AND book=?',
|
self.conn.execute('UPDATE data SET data=? WHERE format=? AND book=?',
|
||||||
(data, ext, id))
|
(data, ext, id))
|
||||||
@ -996,7 +999,8 @@ class LibraryDatabase(object):
|
|||||||
by_author = {}
|
by_author = {}
|
||||||
for index in indices:
|
for index in indices:
|
||||||
id = self.id(index)
|
id = self.id(index)
|
||||||
au = self.conn.execute('SELECT concat(sort) FROM authors WHERE authors.id IN (SELECT author from books_authors_link WHERE book=?)', (id,)).fetchone()[0]
|
au = self.conn.execute('SELECT author_sort FROM books WHERE id=?',
|
||||||
|
(id,)).fetchone()[0]
|
||||||
if not by_author.has_key(au):
|
if not by_author.has_key(au):
|
||||||
by_author[au] = []
|
by_author[au] = []
|
||||||
by_author[au].append(index)
|
by_author[au].append(index)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user