mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Add framework for allowing interface actions to accept drag and drop events. Apple driver: Fix bug preventing sending books to iBooks if no books have been previously added to iBooks. Fixes #1141078 ('NoneType' object is not iterable)
This commit is contained in:
commit
7e004def33
@ -672,6 +672,7 @@ Some limitations of PDF input are:
|
|||||||
* Links and Tables of Contents are not supported
|
* Links and Tables of Contents are not supported
|
||||||
* PDFs that use embedded non-unicode fonts to represent non-English characters will result in garbled output for those characters
|
* PDFs that use embedded non-unicode fonts to represent non-English characters will result in garbled output for those characters
|
||||||
* Some PDFs are made up of photographs of the page with OCRed text behind them. In such cases |app| uses the OCRed text, which can be very different from what you see when you view the PDF file
|
* Some PDFs are made up of photographs of the page with OCRed text behind them. In such cases |app| uses the OCRed text, which can be very different from what you see when you view the PDF file
|
||||||
|
* PDFs that are used to display complex text, like right to left languages and math typesetting will not convert correctly
|
||||||
|
|
||||||
To re-iterate **PDF is a really, really bad** format to use as input. If you absolutely must use PDF, then be prepared for an
|
To re-iterate **PDF is a really, really bad** format to use as input. If you absolutely must use PDF, then be prepared for an
|
||||||
output ranging anywhere from decent to unusable, depending on the input PDF.
|
output ranging anywhere from decent to unusable, depending on the input PDF.
|
||||||
|
@ -30,11 +30,6 @@ class tvn24(BasicNewsRecipe):
|
|||||||
feeds = [(u'Najnowsze', u'http://www.tvn24.pl/najnowsze.xml'), ]
|
feeds = [(u'Najnowsze', u'http://www.tvn24.pl/najnowsze.xml'), ]
|
||||||
#(u'Polska', u'www.tvn24.pl/polska.xml'), (u'\u015awiat', u'http://www.tvn24.pl/swiat.xml'), (u'Sport', u'http://www.tvn24.pl/sport.xml'), (u'Biznes', u'http://www.tvn24.pl/biznes.xml'), (u'Meteo', u'http://www.tvn24.pl/meteo.xml'), (u'Micha\u0142ki', u'http://www.tvn24.pl/michalki.xml'), (u'Kultura', u'http://www.tvn24.pl/kultura.xml')]
|
#(u'Polska', u'www.tvn24.pl/polska.xml'), (u'\u015awiat', u'http://www.tvn24.pl/swiat.xml'), (u'Sport', u'http://www.tvn24.pl/sport.xml'), (u'Biznes', u'http://www.tvn24.pl/biznes.xml'), (u'Meteo', u'http://www.tvn24.pl/meteo.xml'), (u'Micha\u0142ki', u'http://www.tvn24.pl/michalki.xml'), (u'Kultura', u'http://www.tvn24.pl/kultura.xml')]
|
||||||
|
|
||||||
def preprocess_html(self, soup):
|
|
||||||
for item in soup.findAll(style=True):
|
|
||||||
del item['style']
|
|
||||||
return soup
|
|
||||||
|
|
||||||
def preprocess_html(self, soup):
|
def preprocess_html(self, soup):
|
||||||
for alink in soup.findAll('a'):
|
for alink in soup.findAll('a'):
|
||||||
if alink.string is not None:
|
if alink.string is not None:
|
||||||
|
@ -21,7 +21,6 @@ from calibre.utils.config import config_dir, dynamic, prefs
|
|||||||
from calibre.utils.date import now, parse_date
|
from calibre.utils.date import now, parse_date
|
||||||
from calibre.utils.zipfile import ZipFile
|
from calibre.utils.zipfile import ZipFile
|
||||||
|
|
||||||
# DEBUG = False
|
|
||||||
DEBUG = CALIBRE_DEBUG
|
DEBUG = CALIBRE_DEBUG
|
||||||
|
|
||||||
def strftime(fmt='%Y/%m/%d %H:%M:%S', dt=None):
|
def strftime(fmt='%Y/%m/%d %H:%M:%S', dt=None):
|
||||||
@ -861,7 +860,6 @@ class ITUNES(DriverBase):
|
|||||||
Note that most of the initialization is necessarily performed in can_handle(), as
|
Note that most of the initialization is necessarily performed in can_handle(), as
|
||||||
we need to talk to iTunes to discover if there's a connected iPod
|
we need to talk to iTunes to discover if there's a connected iPod
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if self.iTunes is None:
|
if self.iTunes is None:
|
||||||
raise OpenFeedback(self.ITUNES_SANDBOX_LOCKOUT_MESSAGE)
|
raise OpenFeedback(self.ITUNES_SANDBOX_LOCKOUT_MESSAGE)
|
||||||
|
|
||||||
@ -2156,6 +2154,7 @@ class ITUNES(DriverBase):
|
|||||||
if 'iPod' in self.sources:
|
if 'iPod' in self.sources:
|
||||||
connected_device = self.sources['iPod']
|
connected_device = self.sources['iPod']
|
||||||
device = self.iTunes.sources[connected_device]
|
device = self.iTunes.sources[connected_device]
|
||||||
|
if device.playlists() is not None:
|
||||||
dev_books = None
|
dev_books = None
|
||||||
for pl in device.playlists():
|
for pl in device.playlists():
|
||||||
if pl.special_kind() == appscript.k.Books:
|
if pl.special_kind() == appscript.k.Books:
|
||||||
@ -2186,7 +2185,7 @@ class ITUNES(DriverBase):
|
|||||||
pythoncom.CoInitialize()
|
pythoncom.CoInitialize()
|
||||||
connected_device = self.sources['iPod']
|
connected_device = self.sources['iPod']
|
||||||
device = self.iTunes.sources.ItemByName(connected_device)
|
device = self.iTunes.sources.ItemByName(connected_device)
|
||||||
|
if device.Playlists is not None:
|
||||||
dev_books = None
|
dev_books = None
|
||||||
for pl in device.Playlists:
|
for pl in device.Playlists:
|
||||||
if pl.Kind == self.PlaylistKind.index('User') and \
|
if pl.Kind == self.PlaylistKind.index('User') and \
|
||||||
|
@ -101,6 +101,11 @@ class InterfaceAction(QObject):
|
|||||||
#: on calibre as a whole
|
#: on calibre as a whole
|
||||||
action_type = 'global'
|
action_type = 'global'
|
||||||
|
|
||||||
|
#: If True, then this InterfaceAction will have the opportunity to interact
|
||||||
|
#: with drag and drop events. See the methods, :meth:`accept_enter_event`,
|
||||||
|
#: :meth`:accept_drag_move_event`, :meth:`drop_event` for details.
|
||||||
|
accepts_drops = False
|
||||||
|
|
||||||
def __init__(self, parent, site_customization):
|
def __init__(self, parent, site_customization):
|
||||||
QObject.__init__(self, parent)
|
QObject.__init__(self, parent)
|
||||||
self.setObjectName(self.name)
|
self.setObjectName(self.name)
|
||||||
@ -108,6 +113,21 @@ class InterfaceAction(QObject):
|
|||||||
self.site_customization = site_customization
|
self.site_customization = site_customization
|
||||||
self.interface_action_base_plugin = None
|
self.interface_action_base_plugin = None
|
||||||
|
|
||||||
|
def accept_enter_event(self, event, mime_data):
|
||||||
|
''' This method should return True iff this interface action is capable
|
||||||
|
of handling the drag event. '''
|
||||||
|
return False
|
||||||
|
|
||||||
|
def accept_drag_move_event(self, event, mime_data):
|
||||||
|
''' This method should return True iff this interface action is capable
|
||||||
|
of handling the drag event. '''
|
||||||
|
return False
|
||||||
|
|
||||||
|
def drop_event(self, event, mime_data):
|
||||||
|
''' This method should perform some useful action and return True
|
||||||
|
iff this interface action is capable of handling the drag event. '''
|
||||||
|
return False
|
||||||
|
|
||||||
def do_genesis(self):
|
def do_genesis(self):
|
||||||
self.Dispatcher = partial(Dispatcher, parent=self)
|
self.Dispatcher = partial(Dispatcher, parent=self)
|
||||||
self.create_action()
|
self.create_action()
|
||||||
|
@ -8,8 +8,8 @@ __copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
|
|||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
|
||||||
from PyQt4.Qt import (QObject, QToolBar, Qt, QSize, QToolButton, QVBoxLayout,
|
from PyQt4.Qt import (Qt, QAction, QLabel, QMenu, QMenuBar, QObject,
|
||||||
QLabel, QWidget, QAction, QMenuBar, QMenu)
|
QToolBar, QToolButton, QSize, QVBoxLayout, QWidget)
|
||||||
|
|
||||||
from calibre.constants import isosx
|
from calibre.constants import isosx
|
||||||
from calibre.gui2 import gprefs
|
from calibre.gui2 import gprefs
|
||||||
@ -116,13 +116,30 @@ class ToolBar(QToolBar): # {{{
|
|||||||
ch.setPopupMode(menu_mode)
|
ch.setPopupMode(menu_mode)
|
||||||
return ch
|
return ch
|
||||||
|
|
||||||
#support drag&drop from/to library from/to reader/card
|
# support drag&drop from/to library, from/to reader/card, enabled plugins
|
||||||
|
def check_iactions_for_drag(self, event, md, func):
|
||||||
|
if self.added_actions:
|
||||||
|
pos = event.pos()
|
||||||
|
for iac in self.gui.iactions.itervalues():
|
||||||
|
if iac.accepts_drops:
|
||||||
|
aa = iac.qaction
|
||||||
|
w = self.widgetForAction(aa)
|
||||||
|
func = getattr(iac, func)
|
||||||
|
if (( (w is not None and w.geometry().contains(pos)) or
|
||||||
|
aa.menu().geometry().contains(pos)) and func(event, md)):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def dragEnterEvent(self, event):
|
def dragEnterEvent(self, event):
|
||||||
md = event.mimeData()
|
md = event.mimeData()
|
||||||
if md.hasFormat("application/calibre+from_library") or \
|
if md.hasFormat("application/calibre+from_library") or \
|
||||||
md.hasFormat("application/calibre+from_device"):
|
md.hasFormat("application/calibre+from_device"):
|
||||||
event.setDropAction(Qt.CopyAction)
|
event.setDropAction(Qt.CopyAction)
|
||||||
event.accept()
|
event.accept()
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.check_iactions_for_drag(event, md, 'accept_enter_event'):
|
||||||
|
event.accept()
|
||||||
else:
|
else:
|
||||||
event.ignore()
|
event.ignore()
|
||||||
|
|
||||||
@ -141,12 +158,15 @@ class ToolBar(QToolBar): # {{{
|
|||||||
break
|
break
|
||||||
if allowed:
|
if allowed:
|
||||||
event.acceptProposedAction()
|
event.acceptProposedAction()
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.check_iactions_for_drag(event, md, 'accept_drag_move_event'):
|
||||||
|
event.acceptProposedAction()
|
||||||
else:
|
else:
|
||||||
event.ignore()
|
event.ignore()
|
||||||
|
|
||||||
def dropEvent(self, event):
|
def dropEvent(self, event):
|
||||||
data = event.mimeData()
|
data = event.mimeData()
|
||||||
|
|
||||||
mime = 'application/calibre+from_library'
|
mime = 'application/calibre+from_library'
|
||||||
if data.hasFormat(mime):
|
if data.hasFormat(mime):
|
||||||
ids = list(map(int, str(data.data(mime)).split()))
|
ids = list(map(int, str(data.data(mime)).split()))
|
||||||
@ -160,6 +180,7 @@ class ToolBar(QToolBar): # {{{
|
|||||||
tgt = None
|
tgt = None
|
||||||
self.gui.sync_to_device(tgt, False, send_ids=ids)
|
self.gui.sync_to_device(tgt, False, send_ids=ids)
|
||||||
event.accept()
|
event.accept()
|
||||||
|
return
|
||||||
|
|
||||||
mime = 'application/calibre+from_device'
|
mime = 'application/calibre+from_device'
|
||||||
if data.hasFormat(mime):
|
if data.hasFormat(mime):
|
||||||
@ -168,6 +189,13 @@ class ToolBar(QToolBar): # {{{
|
|||||||
self.gui.iactions['Add Books'].add_books_from_device(
|
self.gui.iactions['Add Books'].add_books_from_device(
|
||||||
self.gui.current_view(), paths=paths)
|
self.gui.current_view(), paths=paths)
|
||||||
event.accept()
|
event.accept()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Give added_actions an opportunity to process the drag&drop event
|
||||||
|
if self.check_iactions_for_drag(event, data, 'drop_event'):
|
||||||
|
event.accept()
|
||||||
|
else:
|
||||||
|
event.ignore()
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user