Create subclass InterfaceActionWithLibraryDrop (DRY)

All actual implementation of `accepts_drops` for built-in InterfaceAction
are a "from_library" drag-and-drop. Create a subclass that implement the
relatives methods.
This commit is contained in:
un-pogaz 2024-02-18 20:43:07 +01:00
parent 49e7bf5c97
commit 37d4946e97
10 changed files with 67 additions and 210 deletions

View File

@ -8,8 +8,9 @@ __docformat__ = 'restructuredtext en'
from functools import partial from functools import partial
from zipfile import ZipFile from zipfile import ZipFile
from qt.core import (QToolButton, QAction, QIcon, QObject, QMenu, QPoint, from qt.core import (
QKeySequence) QAction, QIcon, QKeySequence, QMenu, QObject, QPoint, QTimer, QToolButton,
)
from calibre import prints from calibre import prints
from calibre.constants import ismacos from calibre.constants import ismacos
@ -438,3 +439,35 @@ class InterfaceAction(QObject):
long periods of time. long periods of time.
''' '''
pass pass
class InterfaceActionWithLibraryDrop(InterfaceAction):
'''
Subclass of InterfaceAction that implemente methods to execute the default action
by drop some books from the library.
Inside the do_drop() method, the ids of the droped books are provided
by the attribute self.dropped_ids
'''
accepts_drops = True
mime = 'application/calibre+from_library'
def accept_enter_event(self, event, mime_data):
if mime_data.hasFormat(self.mime):
return True
return False
def accept_drag_move_event(self, event, mime_data):
if mime_data.hasFormat(self.mime):
return True
return False
def drop_event(self, event, mime_data):
if mime_data.hasFormat(self.mime):
self.dropped_ids = tuple(map(int, mime_data.data(self.mime).data().split()))
QTimer.singleShot(1, self.do_drop)
return True
return False
def do_drop(self):
raise NotImplementedError()

View File

@ -7,17 +7,17 @@ __docformat__ = 'restructuredtext en'
import os import os
from functools import partial from functools import partial
from qt.core import QModelIndex, QTimer from qt.core import QModelIndex
from calibre.customize.ui import plugin_for_input_format, run_plugins_on_postconvert from calibre.customize.ui import plugin_for_input_format, run_plugins_on_postconvert
from calibre.gui2 import Dispatcher, error_dialog, gprefs from calibre.gui2 import Dispatcher, error_dialog, gprefs
from calibre.gui2.actions import InterfaceAction from calibre.gui2.actions import InterfaceActionWithLibraryDrop
from calibre.gui2.tools import convert_bulk_ebook, convert_single_ebook from calibre.gui2.tools import convert_bulk_ebook, convert_single_ebook
from calibre.utils.config import prefs, tweaks from calibre.utils.config import prefs, tweaks
from calibre.utils.localization import ngettext from calibre.utils.localization import ngettext
class ConvertAction(InterfaceAction): class ConvertAction(InterfaceActionWithLibraryDrop):
name = 'Convert Books' name = 'Convert Books'
action_spec = (_('Convert books'), 'convert.png', _('Convert books between different e-book formats'), _('C')) action_spec = (_('Convert books'), 'convert.png', _('Convert books between different e-book formats'), _('C'))
@ -25,26 +25,6 @@ class ConvertAction(InterfaceAction):
action_type = 'current' action_type = 'current'
action_add_menu = True action_add_menu = True
accepts_drops = True
def accept_enter_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def accept_drag_move_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def drop_event(self, event, mime_data):
mime = 'application/calibre+from_library'
if mime_data.hasFormat(mime):
self.dropped_ids = tuple(map(int, mime_data.data(mime).data().split()))
QTimer.singleShot(1, self.do_drop)
return True
return False
def do_drop(self): def do_drop(self):
book_ids = self.dropped_ids book_ids = self.dropped_ids
del self.dropped_ids del self.dropped_ids

View File

