mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
macOS: Fix keyboard shortcuts for select all, copy and paste not working in file dialogs. Fixes #1874499 [Select-All Broken in Import Dialogue](https://bugs.launchpad.net/calibre/+bug/1874499)
This commit is contained in:
parent
cdc68da194
commit
268a213659
@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from PyQt5.Qt import (
|
from PyQt5.Qt import (
|
||||||
Qt, QAction, QMenu, QObject, QToolBar, QToolButton, QSize, pyqtSignal,
|
Qt, QAction, QMenu, QObject, QToolBar, QToolButton, QSize, pyqtSignal, QKeySequence,
|
||||||
QTimer, QPropertyAnimation, QEasingCurve, pyqtProperty, QPainter, QWidget)
|
QTimer, QPropertyAnimation, QEasingCurve, pyqtProperty, QPainter, QWidget)
|
||||||
try:
|
try:
|
||||||
from PyQt5 import sip
|
from PyQt5 import sip
|
||||||
@ -423,12 +423,17 @@ if isosx:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def native_menubar(self):
|
def native_menubar(self):
|
||||||
return self.gui.native_menubar
|
mb = self.gui.native_menubar
|
||||||
|
if mb.parent() is None:
|
||||||
|
# Without this the menubar does not update correctly with Qt >=
|
||||||
|
# 5.6. See the last couple of lines in updateMenuBarImmediately
|
||||||
|
# in qcocoamenubar.mm
|
||||||
|
mb.setParent(self.gui)
|
||||||
|
return mb
|
||||||
|
|
||||||
def __init__(self, location_manager, parent):
|
def __init__(self, location_manager, parent):
|
||||||
QObject.__init__(self, parent)
|
QObject.__init__(self, parent)
|
||||||
self.gui = parent
|
self.gui = parent
|
||||||
|
|
||||||
self.location_manager = location_manager
|
self.location_manager = location_manager
|
||||||
self.added_actions = []
|
self.added_actions = []
|
||||||
self.last_actions = []
|
self.last_actions = []
|
||||||
@ -440,14 +445,30 @@ if isosx:
|
|||||||
self.refresh_timer = t = QTimer(self)
|
self.refresh_timer = t = QTimer(self)
|
||||||
t.setInterval(200), t.setSingleShot(True), t.timeout.connect(self.refresh_bar)
|
t.setInterval(200), t.setSingleShot(True), t.timeout.connect(self.refresh_bar)
|
||||||
|
|
||||||
def init_bar(self, actions):
|
def adapt_for_dialog(self, enter):
|
||||||
|
|
||||||
|
def ac(text, key, role=QAction.TextHeuristicRole):
|
||||||
|
ans = QAction(text, self)
|
||||||
|
ans.setMenuRole(role)
|
||||||
|
ans.setShortcut(QKeySequence(key))
|
||||||
|
self.edit_menu.addAction(ans)
|
||||||
|
return ans
|
||||||
|
|
||||||
mb = self.native_menubar
|
mb = self.native_menubar
|
||||||
if mb.parent() is None:
|
if enter:
|
||||||
# Without this the menubar does not update correctly with Qt >=
|
self.clear_bar(mb)
|
||||||
# 5.6. See the last couple of lines in updateMenuBarImmediately
|
self.edit_menu = QMenu()
|
||||||
# in qcocoamenubar.mm
|
self.edit_action = QAction(_('Edit'), self)
|
||||||
mb.setParent(self.gui)
|
self.edit_action.setMenu(self.edit_menu)
|
||||||
self.last_actions = actions
|
ac(_('Copy'), QKeySequence.Copy),
|
||||||
|
ac(_('Paste'), QKeySequence.Paste),
|
||||||
|
ac(_('Select all'), QKeySequence.SelectAll),
|
||||||
|
mb.addAction(self.edit_action)
|
||||||
|
self.added_actions = [self.edit_action]
|
||||||
|
else:
|
||||||
|
self.refresh_bar()
|
||||||
|
|
||||||
|
def clear_bar(self, mb):
|
||||||
for ac in self.added_actions:
|
for ac in self.added_actions:
|
||||||
m = ac.menu()
|
m = ac.menu()
|
||||||
if m is not None:
|
if m is not None:
|
||||||
@ -460,6 +481,11 @@ if isosx:
|
|||||||
ac.deleteLater()
|
ac.deleteLater()
|
||||||
self.added_actions = []
|
self.added_actions = []
|
||||||
|
|
||||||
|
def init_bar(self, actions):
|
||||||
|
mb = self.native_menubar
|
||||||
|
self.last_actions = actions
|
||||||
|
self.clear_bar(mb)
|
||||||
|
|
||||||
for what in actions:
|
for what in actions:
|
||||||
if what is None:
|
if what is None:
|
||||||
continue
|
continue
|
||||||
@ -585,6 +611,20 @@ else:
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
|
class AdaptMenuBarForDialog(object):
|
||||||
|
|
||||||
|
def __init__(self, menu_bar):
|
||||||
|
self.menu_bar = menu_bar
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
if isosx and self.menu_bar.is_native_menubar:
|
||||||
|
self.menu_bar.adapt_for_dialog(True)
|
||||||
|
|
||||||
|
def __exit__(self, *a):
|
||||||
|
if isosx and self.menu_bar.is_native_menubar:
|
||||||
|
self.menu_bar.adapt_for_dialog(False)
|
||||||
|
|
||||||
|
|
||||||
class BarsManager(QObject):
|
class BarsManager(QObject):
|
||||||
|
|
||||||
def __init__(self, donate_action, location_manager, parent):
|
def __init__(self, donate_action, location_manager, parent):
|
||||||
@ -598,6 +638,7 @@ class BarsManager(QObject):
|
|||||||
|
|
||||||
self.menu_bar = MenuBar(self.location_manager, self.parent())
|
self.menu_bar = MenuBar(self.location_manager, self.parent())
|
||||||
is_native_menubar = self.menu_bar.is_native_menubar
|
is_native_menubar = self.menu_bar.is_native_menubar
|
||||||
|
self.adapt_menu_bar_for_dialog = AdaptMenuBarForDialog(self.menu_bar)
|
||||||
self.menubar_fallback = native_menubar_defaults['action-layout-menubar'] if is_native_menubar else ()
|
self.menubar_fallback = native_menubar_defaults['action-layout-menubar'] if is_native_menubar else ()
|
||||||
self.menubar_device_fallback = native_menubar_defaults['action-layout-menubar-device'] if is_native_menubar else ()
|
self.menubar_device_fallback = native_menubar_defaults['action-layout-menubar-device'] if is_native_menubar else ()
|
||||||
|
|
||||||
|
@ -24,6 +24,15 @@ def select_initial_dir(q):
|
|||||||
return os.path.expanduser(u'~')
|
return os.path.expanduser(u'~')
|
||||||
|
|
||||||
|
|
||||||
|
class Dummy(object):
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __exit__(self, *a):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class FileDialog(QObject):
|
class FileDialog(QObject):
|
||||||
|
|
||||||
def __init__(self, title=_('Choose Files'),
|
def __init__(self, title=_('Choose Files'),
|
||||||
@ -38,6 +47,9 @@ class FileDialog(QObject):
|
|||||||
combine_file_and_saved_dir=False
|
combine_file_and_saved_dir=False
|
||||||
):
|
):
|
||||||
from calibre.gui2 import dynamic, sanitize_env_vars
|
from calibre.gui2 import dynamic, sanitize_env_vars
|
||||||
|
from calibre.gui2.ui import get_gui
|
||||||
|
gui = get_gui()
|
||||||
|
adapt_menubar = gui.bars_manager.adapt_menu_bar_for_dialog if gui is not None else Dummy()
|
||||||
QObject.__init__(self)
|
QObject.__init__(self)
|
||||||
ftext = ''
|
ftext = ''
|
||||||
if filters:
|
if filters:
|
||||||
@ -82,18 +94,21 @@ class FileDialog(QObject):
|
|||||||
if not use_native_dialog:
|
if not use_native_dialog:
|
||||||
opts |= QFileDialog.DontUseNativeDialog
|
opts |= QFileDialog.DontUseNativeDialog
|
||||||
if mode == QFileDialog.AnyFile:
|
if mode == QFileDialog.AnyFile:
|
||||||
f = QFileDialog.getSaveFileName(parent, title,
|
with adapt_menubar:
|
||||||
initial_dir, ftext, "", opts)
|
f = QFileDialog.getSaveFileName(parent, title,
|
||||||
|
initial_dir, ftext, "", opts)
|
||||||
if f and f[0]:
|
if f and f[0]:
|
||||||
self.selected_files.append(f[0])
|
self.selected_files.append(f[0])
|
||||||
elif mode == QFileDialog.ExistingFile:
|
elif mode == QFileDialog.ExistingFile:
|
||||||
f = QFileDialog.getOpenFileName(parent, title,
|
with adapt_menubar:
|
||||||
initial_dir, ftext, "", opts)
|
f = QFileDialog.getOpenFileName(parent, title,
|
||||||
|
initial_dir, ftext, "", opts)
|
||||||
if f and f[0] and os.path.exists(f[0]):
|
if f and f[0] and os.path.exists(f[0]):
|
||||||
self.selected_files.append(f[0])
|
self.selected_files.append(f[0])
|
||||||
elif mode == QFileDialog.ExistingFiles:
|
elif mode == QFileDialog.ExistingFiles:
|
||||||
fs = QFileDialog.getOpenFileNames(parent, title, initial_dir,
|
with adapt_menubar:
|
||||||
ftext, "", opts)
|
fs = QFileDialog.getOpenFileNames(parent, title, initial_dir,
|
||||||
|
ftext, "", opts)
|
||||||
if fs and fs[0]:
|
if fs and fs[0]:
|
||||||
for f in fs[0]:
|
for f in fs[0]:
|
||||||
f = unicode_type(f)
|
f = unicode_type(f)
|
||||||
@ -108,7 +123,8 @@ class FileDialog(QObject):
|
|||||||
else:
|
else:
|
||||||
if mode == QFileDialog.Directory:
|
if mode == QFileDialog.Directory:
|
||||||
opts |= QFileDialog.ShowDirsOnly
|
opts |= QFileDialog.ShowDirsOnly
|
||||||
f = unicode_type(QFileDialog.getExistingDirectory(parent, title, initial_dir, opts))
|
with adapt_menubar:
|
||||||
|
f = unicode_type(QFileDialog.getExistingDirectory(parent, title, initial_dir, opts))
|
||||||
if os.path.exists(f):
|
if os.path.exists(f):
|
||||||
self.selected_files.append(f)
|
self.selected_files.append(f)
|
||||||
if self.selected_files:
|
if self.selected_files:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user