mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
DBus menu: Implement visibility and automatically hide the menu when the window is blocked by a modal dialog
This commit is contained in:
parent
75a8c36305
commit
ce69866801
@ -10,7 +10,7 @@ import time
|
||||
|
||||
from PyQt5.Qt import (
|
||||
QApplication, QMainWindow, QVBoxLayout, Qt, QKeySequence, QAction,
|
||||
QActionGroup, QMenu, QPushButton, QWidget, QTimer)
|
||||
QActionGroup, QMenu, QPushButton, QWidget, QTimer, QMessageBox, pyqtSignal)
|
||||
|
||||
from calibre.gui2.dbus_export.utils import setup_for_cli_run
|
||||
from calibre.gui2.dbus_export.widgets import factory
|
||||
@ -22,6 +22,9 @@ def make_checkable(ac, checked=True):
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
|
||||
window_blocked = pyqtSignal()
|
||||
window_unblocked = pyqtSignal()
|
||||
|
||||
def __init__(self):
|
||||
QMainWindow.__init__(self)
|
||||
f = factory()
|
||||
@ -84,6 +87,8 @@ class MainWindow(QMainWindow):
|
||||
b.clicked.connect(self.add_menu), l.addWidget(b)
|
||||
self.rb = b = QPushButton('Remove a created menu')
|
||||
b.clicked.connect(self.remove_menu), l.addWidget(b)
|
||||
self.sd = b = QPushButton('Show modal dialog')
|
||||
b.clicked.connect(self.show_dialog), l.addWidget(b)
|
||||
print ('DBUS connection unique name:', f.bus.get_unique_name())
|
||||
|
||||
def update_tooltip(self):
|
||||
@ -143,6 +148,17 @@ class MainWindow(QMainWindow):
|
||||
def about_to_show_two(self):
|
||||
self.menu_two.addAction('Action added by about to show')
|
||||
|
||||
def show_dialog(self):
|
||||
QMessageBox.information(self, 'A test dialog', 'While this dialog is shown, the global menu should be hidden')
|
||||
|
||||
def event(self, ev):
|
||||
if ev.type() in (ev.WindowBlocked, ev.WindowUnblocked):
|
||||
if ev.type() == ev.WindowBlocked:
|
||||
self.window_blocked.emit()
|
||||
else:
|
||||
self.window_unblocked.emit()
|
||||
return QMainWindow.event(self, ev)
|
||||
|
||||
app=QApplication([])
|
||||
app.setAttribute(Qt.AA_DontUseNativeMenuBar, False)
|
||||
app.setApplicationName('com.calibre-ebook.DBusExportDemo')
|
||||
|
@ -34,7 +34,7 @@ def create_properties_for_action(ac, previous=None):
|
||||
ans['label'] = swap_mnemonic_char(text)
|
||||
if not ac.isEnabled():
|
||||
ans['enabled'] = False
|
||||
if not ac.isVisible():
|
||||
if not ac.isVisible() or ac.property('blocked') is True:
|
||||
ans['visible'] = False
|
||||
if ac.menu() is not None:
|
||||
ans['children-display'] = 'submenu'
|
||||
@ -124,6 +124,22 @@ class DBusMenu(QObject):
|
||||
self.add_action(ac)
|
||||
self.dbus_api.LayoutUpdated(self.dbus_api.revision, 0)
|
||||
|
||||
def set_visible(self, visible):
|
||||
ac = self.id_to_action(0)
|
||||
if ac is not None and self.qmenu is not None:
|
||||
changed = False
|
||||
blocked = not visible
|
||||
for ac in ac.menu().actions():
|
||||
ac_id = self.action_to_id(ac)
|
||||
if ac_id is not None:
|
||||
old = ac.property('blocked')
|
||||
if old is not blocked:
|
||||
ac.setProperty('blocked', blocked)
|
||||
self.action_changes.add(ac_id)
|
||||
changed = True
|
||||
if changed:
|
||||
self.action_changed_timer.start()
|
||||
|
||||
def add_action(self, ac):
|
||||
ac_id = 0 if ac.menu() is self.qmenu else self.next_id
|
||||
self._id_to_action[ac_id] = ac
|
||||
|
@ -37,6 +37,8 @@ class ExportedMenuBar(QMenuBar):
|
||||
global menu_counter
|
||||
if not parent.isWindow():
|
||||
raise ValueError('You must supply a top level window widget as the parent for an exported menu bar')
|
||||
self._blocked = False
|
||||
self.is_visible = True
|
||||
QMenuBar.__init__(self, parent)
|
||||
QMenuBar.setVisible(self, False)
|
||||
self.menu_action = MenuBarAction(self)
|
||||
@ -51,6 +53,10 @@ class ExportedMenuBar(QMenuBar):
|
||||
self.dbus_menu.publish_new_menu(self)
|
||||
self.register()
|
||||
parent.installEventFilter(self)
|
||||
# See https://bugreports.qt-project.org/browse/QTBUG-42281
|
||||
if hasattr(parent, 'window_blocked'):
|
||||
parent.window_blocked.connect(self._block)
|
||||
parent.window_unblocked.connect(self._unblock)
|
||||
|
||||
def register(self):
|
||||
wid = self.parent().effectiveWinId()
|
||||
@ -66,16 +72,38 @@ class ExportedMenuBar(QMenuBar):
|
||||
self.bus.call_blocking(*args)
|
||||
|
||||
def setVisible(self, visible):
|
||||
pass # no-op
|
||||
self.is_visible = visible
|
||||
self.dbus_menu.set_visible(self.is_visible and not self._blocked)
|
||||
|
||||
def isVisible(self):
|
||||
return True
|
||||
return self.is_visible
|
||||
|
||||
def show(self):
|
||||
self.setVisible(True)
|
||||
|
||||
def hide(self):
|
||||
self.setVisible(False)
|
||||
|
||||
def menuAction(self):
|
||||
return self.menu_action
|
||||
|
||||
def _block(self):
|
||||
self._blocked = True
|
||||
self.setVisible(self.is_visible)
|
||||
|
||||
def _unblock(self):
|
||||
self._blocked = False
|
||||
self.setVisible(self.is_visible)
|
||||
|
||||
def eventFilter(self, obj, ev):
|
||||
etype = ev.type()
|
||||
# WindowBlocked and WindowUnblocked aren't delivered to event filters,
|
||||
# so we have to rely on co-operation from the mainwindow class
|
||||
# See https://bugreports.qt-project.org/browse/QTBUG-42281
|
||||
# if etype == QEvent.WindowBlocked:
|
||||
# self._block()
|
||||
# elif etype == QEvent.WindowUnblocked:
|
||||
# self._unblock()
|
||||
if etype == QEvent.WinIdChange:
|
||||
self.unregister()
|
||||
self.register()
|
||||
|
Loading…
x
Reference in New Issue
Block a user