@ -11,7 +11,7 @@ from qt.core import QDialog, QModelIndex, QObject, QTimer
from calibre.constants import ismacos from calibre.constants import ismacos
from calibre.gui2 import Aborted, error_dialog from calibre.gui2 import Aborted, error_dialog
from calibre.gui2.actions import InterfaceAction from calibre.gui2.actions import InterfaceActionWithLibraryDrop
from calibre.gui2.dialogs.confirm_delete import confirm from calibre.gui2.dialogs.confirm_delete import confirm
from calibre.gui2.dialogs.confirm_delete_location import confirm_location from calibre.gui2.dialogs.confirm_delete_location import confirm_location
from calibre.gui2.dialogs.delete_matching_from_device import ( from calibre.gui2.dialogs.delete_matching_from_device import (
@ -77,7 +77,7 @@ class MultiDeleter(QObject): # {{{
# }}} # }}}
class DeleteAction(InterfaceAction): class DeleteAction(InterfaceActionWithLibraryDrop):
name = 'Remove Books' name = 'Remove Books'
action_spec = (_('Remove books'), 'remove_books.png', _('Delete books'), 'Backspace' if ismacos else 'Del') action_spec = (_('Remove books'), 'remove_books.png', _('Delete books'), 'Backspace' if ismacos else 'Del')
@ -85,26 +85,6 @@ class DeleteAction(InterfaceAction):
action_add_menu = True action_add_menu = True
action_menu_clone_qaction = _('Remove selected books') action_menu_clone_qaction = _('Remove selected books')
accepts_drops = True
def accept_enter_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def accept_drag_move_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def drop_event(self, event, mime_data):
mime = 'application/calibre+from_library'
if mime_data.hasFormat(mime):
self.dropped_ids = tuple(map(int, mime_data.data(mime).data().split()))
QTimer.singleShot(1, self.do_drop)
return True
return False
def do_drop(self): def do_drop(self):
book_ids = self.dropped_ids book_ids = self.dropped_ids
del self.dropped_ids del self.dropped_ids

View File

@ -21,7 +21,7 @@ from calibre.ebooks.metadata.book.base import Metadata
from calibre.ebooks.metadata.opf2 import OPF, metadata_to_opf from calibre.ebooks.metadata.opf2 import OPF, metadata_to_opf
from calibre.ebooks.metadata.sources.prefs import msprefs from calibre.ebooks.metadata.sources.prefs import msprefs
from calibre.gui2 import Dispatcher, error_dialog, gprefs, question_dialog from calibre.gui2 import Dispatcher, error_dialog, gprefs, question_dialog
from calibre.gui2.actions import InterfaceAction from calibre.gui2.actions import InterfaceActionWithLibraryDrop
from calibre.gui2.actions.show_quickview import get_quickview_action_plugin from calibre.gui2.actions.show_quickview import get_quickview_action_plugin
from calibre.gui2.dialogs.confirm_delete import confirm from calibre.gui2.dialogs.confirm_delete import confirm
from calibre.gui2.dialogs.device_category_editor import DeviceCategoryEditor from calibre.gui2.dialogs.device_category_editor import DeviceCategoryEditor
@ -35,33 +35,13 @@ from polyglot.builtins import iteritems
DATA_FILES_ICON_NAME = 'unpack-book.png' DATA_FILES_ICON_NAME = 'unpack-book.png'
class EditMetadataAction(InterfaceAction): class EditMetadataAction(InterfaceActionWithLibraryDrop):
name = 'Edit Metadata' name = 'Edit Metadata'
action_spec = (_('Edit metadata'), 'edit_input.png', _('Change the title/author/cover etc. of books'), _('E')) action_spec = (_('Edit metadata'), 'edit_input.png', _('Change the title/author/cover etc. of books'), _('E'))
action_type = 'current' action_type = 'current'
action_add_menu = True action_add_menu = True
accepts_drops = True
def accept_enter_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def accept_drag_move_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def drop_event(self, event, mime_data):
mime = 'application/calibre+from_library'
if mime_data.hasFormat(mime):
self.dropped_ids = tuple(map(int, mime_data.data(mime).data().split()))
QTimer.singleShot(1, self.do_drop)
return True
return False
def do_drop(self): def do_drop(self):
book_ids = self.dropped_ids book_ids = self.dropped_ids
del self.dropped_ids del self.dropped_ids

View File

@ -9,11 +9,11 @@ from qt.core import QProgressDialog, Qt, QTimer
from calibre import force_unicode from calibre import force_unicode
from calibre.gui2 import gprefs from calibre.gui2 import gprefs
from calibre.gui2.actions import InterfaceAction from calibre.gui2.actions import InterfaceActionWithLibraryDrop
from calibre.utils.localization import ngettext from calibre.utils.localization import ngettext
class EmbedAction(InterfaceAction): class EmbedAction(InterfaceActionWithLibraryDrop):
name = 'Embed Metadata' name = 'Embed Metadata'
action_spec = (_('Embed metadata'), 'modified.png', _('Embed metadata into book files'), None) action_spec = (_('Embed metadata'), 'modified.png', _('Embed metadata into book files'), None)
@ -21,26 +21,6 @@ class EmbedAction(InterfaceAction):
action_add_menu = True action_add_menu = True
action_menu_clone_qaction = _('Embed metadata into book files') action_menu_clone_qaction = _('Embed metadata into book files')
accepts_drops = True
def accept_enter_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def accept_drag_move_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def drop_event(self, event, mime_data):
mime = 'application/calibre+from_library'
if mime_data.hasFormat(mime):
self.dropped_ids = tuple(map(int, mime_data.data(mime).data().split()))
QTimer.singleShot(1, self.do_drop)
return True
return False
def do_drop(self): def do_drop(self):
book_ids = self.dropped_ids book_ids = self.dropped_ids
del self.dropped_ids del self.dropped_ids

View File

@ -7,11 +7,11 @@ __copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
from functools import partial from functools import partial
from qt.core import ( from qt.core import (
QApplication, QDialog, QDialogButtonBox, QEvent, QGridLayout, QIcon, QLabel, QMenu, QApplication, QDialog, QDialogButtonBox, QEvent, QGridLayout, QIcon, QLabel, QMenu,
QPushButton, Qt, QTimer, QPushButton, Qt,
) )
from calibre.gui2 import error_dialog from calibre.gui2 import error_dialog
from calibre.gui2.actions import InterfaceAction from calibre.gui2.actions import InterfaceActionWithLibraryDrop
from calibre.gui2.widgets2 import HistoryComboBox from calibre.gui2.widgets2 import HistoryComboBox
from calibre.startup import connect_lambda from calibre.startup import connect_lambda
from calibre.utils.icu import sort_key from calibre.utils.icu import sort_key
@ -81,7 +81,7 @@ class MarkWithTextDialog(QDialog):
mark_books_with_text = None mark_books_with_text = None
class MarkBooksAction(InterfaceAction): class MarkBooksAction(InterfaceActionWithLibraryDrop):
name = 'Mark Books' name = 'Mark Books'
action_spec = (_('Mark books'), 'marked.png', _('Temporarily mark books for easy access'), 'Ctrl+M') action_spec = (_('Mark books'), 'marked.png', _('Temporarily mark books for easy access'), 'Ctrl+M')
@ -91,26 +91,6 @@ class MarkBooksAction(InterfaceAction):
'context-menu-device', 'menubar-device', 'context-menu-cover-browser']) 'context-menu-device', 'menubar-device', 'context-menu-cover-browser'])
action_menu_clone_qaction = _('Toggle mark for selected books') action_menu_clone_qaction = _('Toggle mark for selected books')
accepts_drops = True
def accept_enter_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def accept_drag_move_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def drop_event(self, event, mime_data):
mime = 'application/calibre+from_library'
if mime_data.hasFormat(mime):
self.dropped_ids = tuple(map(int, mime_data.data(mime).data().split()))
QTimer.singleShot(1, self.do_drop)
return True
return False
def do_drop(self): def do_drop(self):
book_ids = self.dropped_ids book_ids = self.dropped_ids
del self.dropped_ids del self.dropped_ids

