Finish the implementation of delete files

This commit is contained in:
Kovid Goyal 2013-10-11 17:37:31 +05:30
parent ec9b69a299
commit e5f5f28180
5 changed files with 127 additions and 44 deletions

View File

@ -0,0 +1,84 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
from __future__ import (unicode_literals, division, absolute_import,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
import tempfile, shutil
from PyQt4.Qt import QObject
from calibre.gui2 import error_dialog
from calibre.ptempfile import PersistentTemporaryDirectory
from calibre.ebooks.oeb.polish.main import SUPPORTED
from calibre.ebooks.oeb.polish.container import get_container, clone_container
from calibre.gui2.tweak_book import set_current_container, current_container
from calibre.gui2.tweak_book.undo import GlobalUndoHistory
class Boss(QObject):
def __init__(self, parent=None):
QObject.__init__(self, parent)
self.global_undo = GlobalUndoHistory()
self.container_count = 0
self.tdir = None
def __call__(self, gui):
self.gui = gui
gui.file_list.delete_requested.connect(self.delete_requested)
def mkdtemp(self):
self.container_count += 1
return tempfile.mkdtemp(prefix='%05d-' % self.container_count, dir=self.tdir)
def check_dirtied(self):
# TODO: Implement this
return True
def open_book(self, path):
ext = path.rpartition('.')[-1].upper()
if ext not in SUPPORTED:
return error_dialog(self.gui, _('Unsupported format'),
_('Tweaking is only supported for books in the %s formats.'
' Convert your book to one of these formats first.') % _(' and ').join(sorted(SUPPORTED)),
show=True)
if not self.check_dirtied():
return
self.container_count = -1
if self.tdir:
shutil.rmtree(self.tdir, ignore_errors=True)
self.tdir = PersistentTemporaryDirectory()
self.gui.blocking_job('open_book', _('Opening book, please wait...'), self.book_opened, get_container, path, tdir=self.mkdtemp())
def book_opened(self, job):
if job.traceback is not None:
return error_dialog(self.gui, _('Failed to open book'),
_('Failed to open book, click Show details for more information.'),
det_msg=job.traceback, show=True)
container = job.result
set_current_container(container)
self.current_metadata = self.gui.current_metadata = container.mi
self.global_undo.open_book(container)
self.gui.update_window_title()
self.gui.file_list.build(container)
def add_savepoint(self, msg):
nc = clone_container(current_container(), self.mkdtemp())
self.global_undo.add_savepoint(nc, msg)
set_current_container(nc)
def delete_requested(self, spine_items, other_items):
if not self.check_dirtied():
return
self.add_savepoint(_('Delete files'))
c = current_container()
c.remove_from_spine(spine_items)
for name in other_items:
c.remove_item(name)
self.gui.file_list.delete_done(spine_items, other_items)

View File

@ -260,7 +260,7 @@ class FileList(QTreeWidget):
removals.append(child)
for c in removals:
c.parent().removeChild(c.parent().indexOfChild(c))
c.parent().removeChild(c)
class FileListWidget(QWidget):
@ -274,6 +274,8 @@ class FileListWidget(QWidget):
self.layout().setContentsMargins(0, 0, 0, 0)
for x in ('delete_requested',):
getattr(self.file_list, x).connect(getattr(self, x))
for x in ('delete_done',):
setattr(self, x, getattr(self.file_list, x))
def build(self, container):
self.file_list.build(container)

View File

@ -40,7 +40,7 @@ def main(args=sys.argv):
sys.excepthook = main.unhandled_exception
main.show()
if len(args) > 1:
main.open_book(args[1])
main.boss.open_book(args[1])
app.exec_()
if __name__ == '__main__':

View File

@ -6,23 +6,13 @@ from __future__ import (unicode_literals, division, absolute_import,
__license__ = 'GPL v3'
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
import shutil, tempfile
from PyQt4.Qt import QDockWidget, Qt, QLabel, QIcon
from calibre.ebooks.oeb.polish.container import get_container
from calibre.ebooks.oeb.polish.main import SUPPORTED
from calibre.ptempfile import PersistentTemporaryDirectory
from calibre.gui2 import error_dialog
from calibre.gui2.main_window import MainWindow
from calibre.gui2.tweak_book import set_current_container, current_container
from calibre.gui2.tweak_book import current_container
from calibre.gui2.tweak_book.file_list import FileListWidget
from calibre.gui2.tweak_book.job import BlockingJob
from calibre.gui2.tweak_book.undo import GlobalUndoHistory
def load_book(path_to_ebook, base_tdir):
tdir = tempfile.mkdtemp(dir=base_tdir)
return get_container(path_to_ebook, tdir=tdir)
from calibre.gui2.tweak_book.boss import Boss
class Main(MainWindow):
@ -30,13 +20,13 @@ class Main(MainWindow):
def __init__(self, opts):
MainWindow.__init__(self, opts, disable_automatic_gc=True)
self.boss = Boss(self)
self.setWindowTitle(self.APP_NAME)
self.setWindowIcon(QIcon(I('tweak.png')))
self.opts = opts
self.tdir = None
self.path_to_ebook = None
self.container = None
self.global_undo = GlobalUndoHistory()
self.current_metadata = None
self.blocking_job = BlockingJob(self)
self.file_list_dock = d = QDockWidget(_('&Files Browser'), self)
@ -49,37 +39,11 @@ class Main(MainWindow):
self.l = QLabel('Placeholder')
self.setCentralWidget(self.l)
self.boss(self)
def resizeEvent(self, ev):
self.blocking_job.resize(ev.size())
return super(Main, self).resizeEvent(ev)
def open_book(self, path):
ext = path.rpartition('.')[-1].upper()
if ext not in SUPPORTED:
return error_dialog(self, _('Unsupported format'),
_('Tweaking is only supported for books in the %s formats.'
' Convert your book to one of these formats first.') % _(' and ').join(sorted(SUPPORTED)),
show=True)
# TODO: Handle already open, dirtied book
if self.tdir:
shutil.rmtree(self.tdir, ignore_errors=True)
self.tdir = PersistentTemporaryDirectory()
self.blocking_job('open_book', _('Opening book, please wait...'), self.book_opened, load_book, path, self.tdir)
def book_opened(self, job):
if job.traceback is not None:
return error_dialog(self, _('Failed to open book'),
_('Failed to open book, click Show details for more information.'),
det_msg=job.traceback, show=True)
container = job.result
set_current_container(container)
self.current_metadata = container.mi
self.global_undo.open_book(container)
self.update_window_title()
self.file_list.build(container)
def update_window_title(self):
self.setWindowTitle(self.current_metadata.title + ' [%s] - %s' %(current_container().book_type.upper(), self.APP_NAME))

View File

@ -6,18 +6,51 @@ from __future__ import (unicode_literals, division, absolute_import,
__license__ = 'GPL v3'
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
import shutil
def cleanup(containers):
for container in containers:
try:
shutil.rmtree(container.root, ignore_errors=True)
except:
pass
class State(object):
def __init__(self, container):
self.container = container
self.operation = None
self.message = None
class GlobalUndoHistory(object):
def __init__(self):
self.states = []
self.pos = 0
@property
def current_container(self):
return self.states[self.pos].container
def open_book(self, container):
self.states = [State(container)]
self.pos = 0
def add_savepoint(self, new_container, message):
self.states[self.pos].message = message
extra = self.states[self.pos+1:]
cleanup(extra)
self.states = self.states[:self.pos+1]
self.states.append(State(new_container))
self.pos += 1
def undo(self):
if self.pos > 0:
self.pos -= 1
return self.current_container
def redo(self):
if self.pos < len(self.states) - 1:
self.pos += 1
return self.current_container