From b00781b87a076fdb7c0cd8951573a73c8d54674d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 15 Jul 2014 10:35:43 +0530 Subject: [PATCH] More workarounds for the broken underMouse() function in Qt 5 on X11 Fixes buttons on the toolbar remaining raised even after their popup menus are closed. --- src/calibre/gui2/__init__.py | 11 +++++++++++ src/calibre/gui2/bars.py | 12 +++++++++--- src/calibre/gui2/tweak_book/editor/widget.py | 13 +++++++++++-- src/calibre/gui2/viewer/main.py | 12 ++++++++++-- 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index d00363c6b5..a81d866746 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -1152,3 +1152,14 @@ if _df and os.path.exists(_df): build_forms(_df) +if islinux or isbsd: + def workaround_broken_under_mouse(ch): + import sip + from PyQt5.Qt import QCursor, QToolButton + # See https://bugreports.qt-project.org/browse/QTBUG-40233 + if isinstance(ch, QToolButton) and not sip.isdeleted(ch): + ch.setAttribute(Qt.WA_UnderMouse, ch.rect().contains(ch.mapFromGlobal(QCursor.pos()))) + ch.update() +else: + workaround_broken_under_mouse = None + diff --git a/src/calibre/gui2/bars.py b/src/calibre/gui2/bars.py index b3680ca3ad..9fbf6a088a 100644 --- a/src/calibre/gui2/bars.py +++ b/src/calibre/gui2/bars.py @@ -7,13 +7,15 @@ __license__ = 'GPL v3' __copyright__ = '2011, Kovid Goyal ' __docformat__ = 'restructuredtext en' +from functools import partial + import sip from PyQt5.Qt import (Qt, QAction, QMenu, QMenuBar, QObject, QToolBar, QToolButton, QSize, pyqtSignal, QTimer) from calibre.constants import isosx from calibre.gui2.throbber import create_donate_widget -from calibre.gui2 import gprefs +from calibre.gui2 import gprefs, workaround_broken_under_mouse class ToolBar(QToolBar): # {{{ @@ -106,8 +108,12 @@ class ToolBar(QToolBar): # {{{ ch = self.child_bar.widgetForAction(ac) ch.setCursor(Qt.PointingHandCursor) ch.setAutoRaise(True) - if ac.menu() is not None and menu_mode is not None: - ch.setPopupMode(menu_mode) + m = ac.menu() + if m is not None: + if workaround_broken_under_mouse is not None: + m.aboutToHide.connect(partial(workaround_broken_under_mouse, ch)) + if menu_mode is not None: + ch.setPopupMode(menu_mode) return ch # support drag&drop from/to library, from/to reader/card, enabled plugins diff --git a/src/calibre/gui2/tweak_book/editor/widget.py b/src/calibre/gui2/tweak_book/editor/widget.py index 66a3533bb3..77e6df7514 100644 --- a/src/calibre/gui2/tweak_book/editor/widget.py +++ b/src/calibre/gui2/tweak_book/editor/widget.py @@ -16,8 +16,8 @@ from PyQt5.Qt import ( from calibre import prints from calibre.constants import DEBUG from calibre.ebooks.chardet import replace_encoding_declarations -from calibre.gui2 import error_dialog, open_url from calibre.gui2.tweak_book import actions, current_container, tprefs, dictionaries, editor_toolbar_actions, editor_name, editors +from calibre.gui2 import error_dialog, open_url, workaround_broken_under_mouse from calibre.gui2.tweak_book.editor import SPELL_PROPERTY, LINK_PROPERTY, TAG_NAME_PROPERTY, CSS_PROPERTY from calibre.gui2.tweak_book.editor.help import help_url from calibre.gui2.tweak_book.editor.text import TextEdit @@ -310,10 +310,19 @@ class Editor(QMainWindow): w.setContextMenuPolicy(Qt.CustomContextMenu) w.customContextMenuRequested.connect(w.showMenu) self._build_insert_tag_button_menu() + if workaround_broken_under_mouse is not None: + try: + self.insert_tag_menu.aboutToHide.disconnect() + except TypeError: + pass + self.insert_tag_menu.aboutToHide.connect(partial(workaround_broken_under_mouse, w)) elif name == 'change-paragraph': m = ac.m = QMenu() ac.setMenu(m) - bar.widgetForAction(ac).setPopupMode(QToolButton.InstantPopup) + ch = bar.widgetForAction(ac) + ch.setPopupMode(QToolButton.InstantPopup) + if workaround_broken_under_mouse is not None: + m.aboutToHide.connect(partial(workaround_broken_under_mouse, ch)) for name in tuple('h%d' % d for d in range(1, 7)) + ('p',): m.addAction(actions['rename-block-tag-%s' % name]) diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index ab39d922d5..96cf73a1db 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -13,8 +13,10 @@ from calibre.gui2.viewer.ui import Main as MainWindow from calibre.gui2.viewer.printing import Printing from calibre.gui2.viewer.toc import TOC from calibre.gui2.widgets import ProgressIndicator -from calibre.gui2 import (Application, ORG_NAME, APP_UID, choose_files, - info_dialog, error_dialog, open_url, setup_gui_option_parser, detach_gui) +from calibre.gui2 import ( + Application, ORG_NAME, APP_UID, choose_files, info_dialog, error_dialog, + open_url, setup_gui_option_parser, detach_gui, + workaround_broken_under_mouse) from calibre.ebooks.oeb.iterator.book import EbookIterator from calibre.ebooks import DRMError from calibre.constants import islinux, filesystem_encoding @@ -154,6 +156,12 @@ class EbookViewer(MainWindow): self.action_toggle_paged_mode.toggled[bool].connect(self.toggle_paged_mode) if (start_in_fullscreen or self.view.document.start_in_fullscreen): self.action_full_screen.trigger() + if workaround_broken_under_mouse is not None: + for bar in (self.tool_bar, self.tool_bar2): + for ac in bar.actions(): + m = ac.menu() + if m is not None: + m.aboutToHide.connect(partial(workaround_broken_under_mouse, bar.widgetForAction(ac))) def toggle_paged_mode(self, checked, at_start=False): in_paged_mode = not self.action_toggle_paged_mode.isChecked()