diff --git a/src/calibre/gui2/tweak_book/boss.py b/src/calibre/gui2/tweak_book/boss.py index a6ba0ae644..b336f44369 100644 --- a/src/calibre/gui2/tweak_book/boss.py +++ b/src/calibre/gui2/tweak_book/boss.py @@ -27,7 +27,7 @@ from calibre.ebooks.oeb.polish.replace import rename_files, replace_file, get_re from calibre.ebooks.oeb.polish.split import split, merge, AbortError, multisplit from calibre.ebooks.oeb.polish.toc import remove_names_from_toc, find_existing_toc, create_inline_toc from calibre.ebooks.oeb.polish.utils import link_stylesheets, setup_cssutils_serialization as scs -from calibre.gui2 import error_dialog, choose_files, question_dialog, info_dialog, choose_save_file, open_url +from calibre.gui2 import error_dialog, choose_files, question_dialog, info_dialog, choose_save_file, open_url, choose_dir from calibre.gui2.dialogs.confirm_delete import confirm from calibre.gui2.tweak_book import ( set_current_container, current_container, tprefs, actions, editors, @@ -243,7 +243,7 @@ class Boss(QObject): return get_container(dest, tdir=tdir) self.gui.blocking_job('import_book', _('Importing book, please wait...'), self.book_opened, func, src, dest, tdir=self.mkdtemp()) - def open_book(self, path=None, edit_file=None, clear_notify_data=True): + def open_book(self, path=None, edit_file=None, clear_notify_data=True, open_folder=False): ''' Open the ebook at ``path`` for editing. Will show an error if the ebook is not in a supported format or the current book has unsaved changes. @@ -256,14 +256,24 @@ class Boss(QObject): if not self._check_before_open(): return if not hasattr(path, 'rpartition'): - path = choose_files(self.gui, 'open-book-for-tweaking', _('Choose book'), + if open_folder: + path = choose_dir(self.gui, 'open-book-folder-for-tweaking', _('Choose book folder')) + if path: + path = [path] + else: + path = choose_files(self.gui, 'open-book-for-tweaking', _('Choose book'), [(_('Books'), [x.lower() for x in SUPPORTED])], all_files=False, select_only_single_file=True) + if not path: return path = path[0] + if not os.path.exists(path): + return error_dialog(self.gui, _('File not found'), _( + 'The file %s does not exist.') % path, show=True) + isdir = os.path.isdir(path) ext = path.rpartition('.')[-1].upper() - if ext not in SUPPORTED: + if ext not in SUPPORTED and not isdir: from calibre.ebooks.oeb.polish.import_book import IMPORTABLE if ext.lower() in IMPORTABLE: return self.import_book(path) @@ -271,9 +281,6 @@ class Boss(QObject): _('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 os.path.exists(path): - return error_dialog(self.gui, _('File not found'), _( - 'The file %s does not exist.') % path, show=True) for name in tuple(editors): self.close_editor(name) @@ -972,7 +979,7 @@ class Boss(QObject): ed.is_modified = False path_to_ebook = os.path.abspath(c.path_to_ebook) destdir = os.path.dirname(path_to_ebook) - if not os.path.exists(destdir): + if not c.is_dir and not os.path.exists(destdir): info_dialog(self.gui, _('Path does not exist'), _( 'The file you are editing (%s) no longer exists. You have to choose a new save location.') % path_to_ebook, show_copy_button=False, show=True) @@ -996,6 +1003,9 @@ class Boss(QObject): def save_copy(self): c = current_container() + if c.is_dir: + return error_dialog(self.gui, _('Cannot save a copy'), _( + 'Saving a copy of a folder based book is not supported'), show=True) ext = c.path_to_ebook.rpartition('.')[-1] path = choose_save_file(self.gui, 'tweak_book_save_copy', _( 'Choose path'), filters=[(_('Book (%s)') % ext.upper(), [ext.lower()])], all_files=False) diff --git a/src/calibre/gui2/tweak_book/save.py b/src/calibre/gui2/tweak_book/save.py index 6de2f3127a..fc6babb648 100644 --- a/src/calibre/gui2/tweak_book/save.py +++ b/src/calibre/gui2/tweak_book/save.py @@ -19,7 +19,16 @@ from calibre.utils import join_with_timeout from calibre.utils.filenames import atomic_rename, format_permissions from calibre.utils.ipc import RC +def save_dir_container(container, path): + if not os.path.exists(path): + os.makedirs(path) + if not os.path.isdir(path): + raise ValueError('%s is not a folder, cannot save a directory based container to it' % path) + container.commit(path) + def save_container(container, path): + if container.is_dir: + return save_dir_container(container, path) temp = PersistentTemporaryFile( prefix=('_' if iswindows else '.'), suffix=os.path.splitext(path)[1], dir=os.path.dirname(path)) if hasattr(os, 'fchmod'): diff --git a/src/calibre/gui2/tweak_book/ui.py b/src/calibre/gui2/tweak_book/ui.py index 107de3cb61..d53dd9e7dd 100644 --- a/src/calibre/gui2/tweak_book/ui.py +++ b/src/calibre/gui2/tweak_book/ui.py @@ -327,6 +327,8 @@ class Main(MainWindow): 'new-file', (), _('Create a new file in the current book')) self.action_import_files = treg('document-import.png', _('&Import files into book'), self.boss.add_files, 'new-files', (), _('Import files into book')) self.action_open_book = treg('document_open.png', _('Open &book'), self.boss.open_book, 'open-book', 'Ctrl+O', _('Open a new book')) + self.action_open_book_folder = treg('mimetypes/dir.png', _('Open &folder (unzipped EPUB) as book'), partial(self.boss.open_book, open_folder=True), + 'open-folder-as-book', (), _('Open a folder (unzipped EPUB) as a book')) # Qt does not generate shortcut overrides for cmd+arrow on os x which # means these shortcuts interfere with editing self.action_global_undo = treg('back.png', _('&Revert to before'), self.boss.do_global_undo, 'global-undo', () if isosx else 'Ctrl+Left', @@ -503,6 +505,7 @@ class Main(MainWindow): f.addAction(self.action_open_book) f.addAction(self.action_new_book) f.addAction(self.action_import_book) + f.addAction(self.action_open_book_folder) self.recent_books_menu = f.addMenu(_('&Recently opened books')) self.update_recent_books() f.addSeparator()