mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-31 14:33:54 -04:00
Handle checkable actions and make event processing async
This commit is contained in:
parent
73709f7c00
commit
999bdb0bca
@ -7,37 +7,51 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
from PyQt5.Qt import (
|
||||
QApplication, QMainWindow, QVBoxLayout, Qt, QKeySequence)
|
||||
QApplication, QMainWindow, QVBoxLayout, Qt, QKeySequence, QAction, QActionGroup)
|
||||
|
||||
from calibre.gui2.dbus_export.utils import setup_for_cli_run
|
||||
from calibre.gui2.dbus_export.widgets import factory
|
||||
|
||||
setup_for_cli_run()
|
||||
|
||||
def make_checkable(ac, checked=True):
|
||||
ac.setCheckable(True), ac.setChecked(checked)
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
|
||||
def __init__(self):
|
||||
QMainWindow.__init__(self)
|
||||
self.setMinimumWidth(400)
|
||||
self.setWindowTitle('Demo of DBUS menu exporter and systray integration')
|
||||
self.statusBar().showMessage(self.windowTitle())
|
||||
w = self.centralWidget()
|
||||
self.l = QVBoxLayout(w)
|
||||
mb = f.create_window_menubar(self)
|
||||
self.setMenuBar(mb)
|
||||
m = mb.addMenu('&One')
|
||||
s = self.style()
|
||||
for i, icon in zip(xrange(3), map(s.standardIcon, (s.SP_DialogOkButton, s.SP_DialogCancelButton, s.SP_ArrowUp))):
|
||||
ac = m.addAction('One - &%d' % (i + 1))
|
||||
ac.setShortcut(QKeySequence(Qt.CTRL | (Qt.Key_1 + i), Qt.SHIFT | (Qt.Key_1 + i)))
|
||||
ac.setIcon(icon)
|
||||
m.addSeparator()
|
||||
m.addAction('&Disabled action').setEnabled(False)
|
||||
ac = m.addAction('A checkable action')
|
||||
make_checkable(ac)
|
||||
g = QActionGroup(self)
|
||||
make_checkable(g.addAction(m.addAction('Exclusive 1')))
|
||||
make_checkable(g.addAction(m.addAction('Exclusive 2')), False)
|
||||
for ac in mb.findChildren(QAction):
|
||||
ac.triggered.connect(self.action_triggered)
|
||||
|
||||
def action_triggered(self, checked=False):
|
||||
self.statusBar().showMessage('Action triggered: %s' % self.sender().text())
|
||||
ac = self.sender()
|
||||
text = 'Action triggered: %s' % ac.text()
|
||||
self.statusBar().showMessage(text)
|
||||
|
||||
app = QApplication([])
|
||||
f = factory()
|
||||
mw = MainWindow()
|
||||
mw.setWindowTitle('Demo of DBUS menu exporter and systray integration')
|
||||
mw.statusBar().showMessage(mw.windowTitle())
|
||||
w = mw.centralWidget()
|
||||
mw.l = l = QVBoxLayout(w)
|
||||
mb = f.create_window_menubar(mw)
|
||||
mw.setMenuBar(mb)
|
||||
m = mb.addMenu('&One')
|
||||
s = mw.style()
|
||||
for i, icon in zip(xrange(3), map(s.standardIcon, (s.SP_DialogOkButton, s.SP_DialogCancelButton, s.SP_ArrowUp))):
|
||||
ac = m.addAction('One - &%d' % (i + 1))
|
||||
ac.triggered.connect(mw.action_triggered)
|
||||
k = getattr(Qt, 'Key_%d' % (i + 1))
|
||||
ac.setShortcut(QKeySequence(Qt.CTRL | (Qt.Key_1 + i), Qt.SHIFT | (Qt.Key_1 + i)))
|
||||
ac.setIcon(icon)
|
||||
m.addSeparator()
|
||||
m.addAction('&Disabled action').setEnabled(False)
|
||||
mw.show()
|
||||
print ('DBUS connection unique name:', f.bus.get_unique_name())
|
||||
app.exec_()
|
||||
|
@ -11,7 +11,7 @@ __copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
import dbus
|
||||
from PyQt5.Qt import (
|
||||
QApplication, QMenu, QIcon, QKeySequence, QObject, QEvent, QTimer)
|
||||
QApplication, QMenu, QIcon, QKeySequence, QObject, QEvent, QTimer, pyqtSignal, Qt)
|
||||
|
||||
from calibre.utils.dbus_service import Object, BusName, method as dbus_method, dbus_property, signal as dbus_signal
|
||||
from calibre.gui2.dbus_export.utils import (
|
||||
@ -66,8 +66,13 @@ def create_properties_for_action(ac, previous=None):
|
||||
|
||||
class DBusMenu(QObject):
|
||||
|
||||
handle_event_signal = pyqtSignal(object, object, object, object)
|
||||
|
||||
def __init__(self, object_path, **kw):
|
||||
QObject.__init__(self, kw.get('parent'))
|
||||
# Unity barfs is the Event DBUS method does not return immediately, so
|
||||
# handle it asynchronously
|
||||
self.handle_event_signal.connect(self.handle_event, type=Qt.QueuedConnection)
|
||||
self.dbus_api = DBusMenuAPI(self, object_path, **kw)
|
||||
self.set_status = self.dbus_api.set_status
|
||||
self._next_id = 0
|
||||
@ -219,8 +224,9 @@ class DBusMenu(QObject):
|
||||
def handle_event(self, action_id, event, data, timestamp):
|
||||
ac = self.id_to_action(action_id)
|
||||
if event == 'clicked':
|
||||
# TODO: Handle checkable actions
|
||||
ac.triggered.emit()
|
||||
if ac.isCheckable():
|
||||
ac.toggle()
|
||||
ac.triggered.emit(ac.isCheckable() and ac.isChecked())
|
||||
|
||||
class DBusMenuAPI(Object):
|
||||
|
||||
@ -278,7 +284,7 @@ class DBusMenuAPI(Object):
|
||||
* "closed"
|
||||
Vendor specific events can be added by prefixing them with "x-<vendor>-"'''
|
||||
if self.menu.id_to_action(id) is not None:
|
||||
self.menu.handle_event(id, eventId, data, timestamp)
|
||||
self.menu.handle_event_signal.emit(id, eventId, data, timestamp)
|
||||
|
||||
@dbus_method(IFACE, in_signature='a(isvu)', out_signature='ai')
|
||||
def EventGroup(self, events):
|
||||
@ -289,7 +295,7 @@ class DBusMenuAPI(Object):
|
||||
missing = dbus.Array(signature='u')
|
||||
for id, eventId, data, timestamp in events:
|
||||
if self.menu.id_to_action(id) is not None:
|
||||
self.menu.handle_event(id, eventId, data, timestamp)
|
||||
self.menu.handle_event_signal.emit(id, eventId, data, timestamp)
|
||||
else:
|
||||
missing.append(id)
|
||||
return missing
|
||||
|
Loading…
x
Reference in New Issue
Block a user