Add support for touch screens to the main calibre book list

You can now flick to scroll, tap to select and double-tap to view books.
This commit is contained in:
Kovid Goyal 2017-07-22 14:22:49 +05:30
parent 3eade1a5f2
commit 1be4482c66
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 62 additions and 3 deletions

View File

@ -15,16 +15,17 @@ from textwrap import wrap
from PyQt5.Qt import (
QListView, QSize, QStyledItemDelegate, QModelIndex, Qt, QImage, pyqtSignal,
QTimer, QPalette, QColor, QItemSelection, QPixmap, QApplication,
QTimer, QPalette, QColor, QItemSelection, QPixmap, QApplication, QScroller,
QMimeData, QUrl, QDrag, QPoint, QPainter, QRect, pyqtProperty, QEvent,
QPropertyAnimation, QEasingCurve, pyqtSlot, QHelpEvent, QAbstractItemView,
QStyleOptionViewItem, QToolTip, QByteArray, QBuffer, QBrush, qRed, qGreen,
qBlue, QItemSelectionModel, QIcon, QFont)
qBlue, QItemSelectionModel, QIcon, QFont, QMouseEvent)
from calibre import fit_image, prints, prepare_string_for_xml, human_readable
from calibre.constants import DEBUG, config_dir, islinux
from calibre.ebooks.metadata import fmt_sidx, rating_to_stars
from calibre.utils import join_with_timeout
from calibre.utils.monotonic import monotonic
from calibre.gui2 import gprefs, config, rating_font, empty_index
from calibre.gui2.library.caches import CoverCache, ThumbnailCache
from calibre.utils.config import prefs, tweaks
@ -624,6 +625,53 @@ class CoverDelegate(QStyledItemDelegate):
# }}}
def send_click(view, pos, button=Qt.LeftButton, double_click=False):
if double_click:
ev = QMouseEvent(QEvent.MouseButtonDblClick, pos, button, button, QApplication.keyboardModifiers())
QApplication.postEvent(view.viewport(), ev)
return
ev = QMouseEvent(QEvent.MouseButtonPress, pos, button, button, QApplication.keyboardModifiers())
QApplication.postEvent(view.viewport(), ev)
ev = QMouseEvent(QEvent.MouseButtonRelease, pos, button, button, QApplication.keyboardModifiers())
QApplication.postEvent(view.viewport(), ev)
def handle_gesture(ev, view):
tap = ev.gesture(Qt.TapGesture)
if tap and tap.state() == Qt.GestureFinished:
p, view.last_tap_at = view.last_tap_at, monotonic()
interval = QApplication.instance().doubleClickInterval() / 1000
double_click = monotonic() - p < interval
send_click(view, tap.position(), double_click=double_click)
ev.accept(Qt.TapGesture)
return True
th = ev.gesture(Qt.TapAndHoldGesture)
if th and th.state() in (Qt.GestureStarted, Qt.GestureUpdated, Qt.GestureFinished):
send_click(view, th.position(), button=Qt.RightButton)
ev.accept(Qt.TapAndHoldGesture)
return True
return True
def setup_gestures(view):
v = view.viewport()
view.scroller = QScroller.grabGesture(v, QScroller.TouchGesture)
v.grabGesture(Qt.TapGesture)
v.grabGesture(Qt.TapAndHoldGesture)
view.last_tap_at = 0
def gesture_viewport_event(view, ev):
et = ev.type()
if et in (QEvent.MouseButtonPress, QEvent.MouseMove, QEvent.MouseButtonRelease, QEvent.MouseButtonDblClick):
if ev.source() in (Qt.MouseEventSynthesizedBySystem, Qt.MouseEventSynthesizedByQt):
ev.ignore()
return False
elif et == QEvent.Gesture:
return handle_gesture(ev, view)
# The View {{{
@ -635,6 +683,7 @@ class GridView(QListView):
def __init__(self, parent):
QListView.__init__(self, parent)
setup_gestures(self)
setup_dnd_interface(self)
self.setUniformItemSizes(True)
self.setWrapping(True)
@ -670,6 +719,12 @@ class GridView(QListView):
t.setInterval(200), t.setSingleShot(True)
t.timeout.connect(self.update_memory_cover_cache_size)
def viewportEvent(self, ev):
ret = gesture_viewport_event(self, ev)
if ret is not None:
return ret
return QListView.viewportEvent(self, ev)
@property
def device_pixel_ratio(self):
try:

View File

@ -21,7 +21,7 @@ from calibre.gui2.library.delegates import (RatingDelegate, PubDateDelegate,
CcBoolDelegate, CcCommentsDelegate, CcDateDelegate, CcTemplateDelegate,
CcEnumDelegate, CcNumberDelegate, LanguagesDelegate)
from calibre.gui2.library.models import BooksModel, DeviceBooksModel
from calibre.gui2.library.alternate_views import AlternateViews, setup_dnd_interface
from calibre.gui2.library.alternate_views import AlternateViews, setup_dnd_interface, setup_gestures, gesture_viewport_event
from calibre.utils.config import tweaks, prefs
from calibre.gui2 import error_dialog, gprefs, FunctionDispatcher
from calibre.gui2.library import DEFAULT_SORT
@ -193,10 +193,14 @@ class BooksView(QTableView): # {{{
def viewportEvent(self, event):
if (event.type() == event.ToolTip and not gprefs['book_list_tooltips']):
return False
ret = gesture_viewport_event(self, event)
if ret is not None:
return ret
return QTableView.viewportEvent(self, event)
def __init__(self, parent, modelcls=BooksModel, use_edit_metadata_dialog=True):
QTableView.__init__(self, parent)
setup_gestures(self)
self.default_row_height = self.verticalHeader().defaultSectionSize()
self.gui = parent
self.setProperty('highlight_current_item', 150)