mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Implement Tap And Hold
This commit is contained in:
parent
72119dd2d4
commit
0c565d7fbe
@ -172,3 +172,21 @@ void set_no_activate_on_click(QWidget *widget) {
|
||||
widget->setStyle(new NoActivateStyle);
|
||||
}
|
||||
|
||||
class TouchMenuStyle: public QProxyStyle {
|
||||
private:
|
||||
int extra_margin;
|
||||
|
||||
public:
|
||||
TouchMenuStyle(int margin) : extra_margin(margin) {}
|
||||
QSize sizeFromContents ( ContentsType type, const QStyleOption * option, const QSize & contentsSize, const QWidget * widget = 0 ) const {
|
||||
QSize ans = QProxyStyle::sizeFromContents(type, option, contentsSize, widget);
|
||||
if (type == QStyle::CT_MenuItem) {
|
||||
ans.setHeight(ans.height() + extra_margin); // Make the menu items more easily touchable
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
};
|
||||
|
||||
void set_touch_menu_style(QWidget *widget, int margin) {
|
||||
widget->setStyle(new TouchMenuStyle(margin));
|
||||
}
|
||||
|
@ -103,3 +103,4 @@ int load_style(QString &path, QString &name);
|
||||
bool do_notify(QObject *receiver, QEvent *event);
|
||||
|
||||
void set_no_activate_on_click(QWidget *widget);
|
||||
void set_touch_menu_style(QWidget *widget, int margin=20);
|
||||
|
@ -10,6 +10,7 @@
|
||||
int load_style(QString &path, QString &name);
|
||||
bool do_notify(QObject *receiver, QEvent *event);
|
||||
void set_no_activate_on_click(QWidget *widget);
|
||||
void set_touch_menu_style(QWidget *widget, int margin);
|
||||
%End
|
||||
|
||||
class QProgressIndicator : QWidget {
|
||||
@ -62,3 +63,4 @@ int load_style(QString &path, QString &name);
|
||||
bool do_notify(QObject *receiver, QEvent *event);
|
||||
|
||||
void set_no_activate_on_click(QWidget *widget);
|
||||
void set_touch_menu_style(QWidget *widget, int margin=20);
|
||||
|
@ -705,6 +705,16 @@ class DocumentView(QWebView): # {{{
|
||||
|
||||
for plugin in self.document.all_viewer_plugins:
|
||||
plugin.customize_context_menu(menu, ev, r)
|
||||
if ev.reason() == ev.Other:
|
||||
# Triggered by a touch event
|
||||
from calibre.constants import plugins
|
||||
pi = plugins['progress_indicator'][0]
|
||||
for x in (menu, self.goto_location_menu):
|
||||
if hasattr(pi, 'set_touch_menu_style'):
|
||||
pi.set_touch_menu_style(x)
|
||||
else:
|
||||
self.goto_location_menu.setStyle(self.style())
|
||||
self.context_menu = menu
|
||||
menu.exec_(ev.globalPos())
|
||||
|
||||
def inspect(self):
|
||||
|
@ -7,7 +7,10 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
import time, ctypes, sys
|
||||
from PyQt4.Qt import QObject, QPointF, pyqtSignal, QEvent, QApplication
|
||||
from functools import partial
|
||||
from PyQt4.Qt import (
|
||||
QObject, QPointF, pyqtSignal, QEvent, QApplication, QMouseEvent, Qt,
|
||||
QContextMenuEvent)
|
||||
|
||||
from calibre.constants import iswindows
|
||||
|
||||
@ -64,10 +67,12 @@ class State(QObject):
|
||||
|
||||
tapped = pyqtSignal(object)
|
||||
swiped = pyqtSignal(object)
|
||||
tap_hold_started = pyqtSignal(object)
|
||||
tap_hold_updated = pyqtSignal(object)
|
||||
swipe_hold_started = pyqtSignal(object)
|
||||
swipe_hold_updated = pyqtSignal(object)
|
||||
tap_and_hold_finished = pyqtSignal(object)
|
||||
swipe_and_hold_finished = pyqtSignal(object)
|
||||
tap_hold_finished = pyqtSignal(object)
|
||||
swipe_hold_finished = pyqtSignal(object)
|
||||
|
||||
def __init__(self):
|
||||
QObject.__init__(self)
|
||||
@ -127,10 +132,12 @@ class State(QObject):
|
||||
self.hold_started = True
|
||||
self.possible_gestures = {SwipeAndHold}
|
||||
self.hold_data = (now, st)
|
||||
self.swipe_hold_started.emit(tp)
|
||||
else:
|
||||
self.possible_gestures = {TapAndHold}
|
||||
self.hold_started = True
|
||||
self.hold_data = now
|
||||
self.tap_hold_started.emit(tp)
|
||||
|
||||
def finalize(self):
|
||||
if Tap in self.possible_gestures:
|
||||
@ -151,11 +158,11 @@ class State(QObject):
|
||||
|
||||
if TapAndHold in self.possible_gestures:
|
||||
tp = next(self.touch_points.itervalues())
|
||||
self.tap_and_hold_finished.emit(tp)
|
||||
self.tap_hold_finished.emit(tp)
|
||||
return
|
||||
|
||||
if SwipeAndHold in self.possible_gestures:
|
||||
self.swipe_and_hold_finished.emit(self.hold_data[1])
|
||||
self.swipe_hold_finished.emit(self.hold_data[1])
|
||||
return
|
||||
|
||||
|
||||
@ -166,6 +173,9 @@ class GestureHandler(QObject):
|
||||
self.state = State()
|
||||
self.state.swiped.connect(self.handle_swipe)
|
||||
self.state.tapped.connect(self.handle_tap)
|
||||
self.state.tap_hold_started.connect(partial(self.handle_tap_hold, 'start'))
|
||||
self.state.tap_hold_updated.connect(partial(self.handle_tap_hold, 'update'))
|
||||
self.state.tap_hold_finished.connect(partial(self.handle_tap_hold, 'end'))
|
||||
self.evmap = {QEvent.TouchBegin: 'start', QEvent.TouchUpdate: 'update', QEvent.TouchEnd: 'end'}
|
||||
|
||||
# Ignore fake mouse events generated by the window system from touch
|
||||
@ -216,13 +226,33 @@ class GestureHandler(QObject):
|
||||
ev.accept()
|
||||
return True
|
||||
|
||||
def close_open_menu(self):
|
||||
m = getattr(self.parent(), 'context_menu', None)
|
||||
if m is not None and m.isVisible():
|
||||
m.close()
|
||||
return True
|
||||
|
||||
def handle_swipe(self, direction):
|
||||
if self.close_open_menu():
|
||||
return
|
||||
view = self.parent()
|
||||
func = {Left:'next_page', Right: 'previous_page', Up:'goto_previous_section', Down:'goto_next_section'}[direction]
|
||||
getattr(view, func)()
|
||||
|
||||
def handle_tap(self, tp):
|
||||
if self.close_open_menu():
|
||||
return
|
||||
view = self.parent()
|
||||
threshold = view.width() / 3.0
|
||||
attr = 'previous' if tp.start_position.x() <= threshold else 'next'
|
||||
getattr(view, '%s_page'%attr)()
|
||||
|
||||
def handle_tap_hold(self, action, tp):
|
||||
etype = {'start':QEvent.MouseButtonPress, 'update':QEvent.MouseMove, 'end':QEvent.MouseButtonRelease}[action]
|
||||
ev = QMouseEvent(etype, tp.current_position.toPoint(), tp.current_screen_position.toPoint(), Qt.LeftButton, Qt.LeftButton, Qt.NoModifier)
|
||||
QApplication.sendEvent(self.parent(), ev)
|
||||
if action == 'end':
|
||||
ev = QContextMenuEvent(QContextMenuEvent.Other, tp.current_position.toPoint(), tp.current_screen_position.toPoint())
|
||||
# We have to use post event otherwise the popup remains an alien widget and does not receive events
|
||||
QApplication.postEvent(self.parent(), ev)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user