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);
|
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);
|
bool do_notify(QObject *receiver, QEvent *event);
|
||||||
|
|
||||||
void set_no_activate_on_click(QWidget *widget);
|
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);
|
int load_style(QString &path, QString &name);
|
||||||
bool do_notify(QObject *receiver, QEvent *event);
|
bool do_notify(QObject *receiver, QEvent *event);
|
||||||
void set_no_activate_on_click(QWidget *widget);
|
void set_no_activate_on_click(QWidget *widget);
|
||||||
|
void set_touch_menu_style(QWidget *widget, int margin);
|
||||||
%End
|
%End
|
||||||
|
|
||||||
class QProgressIndicator : QWidget {
|
class QProgressIndicator : QWidget {
|
||||||
@ -62,3 +63,4 @@ int load_style(QString &path, QString &name);
|
|||||||
bool do_notify(QObject *receiver, QEvent *event);
|
bool do_notify(QObject *receiver, QEvent *event);
|
||||||
|
|
||||||
void set_no_activate_on_click(QWidget *widget);
|
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:
|
for plugin in self.document.all_viewer_plugins:
|
||||||
plugin.customize_context_menu(menu, ev, r)
|
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())
|
menu.exec_(ev.globalPos())
|
||||||
|
|
||||||
def inspect(self):
|
def inspect(self):
|
||||||
|
@ -7,7 +7,10 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
import time, ctypes, sys
|
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
|
from calibre.constants import iswindows
|
||||||
|
|
||||||
@ -64,10 +67,12 @@ class State(QObject):
|
|||||||
|
|
||||||
tapped = pyqtSignal(object)
|
tapped = pyqtSignal(object)
|
||||||
swiped = pyqtSignal(object)
|
swiped = pyqtSignal(object)
|
||||||
|
tap_hold_started = pyqtSignal(object)
|
||||||
tap_hold_updated = pyqtSignal(object)
|
tap_hold_updated = pyqtSignal(object)
|
||||||
|
swipe_hold_started = pyqtSignal(object)
|
||||||
swipe_hold_updated = pyqtSignal(object)
|
swipe_hold_updated = pyqtSignal(object)
|
||||||
tap_and_hold_finished = pyqtSignal(object)
|
tap_hold_finished = pyqtSignal(object)
|
||||||
swipe_and_hold_finished = pyqtSignal(object)
|
swipe_hold_finished = pyqtSignal(object)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
QObject.__init__(self)
|
QObject.__init__(self)
|
||||||
@ -127,10 +132,12 @@ class State(QObject):
|
|||||||
self.hold_started = True
|
self.hold_started = True
|
||||||
self.possible_gestures = {SwipeAndHold}
|
self.possible_gestures = {SwipeAndHold}
|
||||||
self.hold_data = (now, st)
|
self.hold_data = (now, st)
|
||||||
|
self.swipe_hold_started.emit(tp)
|
||||||
else:
|
else:
|
||||||
self.possible_gestures = {TapAndHold}
|
self.possible_gestures = {TapAndHold}
|
||||||
self.hold_started = True
|
self.hold_started = True
|
||||||
self.hold_data = now
|
self.hold_data = now
|
||||||
|
self.tap_hold_started.emit(tp)
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
if Tap in self.possible_gestures:
|
if Tap in self.possible_gestures:
|
||||||
@ -151,11 +158,11 @@ class State(QObject):
|
|||||||
|
|
||||||
if TapAndHold in self.possible_gestures:
|
if TapAndHold in self.possible_gestures:
|
||||||
tp = next(self.touch_points.itervalues())
|
tp = next(self.touch_points.itervalues())
|
||||||
self.tap_and_hold_finished.emit(tp)
|
self.tap_hold_finished.emit(tp)
|
||||||
return
|
return
|
||||||
|
|
||||||
if SwipeAndHold in self.possible_gestures:
|
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
|
return
|
||||||
|
|
||||||
|
|
||||||
@ -166,6 +173,9 @@ class GestureHandler(QObject):
|
|||||||
self.state = State()
|
self.state = State()
|
||||||
self.state.swiped.connect(self.handle_swipe)
|
self.state.swiped.connect(self.handle_swipe)
|
||||||
self.state.tapped.connect(self.handle_tap)
|
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'}
|
self.evmap = {QEvent.TouchBegin: 'start', QEvent.TouchUpdate: 'update', QEvent.TouchEnd: 'end'}
|
||||||
|
|
||||||
# Ignore fake mouse events generated by the window system from touch
|
# Ignore fake mouse events generated by the window system from touch
|
||||||
@ -216,13 +226,33 @@ class GestureHandler(QObject):
|
|||||||
ev.accept()
|
ev.accept()
|
||||||
return True
|
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):
|
def handle_swipe(self, direction):
|
||||||
|
if self.close_open_menu():
|
||||||
|
return
|
||||||
view = self.parent()
|
view = self.parent()
|
||||||
func = {Left:'next_page', Right: 'previous_page', Up:'goto_previous_section', Down:'goto_next_section'}[direction]
|
func = {Left:'next_page', Right: 'previous_page', Up:'goto_previous_section', Down:'goto_next_section'}[direction]
|
||||||
getattr(view, func)()
|
getattr(view, func)()
|
||||||
|
|
||||||
def handle_tap(self, tp):
|
def handle_tap(self, tp):
|
||||||
|
if self.close_open_menu():
|
||||||
|
return
|
||||||
view = self.parent()
|
view = self.parent()
|
||||||
threshold = view.width() / 3.0
|
threshold = view.width() / 3.0
|
||||||
attr = 'previous' if tp.start_position.x() <= threshold else 'next'
|
attr = 'previous' if tp.start_position.x() <= threshold else 'next'
|
||||||
getattr(view, '%s_page'%attr)()
|
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