View File

@ -18,7 +18,7 @@ from qt.core import (
) )
from calibre.gui2 import Dispatcher, error_dialog, gprefs, question_dialog from calibre.gui2 import Dispatcher, error_dialog, gprefs, question_dialog
from calibre.gui2.actions import InterfaceAction from calibre.gui2.actions import InterfaceActionWithLibraryDrop
from calibre.gui2.convert.metadata import create_opf_file from calibre.gui2.convert.metadata import create_opf_file
from calibre.gui2.dialogs.progress import ProgressDialog from calibre.gui2.dialogs.progress import ProgressDialog
from calibre.ptempfile import PersistentTemporaryDirectory from calibre.ptempfile import PersistentTemporaryDirectory
@ -409,32 +409,13 @@ class Report(QDialog): # {{{
# }}} # }}}
class PolishAction(InterfaceAction): class PolishAction(InterfaceActionWithLibraryDrop):
name = 'Polish Books' name = 'Polish Books'
action_spec = (_('Polish books'), 'polish.png', action_spec = (_('Polish books'), 'polish.png',
_('Apply the shine of perfection to your books'), _('P')) _('Apply the shine of perfection to your books'), _('P'))
dont_add_to = frozenset(['context-menu-device']) dont_add_to = frozenset(['context-menu-device'])
action_type = 'current' action_type = 'current'
accepts_drops = True
def accept_enter_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def accept_drag_move_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def drop_event(self, event, mime_data):
mime = 'application/calibre+from_library'
if mime_data.hasFormat(mime):
self.dropped_ids = tuple(map(int, mime_data.data(mime).data().split()))
QTimer.singleShot(1, self.do_drop)
return True
return False
def do_drop(self): def do_drop(self):
book_id_map = self.get_supported_books(self.dropped_ids) book_id_map = self.get_supported_books(self.dropped_ids)

