def make_pymol_qicon(): icons_dir = os.path.expandvars('$PYMOL_DATA/pymol/icons') return QtGui.QIcon(os.path.join(icons_dir, 'icon2.svg'))
def props_dialog(parent): #noqa from pymol.setting import name_dict cmd = parent.cmd form = parent.load_form('props', 'floating') parent.addDockWidget(QtCore.Qt.RightDockWidgetArea, form._dialog) def make_entry(parent, label): item = QtWidgets.QTreeWidgetItem(parent) item.setText(0, str(label)) item.setFlags(QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable ) return item def make_cat(parent, label): item = QtWidgets.QTreeWidgetItem(parent) item.setText(0, str(label)) item.setFirstColumnSpanned(True) item.setExpanded(True) item.setChildIndicatorPolicy( QtWidgets.QTreeWidgetItem.ShowIndicator) return item # make first column uneditable form.treeWidget.setItemDelegateForColumn(0, UneditableDelegate()) item_object = make_cat(form.treeWidget, "Object-Level") item_object_ttt = make_entry(item_object, "TTT Matrix") item_object_settings = make_cat(item_object, "Settings") item_ostate = make_cat(form.treeWidget, "Object-State-Level") item_ostate_title = make_entry(item_ostate, "Title") item_ostate_matrix = make_entry(item_ostate, "State Matrix") item_ostate_settings = make_cat(item_ostate, "Settings") item_ostate_properties = make_cat(item_ostate, "Properties (user)") item_atom = make_cat(form.treeWidget, "Atom-Level") item_atom_identifiers = make_cat(item_atom, "Identifiers") item_atom_builtins = make_cat(item_atom, "Properties (built-in)") item_atom_settings = make_cat(item_atom, "Settings") item_atom_properties = make_cat(item_atom, "Properties (user)") item_astate = make_cat(form.treeWidget, "Atom-State-Level") item_astate_builtins = make_cat(item_astate, "Properties (built-in)") item_astate_settings = make_cat(item_astate, "Settings") keys_atom_identifiers = ['model', 'index', 'segi', 'chain', 'resi', 'resn', 'name', 'alt', 'ID', 'rank'] keys_atom_builtins = ['elem', 'q', 'b', 'type', 'formal_charge', 'partial_charge', 'numeric_type', 'text_type', # avoid stereo auto-assignment errors # 'stereo', 'vdw', 'ss', 'color', 'reps', 'protons', 'geom', 'valence', 'elec_radius'] keys_astate_builtins = ['state', 'x', 'y', 'z'] items = {} for key in keys_atom_identifiers: items[key] = make_entry(item_atom_identifiers, key) for key in keys_atom_builtins: items[key] = make_entry(item_atom_builtins, key) for key in keys_astate_builtins: items[key] = make_entry(item_astate_builtins, key) items['model'].setDisabled(True) items['index'].setDisabled(True) items['state'].setDisabled(True) def item_changed(item, column): """ Edits current item. """ if item_changed.skip: return model = form.input_model.currentText() state = form.input_state.value() key = item.text(0) new_value = item.text(1) parent = item.parent() result = False if item == item_object_ttt: try: if new_value: result = cmd.set_object_ttt(model, new_value) except (ValueError, IndexError): result = False elif item == item_ostate_title: result = cmd.set_title(model, state, new_value) elif item == item_ostate_matrix: cmd.matrix_reset(model, state) try: new_value = cmd.safe_eval(new_value) result = cmd.transform_object(model, new_value, state) except: # CmdTransformObject-DEBUG: bad matrix result = False elif parent == item_object_settings: with PopupOnException(): cmd.set(key, new_value, model, quiet=0) elif parent == item_ostate_settings: with PopupOnException(): cmd.set(key, new_value, model, state, quiet=0) elif parent == item_ostate_properties: cmd.set_property(key, new_value, model, state, quiet=0) else: is_state = False if parent == item_atom_properties: key = 'p.' + key elif parent == item_atom_settings: key = 's.' + key elif parent == item_astate_settings: key = 's.' + key is_state = True elif key in keys_astate_builtins: is_state = True def get_new_value(old_value): if isinstance(old_value, (tuple, list)): return cmd.safe_eval(new_value) try: # cast to old type (required for e.g. 'resv = "3"') return type(old_value)(new_value) except ValueError: # return str and let PyMOL handle it (e.g. change # type of user property) return new_value.encode('ascii') alter_args = ('pk1', key + '= get_new_value(' + key + ')', 0, {'get_new_value': get_new_value}) if is_state: result = cmd.alter_state(state, *alter_args) else: result = cmd.alter(*alter_args) if not result: update_treewidget_model() item_changed.skip = False def update_object_settings(parent, model, state): parent.takeChildren() for sitem in (cmd.get_object_settings(model, state) or []): key = name_dict.get(sitem[0], sitem[0]) item = make_entry(parent, key) item.setText(1, str(sitem[2])) def update_atom_settings(wrapper, parent): parent.takeChildren() for key in wrapper: item = make_entry(parent, name_dict.get(key, key)) value = wrapper[key] item.setText(1, str(value)) def update_atom_properties(wrapper, parent): parent.takeChildren() for key in wrapper: item = make_entry(parent, key) value = wrapper[key] item.setText(1, str(value)) def update_atom_fields(ns): for key in keys_atom_identifiers + keys_atom_builtins: try: value = ns[key] except Exception as e: value = 'ERROR: ' + str(e) items[key].setText(1, str(value)) update_atom_settings(ns['s'], item_atom_settings) update_atom_properties(ns['p'], item_atom_properties) def update_astate_fields(ns): for key in keys_astate_builtins: value = ns[key] items[key].setText(1, str(value)) update_atom_settings(ns['s'], item_astate_settings) space = { 'update_atom_fields': update_atom_fields, 'update_astate_fields': update_astate_fields, 'locals': locals, } def update_from_pk1(): pk1_atom = [] if cmd.iterate('?pk1', 'pk1_atom[:] = [model, index]', space=locals()) > 0: form.input_model.setCurrentIndex(form.input_model.findText(pk1_atom[0])) form.input_index.setValue(pk1_atom[1]) def update_pk1(): model = form.input_model.currentText() index = form.input_index.value() if model and index: try: cmd.edit((model, index)) return True except pymol.CmdException: pass return False def update_treewidget(*args): if not update_pk1(): return state = form.input_state.value() item_changed.skip = True count = cmd.iterate( 'pk1', 'update_atom_fields(locals())', space=space) item_atom.setDisabled(not count) if count: count = cmd.iterate_state( state, 'pk1', 'update_astate_fields(locals())', space=space) item_astate.setDisabled(not count) item_changed.skip = False def update_treewidget_state(*args): model = form.input_model.currentText() state = form.input_state.value() if not (model and state): return item_changed.skip = True item_ostate_title.setText( 1, str(cmd.get_title(model, state) or '')) item_ostate_matrix.setText( 1, str( cmd.get_object_matrix( model, state, 0) or '')) update_object_settings(item_ostate_settings, model, state) parent = item_ostate_properties parent.takeChildren() for key in (cmd.get_property_list(model, state) or []): item = make_entry(parent, key) item.setText(1, str(cmd.get_property(key, model, state))) update_treewidget() item_changed.skip = False @suspendable def update_treewidget_model(*args): item_changed.skip = True model = form.input_model.currentText() if not model: return item_object_ttt.setText(1, str(cmd.get_object_ttt(model) or '')) update_object_settings(item_object_settings, model, 0) natoms = cmd.count_atoms('?' + model) nstates = cmd.count_states('?' + model) form.input_state.setMinimum(1) form.input_state.setMaximum(nstates) form.input_index.setMinimum(1) form.input_index.setMaximum(natoms) item_atom.setHidden(natoms == 0) item_astate.setHidden(natoms == 0) item_ostate.setHidden(nstates == 0) update_treewidget_state() item_changed.skip = False def update_model_list(*args): if 'pk1' not in cmd.get_names('selections'): update_pk1() with update_treewidget_model.suspend: form.input_model.clear() form.input_model.addItems(get_object_names(cmd)) update_from_pk1() update_treewidget_model() # init input fields form.input_model.addItems(get_object_names(cmd)) form.input_state.setValue(cmd.get_state()) # select pk1 atom if available update_from_pk1() # hook up events form.input_model.currentIndexChanged.connect(update_treewidget_model) form.input_state.valueChanged.connect(update_treewidget_state) form.input_index.valueChanged.connect(update_treewidget) form.button_refresh.clicked.connect(update_model_list) # themed icons only available by default on X11 if form.button_refresh.icon().isNull(): form.button_refresh.setIcon(QtGui.QIcon( os.path.expandvars('$PYMOL_DATA/pmg_qt/icons/refresh.svg'))) # update and show update_treewidget_model() form.treeWidget.setColumnWidth(0, 200) form.treeWidget.itemChanged.connect(item_changed) return form._dialog
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", 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) self.proxy_model.setSourceModel(self.model) self.proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive) self.proxy_model.setFilterKeyColumn(-1) self.setWindowTitle('Keyboard Shortcut Menu') layout = QtWidgets.QVBoxLayout(self) self.setLayout(layout) # Create layout for filter bar and refresh button top_layout = QtWidgets.QGridLayout() layout.addLayout(top_layout) # Filter self.filter_le = QtWidgets.QLineEdit(self) top_layout.addWidget(self.filter_le) self.filter_le.setPlaceholderText("Filter") 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) # 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") self.refresh_button.clicked.connect(self.refresh_populate) # Table self.table = QtWidgets.QTableView(self) self.table.setModel(self.proxy_model) layout.addWidget(self.table) self.intial_populate() self.formatTable() # Add layout for buttons button_layout = QtWidgets.QGridLayout() layout.addLayout(button_layout) # Buttons self.create_new_button = QtWidgets.QPushButton(self) 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( lambda: self.create_new_form._dialog.show()) self.delete_selected_button = QtWidgets.QPushButton(self) 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.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) self.reset_selected_button.setText("Reset Selected") 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) 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.clicked.connect(self.reset_all_default) self.save_button = QtWidgets.QPushButton(self) 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.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)