diff --git a/src/calibre/devices/interface.py b/src/calibre/devices/interface.py
index f0c917d475..913c686f2e 100644
--- a/src/calibre/devices/interface.py
+++ b/src/calibre/devices/interface.py
@@ -8,6 +8,14 @@ from calibre.constants import iswindows
from calibre.customize import Plugin
+class OpenPopupMessage:
+
+ def __init__(self, title='', message='', level='info'):
+ self.title = title
+ self.message = message
+ self.level = level
+
+
class DevicePlugin(Plugin):
"""
Defines the interface that should be implemented by backends that
@@ -69,7 +77,7 @@ class DevicePlugin(Plugin):
# Encapsulates an annotation fetched from the device
UserAnnotation = namedtuple('Annotation','type, value')
- #: GUI displays this as a message if not None. Useful if opening can take a
+ #: GUI displays this as a message if not None in the status bar. Useful if opening can take a
#: long time
OPEN_FEEDBACK_MESSAGE = None
@@ -126,6 +134,11 @@ class DevicePlugin(Plugin):
return cls.__name__
return cls.name
+ @classmethod
+ def get_open_popup_message(self):
+ ' GUI displays this as a non-modal popup. Should be an instance of OpenPopupMessage '
+ return None
+
# Device detection {{{
def test_bcd(self, bcdDevice, bcd):
if bcd is None or len(bcd) == 0:
diff --git a/src/calibre/devices/kindle/driver.py b/src/calibre/devices/kindle/driver.py
index fe9e4f411f..65d69463e9 100644
--- a/src/calibre/devices/kindle/driver.py
+++ b/src/calibre/devices/kindle/driver.py
@@ -9,6 +9,7 @@ Device driver for Amazon's Kindle
import datetime, os, re, json, hashlib, errno
from calibre.constants import DEBUG, filesystem_encoding
+from calibre.devices.interface import OpenPopupMessage
from calibre.devices.kindle.bookmark import Bookmark
from calibre.devices.usbms.driver import USBMS
from calibre import strftime, fsync, prints
@@ -95,6 +96,18 @@ class KINDLE(USBMS):
' Click "Show details" to see the list of books.'
)
+ @classmethod
+ def get_open_popup_message(cls):
+ from calibre.utils.localization import localize_website_link
+ return OpenPopupMessage(title=_('WARNING: E-book covers'), message=_(
+ 'Amazon has broken display of covers for books sent to the Kindle by USB cable. To workaround it,'
+ ' you have to:
- Send the books to the Kindle
- Disconnect the Kindle and wait for the covers to be deleted'
+ ' by Amazon
- Reconnect the Kindle and calibre will restore the covers.
After this the'
+ ' covers for those books should stay put. Click here for details.').format(localize_website_link(
+ 'https://manual.calibre-ebook.com/faq.html#covers-for-books-i'
+ '-send-to-my-e-ink-kindle-show-up-momentarily-and-then-are-replaced-by-a-generic-cover')
+ ))
+
def is_allowed_book_file(self, filename, path, prefix):
lpath = os.path.join(path, filename).partition(self.normalize_path(prefix))[2].replace('\\', '/')
return '.sdr/' not in lpath
diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py
index b0f82747b6..ff9b92de0a 100644
--- a/src/calibre/gui2/device.py
+++ b/src/calibre/gui2/device.py
@@ -132,6 +132,37 @@ class BusyCursor:
QApplication.restoreOverrideCursor()
+def convert_open_popup(opm, skip_key):
+ class OPM(OpenFeedback):
+
+ def __init__(self, opm):
+ super().__init__('placeholder')
+ self.opm = opm
+ self.skip_key = skip_key
+
+ def custom_dialog(self, parent):
+ from calibre.gui2.dialogs.message_box import MessageBox
+
+ class M(MessageBox):
+ def on_cd_finished(s):
+ gprefs.set(self.skip_key, not s.toggle_checkbox.isChecked())
+ m = M({
+ 'info': MessageBox.INFO, 'information': MessageBox.INFO,
+ 'warn': MessageBox.WARNING, 'warning': MessageBox.WARNING,
+ }[self.opm.level], self.opm.title, self.opm.message,
+ parent=parent
+ )
+ tc = m.toggle_checkbox
+ tc.setVisible(True)
+ tc.setText(_('Show this message again'))
+ tc.setChecked(True)
+ m.resize_needed.emit()
+ m.finished.connect(m.on_cd_finished)
+ return m
+
+ return OPM(opm)
+
+
class DeviceManager(Thread): # {{{
def __init__(self, connected_slot, job_manager, open_feedback_slot,
@@ -191,6 +222,11 @@ class DeviceManager(Thread): # {{{
for dev, detected_device in connected_devices:
if dev.OPEN_FEEDBACK_MESSAGE is not None:
self.open_feedback_slot(dev.OPEN_FEEDBACK_MESSAGE)
+ opm = dev.get_open_popup_message()
+ if opm is not None:
+ skip_key = f'do_not_show_device_open_popup_message_{dev.__class__.__name__}'
+ if not gprefs.get(skip_key, False):
+ self.open_feedback_msg(dev.get_gui_name(), convert_open_popup(opm, skip_key))
try:
dev.reset(detected_device=detected_device,
report_progress=self.report_progress)