View File

@ -13,7 +13,7 @@ from qt.core import (
) )
from calibre.gui2 import error_dialog, gprefs, question_dialog from calibre.gui2 import error_dialog, gprefs, question_dialog
from calibre.gui2.actions import InterfaceAction from calibre.gui2.actions import InterfaceActionWithLibraryDrop
from calibre.startup import connect_lambda from calibre.startup import connect_lambda
from calibre.utils.monotonic import monotonic from calibre.utils.monotonic import monotonic
from polyglot.builtins import iteritems from polyglot.builtins import iteritems
@ -68,32 +68,13 @@ class ChooseFormat(QDialog): # {{{
# }}} # }}}
class ToCEditAction(InterfaceAction): class ToCEditAction(InterfaceActionWithLibraryDrop):
name = 'Edit ToC' name = 'Edit ToC'
action_spec = (_('Edit ToC'), 'toc.png', action_spec = (_('Edit ToC'), 'toc.png',
_('Edit the Table of Contents in your books'), _('K')) _('Edit the Table of Contents in your books'), _('K'))
dont_add_to = frozenset(['context-menu-device']) dont_add_to = frozenset(['context-menu-device'])
action_type = 'current' action_type = 'current'
accepts_drops = True
def accept_enter_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def accept_drag_move_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def drop_event(self, event, mime_data):
mime = 'application/calibre+from_library'
if mime_data.hasFormat(mime):
self.dropped_ids = tuple(map(int, mime_data.data(mime).data().split()))
QTimer.singleShot(1, self.do_drop)
return True
return False
def do_drop(self): def do_drop(self):
book_id_map = self.get_supported_books(self.dropped_ids) book_id_map = self.get_supported_books(self.dropped_ids)

View File

@ -7,11 +7,11 @@ __docformat__ = 'restructuredtext en'
import time import time
from qt.core import ( from qt.core import (
QCheckBox, QDialog, QDialogButtonBox, QLabel, Qt, QTimer, QVBoxLayout, QCheckBox, QDialog, QDialogButtonBox, QLabel, Qt, QVBoxLayout,
) )
from calibre.gui2 import error_dialog, question_dialog from calibre.gui2 import error_dialog, question_dialog
from calibre.gui2.actions import InterfaceAction from calibre.gui2.actions import InterfaceActionWithLibraryDrop
from calibre.startup import connect_lambda from calibre.startup import connect_lambda
@ -54,33 +54,13 @@ class Choose(QDialog):
QDialog.accept(self) QDialog.accept(self)
class TweakEpubAction(InterfaceAction): class TweakEpubAction(InterfaceActionWithLibraryDrop):
name = 'Tweak ePub' name = 'Tweak ePub'
action_spec = (_('Edit book'), 'edit_book.png', _('Edit books in the EPUB or AZW formats'), _('T')) action_spec = (_('Edit book'), 'edit_book.png', _('Edit books in the EPUB or AZW formats'), _('T'))
dont_add_to = frozenset(('context-menu-device',)) dont_add_to = frozenset(('context-menu-device',))
action_type = 'current' action_type = 'current'
accepts_drops = True
def accept_enter_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def accept_drag_move_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def drop_event(self, event, mime_data):
mime = 'application/calibre+from_library'
if mime_data.hasFormat(mime):
self.dropped_ids = tuple(map(int, mime_data.data(mime).data().split()))
QTimer.singleShot(1, self.do_drop)
return True
return False
def do_drop(self): def do_drop(self):
book_ids = self.dropped_ids book_ids = self.dropped_ids
del self.dropped_ids del self.dropped_ids

