mirror of
https://github.com/schrodinger/pymol-open-source.git
synced 2026-06-04 20:04:21 +08:00
PYMOL-3590 Shortcut menu Create/Confirm fixes
- Fixed previous assignment being called - Create/confirm are now QDialog - Create/confirm no longer dockable - Improved key recognition in create - Replacing _weakrefproxy with _
This commit is contained in:
committed by
Jarrett Johnson
parent
fb5fae24b3
commit
a30c11bc5a
@@ -2,16 +2,31 @@
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>412</width>
|
||||
<height>89</height>
|
||||
<height>90</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>412</width>
|
||||
<height>90</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
<string>Confirm Changing Existing Binding</string>
|
||||
</property>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
<height>104</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Create Shortcut</string>
|
||||
</property>
|
||||
|
||||
@@ -11,6 +11,7 @@ from pymol.keyboard import get_default_keys
|
||||
Qt = QtCore.Qt
|
||||
QSI = QtGui.QStandardItem # For brevity
|
||||
|
||||
|
||||
def get_shortcut_key_map():
|
||||
shortcut_key_map = {}
|
||||
for key, value in vars(Qt).items():
|
||||
@@ -18,6 +19,7 @@ def get_shortcut_key_map():
|
||||
shortcut_key_map[value] = key.partition('_')[2]
|
||||
return shortcut_key_map
|
||||
|
||||
|
||||
_SHORTCUT_KEY_MAP = get_shortcut_key_map()
|
||||
|
||||
_SHORTCUT_MODIFIER_MAP = {
|
||||
@@ -25,13 +27,26 @@ _SHORTCUT_MODIFIER_MAP = {
|
||||
Qt.AltModifier: _SHORTCUT_KEY_MAP[Qt.Key_Alt],
|
||||
Qt.ShiftModifier: _SHORTCUT_KEY_MAP[Qt.Key_Shift],
|
||||
Qt.MetaModifier: _SHORTCUT_KEY_MAP[Qt.Key_Meta],
|
||||
}
|
||||
}
|
||||
|
||||
_REPLACE_KEYS = {
|
||||
'PageUp': 'pgup',
|
||||
'PageDown': 'pgdn',
|
||||
'Home': 'home',
|
||||
'Insert': 'insert',
|
||||
'Up': 'up',
|
||||
'Down': 'down',
|
||||
'Left': 'left',
|
||||
'Right': 'right',
|
||||
'End':'end'
|
||||
}
|
||||
|
||||
class PyMOLShortcutMenu(QtWidgets.QWidget):
|
||||
'''
|
||||
Keyboard shortcut dialog for PyMOL. This displays all assigned shortcuts
|
||||
and allows them to be changed or new shortcuts to be created.
|
||||
'''
|
||||
|
||||
def __init__(self, parent, saved_shortcuts, cmd):
|
||||
QtWidgets.QWidget.__init__(self, parent, Qt.Window)
|
||||
self.resize(700, 700)
|
||||
@@ -40,13 +55,13 @@ class PyMOLShortcutMenu(QtWidgets.QWidget):
|
||||
|
||||
self.build_panel_elements(parent)
|
||||
|
||||
def build_panel_elements(self,parent):
|
||||
def build_panel_elements(self, parent):
|
||||
'''
|
||||
Responsible for creating all panel elements in order and adding them to the layout.
|
||||
'''
|
||||
self.create_new_form = parent.load_form("create_shortcut","floating")
|
||||
self.help_form = parent.load_form("help_shortcut","floating")
|
||||
self.confirm_change = parent.load_form("change_confirm","floating")
|
||||
self.create_new_form = parent.load_form("create_shortcut", None)
|
||||
self.help_form = parent.load_form("help_shortcut", None)
|
||||
self.confirm_change = parent.load_form("change_confirm", None)
|
||||
|
||||
self.model = QtGui.QStandardItemModel(self)
|
||||
self.proxy_model = QtCoreModels.QSortFilterProxyModel(self)
|
||||
@@ -69,13 +84,14 @@ class PyMOLShortcutMenu(QtWidgets.QWidget):
|
||||
self.filter_le.textChanged.connect(self.proxy_model.setFilterRegExp)
|
||||
|
||||
self.refresh_button = QtWidgets.QPushButton(self)
|
||||
self.refresh_button.resize(26,26)
|
||||
top_layout.addWidget(self.refresh_button,0,1)
|
||||
self.refresh_button.resize(26, 26)
|
||||
top_layout.addWidget(self.refresh_button, 0, 1)
|
||||
# themed icons only available by default on X11
|
||||
if self.refresh_button.icon().isNull():
|
||||
self.refresh_button.setIcon(QtGui.QIcon(
|
||||
os.path.expandvars('$PYMOL_DATA/pmg_qt/icons/refresh.svg')))
|
||||
self.refresh_button.setToolTip("Refresh the table to reflect any external changes")
|
||||
os.path.expandvars('$PYMOL_DATA/pmg_qt/icons/refresh.svg')))
|
||||
self.refresh_button.setToolTip(
|
||||
"Refresh the table to reflect any external changes")
|
||||
self.refresh_button.clicked.connect(self.refresh_populate)
|
||||
|
||||
# Table
|
||||
@@ -91,37 +107,51 @@ class PyMOLShortcutMenu(QtWidgets.QWidget):
|
||||
|
||||
# Buttons
|
||||
self.create_new_button = QtWidgets.QPushButton(self)
|
||||
button_layout.addWidget(self.create_new_button,0,0)
|
||||
button_layout.addWidget(self.create_new_button, 0, 0)
|
||||
self.create_new_button.setText("Create New")
|
||||
self.create_new_button.setToolTip("Add a key binding that does not currently appear on the table")
|
||||
self.create_new_button.clicked.connect(self.create_new_shortcut_menu)
|
||||
self.create_new_button.setToolTip(
|
||||
"Add a key binding that does not currently appear on the table")
|
||||
self.create_new_button.clicked.connect(
|
||||
lambda: self.create_new_form._dialog.show())
|
||||
|
||||
self.delete_selected_button = QtWidgets.QPushButton(self)
|
||||
button_layout.addWidget(self.delete_selected_button,0,1)
|
||||
button_layout.addWidget(self.delete_selected_button, 0, 1)
|
||||
self.delete_selected_button.setText("Delete Selected")
|
||||
self.delete_selected_button.setToolTip("Unbind selected key bindings and remove any that have been created")
|
||||
self.delete_selected_button.setToolTip(
|
||||
"Unbind selected key bindings and remove any that have been created")
|
||||
self.delete_selected_button.clicked.connect(self.delete_selected)
|
||||
self.delete_selected_button.setEnabled(False)
|
||||
|
||||
self.reset_selected_button = QtWidgets.QPushButton(self)
|
||||
button_layout.addWidget(self.reset_selected_button,0,2)
|
||||
button_layout.addWidget(self.reset_selected_button, 0, 2)
|
||||
self.reset_selected_button.setText("Reset Selected")
|
||||
self.reset_selected_button.setToolTip("Restore selected key bindings to their default values")
|
||||
self.reset_selected_button.setToolTip(
|
||||
"Restore selected key bindings to their default values")
|
||||
self.reset_selected_button.clicked.connect(self.reset_selected)
|
||||
self.reset_selected_button.setEnabled(False)
|
||||
|
||||
self.reset_all_button = QtWidgets.QPushButton(self)
|
||||
button_layout.addWidget(self.reset_all_button,0,3)
|
||||
button_layout.addWidget(self.reset_all_button, 0, 3)
|
||||
self.reset_all_button.setText("Reset All")
|
||||
self.reset_all_button.setToolTip("Restore all key bindings to their default values and remove any that have been created")
|
||||
self.reset_all_button.setToolTip(
|
||||
"Restore all key bindings to their default values and remove any that have been created")
|
||||
self.reset_all_button.clicked.connect(self.reset_all_default)
|
||||
|
||||
self.save_button = QtWidgets.QPushButton(self)
|
||||
button_layout.addWidget(self.save_button,0,4)
|
||||
button_layout.addWidget(self.save_button, 0, 4)
|
||||
self.save_button.setText("Save")
|
||||
self.save_button.setToolTip("Save the current key bindings to be loaded automatically when opening PyMOL")
|
||||
self.save_button.setToolTip(
|
||||
"Save the current key bindings to be loaded automatically when opening PyMOL")
|
||||
self.save_button.clicked.connect(self.shortcut_manager.save_shortcuts)
|
||||
|
||||
# Ensuring that confirmed key and binding remain in scope
|
||||
self.confirm_new_key = ''
|
||||
self.confirm_new_binding = ''
|
||||
|
||||
# Connect create new and confirm menus
|
||||
self.create_new_shortcut_menu_connect()
|
||||
self.confirm_menu_connect()
|
||||
|
||||
self.model.itemChanged.connect(self.itemChanged)
|
||||
|
||||
def populateData(self):
|
||||
@@ -129,7 +159,8 @@ class PyMOLShortcutMenu(QtWidgets.QWidget):
|
||||
Fill the model with data from shortcut_dict.
|
||||
'''
|
||||
self.model.clear()
|
||||
self.model.setHorizontalHeaderLabels(['Key','Command (click to edit)','Description'])
|
||||
self.model.setHorizontalHeaderLabels(
|
||||
['Key', 'Command (click to edit)', 'Description'])
|
||||
|
||||
for key, shortcut_list in self.shortcut_manager.cmd.shortcut_dict.items():
|
||||
key_item = QSI(key)
|
||||
@@ -195,15 +226,15 @@ class PyMOLShortcutMenu(QtWidgets.QWidget):
|
||||
delete_keys = []
|
||||
|
||||
for ind, table_index in enumerate(list_indexes):
|
||||
table_colm_key = self.table.model().index(table_index.row(),0)
|
||||
table_colm_command = self.table.model().index(table_index.row(),1)
|
||||
table_colm_descipt = self.table.model().index(table_index.row(),2)
|
||||
table_colm_key = self.table.model().index(table_index.row(), 0)
|
||||
table_colm_command = self.table.model().index(table_index.row(), 1)
|
||||
table_colm_descipt = self.table.model().index(table_index.row(), 2)
|
||||
|
||||
delete_key = table_colm_key.data()
|
||||
self.cmd.set_key(delete_key,'')
|
||||
self.cmd.set_key(delete_key, '')
|
||||
if delete_key in self.shortcut_manager.default_bindings:
|
||||
self.table.model().setData(table_colm_command,'Deleted')
|
||||
self.table.model().setData(table_colm_descipt,'Deleted')
|
||||
self.table.model().setData(table_colm_command, 'Deleted')
|
||||
self.table.model().setData(table_colm_descipt, 'Deleted')
|
||||
self.shortcut_manager.cmd.shortcut_dict[delete_key][ShortcutIndex.USER_DEF] = 'Deleted'
|
||||
else:
|
||||
self.model.removeRow(table_index.row())
|
||||
@@ -221,32 +252,35 @@ class PyMOLShortcutMenu(QtWidgets.QWidget):
|
||||
list_indexes = selection_model.selectedIndexes()
|
||||
|
||||
for ind, table_index in enumerate(list_indexes):
|
||||
table_colm_key = self.table.model().index(table_index.row(),0)
|
||||
table_colm_command = self.table.model().index(table_index.row(),1)
|
||||
table_colm_descipt = self.table.model().index(table_index.row(),2)
|
||||
table_colm_key = self.table.model().index(table_index.row(), 0)
|
||||
table_colm_command = self.table.model().index(table_index.row(), 1)
|
||||
table_colm_descipt = self.table.model().index(table_index.row(), 2)
|
||||
|
||||
reset_key = table_colm_key.data()
|
||||
if reset_key not in self.shortcut_manager.default_bindings:
|
||||
print("This key does not have a default value.")
|
||||
else:
|
||||
reset_binding = self.shortcut_manager.default_bindings[reset_key]
|
||||
reset_command = self.shortcut_manager.cmd.shortcut_dict[reset_key][ShortcutIndex.COMMAND]
|
||||
reset_description = self.shortcut_manager.cmd.shortcut_dict[reset_key][ShortcutIndex.DESCRIPT]
|
||||
reset_command = self.shortcut_manager.cmd.shortcut_dict[
|
||||
reset_key][ShortcutIndex.COMMAND]
|
||||
reset_description = self.shortcut_manager.cmd.shortcut_dict[
|
||||
reset_key][ShortcutIndex.DESCRIPT]
|
||||
|
||||
self.table.model().setData(table_colm_command, reset_command)
|
||||
self.table.model().setData(table_colm_descipt, reset_description)
|
||||
|
||||
self.shortcut_manager.cmd.shortcut_dict[reset_key][ShortcutIndex.USER_DEF] = ''
|
||||
|
||||
self.cmd.set_key(reset_key,reset_binding)
|
||||
self.cmd.set_key(reset_key, reset_binding)
|
||||
|
||||
def create_new_shortcut_menu(self):
|
||||
self.create_new_form._dialog.show()
|
||||
self.create_new_form.keyEdit.returnPressed.connect(self.create_new_shortcut)
|
||||
self.create_new_form.commandEdit.returnPressed.connect(self.create_new_shortcut)
|
||||
self.create_new_form.createButton.clicked.connect(self.create_new_shortcut)
|
||||
self.create_new_form.helpButton.clicked.connect(self.help_menu_shortcut)
|
||||
def create_new_shortcut_menu_connect(self):
|
||||
self.create_new_form.createButton.clicked.connect(
|
||||
self.create_new_shortcut_caller)
|
||||
self.create_new_form.helpButton.clicked.connect(
|
||||
self.help_menu_shortcut)
|
||||
self.create_new_form.keyEdit.installEventFilter(self)
|
||||
self.create_new_form.helpButton.setDefault(False)
|
||||
self.create_new_form.helpButton.setAutoDefault(False)
|
||||
|
||||
def eventFilter(self, source, event):
|
||||
'''
|
||||
@@ -288,23 +322,40 @@ class PyMOLShortcutMenu(QtWidgets.QWidget):
|
||||
'''
|
||||
split_string = raw_string.split()
|
||||
process_list = []
|
||||
prefix_key = split_string[0]
|
||||
if len(split_string) >= 2:
|
||||
if (split_string[0] == 'Control' or split_string[0] == 'Meta') and split_string[1]:
|
||||
if split_string[1] == 'Shift' and len(split_string) > 2:
|
||||
prefix_key = split_string[0]
|
||||
suffix_key = split_string[1]
|
||||
if (prefix_key == 'Control' or prefix_key == 'Meta') and split_string[1]:
|
||||
if suffix_key == 'Shift' and len(split_string) > 2:
|
||||
process_list.append('CTSH')
|
||||
process_list.append(split_string[2])
|
||||
suffix_key = split_string[2]
|
||||
else:
|
||||
process_list.append('CTRL')
|
||||
process_list.append(split_string[1])
|
||||
elif split_string[0] == 'Alt':
|
||||
elif prefix_key == 'Alt':
|
||||
process_list.append('ALT')
|
||||
process_list.append(split_string[1])
|
||||
elif prefix_key == 'Shift':
|
||||
process_list.append('SHFT')
|
||||
if suffix_key in _REPLACE_KEYS:
|
||||
suffix_key = _REPLACE_KEYS[suffix_key]
|
||||
process_list.append(suffix_key)
|
||||
elif prefix_key in _REPLACE_KEYS:
|
||||
process_list.append(_REPLACE_KEYS[prefix_key])
|
||||
return('-'.join(process_list))
|
||||
|
||||
def help_menu_shortcut(self):
|
||||
self.help_form._dialog.show()
|
||||
|
||||
def create_new_shortcut(self):
|
||||
def confirm_menu_connect(self):
|
||||
self.confirm_change.confirmButton.clicked.connect(
|
||||
lambda: self.shortcut_manager.create_new_shortcut(self.confirm_new_key, self.confirm_new_binding))
|
||||
self.confirm_change.confirmButton.clicked.connect(lambda: self.populateData())
|
||||
self.confirm_change.confirmButton.clicked.connect(
|
||||
lambda: self.confirm_change._dialog.hide())
|
||||
self.confirm_change.cancelButton.clicked.connect(
|
||||
lambda: self.confirm_change._dialog.hide())
|
||||
|
||||
def create_new_shortcut_caller(self):
|
||||
'''
|
||||
Creates a new shortcut after checking existing and reserved keys.
|
||||
'''
|
||||
@@ -316,28 +367,24 @@ class PyMOLShortcutMenu(QtWidgets.QWidget):
|
||||
elif new_key in self.shortcut_manager.cmd.shortcut_dict:
|
||||
hide_confirm_menu = self.confirm_change.doNotShowCheckBox.isChecked()
|
||||
if not hide_confirm_menu:
|
||||
self.confirm_new_key = new_key
|
||||
self.confirm_new_binding = new_binding
|
||||
self.confirm_change._dialog.show()
|
||||
self.confirm_change.confirmButton.clicked.connect(
|
||||
lambda: self.shortcut_manager.create_new_shortcut(new_key, new_binding))
|
||||
self.confirm_change.confirmButton.clicked.connect(
|
||||
lambda: self.confirm_change._dialog.hide())
|
||||
self.confirm_change.cancelButton.clicked.connect(
|
||||
lambda: self.confirm_change._dialog.hide())
|
||||
else:
|
||||
self.shortcut_manager.create_new_shortcut(new_key, new_binding)
|
||||
|
||||
self.populateData()
|
||||
else:
|
||||
self.shortcut_manager.create_new_shortcut(new_key, new_binding)
|
||||
self.populateData()
|
||||
self.table.scrollToBottom()
|
||||
|
||||
self.populateData()
|
||||
|
||||
def formatTable(self):
|
||||
'''
|
||||
Set up the table to look appropriately
|
||||
'''
|
||||
hh = self.table.horizontalHeader()
|
||||
hh.setStretchLastSection(True)
|
||||
hh.setSectionResizeMode(QtWidgets.QHeaderView.Fixed)
|
||||
self.table.verticalHeader().setVisible(False)
|
||||
self.table.setFocus()
|
||||
self.table.hide()
|
||||
@@ -353,14 +400,17 @@ class PyMOLShortcutMenu(QtWidgets.QWidget):
|
||||
"""
|
||||
try:
|
||||
if item.column() == 1 and item.text() != "Deleted":
|
||||
changed_key = self.model.index(item.row(),0).data()
|
||||
changed_index = self.table.model().index(item.row(),0)
|
||||
changed_key = self.model.index(item.row(), 0).data()
|
||||
changed_index = self.table.model().index(item.row(), 0)
|
||||
|
||||
self.cmd.set_key(changed_key, item.text())
|
||||
self.shortcut_manager.cmd.shortcut_dict[changed_key][2] = item.text()
|
||||
|
||||
self.table.model().setData(self.table.model().index(item.row(),2),'user defined')
|
||||
filter_active = bool(self.filter_le.text())
|
||||
if not filter_active:
|
||||
self.table.model().setData(self.table.model().index(item.row(), 2), 'user defined')
|
||||
else:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("Failed to change key binding")
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
# truncated for this purpose.
|
||||
#============================================================================#
|
||||
shortcut_dict_ref = {
|
||||
'left': ('cmd._weakrefproxy.backward()',"previous movie frame",''),
|
||||
'right': ('cmd._weakrefproxy.forward()',"next movie frame",''),
|
||||
'left': ('_ backward',"previous movie frame",''),
|
||||
'right': ('_ forward',"next movie frame",''),
|
||||
'pgup': ('scene action=previous',"previous scene",''),
|
||||
'pgdn': ('scene action=next',"last scene",''),
|
||||
'home': ('zoom animate=-1',"zoom all",''),
|
||||
@@ -24,8 +24,8 @@ shortcut_dict_ref = {
|
||||
'SHFT-insert': ('rock','',''),
|
||||
'CTRL-left': ('backward','',''),
|
||||
'CTRL-right': ('forward','',''),
|
||||
'CTRL-pgup': ("cmd._weakrefproxy.scene('', 'insert_before')",'insert scene before current',''),
|
||||
'CTRL-pgdn': ("cmd._weakrefproxy.scene('', 'insert_after')",'insert scene after current',''),
|
||||
'CTRL-pgup': ("_ scene new, insert_before",'insert scene before current',''),
|
||||
'CTRL-pgdn': ("_ scene new, insert_after",'insert scene after current',''),
|
||||
'CTRL-home': ('zoom animate=-1','zoom all',''),
|
||||
'CTRL-end': ('scene new, store','store new scene',''),
|
||||
'CTRL-insert': ('scene auto, store','store auto scene',''),
|
||||
@@ -82,8 +82,8 @@ shortcut_dict_ref = {
|
||||
'ALT-Z': ("editor.attach_amino_acid('pk1', 'nme')",'attach nme',''),
|
||||
'CTSH-left': ('backward','',''),
|
||||
'CTSH-right': ('forward','',''),
|
||||
'CTSH-pgup': ("cmd._weakrefproxy.scene('', 'insert_before')",'insert scene before current',''),
|
||||
'CTSH-pgdn': ("cmd._weakrefproxy.scene('', 'insert_after')",'insert scene after current',''),
|
||||
'CTSH-pgup': ("scene new, insert_before",'insert scene before current',''),
|
||||
'CTSH-pgdn': ("scene new, insert_after",'insert scene after current',''),
|
||||
'CTSH-home': ('zoom animate=-1','zoom all',''),
|
||||
'CTSH-end': ('mtoggle','',''),
|
||||
'CTSH-insert': ('rock','',''),
|
||||
|
||||
@@ -18,7 +18,7 @@ class ShortcutManager():
|
||||
self.cmd.shortcut_dict = {key: list(value) for key,value in shortcut_dict_ref.items()}
|
||||
|
||||
# Tuple of keys that are reserved for the system
|
||||
self.reserved_keys = ('CTRL-S','CTRL-E','CTRL-O','CTRL-M')
|
||||
self.reserved_keys = ('CTRL-S','CTRL-E','CTRL-O','CTRL-M','up','down')
|
||||
|
||||
def check_saved_dict(self):
|
||||
'''
|
||||
|
||||
Reference in New Issue
Block a user