mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Save to disk implemented.
This commit is contained in:
parent
fe2336d227
commit
a1c8fcff51
@ -162,6 +162,15 @@ class Device(object):
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_file(self, path, outfile, end_session=True):
|
||||
'''
|
||||
Read the file at C{path} on the device and write it to outfile.
|
||||
@param outfile: file object like C{sys.stdout} or the result of an C{open} call
|
||||
'''
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
|
||||
class BookList(list):
|
||||
'''
|
||||
A list of books. Each Book object must have the fields:
|
||||
|
@ -1231,7 +1231,7 @@ class HTMLConverter(object):
|
||||
except Exception, err:
|
||||
print 'WARNING: An error occurred while processing a table:', err
|
||||
print 'Ignoring table markup for table:'
|
||||
print str(tag)[:100]
|
||||
print str(tag)[:300]
|
||||
self.in_table = False
|
||||
self.process_children(tag, tag_css)
|
||||
else:
|
||||
|
@ -186,6 +186,13 @@ class FileDialog(QObject):
|
||||
settings.setValue(self.dialog_name, QVariant(self.fd.saveState()))
|
||||
|
||||
|
||||
def choose_dir(window, name, title):
|
||||
settings = QSettings()
|
||||
dir = settings.value(name, QVariant(os.path.expanduser('~'))).toString()
|
||||
dir = qstring_to_unicode(QFileDialog.getExistingDirectory(window, title, dir))
|
||||
if os.path.exists(dir):
|
||||
return dir
|
||||
|
||||
def choose_files(window, name, title,
|
||||
filters=[], all_files=True, select_only_single_file=False):
|
||||
'''
|
||||
|
@ -12,7 +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.Warning
|
||||
import sys
|
||||
import sys, os
|
||||
|
||||
from PyQt4.QtCore import QThread, SIGNAL, QObject
|
||||
|
||||
@ -111,9 +111,21 @@ class DeviceManager(QObject):
|
||||
def delete_books_func(self):
|
||||
'''Remove books from device'''
|
||||
def delete_books(updater, paths):
|
||||
'''Delete books from device'''
|
||||
'''Remove books from device'''
|
||||
self.device.delete_books(paths, end_session=True)
|
||||
return delete_books
|
||||
|
||||
def remove_books_from_metadata(self, paths, booklists):
|
||||
self.device_class.remove_books_from_metadata(paths, booklists)
|
||||
|
||||
def save_books_func(self):
|
||||
'''Copy books from device to disk'''
|
||||
def save_books(updater, paths, target):
|
||||
'''Copy books from device to disk'''
|
||||
self.device.set_progress_reporter(updater)
|
||||
for path in paths:
|
||||
name = path.rpartition('/')[2]
|
||||
f = open(os.path.join(target, name), 'wb')
|
||||
self.device.get_file(path, f)
|
||||
f.close()
|
||||
return save_books
|
@ -29,6 +29,7 @@
|
||||
<file>images/mimetypes/zip.svg</file>
|
||||
<file>images/plus.svg</file>
|
||||
<file>images/reader.svg</file>
|
||||
<file>images/save.svg</file>
|
||||
<file>images/sd.svg</file>
|
||||
<file>images/sync.svg</file>
|
||||
<file>images/trash.svg</file>
|
||||
|
@ -103,6 +103,10 @@ class BooksModel(QAbstractTableModel):
|
||||
''' Return list indices of all cells in index.row()'''
|
||||
return [ self.index(index.row(), c) for c in range(self.columnCount(None))]
|
||||
|
||||
def save_to_disk(self, rows, path):
|
||||
rows = [row.row() for row in rows]
|
||||
self.db.export_to_dir(path, rows)
|
||||
|
||||
def delete_books(self, indices):
|
||||
ids = [ self.id(i) for i in indices ]
|
||||
for id in ids:
|
||||
|
@ -19,13 +19,13 @@ from PyQt4.QtCore import Qt, SIGNAL, QObject, QCoreApplication, \
|
||||
from PyQt4.QtGui import QPixmap, QColor, QPainter, QMenu, QIcon, QMessageBox
|
||||
from PyQt4.QtSvg import QSvgRenderer
|
||||
|
||||
from libprs500 import __version__, __appname__, iswindows, isosx
|
||||
from libprs500 import __version__, __appname__
|
||||
from libprs500.ebooks.metadata.meta import get_metadata
|
||||
from libprs500.devices.errors import FreeSpaceError
|
||||
from libprs500.devices.interface import Device
|
||||
from libprs500.gui2 import APP_TITLE, warning_dialog, choose_files, error_dialog, \
|
||||
initialize_file_icon_provider, BOOK_EXTENSIONS, \
|
||||
pixmap_to_data
|
||||
pixmap_to_data, choose_dir
|
||||
from libprs500.gui2.main_ui import Ui_MainWindow
|
||||
from libprs500.gui2.device import DeviceDetector, DeviceManager
|
||||
from libprs500.gui2.status import StatusBar
|
||||
@ -95,7 +95,7 @@ class Main(QObject, Ui_MainWindow):
|
||||
QObject.connect(self.action_sync, SIGNAL("triggered(bool)"), self.sync_to_main_memory)
|
||||
QObject.connect(sm.actions()[0], SIGNAL('triggered(bool)'), self.sync_to_main_memory)
|
||||
QObject.connect(sm.actions()[1], SIGNAL('triggered(bool)'), self.sync_to_card)
|
||||
|
||||
QObject.connect(self.action_save, SIGNAL("triggered(bool)"), self.save_to_disk)
|
||||
self.action_sync.setMenu(sm)
|
||||
self.action_edit.setMenu(md)
|
||||
self.tool_bar.addAction(self.action_sync)
|
||||
@ -423,6 +423,29 @@ class Main(QObject, Ui_MainWindow):
|
||||
|
||||
############################################################################
|
||||
|
||||
############################## Save to disk ################################
|
||||
def save_to_disk(self, checked):
|
||||
rows = self.current_view().selectionModel().selectedRows()
|
||||
if not rows or len(rows) == 0:
|
||||
d = error_dialog(self.window, 'Cannot save to disk', 'No books selected')
|
||||
d.exec_()
|
||||
return
|
||||
dir = choose_dir(self.window, 'save to disk dialog', 'Choose destination directory')
|
||||
if not dir:
|
||||
return
|
||||
if self.current_view() == self.library_view:
|
||||
self.current_view().model().save_to_disk(rows, dir)
|
||||
else:
|
||||
paths = self.current_view().model().paths(rows)
|
||||
self.job_manager.run_device_job(self.books_saved,
|
||||
self.device_manager.save_books_func(), paths, dir)
|
||||
|
||||
def books_saved(self, id, description, result, exception, formatted_traceback):
|
||||
if exception:
|
||||
self.device_job_exception(id, description, exception, formatted_traceback)
|
||||
return
|
||||
|
||||
############################################################################
|
||||
def location_selected(self, location):
|
||||
'''
|
||||
Called when a location icon is clicked (e.g. Library)
|
||||
|
@ -319,6 +319,7 @@
|
||||
</attribute>
|
||||
<addaction name="action_add" />
|
||||
<addaction name="action_del" />
|
||||
<addaction name="action_save" />
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar" >
|
||||
<property name="mouseTracking" >
|
||||
@ -378,6 +379,14 @@
|
||||
<string>Send to device</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_save" >
|
||||
<property name="icon" >
|
||||
<iconset resource="images.qrc" >:/images/save.svg</iconset>
|
||||
</property>
|
||||
<property name="text" >
|
||||
<string>Save to disk</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
@ -12,11 +12,12 @@
|
||||
## 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 import __appname__
|
||||
"""
|
||||
Backend that implements storage of ebooks in an sqlite database.
|
||||
"""
|
||||
import sqlite3 as sqlite
|
||||
import datetime, re
|
||||
import datetime, re, os
|
||||
from zlib import compress, decompress
|
||||
|
||||
class Concatenate(object):
|
||||
@ -898,3 +899,31 @@ class LibraryDatabase(object):
|
||||
pass
|
||||
self.conn.execute('DELETE FROM books WHERE id=?', (id,))
|
||||
self.conn.commit()
|
||||
|
||||
def export_to_dir(self, dir, indices):
|
||||
by_author = {}
|
||||
for index in indices:
|
||||
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]
|
||||
if not by_author.has_key(au):
|
||||
by_author[au] = []
|
||||
by_author[au].append(index)
|
||||
for au in by_author.keys():
|
||||
apath = os.path.join(dir, au)
|
||||
if not os.path.exists(apath):
|
||||
os.mkdir(apath)
|
||||
for idx in by_author[au]:
|
||||
title = self.title(idx)
|
||||
tpath = os.path.join(apath, title)
|
||||
id = str(self.id(idx))
|
||||
if not os.path.exists(tpath):
|
||||
os.mkdir(tpath)
|
||||
for fmt in self.formats(idx).split(','):
|
||||
data = self.format(idx, fmt)
|
||||
f = open(os.path.join(tpath, __appname__+'_'+id+'.'+fmt.lower()), 'wb')
|
||||
f.write(data)
|
||||
|
||||
if __name__ == '__main__':
|
||||
db = LibraryDatabase('/home/kovid/library1.db')
|
||||
db.refresh('title', True)
|
||||
db.export_to_dir('/tmp/test', range(1, 10))
|
Loading…
x
Reference in New Issue
Block a user