View File

@ -5,17 +5,19 @@ __license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import os, weakref, shutil import os
import shutil
from qt.core import (QDialog, QVBoxLayout, QHBoxLayout, QRadioButton, QFrame, import weakref
QPushButton, QLabel, QGroupBox, QGridLayout, QIcon, QSize, QTimer) from qt.core import (
QDialog, QFrame, QGridLayout, QGroupBox, QHBoxLayout, QIcon, QLabel, QPushButton,
QRadioButton, QSize, QTimer, QVBoxLayout,
)
from calibre import as_unicode from calibre import as_unicode
from calibre.constants import ismacos from calibre.constants import ismacos
from calibre.gui2 import error_dialog, question_dialog, open_local_file, gprefs from calibre.gui2 import error_dialog, gprefs, open_local_file, question_dialog
from calibre.gui2.actions import InterfaceAction from calibre.gui2.actions import InterfaceActionWithLibraryDrop
from calibre.ptempfile import (PersistentTemporaryDirectory, from calibre.ptempfile import PersistentTemporaryDirectory, PersistentTemporaryFile
PersistentTemporaryFile)
from calibre.utils.config import prefs, tweaks from calibre.utils.config import prefs, tweaks
@ -163,7 +165,7 @@ class UnpackBook(QDialog):
return question_dialog(self, _('Are you sure?'), msg) return question_dialog(self, _('Are you sure?'), msg)
def do_explode(self): def do_explode(self):
from calibre.ebooks.tweak import get_tools, Error, WorkerError from calibre.ebooks.tweak import Error, WorkerError, get_tools
tdir = PersistentTemporaryDirectory('_tweak_explode') tdir = PersistentTemporaryDirectory('_tweak_explode')
self._cleanup_dirs.append(tdir) self._cleanup_dirs.append(tdir)
det_msg = None det_msg = None
@ -201,7 +203,7 @@ class UnpackBook(QDialog):
open_local_file(tdir) open_local_file(tdir)
def rebuild_it(self): def rebuild_it(self):
from calibre.ebooks.tweak import get_tools, WorkerError from calibre.ebooks.tweak import WorkerError, get_tools
src_dir = self._exploded src_dir = self._exploded
det_msg = None det_msg = None
of = PersistentTemporaryFile('_tweak_rebuild.'+self.current_format.lower()) of = PersistentTemporaryFile('_tweak_rebuild.'+self.current_format.lower())
@ -284,7 +286,7 @@ class UnpackBook(QDialog):
return str(b.text()) return str(b.text())
class UnpackBookAction(InterfaceAction): class UnpackBookAction(InterfaceActionWithLibraryDrop):
name = 'Unpack Book' name = 'Unpack Book'
action_spec = (_('Unpack book'), 'unpack-book.png', action_spec = (_('Unpack book'), 'unpack-book.png',
@ -292,26 +294,6 @@ class UnpackBookAction(InterfaceAction):
dont_add_to = frozenset(['context-menu-device']) dont_add_to = frozenset(['context-menu-device'])
action_type = 'current' action_type = 'current'
accepts_drops = True
def accept_enter_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def accept_drag_move_event(self, event, mime_data):
if mime_data.hasFormat("application/calibre+from_library"):
return True
return False
def drop_event(self, event, mime_data):
mime = 'application/calibre+from_library'
if mime_data.hasFormat(mime):
self.dropped_ids = tuple(map(int, mime_data.data(mime).data().split()))
QTimer.singleShot(1, self.do_drop)
return True
return False
def do_drop(self): def do_drop(self):
book_ids = self.dropped_ids book_ids = self.dropped_ids
del self.dropped_ids del self.dropped_ids